閉じる

【C言語】switch文入門|break・default・複数caseを一気にマスター

C言語のswitch文は、複数の条件分岐をすっきり書ける強力な構文です。

特にメニュー選択やエラーコード判定など、整数や文字の値によって処理を切り替えたい場面で活躍します。

本記事ではswitch文の基本から、break・default・複数case・実用サンプルまでを、図解とコード例を交えながら丁寧に解説します。

if文との違いや、書き忘れで起こりがちなバグもあわせて理解し、読みやすく安全なswitch文を書けるようになりましょう。

C言語のswitch文とは

switch文の基本構文と使いどころ

switch文は、1つの式の結果(整数や文字など)に応じて、複数の処理パターンから1つを選ぶための構文です。

典型的な書き方は次のようになります。

C言語
#include <stdio.h>

int main(void) {
    int num = 2;  // 判定したい値

    // switch文の基本構文
    switch (num) {
        case 1:  // num が 1 のとき
            printf("num は 1 です。\n");
            break; // ここで switch を抜ける

        case 2:  // num が 2 のとき
            printf("num は 2 です。\n");
            break;

        case 3:  // num が 3 のとき
            printf("num は 3 です。\n");
            break;

        default: // どの case にも当てはまらないとき
            printf("num は 1〜3 ではありません。\n");
            break;
    }

    return 0;
}
実行結果
num は 2 です。

switch文では、式の値と一致するcaseラベルの位置にジャンプし、そこから処理を実行します。

多くの場合は、それぞれのcaseの末尾にbreakを書き、そこでswitch文の処理を終えます。

switch文が活躍する典型的な場面としては、次のようなものがあります。

  • メニュー番号(1〜5など)による処理分岐
  • エラーコード(0、1、2、…)によるメッセージ表示
  • キーボード入力された文字('a', 'b', 'c')ごとの処理分岐

このように「決まった候補の中から1つを選ぶ」場合にswitch文は非常に読みやすいコードになります。

if文との違いと使い分けのポイント

if文とswitch文はどちらも条件分岐を行いますが、得意な分野が異なります

if文の特徴

if文は、次のような複雑な条件に向いています。

  • 範囲比較(cst-code>x < 10 && x >= 3など)
  • 複数の条件の組み合わせ
  • 浮動小数点(double, float)など、switchでは扱えない型
C言語
if (score >= 80) {
    printf("合格\n");
} else if (score >= 60) {
    printf("追試\n");
} else {
    printf("不合格\n");
}

switch文の特徴

switch文は、同じ変数(または式)が特定の値に等しいかどうかを判定するのに向いています。

  • 候補値がはっきり決まっている(1, 2, 3, …)
  • 条件が「等しいかどうか」だけ
  • 分岐パターンが多く、if文だと縦長になってしまう
C言語
switch (command) {
    case 1:
        // ...
        break;
    case 2:
        // ...
        break;
    case 3:
        // ...
        break;
    default:
        // ...
        break;
}

使い分けの目安

範囲や不等号を使うならif文、値の候補が列挙できるならswitch文を使うと覚えておくとよいです。

  • 「80点以上なら合格」のように境界で分けたいとき → if文
  • 「メニュー1〜4から1つ選ぶ」のように選択肢の番号で分けたいとき → switch文

caseラベルとbreakの基本

caseの書き方と値のルール

switch文の中には複数のcaseラベルを書き、どの値のときにどの処理を実行するかを指定します。

基本形はcase 定数値:です。

C言語
switch (式) {
    case 0:
        // 式 == 0 のときの処理
        break;

    case 1:
        // 式 == 1 のときの処理
        break;

    case 2:
        // 式 == 2 のときの処理
        break;

    default:
        // どのcaseにも一致しないとき
        break;
}

caseラベルの値には、次のようなルールがあります。

  • 整数型に変換できる定数式のみが使用できます
    • リテラル値0, 1, 2
    • 文字リテラル'A', '0'
    • 定数マクロ#defineで定義した値
    • 列挙型enumの列挙子
  • 同じswitch文の中で、同じ値のcaseを2回書くことはできません

たとえば、次のような書き方はエラーになります。

C言語
switch (x) {
    case 1:
        // ...
        break;
    case 1:  // エラー: 同じ値の case が重複
        // ...
        break;
}

breakの役割と書き忘れによる落とし穴

breakは「ここでswitch文を抜ける」という命令です。

多くの場合、各caseの末尾にbreak;を書きます。

C言語
#include <stdio.h>

int main(void) {
    int x = 1;

    switch (x) {
        case 1:
            printf("case 1\n");
            break;  // ここで switch を終了

        case 2:
            printf("case 2\n");
            break;

        default:
            printf("default\n");
            break;
    }

    return 0;
}
実行結果
case 1

ここでもしbreakを書き忘れると、次のcaseの処理まで続けて実行されてしまいます。

これをフォールスルー(fall-through)と呼びます。

C言語
#include <stdio.h>

