中間テストはペーパーテストが 12 点満点、
オンラインテストが 8 点満点で採点する。
(ただし、最終的な成績の計算にはこの半分 — ペーパーテスト 6点満点、
オンラインテスト 4 点満点 — の割合で用いる。)
中間テストは、大部分の人にとっては「簡単過ぎる」 と感じる程度の難易度だったはずである。 期末テストは、もっと難易度は高くなる。
今回はテストであるので、NG というメッセージがあっても、 再提出する必要はない。
ペーパーとオンラインを合算して、得点率が 6 割未満の者には、
追試験を実施する予定である。詳細は追って連絡する。(nov20_1.c
へのメッセージにペーパーテスト・オンラインテストの得点を通知する予定である。)
(11/27) 通知済みです。
問1:
次のプログラムは一つの整数値を読み込んで、 それを整数として 3 で割った値と 実数として 3 で割った値を表示するプログラムである。 例えば、10 を入力すると、
それを整数として 3 で割った値は 3 です。 それを実数として 3 で割った値は 3.333333 です。
と出力する。 空欄を埋めて、プログラムを完成せよ。
int main(void) { int k; printf("整数を入力して下さい: "); scanf("", ); printf("それを整数として 3 で割った値は です。\n", ); printf("それを実数として 3 で割った値は です。\n", ); return 0; }
正解(例)とコメントは以下のとおりである。
番号 | 正解例 | コメント |
---|---|---|
(ⅰ) | %d | %lf という誤答が少しあった。 |
(ⅱ) | &k | &n という誤答が多かった。問題文をよく読むこと。 |
(ⅲ) | %d | |
(ⅳ) | k / 3 | |
(ⅴ) | %f | %lf は望ましくない。 |
(ⅵ) | k / 3.0 | 他に (double)k / 3 や k / (double)3 などでも良い。 k / 3 という誤答が多かった。整数 / 整数 は切捨てになってしまう。 |
問2:
次のプログラムの出力を書け。
int main(void) { int k = 12, a = 1; if (k % 2 == 0) { a *= 2; } if (k % 3 == 0) { a *= 3; } else if (k % 4 == 0) { a *= 5; } printf("%d\n", a); return 0; }
正解は、「6」。 k % 3 == 0 という条件が成り立つので else 節の if (k % 4 == 0) { a *= 5; } は評価されない。
a *= 2 は a = a * 2 と同じ意味になる。
問3:
int main(void) {
int n;
do {
printf("1 〜 8 の整数を入力してください: ");
scanf("%d", &n);
} while ( );
printf("太陽系の第 %d 惑星は、", n);
switch (n) {
case 1: printf("水星"); break;
case 2: printf("金星"); break;
case 3: printf("地球"); break;
case 4: printf("火星"); break;
case 5: printf("木星"); break;
case 6: printf("土星"); break;
case 7: printf("天王星"); break;
case 8: printf("海王星"); break;
}
printf("です。\n");
return 0;
}
正解例は、「n < 1 || 8 < n」。
&& を使っている誤答が多かった。&& を使う場合は、 「!(1 <= n && n <= 8)」のように否定演算子「!」を使わなければいけない。
問4:
int main(void) { int i, j, n = 3; for (i = 0; i < n; i++) { for (j = n; j > i; j--) { printf("(%d,%d) ", i, j); } printf("\n"); } return 0; }
正解は以下の通りである。
(0,3)␣(0,2)␣(0,1)␣↓ (1,3)␣(1,2)␣↓ (2,3)␣↓
以下のプログラムは動作はする(はずだ)がインデンテーションが滅茶苦茶である。 プログラミングのインデンテーションの約束事に厳密に従って(特に 5 番目のルールに注意)、インデントしなおせ。ブレース内の字下げは 4 文字分とせよ。 もちろん、 プログラムの意味(実行結果)が変わらないことを確認しておくこと。
#include <stdio.h> int main(void) { int i; for (i = 0; i < 10; i++) if (i % 2 == 0) putchar('*'); if (i % 5 == 0) putchar('@'); putchar('\n');return 0; }
正解は以下の通りである。
#include <stdio.h> int main(void) { int i; for (i = 0; i < 10; i++) { if (i % 2 == 0) { putchar('*'); } } if (i % 5 == 0) { putchar('@'); } putchar('\n'); return 0; }
以下のようにブレースをいれてしまうと、プログラムの意味が変わってしまう。
/* 間違い */
#include <stdio.h>
int main(void) {
int i;
for (i = 0; i < 10; i++) {
if (i % 2 == 0) {
putchar('*');
}
if (i % 5 == 0) {
putchar('@');
}
}
putchar('\n');
return 0;
}
開発チームの他の人や 3 ヵ月後の自分がソースを読んだときにこのような勘違いが起きないよう、 インデンテーションの約束事がある。 特に:
ブレース({ 〜 })の中は、外よりも 4 または 8 字分(首尾一貫した文字数)を字下げする。
if 文, if 〜 else 文 や for 文, while 文, do 〜 while 文などでは、 選択されたり、繰り返したりされる文が一つだけの場合も、 ブレース({〜})に囲む。
は徹底する必要がある。
インデンテーションがうまくできない人は、肝心のプログラムの構造がわかっていない、と判断せざるをえない。
なお、このようなブレースを追加しても、 コンパイルされた結果である実行可能ファイルの効率が悪くなる心配はない。
繰返しを用いて、1 から 31 までの整数 i に対して i を 7 で割った商 (i / 7) と 余り (i % 7) を表示するプログラムを作成せよ。
各行は「i = 7 * 商 + 余り」 という形式で表示せよ、ただし、 余りが 0 のときは「 + 余り」 の部分は表示せず、 「i = 7 * 商」という形式で表示せよ。1 = 7 * 0 + 1 2 = 7 * 0 + 2 3 = 7 * 0 + 3 4 = 7 * 0 + 4 5 = 7 * 0 + 5 6 = 7 * 0 + 6 7 = 7 * 1 8 = 7 * 1 + 1 … 28 = 7 * 4 29 = 7 * 4 + 1 30 = 7 * 4 + 2 31 = 7 * 4 + 3
出力のための命令(printf, putchar, puts など)を使用できるのは 3 箇所までとする。
参考にするプログラム: List 4-12
正解例は以下のとおりである。
#include <stdio.h> int main(void) { int d; for (d = 1; d <= 31; d++) { int q = d / 7, r = d % 7; if (r != 0) { printf("%d = 7 * %d + %d\n", d, q, r); } else { printf("%d = 7 * %d\n", d, q); } } return 0; }
「余りが 0 のときは…」の要件が満されていない解答が多かった。 できなかったのか、見落していたのか?
やはりインデンテーションが約束事にそってできていない解答が多い。 この問題の場合はインデンテーションの誤りは 25 〜 50 % の減点とした。