Switch文
テンプレート:小文字 switch文(スイッチぶん)とは、プログラミング言語において、ある式の値に応じて多分岐をおこなう文である。
最適化の仕方によって多少変わることはあるが、場合によってはテーブルジャンプなどにより、条件判断を繰り返すif文より効率的に実行される。
目次
文法
C
構文は以下の通り。
switch (制御式) {
case 値1:
文
文
………
break;
case 値2:
文
文
………
break;
default:
文
}
上記の「case」はいくつでも記述することができる。
この文は次のような手順で実行される。
- 制御式を評価し、整数値を得る。
- その整数値がどれかのcaseで指定された値であるなら、そのcaseに引き続く文に飛ぶ。
- どのcaseでも指定されていなければ、defaultに引き続く文に飛ぶ。
- もしdefaultが記述されていなければ、何も実行せずにswitch文を抜ける。
フォールスルー
ここで注意しなければならないのが、caseはラベルに過ぎず、そのcaseより前からの実行から、そこでswitch文を抜けさせる働きはない点である(一般的には、次のcaseがあらわれる直前にbreak文を置く)。このルールはフォールスルー(fall through)と言い、制御の流れが合流する動作をさせたい場合に便利であるが、一方でbreak文の書き忘れによるバグ、ループを抜けるbreakと取り違える誤読によるバグなど、バグの温床として問題視されてきた。
そのためlintでは、意図的にフォールスルーしていることを示す/* FALLTHROUGH */
などのコメントが記述されていない限り警告を出す。また、Cに類似した構文を採用した言語でも、C#のように対策(後述)した言語仕様にされていることがある。
上記の例は、if文を羅列することで同様の動作を実現することができる。
_tmp_ = 制御式;
if (_tmp_ == 値) {
文
} else if (_tmp_ == 値) {
文
}
………
else {
文
}
defaultは最後に記述される場合が多いが、必ずしも最後である必要はない。
switchによる分岐は以下のようにdo-while文と組み合わせることも可能である。
switch(count)
{
default: do { printf("%d\n", count); count++;
case 0: printf("%d\n", count); count++;
case 1: printf("%d\n", count); count++;
case 2: printf("%d\n", count); count++;
} while (count);
}
例えばDuff's deviceではそのような使われ方をしている。
C#
C#でのswitch文はC言語と似たような見た目であるが、フォールスルーについての挙動は異なる。
switch (someInteger)
{
case 0:
case 1:
return 1; // 変数someIntegerが0か1の時に実行
case 2:
someInteger++;
goto case 3: // case 3も実行
case 3:
文A;
break;
default:
文B;
break; // ここのbreakも省略不可
}
C#では、caseラベルは文に付属する扱いとなるが、1つの文に複数のcaseラベルを付けることができる。また、C言語のようなフォールスルーは禁止されており、次のcaseラベル付きの文、あるいはswitchブロックの末端に、通常の制御フローで到達してはならない。すなわち、breakでswitchを抜ける、returnで関数ごと抜ける、例外を投げる、無限ループしてそれ以上進まない、goto caseするなどの書き方が必要となる[1]。goto caseにより、C言語ではフォールスルーを使って書くことができた、制御の合流を書くことができる。
C#では、CやC++が整数型しか制御式の値に使用できないのに対し、文字列型も使用できる。
Go
Goでは、caseに複数の値を指定できる。次のcaseの直前にfallthrough文を置くとフォールスルーになる。
PHP
PHPでは、C#と同様、文字列にも、switch文が適用できる。
switch (str) {
case "ABC":
文A;
break;
case "XYZ":
文B;
break;
case "123":
文C;
break;
default:
文D;
break;
}
BASIC
テンプレート:節stub 構造化されたBASICでは、Select Caseステートメントが存在することが多い。このステートメントでは、文字列または整数を対象にできる。
Select Case str
Case "ABC"
文A
Case "XYZ"
文B
Case "123"
文C
Case Else
文D
End Select
Select Case age
Case Is < 20
文A
Case 20 To 29
文B
Case 30,50,70
文C
Case Else
文D
End Select
Cなどと違い、各Caseはラベルではなく、Selectステートメントはフォールスルーでない。
Perl
Perlでは、perl-5.8以降からuse Switchとした上でswitch case文が使えるようになった。それ以前のバージョンのperlに関しては、Perl付属文章perlsynドキュメントのBasic BLOCKs and Switch Statementsの節に書式の例が書かれている。
Ruby
Rubyでは、case式により同様の多分岐ができる。フォールスルーはない。ラベルとして置いたものと条件値は===
演算子で比較される[2][* 1]ため、これをオーバーロードすることでクラスに応じた一致判定を行うことができる。Ruby自体のクラスライブラリ内でも、正規表現の一致判定[3]、範囲オブジェクトでの範囲内かどうかの判定、オブジェクトがあるクラスに属するかの判定など、各種の定義がなされている。
条件式ベースで使う
Ruby[2]やSQL[* 2]では、switchに相当する文の後の式が必須ではなく、省略した場合はwhenとして書かれた式のうち、最初に真となるところを実行するようになる。PHPやJavaScriptなど、caseの式が定数である必要性がない言語の場合、switch(true)
と書くことで同様の動作を実現できる。
脚注
脚注
出典
関連項目
テンプレート:Asboxru:Оператор ветвления#Переключатель- ↑ switch(C#リファレンス)、MSDN(2014年5月30日閲覧)。
- ↑ 2.0 2.1 Ruby 1.9.3マニュアル - 制御構造、2014年3月3日閲覧。
- ↑ Ruby 1.9.3マニュアル - class Regexp、2014年3月3日閲覧。
引用エラー: 「*」という名前のグループの <ref>
タグがありますが、対応する <references group="*"/>
タグが見つからない、または閉じる </ref>
タグがありません