int main(void) {
    int x = 1;

    switch (x) {
        case 1:
            printf("case 1\n");
            // break を書き忘れた!

        case 2:
            printf("case 2\n");
            break;

        default:
            printf("default\n");
            break;
    }

    return 0;
}
実行結果
case 1
case 2

このように、意図しないフォールスルーは典型的なバグの原因になります。

各caseの末尾には必ずbreakを書くことを習慣化すると安全です。

breakをあえて省略するケース

一方で、あえてbreakを書かずにフォールスルーを利用することもあります。

代表的なのは、複数のcaseを同じ処理にまとめたいときです。

C言語
#include <stdio.h>

int main(void) {
    char c = 'A';

    switch (c) {
        case 'A':
        case 'a':  // 'A' と 'a' のどちらも同じ処理
            printf("A または a が入力されました。\n");
            break;

        default:
            printf("それ以外の文字が入力されました。\n");
            break;
    }

    return 0;
}
実行結果
A または a が入力されました。

このように、同じ処理を共有したい複数のcaseを、breakなしで並べることで、コードの重複を避けられます。

ただし、意図的なフォールスルーを使う場合でも、コメントで「フォールスルーする」ことを明示すると、他の人や未来の自分が読んだときに誤解しにくくなります。

defaultと複数caseの書き方

defaultの意味と配置場所のルール

defaultは、どのcaseにも一致しなかったときに実行される「その他」用のラベルです。

書き方は次のようになります。

C言語
switch (value) {
    case 0:
        // ...
        break;

    case 1:
        // ...
        break;

    default:  // 0でも1でもないとき
        // ...
        break;
}

defaultには次のようなルールがあります。

  • 1つのswitch文の中に書けるdefaultは1つだけです
  • 書く位置はどこでもよいですが、最後に書くのが一般的です

defaultを最後以外の場所に書いた例も、文法的には有効です。

C言語
switch (x) {
    case 0:
        // ...
        break;

    default:   // ここで default
        // ...
        break;

    case 1:
        // ...
        break;
}

ただし、このように書くと読み手を混乱させる可能性が高いので、実務ではほぼ必ず最後に書きます

複数のcaseをまとめて処理する書き方

複数のcaseを同じ処理にしたい場合、caseラベルを連続して書き、最後のブロックにだけ処理を書くことで、シンプルにまとめられます。

C言語
#include <stdio.h>

int main(void) {
    int month = 5;

    switch (month) {
        case 3:
        case 4:
        case 5:
            printf("春です。\n");
            break;

        case 6:
        case 7:
        case 8:
            printf("夏です。\n");
            break;

        case 9:
        case 10:
        case 11:
            printf("秋です。\n");
            break;

        case 12:
        case 1:
        case 2:
            printf("冬です。\n");
            break;

        default:
            printf("月は 1〜12 を指定してください。\n");
            break;
    }

    return 0;
}
実行結果
春です。

ここでは、3,4,5 → 春 / 6,7,8 → 夏 …というように、季節ごとにまとめています。

同じ処理をコピペせずに書けるため、保守性も高くなります。

文字(char)や列挙型(enum)を使ったswitch文

switch文でよく使われるのはint型ですが、char型やenum(列挙型)も利用できます

char型を使った例

C言語
#include <stdio.h>

int main(void) {
    char op = '+';

    switch (op) {
        case '+':
            printf("足し算をします。\n");
            break;
        case '-':
            printf("引き算をします。\n");
            break;
        case '*':
            printf("掛け算をします。\n");
            break;
        case '/':
            printf("割り算をします。\n");
            break;
        default:
            printf("不正な演算子です。\n");
            break;
    }

    return 0;
}
実行結果
足し算をします。

文字リテラル'+''A'は、内部的には整数値として扱われるため、switch文で問題なく使用できます。

enum(列挙型)を使った例

enumを使うと、意味のある名前で状態やモードを表現でき、コードの可読性が上がります。

C言語
#include <stdio.h>

// 動作モードを表す列挙型
typedef enum {
    MODE_AUTO,   // 0
    MODE_MANUAL, // 1
    MODE_TEST    // 2
} Mode;

int main(void) {
    Mode mode = MODE_MANUAL;

    switch (mode) {
        case MODE_AUTO:
            printf("自動モードです。\n");
            break;

        case MODE_MANUAL:
            printf("手動モードです。\n");
            break;

        case MODE_TEST:
            printf("テストモードです。\n");
            break;

        default:
            // 通常はここには来ない想定だが、安全のために書く
            printf("不明なモードです。\n");
            break;
    }

    return 0;
}
実行結果
手動モードです。

このようにenum + switchの組み合わせは、状態遷移やモード分岐を表す際にとても便利です。

実用的なswitch文サンプル集

メニュー選択で使うswitch文の例

コンソールプログラムでよくあるのが、数字でメニューを選択させるパターンです。

switch文を使うと、各メニューの処理を見通しよく書けます。

C言語
#include <stdio.h>

