中間テストはペーパーテストが 12 点満点(順に 2, 3, 2, 2, 3 点)、
オンラインテストが 8 点満点(4, 4 点)で採点する。
(ただし、最終的な成績の計算にはこの半分 — ペーパーテスト 6点満点、
オンラインテスト 4 点満点 — の割合で用いる。)
オンラインテストでセミコロンの付け忘れなど基本的な文法事項で何度もエラーを出しているようでは、 時間内に課題を仕上げることが非常に困難になる。 文法は“何となく”ではなく、確実に理解しておく必要がある。
以下のプログラムは動作はするがインデンテーションが滅茶苦茶でプログラムの構造を正しく反映していない。 (そして、おそらく作成者の意図したようには動かない。) プログラムの構造を明確にするために「プログラミング」のインデンテーションの約束事(別紙)に厳密に従って(特に Ⅴ 番目のルールに注意)、必要に応じてブレースを挿入し、インデントしなおせ。ただし、 ブレース内の字下げは紙幅の制限のため 3文字分とせよ。
もちろん、プログラムの意味(実行結果)が変わらないようにすること。 (つまり、作成者の(よくわからない)意図を忖度するのではなく、 コンパイラーが解釈する通りにインデントすること。
解答は、最初の #include <stdio.h>
は省略せよ。また、
解答欄のスペースの都合で、(最後は別として)空行は入れずに記入せよ。
int main(void) { int i, j; for (i = 0; i < 6; i++) if (i % 2 == 0) for (j = 0; j < i; j++) putchar('*'); if (i % 3 == 0) for (j = 0; j < i; j++) putchar('@'); putchar('\n'); return 0; }
正解は以下の通りである。
int main(void) { int i, j; for (i = 0; i < 6; i++) { if (i % 2 == 0) { for (j = 0; j < i; j++) { putchar('*'); } } } if (i % 3 == 0) { for (j = 0; j < i; j++) { putchar('@'); } } putchar('\n'); return 0; }
次のような誤りが多い。ほぼ、半数が以下のどちらかの誤りを犯している。 この2つはどちらもプログラムの意味が変わってしまっている。
int main(void) {
int i, j;
for (i = 0; i < 6; i++) {
if (i % 2 == 0) {
for (j = 0; j < i; j++) {
putchar('*');
}
}
if (i % 3 == 0) {
for (j = 0; j < i; j++) {
putchar('@');
}
}
putchar('\n');
}
return 0;
}
あるいは、
int main(void) {
int i, j;
for (i = 0; i < 6; i++) {
if (i % 2 == 0) {
for (j = 0; j < i; j++) {
putchar('*');
}
}
if (i % 3 == 0) {
for (j = 0; j < i; j++) {
putchar('@');
putchar('\n');
}
}
}
return 0;
}
正解したのは 15 名で、 16.9 % (15 / 89) だった。
インデンテーションがちゃんとできない人は、 肝心のプログラムの構造がわかっていない、勘でプログラムを作っている、 と判断せざるをえない。教科書を読み返して、C 言語の文法を充分に理解しておくこと。
プログラミング言語の文法は、日本語や英語などの自然言語の文法に比べてはるかに単純である。 理解せずに勘でプログラムを書こうとするのは、時間の浪費で、今後の進歩が望めない。
プログラムの意味(実行結果)を変えてしまうようにブレースを入れてしまう誤答も
とても多い。if
や for
の対象となるのは、1 つの文だから、
(スペースや改行の位置は別にして、)ブレースは以下の位置に入る。
int main(void) { int main(void) { int i, j; for (i = 0; i < 6; i++) { if (i % 2 == 0) { for (j = 0; j < i; j++) { putchar('*'); }}} if (i % 3 == 0) { for (j = 0; j < i; j++) { putchar('@'); }} putchar('\n'); return 0; }
教科書の p.43, p.44, p.46, pp.58-59, p.72-73, p.80, pp.90-91 の図を確認しておくこと。
開発チームの他の人や 3 ヵ月後の自分がソースを読んだときに、 このような勘違いが起きないよう、インデンテーションの約束事がある。 特に:
ブレース({
〜 }
)の中は、外よりも 4(ただし、今回のテストでは 3)
字分(首尾一貫した文字数)を字下げする。
if
文, if
〜 else
文 や for
文,
while
文, do
〜 while
文などでは、
選択されたり、繰り返したりされる文が一つだけの場合も、
ブレース({
〜}
)に囲む。
は徹底する必要がある。
なお、このようなブレースを追加しても、 コンパイルされた結果である実行可能ファイルの効率が悪くなる心配はない。
次のプログラムは一つの整数値を読み込んで、 それを3.14倍した値と、10倍してから(整数として)9で割った値を表示するプログラムである。
たとえば、30 を入力すると、
それを 3.14 倍した値は 94.200000 です。 それを 10 倍してから 9 で割った値は 33 です。
と出力する。 空欄を埋めて、プログラムを完成せよ。
int main(void) { int num; printf("整数を入力して下さい: "); scanf("", ); printf("それを 3.14 倍した値は です。\n", ); printf("それを 10 倍して 9 で割った値は です。\n", ); return 0; }
正解(例)とコメントは以下のとおりである。
番号 | 正解例 | コメント |
---|---|---|
(ⅰ) | %d |
%lf は double 型のための変換指定 |
(ⅱ) | &num |
手書きのとき & が裏返しになっている人が少しいる。 |
(ⅲ) | %f |
%lf は誤り。 |
(ⅳ) | num * 3.14 |
キャストや括弧は必要ないが、結果が変わらなければ正解とする。 |
(ⅴ) | %d |
|
(ⅵ) | num * 10 / 9 |
キャストや括弧は必要ないが、結果が変わらなければ正解とする。 |
次のプログラムの出力を書け。
int main(void) { int k = 45; if (k % 5 == 0) { printf("A "); } if (k % 15 == 0) { printf("B "); } else if (k % 9 == 0) { printf("C "); } else if (k % 3 == 0) { printf("D "); } printf("\n"); return 0; }
正解は、「A B
」。
ほとんどできていたが、間違えた人は if〜else 文の意味を再確認しておくこと。
k % 15 == 0
という条件が成り立つので、else
部の
if (k % 9 == 0) { … }
は評価されない。つまり C
は出力されない。
同様に if (k % 3 == 0) { … }
も評価されない。
以下の空欄を埋めて、 初項 5、公比 3 の等比数列 5, 15, 45, 135, … の 99999 以下の部分を出力する プログラムを完成させよ。
int main(void) {
int n;
for ( ) {
printf("%d ", n);
}
putchar('\n');
return 0;
}
正解例は、「n = 5; n <= 99999; n *= 3
」である。
「n = 5; n < 99999; n *= 3
」でも結果は変わらないが、初期値が 5
以外の値なら、結果が変わる可能性があるので、「<=
」とするべきだろう。
「n =< 99999
」や「n ≦ 99999
」という解答があったが、
「=<
」や「≦
」という演算子は C 言語にはない。
「i = 5; i <= 99999; i *= 3
」など、変数名が違うのはもちろんダメである。
「n <= 9999
」などの間違いも意外に多い。
「n *= 3
」のところを「n * 3
」という誤答が多かった。これでは変数の値は変わらない。
「n = n * 3
」なら良い。
(i,j)
という形式で出力する。
このプログラムの出力を書け。ただし、
空白は明示的に空白記号(␣)を、
改行は明示的に矢印(↓)を書くこと。
int main(void) { int main(void) { int i, j, n = 4; for (i = 0; i < 2 * n; i += 2) { for (j = i; j < 2 * n; j += 3) { printf("(%d,%d) ", i, j); } printf("\n"); } return 0; }
正解は以下の通りである。
(0,0)␣(0,3)␣(0,6)␣↓ (2,2)␣(2,5)␣↓ (4,4)␣(4,7)␣↓ (6,6)␣↓
下に示すように、正の整数 n を受け取って、初項 2, 公差 5 の等差数列の
第 1 項から第 n 項までを表示するプログラムを作成せよ。ただし、3 の倍数は
数の前に #
を表示せよ。(n として負の数または 0
を受け取ったときは、改行のみ表示するか、もしくは何も表示しなくてよい。)
正の整数を入力してください: 4↵
2 7 #12 17
実行例 2:
正の整数を入力してください: 9↵
2 7 #12 17 22 #27 32 37 #42
実行例 3:
正の整数を入力してください: -1↵
実行例 4:
正の整数を入力してください: 1↵
2
正解例は以下のとおりである。
#include <stdio.h> int main(void) { int i, n; printf("正の整数を入力してください: "); scanf("%d", &n); for (i = 0; i < n; i++) { int k = i * 5 + 2; if (k % 3 == 0) { printf("#%d ", k); } else { printf("%d ", k); } } putchar('\n'); return 0; }
正解率は 71 / 89(79.8 %)である。ただし、ここで正解とカウントしていても、 インデンテーションなどでの減点はありうる。
「n 回繰り返す」(「for (i = 0; i < n; i++)
」
または、 「for (i = 1; i <= n; i++)
」)というのは繰返しの基本の形だが、
それができていない解答が多い。
(
〜)
」内にループの制御に関係ない変数の代入や初期化を書くのは、
for 文を使う意味がなく,良くない。
/* 良くない */
i = 0;
for (k = 2; i < n; k += 5) {
…
i++:
}
次のように書くべきである。
k = 2; for (i = 0; i < n; i++) { … k += 5: }
やはりインデンテーションが約束事にそってできていない解答が多い。 この問題の場合はインデンテーションの誤りは 10 〜 20 % の減点とする。
下に示すように、正の整数 n を受け取ってディスプレイ上に、
下の実行例のように
左上から右下への対角線の位置は 1234567890…
を順に繰り返して表示し、
それ以外の位置は *
を表示して、
高さが n, 幅が n の正方形を作成するプログラムを作成せよ。
正の整数を入力してください: 4↵
1***
*2**
**3*
***4
実行例 2:
正の整数を入力してください: 13↵
1************
*2***********
**3**********
***4*********
****5********
*****6*******
******7******
*******8*****
********9****
*********0***
**********1**
***********2*
************3
実行例 2:
正の整数を入力してください: 0↵
正解例は以下のとおりである。
#include <stdio.h> int main(void) { int i, j, n; printf("正の整数を入力してください: "); scanf("%d", &n); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (i == j) { printf("%d", j % 10); } else { putchar('*'); } } putchar('\n'); } return 0; }または、
#include <stdio.h> int main(void) { int i, j, n; printf("正の整数を入力してください: "); scanf("%d", &n); for (i = 1; i <= n; i++) { for (j = 1; j < i; j++) { putchar('*'); } printf("%d", j++ % 10); for ( ; j <= n; j++) { putchar('*'); } putchar('\n'); } return 0; }
後者のほうが、条件式の評価回数が少なく望ましいが、前者でも OK とする。
正解率は 53 / 89 (59.6 %)である。ただし、ここで正解とカウントしていても、インデンテーションなどでの減点はありうる。
「i == j
」と書くべきところが「i = j
」になっているなどの、
初歩的な間違いが多かった。