
C言語の基本|switch文の使い方
値が決まれば、進む先もすぐ決まる。switch文で、選択肢が並ぶ条件分岐をすっきり整理しよう。
if~else if~elseを使うと、範囲判定や複数の条件を組み合わせた分岐を作れます。
一方、プログラムでは、入力された値が1なら処理A、2なら処理B、3なら処理Cというように、特定の値との一致によって処理を選びたい場面もあります。
このような分岐をif文で書くと、同じ変数を何度も比較することになります。
if (mode == 1) {
処理1;
} else if (mode == 2) {
処理2;
} else if (mode == 3) {
処理3;
} else {
その他の処理;
}値ごとの選択肢を並べたいときに便利なのがswitch文です。switch文では、それぞれの選択肢をcaseとして一覧のように記述できます。
図1:値に対応するcaseを選ぶswitch文

この図から分かること
switch文は、式の結果と各caseの値を照合し、一致した場所から処理を始めます。
たとえば式の結果が2なら、case 2の処理が選ばれます。どのcaseにも一致しなかった場合は、defaultの処理へ進みます。
switch文の基本構文
switch文は、次の形で記述します。
switch (式) {
case 定数式1:
文1;
break;
case 定数式2:
文2;
break;
default:
文3;
break;
}処理の流れは次のとおりです。
- switchの式を評価する
- 式の結果と各caseの値を照合する
- 一致するcaseがあれば、その場所から処理を始める
- breakを実行したらswitch文を抜ける
- 一致するcaseがなければdefaultへ進む
- defaultもなければswitch文の中では何も実行しない
switch文を構成する要素
| 要素 | 役割 | 注意点 |
|---|---|---|
| switch | 分岐に使用する式を指定する | 式の結果は整数型または列挙型である必要がある |
| case | 一致させる値を指定する | 右側には整数定数式を書く |
| 文 | caseが選ばれた場合の処理 | 複数の文を続けて書ける |
| break | switch文から抜ける | 忘れると次のcaseの処理へ進む |
| default | どのcaseにも一致しない場合の処理 | 省略できるが、想定外の値への対応に役立つ |
switchの式で使える型
switchの丸括弧内には、結果が整数型または列挙型になる式を指定します。
| 使用できる代表例 | 使用できない代表例 |
|---|---|
| int | float |
| char | double |
| short | 小数を結果とする式 |
| long | 文字列 |
| enum | 構造体 |
char型も整数型の一種なので、文字による分岐にも使用できます。
switch (command)ただし、doubleやfloatのような浮動小数点型はswitch文の式には使用できません。小数の範囲を調べたい場合は、if文を使用するのが自然です。
caseには固定された値を書く
caseの右側には、コンパイル時に値が決まる整数定数式を記述します。
| 記述例 | 使用できるか | 理由 |
|---|---|---|
| case 1: | 使用できる | 整数定数 |
| case 'A': | 使用できる | 文字定数 |
| case 10 + 2: | 使用できる | コンパイル時に12と計算できる |
| case x: | 通常は使用できない | 変数の値は実行時に決まる |
| case 1.5: | 使用できない | 浮動小数点の定数 |
| case scanf(...): | 使用できない | 関数の実行結果は定数式ではない |
同じswitch文の中に、同じ値のcaseを複数書くこともできません。
case 1:
処理1;
break;
case 1:
処理2;
break;この例ではcase 1が重複しているため、どちらを選ぶべきか決められず、コンパイルエラーになります。
caseと値の間には区切りが必要
caseはC言語のキーワードです。値とは別の字句として記述する必要があります。
case 1:case1:と書くと、caseと1を組み合わせたcaseラベルにはなりません。case1という通常の識別子によるラベルとして解釈される可能性があり、意図したswitch文の分岐にならないため注意しましょう。
caseの後に波括弧は必須ではない
caseはif文のようなブロックではなく、処理を開始する位置を示すラベルです。そのため、通常はcaseごとに波括弧を付けません。
case 1:
printf("処理1です。\n");
printf("複数の文を実行できます。\n");
break;この例では、case 1が選ばれると2つのprintfを順番に実行し、breakでswitch文を抜けます。
必要があればcaseの中に波括弧を使うこともできますが、基本的なswitch文では、case、処理、breakという並びで覚えると分かりやすいでしょう。
breakでswitch文を抜ける
breakは、現在実行しているswitch文を終了させるために使います。
case 1:
printf("気温データを表示します。\n");
break;case 1の処理が終わった後にbreakが実行されると、プログラムはswitch文の後へ進みます。
breakはswitch文全体を終了させるものであり、プログラムそのものを終了させる命令ではありません。
breakがない場合は次のcaseへ進む
caseの処理にbreakがない場合、次に書かれているcaseの処理も続けて実行されます。この動きをフォールスルーと呼びます。
switch (value) {
case 1:
printf("case 1です。\n");
case 2:
printf("case 2です。\n");
break;
}valueが1の場合、実行はcase 1から始まります。しかし、case 1にbreakがないため、そのままcase 2の処理まで実行されます。
図2:breakの有無による処理の違い

