制御構文: フロー制御
if/switch で分岐。for/while で繰り返し。
if/else
条件分岐の基本。
switch
値による多岐分岐。
break
ループやswitchを抜ける。
continue
次の周回へスキップ。
詳細解説
上から下に流れるだけのプログラムでは何もできません。 「分岐(もし〜なら)」と「反復(繰り返し)」 を使って、複雑なロジックを組む方法を学びます。
分岐 (Branch)
- if - else if - else: ブロック
{}は1行でも省略しないこと!(バグの温床になります) - switch: 値による分岐。
break忘れの恐怖(フォールスルー)に注意。C言語のswitchは整数(と文字)しか使えない制約があります。
反復 (Loop)
- for: 回数が決まっている繰り返しに最適。
iはindexの略。 - while: 条件が満たされている間ずっと実行。無限ループ
while(1)はサーバーなどで活用。 - do-while: 「少なくとも1回は実行する」場合に使用(入力チェックなど)。
制御の脱出
- break: ループを抜ける。
- continue: 今回の周をスキップして次へ。
- goto: 禁忌の技。組み込みのエラー処理など特殊な場面以外では使わないこと。
実践テクニック
選び方ガイド
switch vs if
整数・3分岐以上なら switch。範囲判定や複雑な条件は if。
for vs while
回数が決まっているなら for。条件で回すなら while。
早期リターン(ガード節)
ネストを深くしないために、異常系を先に弾きます。
Good
// 早期リターン(ガード節)で書く// 現場ではこちらが好まれるint process_user(User* user) { // 異常系を先に弾く if (user == NULL) { return -1; } if (!user->is_active) { return -1; } if (user->age < 18) { return -1; }
// 本来の処理(ネストが浅い) return do_something(user);}入力検証パターン
// 現場でよく見る「if のみ」パターン// else を書かずに早期リターンする
int validate_input(const char* input) { // 入力チェック: 問題があれば即 return if (input == NULL) { return ERROR_NULL_INPUT; } if (strlen(input) == 0) { return ERROR_EMPTY_INPUT; } if (strlen(input) > MAX_LENGTH) { return ERROR_TOO_LONG; }
// ここまで来たら正常 return SUCCESS;}条件分岐
// if文: 条件に応じて処理を分岐// 条件式は括弧 () で囲み、処理は {} で囲む// ※ 1行でも {} を省略しない(バグ防止)int number = 5; // ※ 変数名は意味のある名前にする(x より number)
if (number > 0) { printf("positive\n"); // number が正の場合} else if (number < 0) { printf("negative\n"); // number が負の場合} else { printf("zero\n"); // number が 0 の場合}
// switch文: 値による多岐分岐// break を忘れると次の case に流れる(フォールスルー)switch (grade) {case 'A': // case は switch と同じ列(Kernel Style) printf("Excellent\n"); break; // ここで switch を抜けるcase 'B': printf("Good\n"); break;default: // どの case にも一致しない場合 printf("Other\n");}Bad
// break 忘れでフォールスルーint command = get_command();
switch (command) {case 1: handle_create(); // break がない!case 2: handle_delete(); // command == 1 でも実行される}Good
// 各 case に break を書くint command = get_command();
switch (command) {case 1: handle_create(); break; // 必ず breakcase 2: handle_delete(); break;}ループ
// for ループ: 回数が決まった繰り返し// (初期化; 条件; 更新) の3部分で構成for (int i = 0; i < 10; i++) { printf("%d ", i); // 0 1 2 3 4 5 6 7 8 9}
// while ループ: 条件が真の間繰り返す// 条件判定が先(0回実行の可能性あり)int count = 0;while (count < 5) { printf("%d ", count); count++; // 更新を忘れると無限ループ!}
// do-while ループ: 最低1回は実行// 条件判定が後(入力検証に便利)do { printf("At least once\n");} while (0); // 条件が偽でも1回は実行される
// break: ループを途中で抜ける// continue: 今回の周をスキップして次へfor (int i = 0; i < 10; i++) { if (i == 3) continue; // 3をスキップ if (i == 7) break; // 7で終了 printf("%d ", i); // 出力: 0 1 2 4 5 6} Tip: do-while は入力検証に便利(最低1回実行)。
よくある間違い
1. {} の省略
if の後に1行だけでも {} を省略すると、後から行を追加したときにバグになりやすい。Apple の goto fail バグが有名な例。
2. switch の break 忘れ
フォールスルー(次のcaseまで流れる)は意図的でない限りバグ。コメントで明記するか、必ず break を書く。
3. 無限ループ
while や for の条件が永遠に真のままになる。ループ変数の更新忘れに注意。
// goto - 禁忌の技// 組み込みのエラー処理など特殊な場面以外では使わない// 可読性が著しく低下するため、通常は避ける
int process_data() { FILE* f = fopen("data.txt", "r"); if (!f) goto cleanup; // ファイルオープン失敗
int* buf = malloc(1000); if (!buf) goto close_file; // メモリ確保失敗
// ... 処理 ...
free(buf);close_file: fclose(f);cleanup: return -1;}演習課題
課題1: FizzBuzz
1から100まで出力。3の倍数で "Fizz"、5の倍数で "Buzz"、両方の倍数で "FizzBuzz" を表示する。
解答例を見る
// FizzBuzz の解答例// 3と5の両方の倍数を最初に判定するのがポイントfor (int i = 1; i <= 100; i++) { if (i % 15 == 0) { // 3と5の公倍数 = 15の倍数 printf("FizzBuzz\n"); } else if (i % 3 == 0) { // 3の倍数 printf("Fizz\n"); } else if (i % 5 == 0) { // 5の倍数 printf("Buzz\n"); } else { printf("%d\n", i); // それ以外は数字 }} 課題2: 九九の表
二重ループを使って九九の表をきれいに表示する。
解答例を見る
// 九九の表の解答例// 二重ループで行と列を回すfor (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { printf("%2d ", i * j); // %2d で2桁揃え } printf("\n"); // 行の終わりで改行} 課題3: 合計計算機
ユーザーが「0」を入力するまで、入力された数字を足し続けるプログラム。
解答例を見る
// 合計計算機の解答例// do-while で「最低1回は入力を受ける」パターンint sum = 0;int num;
do { printf("数字を入力 (0で終了): "); scanf("%d", &num); sum += num;} while (num != 0);
printf("合計: %d\n", sum);参考リンク
公式ドキュメント
書籍
プログラミング言語C 第2版(K&R) — C言語のバイブル。制御構文の基本はここから。
新・明解C言語 入門編 — 日本語の定番入門書。
コーディングスタイル
学習サイト
合格ライン
switch で break を忘れない
for/while/do-while を使い分けられる
FizzBuzz を書ける
goto を避けるべき理由を説明できる