int main(void) {
    int choice;

    // メニュー表示
    printf("=== メニュー ===\n");
    printf("1: 新規ゲーム開始\n");
    printf("2: オプション設定\n");
    printf("3: 終了\n");
    printf("番号を選んでください: ");

    scanf("%d", &choice);  // ユーザーから番号を読み取る

    // 入力された番号に応じて処理を分岐
    switch (choice) {
        case 1:
            printf("新規ゲームを開始します。\n");
            // ここにゲーム開始処理を書く
            break;

        case 2:
            printf("オプション設定画面を開きます。\n");
            // ここに設定処理を書く
            break;

        case 3:
            printf("プログラムを終了します。\n");
            // 終了処理
            break;

        default:
            printf("不正な番号が入力されました。\n");
            break;
    }

    return 0;
}
実行結果
=== メニュー ===
1: 新規ゲーム開始
2: オプション設定
3: 終了
番号を選んでください: 2
オプション設定画面を開きます。

このように、メニュー番号と処理内容が1対1で対応しているケースでは、switch文が非常に読みやすくなります。

エラーコード分岐に使うswitch文の例

エラーコードが整数で定義されている場合にも、switch文は便利です。

エラーコードとメッセージを一覧で管理できます。

C言語
#include <stdio.h>

// 仮のエラーコード定義
#define ERR_OK          0
#define ERR_NOT_FOUND   1
#define ERR_ACCESS_DENY 2
#define ERR_TIMEOUT     3

void print_error_message(int err) {
    switch (err) {
        case ERR_OK:
            printf("エラーは発生していません。\n");
            break;

        case ERR_NOT_FOUND:
            printf("ファイルが見つかりません。\n");
            break;

        case ERR_ACCESS_DENY:
            printf("アクセスが拒否されました。\n");
            break;

        case ERR_TIMEOUT:
            printf("タイムアウトが発生しました。\n");
            break;

        default:
            printf("不明なエラーコードです。(コード: %d)\n", err);
            break;
    }
}

int main(void) {
    print_error_message(ERR_NOT_FOUND);
    print_error_message(999);  // 未定義のエラーコード

    return 0;
}
実行結果
ファイルが見つかりません。
不明なエラーコードです。(コード: 999)

定数マクロやenumでエラーコードを定義し、switchで分岐する形にしておくと、コードが整理され、他の人にも意図が伝わりやすくなります。

switch文を安全に書くためのベストプラクティス

最後に、switch文を安全かつ読みやすく書くためのポイントを整理します。

1. すべてのcaseの末尾にbreakを書く(意図的な例外を除く)

breakの書き忘れは典型的なバグです。

フォールスルーを使わないのであれば、すべてのcaseの末尾にbreakを付ける習慣を徹底しましょう。

C言語
switch (x) {
    case 1:
        // 処理
        break;  // 忘れない

    case 2:
        // 処理
        break;

    // ...
}

2. フォールスルーはコメントで明示する

フォールスルーを意図して使う場合は、コメントで明示することで、読み間違いを防げます。

C言語
switch (c) {
    case 'A':
        // 'A' は 'a' と同じ処理にする
        /* fall through */

    case 'a':
        printf("A または a\n");
        break;
}

意図的なフォールスルーだけが残るようにすると、コードレビューでも判断しやすくなります。

3. defaultはできる限り用意する

例外や想定外の値を受け取ったときの安全弁として、defaultを用意することが推奨されます。

  • 不正な値を検知してエラーメッセージを出す
  • ログを出力して原因調査に役立てる
C言語
default:
    printf("不正な値です。(value = %d)\n", value);
    break;

「ここには絶対に来ないはず」と思っていても、将来の仕様変更やバグで来てしまう可能性があるため、defaultで安全側に倒しておくのが無難です。

4. enumと組み合わせて使う

状態やモードを整数の「生値」で扱うより、enumで名前を付けてからswitch文で分岐したほうが、コードの意味が明確になります。

C言語
typedef enum {
    STATE_INIT,
    STATE_RUNNING,
    STATE_STOPPED
} State;

void handle_state(State s) {
    switch (s) {
        case STATE_INIT:
            // 初期化処理
            break;
        case STATE_RUNNING:
            // 実行中処理
            break;
        case STATE_STOPPED:
            // 停止中処理
            break;
        default:
            // 想定外の状態
            break;
    }
}

このようにenumと組み合わせることで、状態の追加・削除があっても追いやすい構造になります。

5. 条件が複雑になりすぎる場合はif文や他の構造も検討する

switch文は単純な比較には強いですが、範囲比較や複合条件には向きません。

そのような場合は、if文に切り替えたり、関数ポインタや表駆動など別の設計を検討することも大切です。

まとめ

switch文は、「1つの値」によって処理を切り替える場面で非常に有効な構文です。

if文との違いを理解し、caseラベル・break・defaultの役割を正しく押さえることで、読みやすく安全なコードを書けるようになります。

特に「すべてのcaseにbreakを書く」「defaultを用意する」「意図的なフォールスルーにはコメント」という3点を意識しておくと、バグの少ないswitch文を実現できます。

メニュー選択やエラーコード分岐など、実用的な場面で積極的にswitch文を活用し、C言語の条件分岐を一段階レベルアップさせていきましょう。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!