この図から分かること
breakがある場合は、選ばれたcaseの処理だけを実行してswitch文から抜けます。
breakがない場合は、次のcaseラベルを通過して、その下の処理まで続けて実行します。意図していないフォールスルーは、複数のメッセージが表示されるなどの不具合につながります。
意図的にフォールスルーを使う場合
複数のcaseで同じ処理を行いたいときは、caseを続けて記述できます。
case 1:
case 2:
printf("1または2が入力されました。\n");
break;この場合、値が1でも2でも同じprintfが実行されます。
case 1の直後には実行する文がなく、そのままcase 2へ進むことを利用しています。意図的なフォールスルーは便利ですが、処理の意味が分かりにくくならないように使うことが大切です。
defaultは一致するcaseがない場合を受け持つ
defaultは、switchの式と一致するcaseがなかったときに実行されます。
default:
printf("対応していない値です。\n");
break;defaultは省略できます。省略した状態でどのcaseにも一致しなかった場合、switch文の中では何も実行されません。
利用者が番号を入力するプログラムでは、想定外の値が入力される可能性があります。そのため、入力エラーや再入力の案内を表示するdefaultを用意すると親切です。
defaultを最後に書いた場合、その後にcaseはありません。そのため、最後のbreakを省略しても直後のcaseへ進む問題は起きません。ただし、後からcaseを追加する可能性や書き方の統一を考え、breakを記述しておくと分かりやすくなります。
観測データの種類を番号で選ぶ
次のプログラムでは、入力された番号に応じて、表示する気象観測データを選択します。
| 入力する番号 | 選択されるデータ |
|---|---|
| 1 | 気温データ |
| 2 | 湿度データ |
| 3 | 風速データ |
| その他 | 対応していない番号 |
番号から表示する気象観測データを選ぶプログラム
ファイル名:8_8_1.c
#include <stdio.h>
int main(void)
{
int sensor;
printf("表示するデータを選んでください。\n");
printf("1:気温 2:湿度 3:風速 > ");
scanf("%d", &sensor);
switch (sensor) {
case 1:
printf("気温データを表示します。\n");
break;
case 2:
printf("湿度データを表示します。\n");
break;
case 3:
printf("風速データを表示します。\n");
break;
default:
printf("対応していない番号です。\n");
break;
}
return 0;
}実行結果の例
2を入力した場合は、case 2が選ばれます。
表示するデータを選んでください。
1:気温 2:湿度 3:風速 > 2
湿度データを表示します。どのcaseにも一致しない番号を入力した場合は、defaultが実行されます。
表示するデータを選んでください。
1:気温 2:湿度 3:風速 > 9
対応していない番号です。プログラムの詳しい解説
入力された整数はsensorに格納されます。
scanf("%d", &sensor);続いて、switchの式としてsensorを指定しています。
switch (sensor)sensorが2の場合、switch文はcase 2を探します。
case 2:
printf("湿度データを表示します。\n");
break;case 2のprintfを実行した後、breakによってswitch文を抜けます。case 3やdefaultの処理は実行されません。
9を入力した場合、case 1、case 2、case 3のどれにも一致しません。そのため、defaultの処理が実行されます。
if文とswitch文の使い分け
switch文で書ける分岐の多くは、if~else if~elseでも表現できます。ただし、それぞれ得意な条件が異なります。
| 観点 | if~else if~else | switch |
|---|---|---|
| 得意な判定 | 範囲や複雑な条件 | 特定の値との一致 |
| 条件の例 | score >= 80 | case 1: |
| 論理演算子 | &&や||を使用できる | caseには固定された値を書く |
| 浮動小数点 | 条件式で比較できる | switchの式には使用できない |
| 見た目 | 条件式が長くなることがある | 選択肢を一覧で確認しやすい |
| 主な注意点 | 条件を書く順番 | breakの書き忘れ |
たとえば、点数が80以上かどうかを調べる処理は、範囲判定なのでif文が向いています。
一方、メニュー番号が1、2、3のどれと一致するかを調べる処理は、switch文が向いています。
switch文では範囲を直接指定できない
caseには、特定の値を指定します。そのため、次のような範囲条件をcaseに書くことはできません。
- 80以上
- 50以上80未満
- 0以上100以下
このような条件には、関係演算子を使えるif~else if~elseが適しています。
switch文を使うか迷ったときは、次のように考えると選びやすくなります。
- 値が特定の番号や文字と一致するかを調べるならswitch
- 大小関係や範囲を調べるならif
- 複数の条件を&&や||で組み合わせるならif
scanfで文字を読み取るときの空白
char型の値をswitch文で分岐させることもできます。
文字をscanfの%cで読み取る場合、改行や空白も1文字として読み取られます。直前の入力で残った改行を読み飛ばしたい場合は、%cの前に空白を入れます。
scanf(" %c", &command);先頭の空白には、改行、スペース、タブなどの空白文字を読み飛ばす働きがあります。
| 書き方 | 動作 |
|---|---|
| scanf("%c", &command); | 次の1文字をそのまま読み取る |
| scanf(" %c", &command); | 空白文字を読み飛ばしてから1文字を読み取る |
int型を%dで読み取る場合、先頭の空白文字は自動的に読み飛ばされます。そのため、今回のsensorの入力では、%dの前に空白を付けなくても問題ありません。
図3:switch文が値を選択して終了するまでの流れ

この図から分かること
switch文では、最初に式の値を確認し、一致するcaseへ処理を移します。一致するcaseがなければdefaultへ進みます。
選ばれた処理の後にbreakを実行すると、各分岐はswitch文の外側へ合流します。この流れを理解しておくと、caseの選択とbreakの役割を一緒に捉えられるようになります。
