for文・while文を使う問題を、初級から上級まで13問そろえました。ブラウザでコードを書いて「採点する」を押すと、本物の gcc でいくつかの入力を試し、出力が正しいかを判定します。
※ 実行と採点では、コードを外部の無料コンパイルサービス Wandbox に送信して gcc で動かします。
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
sum を 0 で初期化してから、for (i = 1; i <= n; i++) で sum += i; を繰り返します。#include <stdio.h> int main(void) { int n; scanf("%d", &n); int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } printf("合計: %d\n", sum); return 0; }
sum を初期化し忘れると、中身が不定の値から足し始めてしまいます。条件を i < n にすると N が足されません(1 つ足りない「オフバイワン」)。%3d で幅3にそろえること。入力はない。「実行」で入力を与えて動かす/「採点する」で 1 個のテストを自動で試します
printf("\n"); で改行します。#include <stdio.h> int main(void) { for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { printf("%3d", i * j); } printf("\n"); } return 0; }
printf("\n") を内側のループの中に書いてしまうと、1つ表示するたびに改行されます。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
i を 2 から始めて i += 2 で増やせば、偶数だけを順に取り出せます。i % 2 == 0 で判定する方法でも解けます。#include <stdio.h> int main(void) { int n; scanf("%d", &n); for (int i = 2; i <= n; i += 2) { printf("%d ", i); } printf("\n"); return 0; }
i++ に限らず、i += 2 のように自由に書けます。この採点では行末の空白は無視するので、"%d " で末尾に空白が残っても正解になります。N! = 値」の形で表示せよ。0! は 1 とする。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
long long 型と書式 %lld を使います。#include <stdio.h> int main(void) { int n; scanf("%d", &n); long long fact = 1; for (int i = 1; i <= n; i++) { fact *= i; } printf("%d! = %lld\n", n, fact); return 0; }
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
n % 10 で一の位が取り出せ、n / 10 で一の位を捨てられます。これを n が 0 になるまで while文で繰り返します。#include <stdio.h> int main(void) { int n; scanf("%d", &n); int sum = 0; while (n > 0) { sum += n % 10; n /= 10; } printf("各桁の和: %d\n", sum); return 0; }
データがありません」と表示する。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
while (1) で無限ループにして、読んだ値が 0 なら break で抜けます。平均は (double)sum / count のように片方を double にして割ります。#include <stdio.h> int main(void) { int x, count = 0, sum = 0; while (1) { scanf("%d", &x); if (x == 0) break; count++; sum += x; } if (count == 0) { printf("データがありません\n"); } else { printf("個数: %d\n", count); printf("合計: %d\n", sum); printf("平均: %.2f\n", (double)sum / count); } return 0; }
sum / count と書くと整数どうしの割り算になり、小数部分が切り捨てられます。しかもその int の値を %.2f に渡すことになるので、表示はでたらめになります(未定義動作。0.00 と出る環境もあります)。コンパイラも警告を出すので、警告は必ず読みましょう。また count が 0 のまま割ると0除算になるので、先に分けて処理します。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
i について、n % i == 0(割り切れる)なら約数です。表示と同時に個数も数えておきます。#include <stdio.h> int main(void) { int n; scanf("%d", &n); int count = 0; for (int i = 1; i <= n; i++) { if (n % i == 0) { printf("%d ", i); count++; } } printf("\n約数の個数: %d\n", count); return 0; }
i <= n にします。* で N 段の直角三角形を表示せよ。i 段目には * を i 個並べる。「実行」で入力を与えて動かす/「採点する」で 3 個のテストを自動で試します
i を 1〜N と回し、内側のループで * を i 個表示します。内側の終了条件が外側の変数 i で決まるのがポイントです。#include <stdio.h> int main(void) { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { printf("*"); } printf("\n"); } return 0; }
* が i 個なので、内側を j <= i にします。Fizz、5 の倍数なら Buzz、3 と 5 の両方の倍数なら FizzBuzz と表示する。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
#include <stdio.h> int main(void) { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { if (i % 15 == 0) { printf("FizzBuzz\n"); } else if (i % 3 == 0) { printf("Fizz\n"); } else if (i % 5 == 0) { printf("Buzz\n"); } else { printf("%d\n", i); } } return 0; }
i % 3 == 0 を判定すると、15 のときも「Fizz」で止まってしまい、FizzBuzz が出ません。条件が重なるときは、より厳しい条件を先に書きます。「実行」で入力を与えて動かす/「採点する」で 5 個のテストを自動で試します
k を 2〜N と回し、内側のループで「2 から √k までのどれかで割り切れるか」を調べます。j * j <= k を条件にすると、√ を使わずに済みます。#include <stdio.h> int main(void) { int n; scanf("%d", &n); int count = 0; for (int k = 2; k <= n; k++) { int is_prime = 1; for (int j = 2; j * j <= k; j++) { if (k % j == 0) { is_prime = 0; break; } } if (is_prime) { printf("%d ", k); count++; } } printf("\n素数の個数: %d\n", count); return 0; }
is_prime)を、候補ごとに 1 に戻すのを忘れないようにします。割り切れた時点で break すると無駄な計算を省けます。* で N 段のピラミッドを表示せよ。i 段目は、空白を N−i 個並べたあとに * を 2i−1 個並べる(行末に空白は付けない)。「実行」で入力を与えて動かす/「採点する」で 3 個のテストを自動で試します
n - i 個、2つ目で * を 2 * i - 1 個表示し、最後に改行します。#include <stdio.h> int main(void) { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { for (int j = 0; j < n - i; j++) { printf(" "); } for (int j = 0; j < 2 * i - 1; j++) { printf("*"); } printf("\n"); } return 0; }
「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
b が 0 になるまで、(a, b) を (b, a % b) に置き換える」だけです。そのときの a が最大公約数。最小公倍数は a / g * b(g は最大公約数)で求めます。結果は int に入らないことがあるので、(long long)a / g * b として %lld で表示します。#include <stdio.h> int main(void) { int a, b; scanf("%d %d", &a, &b); int x = a, y = b; while (y != 0) { int r = x % y; x = y; y = r; } int g = x; long long l = (long long)a / g * b; printf("最大公約数: %d\n", g); printf("最小公倍数: %lld\n", l); return 0; }
a * b / g の順だと掛け算の時点であふれやすいので、先に割ります。「実行」で入力を与えて動かす/「採点する」で 4 個のテストを自動で試します
while (n != 1) で回し、毎回 steps++ と最大値の更新をします。途中の値は N の数百倍になることもあるので、long long で扱うと安全です。#include <stdio.h> int main(void) { long long n; scanf("%lld", &n); int steps = 0; long long max = n; while (n != 1) { if (n % 2 == 0) { n /= 2; } else { n = 3 * n + 1; } steps++; if (n > max) max = n; } printf("ステップ数: %d\n", steps); printf("最大値: %lld\n", max); return 0; }