コンピュータプログラミング演習(CPII) 中間テスト(最終)(2005/1/21)

制限時間90分 20点満点
http://www.tuat.ac.jp/~kamelab/CPII/050128/kaitourei050121.html

解答及び採点基準

第1問

以下は、三角形の2辺及びその挟角(2辺に挟まれた角)の値をそれぞれキーボードから入力すると、その三角形の面積を求め画面に表示するプログラムの例です(左端の行番号は便宜上付けたにすぎません。第2問も同様)。

(参考)

2辺a, bとその挟角θ(単位ラジアンで0<θ<π)とで構成される三角形

1: #include <stdio.h>
2: #include <[空欄1]>
3: [空欄2] PI 3.141592
4: void main(void)
5: {
6:	double a,b,theta,area;
7:	printf("三角形1辺aの値を代入\n");
8:	scanf("%lf",&a);
9:	printf("三角形1辺bの値を代入\n");
10:	scanf("%lf",&b);
11:	printf("2辺a,bに挟まれた角度の値を代入\n");
12:	scanf("%lf",&theta);
13:	if([空欄3])
14:	{
15:	area=[空欄4];
16:	printf("三角形の面積:%lf\n",area);
17:	}
18:	else
19:	{
20:		printf("正しい値を入力して下さい\n");
21:	}
22: }
問1
2行目、本プログラム中において数学関数sin()を使用するために、必要なヘッダーファイルの名称を[空欄1]へ書きなさい。
(解答 2点)
math.h

問2
3行目、定数πの代わりに、マクロとしてPIを定義します。[空欄2]を埋めなさい。
(解答 2点)
#define

問3
13行目、キーボードから値を代入された変数a、b、thetaに関して、以下の条件を満たす場合のみ三角形の面積を計算し、それ以外の場合は20行目で「正しい値を入力して下さい」と表示します。題意に沿うように[空欄3]を埋めなさい。なお、変数thetaの単位は「ラジアン」でも「度(゜)」でも可とします。

三角形が成立する条件(角度の単位がラジアンの場合)
a > 0かつb > 0かつ0 < theta < π
角度の単位が「度」の場合は、0゜ < theta < 180゜(πラジアン=180゜)

(解答 2点)
(ラジアン単位の場合)
a>0 && b>0 && theta>0 && theta<PI
(度(゜)単位の場合)
a>0 && b>0 && theta>0 && theta<180

問4
15行目、三角形の面積を計算し、変数areaに代入します。題意に沿うように[空欄4]を埋めなさい。なお、問3において変数のthetaの単位に「ラジアン」または「度 (゜)」を採用した場合との整合性を取ること。なお、関数sin()の引数と返り値は以下の通りです。引数の単位はラジアンを取ります。

double sin(double x)

(解答 2点)
(ラジアン単位の場合)
0.5*a*b*sin(theta)
(度(゜)単位の場合)
0.5*a*b*sin(theta*PI/180)

(注意!!)
1/2*a*b*sin(theta)のように、1/2という演算を最初に行うと、int型の演算のため0になってしまう。また、a*b*(1/2)*sin(theta)のように、(1/2)の演算をまとめて行うと、これもまたint型演算のため0になってしまう。このような解答は1点減点とする。
これを回避するには、1.0/2.0とするか、もしくは、(double)1/2または1/(double)2というようにキャストする必要がある(但し、(double)(1/2)では先にint型演算の1/2が行われるのでやはり0になってしまうことに注意せよ)。
なお、a*b*sin(theta)/2は、double型へと自動的に格上げされるので正しく計算される(当然正解である)。

第2問

以下は、キーボードから入力された個数分、整数乱数を発生させ、そのうちの偶数の個数をカウントするプログラムの例です。

(例)キーボードから3を入力した場合
8563
29767
21696
乱数3個のうち偶数は1個

1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <time.h>
4: int calc(int *aa, int nn); 
5: void main(void)
6: {
7: 	int i, rn, n, num, a[100];
8: 	unsigned int seed;
9: 	int nowtime;
10: 	time(&nowtime);
11: 	seed=(unsigned int)nowtime;
12: 	srand([空欄1]);
13: 	printf("発生させる乱数の数を指定(1個以上100個以下)\n");
14: 	scanf("%d",&n);
15: 	if([空欄2])
16: 		{
17: 		printf("乱数表示開始\n");
18: 			for(i=0; i< n ; i++)
19: 				{
20: 				rn=rand();
21: 				printf("%d\n",rn);
22: 				a[i]=rn;
23: 				}
24: 		num=calc([空欄3]);
25: 		printf("乱数%d個中、偶数は%d個\n",n,num);
26: 		}
27: 		else
28: 		{
29:		printf("正しい値を入力して下さい\n");
30: 		}
31: }
32: int calc(int *aa, int nn)
33: 	{
34: 	int i,count;
35: 	count=0;
36: 	for(i=0; i < nn ; i++)
37: 		{
38: 			if([空欄4])
39: 			[空欄5]
40:		}
41: [空欄6]
42: }

問1
12行目、乱数表の種を決める関数srand()の実引数として、本プログラム中で適切な変数を考え、[空欄1]を埋めなさい。
(解答 2点)
seed

問2
15行目、キーボードから入力された値nが1個以上100個以下の場合のみに乱数を発生させ、その他の値が入力された場合には、29行目で「正しい値を入力してください」と表示します。題意に沿うように[空欄2]を埋めなさい。
(解答 2点)
n>=1 && n<=100
または
n>0 && n<101

問3
発生したn個の乱数は配列a[i]に順次格納されます(22行目)。24行目、関数calc()を呼び出し、配列a[i]をその個数nと共に引き渡します。関数calc()からの返り値(戻り値)は変数numに代入されます。
4行目の関数calc()のプロトタイプ宣言及び32行目に注意し、関数calc()が取るべき実引数[空欄3]へ書きなさい。
(4行目, 32行目の再掲)

4: int calc(int *aa, int nn); 
32: int calc(int *aa, int nn);

(解答 2点)
a,n
または
&a[0],n

問4
38行目、関数calc()に引き渡された配列成分が偶数か否かを調べます。偶数の場合、39行目にて変数countの値をインクリメント(1つづ増加)します。題意に沿うように[空欄4][空欄5]を埋めなさい。
(解答 空欄4 2点)
aa[i]5%2==0
または
*(aa+i)%2==0
また、剰余演算子(%)を使わず、aa[i]がint型であることを利用した
(aa[i]/2)*2==aa[i]
も正解である。
(解答 空欄5 2点)
count++;
または
count=count+1;

問5
41行目、変数countの値を関数calc()の返り値(戻り値)とします。題意に沿うように[空欄6]を埋めなさい。
(解答 2点)
return count;
または
return(count);

<全体への注意点>
文の最後のセミコロン(;)抜けミスや余分に付けるミスについては、1点減点する。

得点分布(亀田・佐藤クラス)

***解答例ここまで***