中間テストはペーパーテストが 12 点満点、
オンラインテストが 8 点満点で採点する。
(ただし、最終的な成績の計算にはこの半分 — ペーパーテスト 6点満点、
オンラインテスト 4 点満点 — の割合で用いる。)
問1:
次のプログラムは一つの実数値を読み込んで、 それを 3 倍した値と 切り捨てた値を表示するプログラムである。 例えば、2.7 を入力すると、
それを 3 倍した値は 8.100000 です。 それを切り捨てた値は 2 です。
と出力する。 空欄を埋めて、プログラムを完成せよ。
int main(void) { double x; printf("実数を入力して下さい: "); scanf("", ); printf("それを 3 倍した値は です。\n", ); printf("それを切り捨てた値は です。\n", ); return 0; }
正解(例)とコメントは以下のとおりである。
番号 | 正解例 | コメント |
---|---|---|
(ⅰ) | %lf | |
(ⅱ) | &x | |
(ⅲ) | %f | %lf は望ましくない。 |
(ⅳ) | x * 3 | |
(ⅴ) | %d | |
(ⅵ) | (int)x | 正答率がやや悪い。int(x)などの間違いが多い。 |
問2:
次のプログラムの出力を書け。
int main(void) { int k = 60, a = 1; if (k % 2 == 0) { a *= 2; } else if (k % 3 == 0) { a *= 3; } if (k % 5 == 0) { a *= 5; } printf("%d\n", a); return 0; }
正解は、「10」。 k % 2 == 0 という条件が成り立つので else 節の if (k % 3 == 0) { a *= 3; } は評価されない。if (k % 5 == 0) { a *= 5; } は次の文なので評価される。
a *= 2 は a = a * 2 と同じ意味になる。
問3:
以下の空欄を埋めて、 初項1、公比3の等比数列 \(1, 3, 9, 27, \ldots\) の1000未満の部分を出力する プログラムを完成させよ。
int main(void) {
int n;
for ( ) {
printf("%d ", n);
}
printf("\n");
return 0;
}
正解例は、「n = 1; n < 1000; n *= 3」。
n *= 3 のところは、n = n * 3 でもよい。 ここを、単に n * 3 とする間違いが多い。 第 3 式は式の値は無視されるので、代入でないといけない。
問4:
int main(void) { int i, j, n = 3; for (i = n; i > 0; i--) { for (j = 1; j <= i; j++) { printf("(%d,%d) ", i, j); } printf("\n"); } return 0; }
正解は以下の通りである。
(3,1)␣(3,2)␣(3,3)␣↓ (2,1)␣(2,2)␣↓ (1,1)␣↓
以下のプログラムは動作はする(はずだ)がインデンテーションが滅茶苦茶である。 プログラミングのインデンテーションの約束事に厳密に従って(特に 5 番目のルールに注意)、インデントしなおせ。ブレース内の字下げは 4 文字分とせよ。 もちろん、 プログラムの意味(実行結果)が変わらないことを確認しておくこと。
#include <stdio.h> int main(void) { int i, j; for (i = 0; i < 10; i++) for (j = 0; j < i; j++) if (j % 5 == 0) putchar('@'); else putchar('*'); putchar(','); putchar('\n');return 0; }
インデンテーションがうまくできない人は、肝心のプログラムの構造がわかっていない、 勘でプログラムを作っている、 と判断せざるをえない。教科書を読み返して、C 言語の文法を充分に理解しておくこと。
プログラミング言語の文法は、日本語や英語などの自然言語の文法に比べてはるかに単純である。 理解せずに勘でプログラムを書こうとするのは、時間の浪費である。
プログラムの意味(実行結果)を変えてしまうようにブレースを入れている誤答がたいへん多い。 (スペースや改行の位置は別にして、)ブレースは以下の位置に入る。
#include <stdio.h> int main(void) { int i, j; for (i = 0; i < 10; i++) { for (j = 0; j < i; j++) { if (j % 5 == 0) { putchar('@'); } else { putchar('*'); }}} putchar(','); putchar('\n');return 0; }
例えば、以下のようにブレースをいれてしまうと、プログラムの意味が変わってしまう。
/* 間違い */
int main(void) {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < i; j++) {
if (j % 5 == 0) {
putchar('@');
} else {
putchar('*');
putchar(',');
}
}
putchar('\n');
}
return 0;
}
開発チームの他の人や 3 ヵ月後の自分がソースを読んだときにこのような勘違いが起きないよう、 インデンテーションの約束事がある。 特に:
ブレース({ 〜 })の中は、外よりも 4 または 8 字分(首尾一貫した文字数)を字下げする。
if 文, if 〜 else 文 や for 文, while 文, do 〜 while 文などでは、 選択されたり、繰り返したりされる文が一つだけの場合も、 ブレース({〜})に囲む。
は徹底する必要がある。
なお、このようなブレースを追加しても、 コンパイルされた結果である実行可能ファイルの効率が悪くなる心配はない。
繰返しを用いて、1 から 50 までの整数 i に対して、 偶数の場合は、i を 2 で割った商 (i / 2)を、 3 の倍数の場合は、i を 3 で割った商 (i / 3)を、表示せよ。 2 でも 3 でも割り切れない場合は何も表示せず空行とし、 2 と 3 の両方で割り切れるばあいは、3 で割った商 (i / 3)を優先せよ。
出力は以下のようになる。
1 = 7 * 0 + 1 2 = 2 * 1 3 = 3 * 1 4 = 2 * 2 6 = 3 * 2 8 = 2 * 4 9 = 3 * 3 10 = 2 * 5 12 = 3 * 4 … 48 = 3 * 16 50 = 2 * 25
出力のための命令(printf, putchar, puts など)を使用できるのは 3 箇所までとする。
参考にするプログラム: List 4-12
正解例は以下のとおりである。
#include <stdio.h> int main(void) { int i; for (i = 1; i <= 50; i++) { if (i % 3 == 0) { printf("%d = 3 * %d\n", i, i / 3); } else if (i % 2 == 0) { printf("%d = 2 * %d\n", i, i / 2); } else { printf("\n"); } } return 0; }
あるいは
#include <stdio.h> int main(void) { int i; for (i = 1; i <= 50; i++) { if (i % 3 == 0) { printf("%d = 3 * %d", i, i / 3); } else if (i % 2 == 0) { printf("%d = 2 * %d", i, i / 2); } printf("\n"); } return 0; }
やはりインデンテーションが約束事にそってできていない解答が多い。 この問題の場合はインデンテーションの誤りは 25 〜 50 % の減点とする。