制御構文: フロー制御

if/switch で分岐。for/while で繰り返し。

if/else
条件分岐の基本。
switch
値による多岐分岐。
break
ループやswitchを抜ける。
continue
次の周回へスキップ。

詳細解説

道路の標識 (Traffic Rules)

プログラムの動きは「ドライブ」に似ています。 ・if / switch は「分岐点」です。右に行くか左に行くか、条件(信号や標識)を見て決めます。 ・while / for は「周回コース」です。10周するまで走る(for)、ガソリンがある限り走る(while)など、条件を満たすまで同じ道をぐるぐる回ります。 一方通行の道をただ走るだけ(上から下への実行)では、目的地(複雑な計算結果)には辿り着けません。

上から下に流れるだけのプログラムでは何もできません。 「分岐(もし〜なら)」「反復(繰り返し)」 を使って、複雑なロジックを組む方法を学びます。

分岐 (Branch)

  • if - else if - else: ブロック {} は1行でも省略しないこと!(バグの温床になります)
  • switch: 値による分岐。break 忘れの恐怖(フォールスルー)に注意。C言語のswitchは整数(と文字)しか使えない制約があります。

反復 (Loop)

  • for: 回数が決まっている繰り返しに最適。iindex の略。
  • 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, switch
// 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; // 必ず break
case 2:
handle_delete();
break;
}

ループ

for, while, do-while
// 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 - 例外的なユースケース
// 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 を避けるべき理由を説明できる