条件分岐

条件分岐は交差点の信号機のようなものです——条件が満たされれば一方の道を、そうでなければもう一方の道を進みます。プログラムは判断によって知性を持ちます。

if文

ifは最も基本的な条件分岐です。条件が真(非ゼロ)なら波括弧内のコードが実行され、偽(ゼロ)ならスキップされます。

C
#include <stdio.h>

int main(void) {
    int score = 95;
    if (score >= 90) {
        printf("Excellent!\n");
    }
    printf("Program continues\n");
    return 0;
}
TEXT
Excellent!
Program continues
💡 ヒント: ifの後に文が1つだけの場合、波括弧は省略可能です。しかし、後から文を追加した際に波括弧の追加を忘れると論理エラーの原因になるため、常に波括弧を使うことを強く推奨します。

if-else文

if-elseは2つの分岐を提供します。条件が真ならifブロックが、偽ならelseブロックが実行されます。どちらか一方は必ず実行されます。

C
#include <stdio.h>

int main(void) {
    int age = 16;
    if (age >= 18) {
        printf("You are an adult\n");
    } else {
        printf("You are a minor\n");
    }
    return 0;
}
TEXT
You are a minor

ダングリングelse問題

複数のif文がネストされている場合、elseは最も近いifと対になります。

C
#include <stdio.h>

int main(void) {
    int a = 5, b = 0;
    if (a > 10)
        if (b > 0)
            printf("A\n");
    else
        printf("B\n");
    return 0;
}

elseは最初のifと対になっているように見えますが、実際は2番目のifと対になるため、何も出力されません。波括弧を追加すれば対関係が明確になります。

C
if (a > 10) {
    if (b > 0) {
        printf("A\n");
    } else {
        printf("B\n");
    }
}
⚠️ 注意: 波括弧を常に使えば、ダングリングelse問題を完全に防ぐことができます。

if-else if-elseチェーン

複数の条件を順番に確認する必要がある場合、else ifで複数の分岐を連鎖させます。

C
#include <stdio.h>

int main(void) {
    int score = 78;
    if (score >= 90) {
        printf("Grade: A\n");
    } else if (score >= 80) {
        printf("Grade: B\n");
    } else if (score >= 70) {
        printf("Grade: C\n");
    } else if (score >= 60) {
        printf("Grade: D\n");
    } else {
        printf("Grade: F\n");
    }
    return 0;
}
TEXT
Grade: C

else ifの条件は上から順に評価されます。一度条件が満たされると、以降の分岐はすべてスキップされます。条件の順序は重要です。

💡 ヒント: 効率を上げるため、最も成立しやすい条件を先に配置しましょう。範囲を扱う場合は大きい順に並べ、論理の隙間を防ぎます。

ネストされたif文

ifの中に別のifを入れることで、より細かな条件分岐が可能です。

C
#include <stdio.h>

int main(void) {
    int age = 25;
    char gender = 'M';
    if (age >= 18) {
        if (gender == 'M') {
            printf("Adult male\n");
        } else {
            printf("Adult female\n");
        }
    } else {
        printf("Minor\n");
    }
    return 0;
}
TEXT
Adult male
⚠️ 注意: ネストは3レベルを超えないようにしましょう。深すぎると可読性が低下します。複雑な条件は論理演算子でまとめるか、else ifで平坦化できます。

switch-case文

switchは整数式の値に応じて一致するcase分岐へジャンプします。離散値による分岐に最適です。

基本構文

C
switch (expression) {
    case constant1:
        statement;
        break;
    case constant2:
        statement;
        break;
    default:
        statement;
        break;
}
C
#include <stdio.h>

int main(void) {
    int day = 3;
    switch (day) {
        case 1: printf("Monday\n"); break;
        case 2: printf("Tuesday\n"); break;
        case 3: printf("Wednesday\n"); break;
        case 4: printf("Thursday\n"); break;
        case 5: printf("Friday\n"); break;
        case 6: printf("Saturday\n"); break;
        case 7: printf("Sunday\n"); break;
        default: printf("Invalid day\n"); break;
    }
    return 0;
}
TEXT
Wednesday

breakの重要性

switchcaseに一致した後、breakまたはswitchの終わりに達するまで、そこから先のすべての文を実行します。これは「フォールスルー」と呼ばれます。

C
#include <stdio.h>

