switch文とは?
switch
文は、C++における条件分岐構文の一つです。特定の式(変数など)の値を評価し、その値が一致するcase
ラベルへ処理をジャンプさせます。
多くのif-else if
が連なるような条件分岐、特に「一つの変数が特定の値であるか」を順に比較する場合において、switch
文を用いるとコードがより簡潔で読みやすくなる場合があります。
switch文の基本構文
switch
文は、switch
、case
、break
、default
といったキーワードを組み合わせて構成されます。
#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
文の終わり(}
)に達するまで、後続のcase
やdefault
の処理がすべて実行され続けます。
この動作を「フォールスルー(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
ラベルを活用することが推奨されます。