C++のswitch文:基本構文とbreak、defaultの使い方を解説

目次

switch文とは?

switch文は、C++における条件分岐構文の一つです。特定の式(変数など)の値を評価し、その値が一致するcaseラベルへ処理をジャンプさせます。

多くのif-else ifが連なるような条件分岐、特に「一つの変数が特定の値であるか」を順に比較する場合において、switch文を用いるとコードがより簡潔で読みやすくなる場合があります。

switch文の基本構文

switch文は、switchcasebreakdefaultといったキーワードを組み合わせて構成されます。

#include <iostream>

int main() {
    int selection;
    std::cout << "飲み物を選んでください (1: コーヒー, 2: 紅茶, 3: 水): ";
    std::cin >> selection;

    switch (selection) {
        case 1:
            // selection の値が 1 だった場合の処理
            std::cout << "コーヒーが選ばれました。" << std::endl;
            break; // switch文を抜ける

        case 2:
            // selection の値が 2 だった場合の処理
            std::cout << "紅茶が選ばれました。" << std::endl;
            break; // switch文を抜ける

        case 3:
            // selection の値が 3 だった場合の処理
            std::cout << "水が選ばれました。" << std::endl;
            break; // switch文を抜ける

        default:
            // どのcaseにも一致しなかった場合の処理
            std::cout << "1から3の番号を選んでください。" << std::endl;
            break; // default文の最後にもbreakを置くのが一般的
    }

    return 0;
}

case ラベルと default ラベル

case ラベル

caseは、switchの括弧内で評価された式の結果と比較される「飛び先」の目印(ラベル)です。caseの後ろには、コンパイル時に値が確定する定数式(リテラル値、const変数、enumの列挙子など)を指定する必要があります。

// 良い例
case 1:
case 'A':

// 悪い例 (変数は使えません)
int num = 10;
case num: // エラー

default ラベル

defaultラベルは、評価された式の値がどのcaseラベルとも一致しなかった場合に実行される処理を指定します。defaultラベルは省略可能ですが、予期せぬ値が入力された場合の処理(エラーハンドリングなど)を記述するために、できるだけ記述することが推奨されます。

break文の重要な役割

switch文を扱う上で最も重要なのがbreak文です。break文は、現在の処理ブロック(この場合はswitch文)を強制的に終了させる命令です。

switch文の動作は、if文とは異なり、caseラベルは単なる「実行開始位置」を示すラベルに過ぎません。一致したcaseラベルに処理が飛んだ後、break文に遭遇するかswitch文の終わり(})に達するまで、後続のcasedefaultの処理がすべて実行され続けます。

この動作を「フォールスルー(Fall-through)」と呼びます。

breakがない場合の動作(フォールスルー)

もしbreak文を書き忘れると、意図しない動作を引き起こすことがよくあります。

// 悪い例:breakを忘れた場合
int selection = 1;

switch (selection) {
    case 1:
        std::cout << "コーヒー"; // 実行される
    case 2:
        std::cout << "紅茶"; // breakがないため、これも実行される
    case 3:
        std::cout << "水"; // これも実行される
    default:
        std::cout << "その他"; // これも実行される
}
// 出力: "コーヒー紅茶水その他"

意図的なフォールスルーと C++17 [[fallthrough]]

フォールスルーは、場合によっては意図的に使用されます。例えば、複数のcaseで全く同じ処理を行いたい場合です。

int dayType = 1; // 0:日曜, 1-5:平日, 6:土曜

switch (dayType) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        // dayTypeが1, 2, 3, 4, 5 のいずれかの場合
        std::cout << "平日の処理" << std::endl;
        break;

    case 0:
    case 6:
        // dayTypeが 0 か 6 の場合
        std::cout << "休日の処理" << std::endl;
        break;

    default:
        std::cout << "無効な値" << std::endl;
        break;
}

ただし、breakの書き忘れによるバグと区別がつきにくいため、近年のC++コンパイラは、case間に処理がありながらbreakがない場合に警告を出すことがあります。

C++17以降では、意図的なフォールスルーであることをコンパイラや他の開発者に明示するため、[[fallthrough]]属性を使用することが推奨されます。

// C++17以降の推奨される書き方
int val = 0;
switch (val) {
    case 0:
        std::cout << "A";
        std::cout << "B";
        // 意図的に case 2 へ処理を継続する
        [[fallthrough]]; 

    case 2:
        std::cout << "C";
        break;

    default:
        std::cout << "F";
        break;
}
// 出力: "ABC"

総合サンプルコード

switch文を使って、入力された文字が母音か子音かを判定するサンプルコードです。意図的なフォールスルー(caseのグルーピング)を活用しています。

#include <iostream>
#include <cctype> // std::tolower のために必要

int main() {
    char inputChar;
    std::cout << "アルファベットを1文字入力してください: ";
    std::cin >> inputChar;

    // 比較を容易にするため、入力された文字を小文字に変換
    char c = std::tolower(inputChar);

    // アルファベットかどうかを判定
    if (c >= 'a' && c <= 'z') {
        
        switch (c) {
            // 母音 (a, i, u, e, o) の場合
            case 'a':
            case 'e':
            case 'i':
            case 'o':
            case 'u':
                std::cout << "入力された文字「" << inputChar << "」は母音(Vowel)です。" << std::endl;
                break;

            // それ以外のアルファベットの場合
            default:
                std::cout << "入力された文字「" << inputChar << "」は子音(Consonant)です。" << std::endl;
                break;
        }

    } else {
        // アルファベット以外が入力された場合
        std::cout << "入力されたのはアルファベットではありません。" << std::endl;
    }

    return 0;
}

まとめ

switch文は、単一の式の値に基づいて多岐に分岐する処理を記述する際に非常に有効な構文です。

  • caseラベルにはコンパイル時定数を使用します。
  • break文の省略による「フォールスルー」の動作を正確に理解することが重要です。
  • 意図しないバグを防ぐため、各caseの最後には原則としてbreak文を記述します。
  • どのcaseにも一致しない場合の処理としてdefaultラベルを活用することが推奨されます。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次