int main(void) {
    int num = 2;
    switch (num) {
        case 1: printf("One\n");
        case 2: printf("Two\n");
        case 3: printf("Three\n");
        default: printf("Default\n");
    }
    return 0;
}
TEXT
Two
Three
Default
⚠️ 注意: breakの書き忘れはswitchで最もよくある間違いです。意図的なフォールスルーでない限り、各caseの最後に必ずbreakを追加しましょう。

フォールスルーで分岐をまとめる

複数のcaseラベルで同じ処理を実行したい場合、意図的にbreakを省略できます。

C
#include <stdio.h>

int main(void) {
    char grade = 'B';
    switch (grade) {
        case 'A':
        case 'B':
        case 'C':
            printf("Pass\n"); break;
        case 'D':
            printf("Retake\n"); break;
        case 'F':
            printf("Fail\n"); break;
        default:
            printf("Invalid grade\n"); break;
    }
    return 0;
}
TEXT
Pass

switchの制限

条件演算子(三項演算子)

条件演算子?:は単純なif-else文を置き換えられます。第6回で紹介しましたが、ここではさらに使用例を示します。

C
#include <stdio.h>

int main(void) {
    int a = -5;
    int abs_a = a >= 0 ? a : -a;
    printf("|%d| = %d\n", a, abs_a);

    int x = 10, y = 10;
    printf("%s\n", x == y ? "Equal" : "Not equal");
    return 0;
}
TEXT
|-5| = 5
Equal
💡 ヒント: 条件演算子はネスト可能ですが、可読性が急速に低下します。1レベルを超えるネストにはif-elseを使いましょう。

BMIに基づいて体型を判定する、多分岐条件分岐の実例です。

C
#include <stdio.h>

int main(void) {
    double weight = 70.0;
    double height = 1.75;
    double bmi = weight / (height * height);

    printf("BMI: %.1f\n", bmi);
    if (bmi < 18.5) {
        printf("Underweight\n");
    } else if (bmi < 24.0) {
        printf("Normal\n");
    } else if (bmi < 28.0) {
        printf("Overweight\n");
    } else {
        printf("Obese\n");
    }
    return 0;
}
▶ 試してみよう
TEXT
BMI: 22.9
Normal

switchを使ったシンプルなメニュー選択の実装です。

C
#include <stdio.h>

int main(void) {
    int choice = 2;
    printf("===== Menu =====\n");
    printf("1. New Game\n");
    printf("2. Continue\n");
    printf("3. Settings\n");
    printf("4. Exit\n");
    printf("================\n");
    printf("Your choice: %d\n", choice);

    switch (choice) {
        case 1: printf("Starting new game!\n"); break;
        case 2: printf("Loading save...\n"); break;
        case 3: printf("Opening settings\n"); break;
        case 4: printf("Exiting game\n"); break;
        default: printf("Invalid choice\n"); break;
    }
    return 0;
}
▶ 試してみよう
TEXT
===== Menu =====
1. New Game
2. Continue
3. Settings
4. Exit
================
Your choice: 2
Loading save...

❓ よくある質問

Q ifの後の波括弧はいつ省略できますか?
A 構文的にはif/elseの後に文が1つだけの場合に省略可能ですが、後から文を追加した際のバグを防ぐため、常に使うことを推奨します。
Q switchで浮動小数点数や文字列を評価できますか?
A いいえ。switchは整数式のみを受け付けます。浮動小数点数も文字列も使えません。文字列の比較にはif-else ifチェーンを使ってください。
Q default分岐は省略できますか?
A 構文的には可能ですが、想定外の値による無言のエラーを防ぐため、常に記述することを推奨します。
Q else ifとネストされたifの違いは何ですか?
A else ifは平坦な多分岐構造で読みやすく、ネストされたifは階層的で条件同士が依存する場合に適しています。どちらでも書ける場合は、読みやすい方を選んでください。

📖 まとめ

📝 練習問題

  1. 整数を1つ読み込み、それが正の数、負の数、ゼロのいずれかを判定して結果を出力するプログラムを書いてください。
  2. 月番号(1〜12)を読み込み、switchを使ってその月の日数を出力するプログラムを書いてください(閏年ではないと仮定し、2月は28日とします)。
  3. 文字を1つ読み込み、それが大文字、小文字、数字、その他の文字のいずれかを判定するプログラムを書いてください。
100%