コンテンツにスキップ
Wikipedia

switch文

出典: フリー百科事典『ウィキペディア(Wikipedia)』

switch文(スイッチぶん、: switch statement)とは、プログラミング言語において、ある式の値に応じて多分岐を行なうである。最適化の仕方にも左右されるが、場合によってはテーブルジャンプなどに展開されることで、条件判断を繰り返すif文よりも効率的に実行されることがある。言語によっては、値を返すとして記述できるものもある。また、検査対象の式のランタイム型(実行時型情報)に応じて分岐するような、複雑なパターンマッチングの機能を持つ言語もある[1]

言語ごとの構文

[編集 ]

C言語

[編集 ]

構文は以下の通り。

switch(制御式){
case値1:


.........
break;
case値2:


.........
break;
default:

}

上記の「case」ラベルはいくつでも記述することができる。caseラベルの「値」はコンパイル時に決まる整定数式 (integer constant expression) である必要がある。

この文は次のような手順で実行される。

  1. 制御式を評価し、整数値を得る。
  2. その整数値がどれかのcaseで指定された値であるなら、そのcaseに引き続く文に飛ぶ。
  3. どのcaseでも指定されていなければ、defaultに引き続く文に飛ぶ。
  4. もしdefaultが記述されていなければ、何も実行せずにswitch文を抜ける。

フォールスルー

[編集 ]

ここで注意しなければならないのが、caseはラベルに過ぎず、そのcaseより前からの実行から、そこでswitch文を抜けさせる働きはない点である(一般的には、次のcaseがあらわれる直前にbreak文を置く)。このルールはフォールスルー (fall through) と言い、制御の流れが合流する動作をさせたい場合に便利であるが、一方でbreak文の書き忘れによるバグ、ループを抜けるbreakと取り違える誤読によるバグなど、バグの温床として問題視されてきた。

そのためlintでは、意図的にフォールスルーしていることを示す/* FALLTHROUGH */などのコメントが記述されていない限り警告を出す。また、Cに類似した構文を採用した言語でも、C#のように対策(後述)した言語仕様にされていることがある。

上記の例は、if文を羅列することで同様の動作を実現することができる。なおif文では比較対象の「値」が整定数式である必要がない点においてswitch文よりも柔軟である。

_tmp_=制御式;
if(_tmp_==値1){

}
elseif(_tmp_==値2){

}
.........
else{

}

defaultは最後に記述される場合が多いが、必ずしも最後である必要はない。

switchによる分岐は以下のようにdo-while文と組み合わせることも可能である。

switch(count)
{
default:do{printf("%d\n",count);count++;
case0:printf("%d\n",count);count++;
case1:printf("%d\n",count);count++;
case2:printf("%d\n",count);count++;
}while(count);
}

例えばDuff's deviceではそのような使われ方をしている。

C#

[編集 ]

C#でのswitch文はC言語と似たような見た目であるが、フォールスルーについての挙動は異なる。

switch()
{
case0:
case1:
// 式が0か1の時に実行
System.Console.WriteLine("Case 0 or 1.");
return1;
case2:
System.Console.WriteLine("Case 2.");
gotocase3:// case 3も実行
case3:
System.Console.WriteLine("Case 3.");
break;
default:
System.Console.WriteLine("Default.");
break;// ここのbreakも省略不可
}

C#では、caseラベルは文に付属する扱いとなるが、1つの文に複数のcaseラベルを付けることができる。また、C言語のようなフォールスルーは禁止されており、次のcaseラベル付きの文、あるいはswitchブロックの末端に、通常の制御フローで到達してはならない。すなわち、breakでswitchを抜ける、returnで関数ごと抜ける、例外を投げる、無限ループしてそれ以上進まない[注釈 1] 、goto caseするなどの書き方が必要となる[2] 。goto caseにより、C言語ではフォールスルーを使って書くことができた、制御の合流を書くことができる。

CやC++では、switch文の制御式には整数型の式、またcaseラベルには整定数式しか使用できないのに対し、C#ではそれぞれ文字列型および文字列リテラルも使用できる。また、整数型あるいは整数型に準ずる値型のnull許容型System.Nullableも使用することができる。

C# 7.0以降では型switchを使用できる。

// C# 7.0以降
switch(obj)
{
caseintnumwhennum<0:
Console.WriteLine($"objは負の32bit整数{num}です。");
break;
casestringstrwhenstr.StartsWith("H"):
Console.WriteLine($"objはHから始まる文字列{str}です。");
break;
casestringstr:
Console.WriteLine($"objは文字列{str}です。");
break;
default:
Console.WriteLine("objは想定外の型あるいは値です。");
break;
}

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;
}

PHPのswitch文においては、比較が===演算子ではなく==演算子で行われる。そのため、曖昧一致に起因し、開発者が予期しない動作となる場合がある。

BASIC

[編集 ]
[icon]
この節の加筆が望まれています。

構造化されたBASICでは、Select Caseステートメントが存在することが多い。このステートメントでは、文字列または整数を対象にできる。

SelectCasestr
Case"ABC"
A
Case"XYZ"
B
Case"123"
C
CaseElse
D
EndSelect
SelectCaseage
CaseIs<20
A
Case20To29
B
Case30,50,70'Caseに複数の値を指定することができる
C
CaseElse
D
EndSelect

Cなどと違い、各Caseはラベルではなく、Selectステートメントはフォールスルーでない。

Perl

[編集 ]

Perlでは、perl-5.8以降からuse Switchとした上でswitch case文が使えるようになった。それ以前のバージョンのperlに関しては、Perl付属文章perlsynドキュメントのBasic BLOCKs and Switch Statementsの節に書式の例が書かれている。

Ruby

[編集 ]

Rubyでは、case式により同様の多分岐ができる。フォールスルーはない。ラベルとして置いたものと条件値は===演算子で比較される[3] [注釈 2] ため、これをオーバーロードすることでクラスに応じた一致判定を行うことができる。Ruby自体のクラスライブラリ内でも、正規表現の一致判定[4] 、範囲オブジェクトでの範囲内かどうかの判定、オブジェクトがあるクラスに属するかの判定など、各種の定義がなされている。

Mediawiki

[編集 ]

Mediawiki系のTemplateにおいては、ParserFunctionsを用いて多分岐をおこなうことができる。一対一の分岐処理の他、複数の値に対して同一の処理を定義する一種のフォールスルーも実現できる。しかし、CやC#といった言語でのreturn文やbreak文が無い。そのため処理の途中でSwitch文を抜けるにはif等の条件文で処理を囲み、実行させないよう制御する必要がある。

詳細については、Help:条件文#switchの項を参照の事。

表計算ソフトウェア

[編集 ]

多くの表計算ソフトウェアでは、CHOOSE関数の拡張としてSWITCH関数が利用できる。

例えばMicrosoft Excel 2019以降(Office 365含む)[5] LibreOffice Calc 5.2以降[6] Google スプレッドシート [7] でサポートされている。指定可能なケースと結果値のペアの上限は環境によって異なるが、概ね以下のような構文である。

SWITCH(式, ケース1, 結果値1[, ケース2, 結果値2, ...][, 既定の結果値])
検査される任意の有効な値。
ケース 式に対して比較されるケース。
結果値 ケースが式と一致したときに返される値。
既定の結果値 最後のパラメータとして指定される省略可能な値で、いずれのケースも式と一致しなかった場合に返される。

もし式がどのケースとも一致せず、さらに既定の結果値が与えられていない場合、#N/Aのエラーが返却される。

条件式ベースで使う

[編集 ]

Ruby[3] SQL [注釈 3] では、switchに相当する文の後の式が必須ではなく、省略した場合はwhenとして書かれた式のうち、最初に真となるところを実行するようになる。PHPやJavaScriptなど、caseの式が定数である必要性がない言語の場合、switch(true)と書くことで同様の動作を実現できる。

脚注

[編集 ]

注釈

[編集 ]
  1. ^ むろん、C#コンパイラが停止性問題を解くことはできないため、この扱いはループ条件が定数の場合に限られる。
  2. ^ なお、Rubyの===演算子は、JavaScriptやPHPでのような「厳密に等しい」という意味ではない。
  3. ^ どちらの言語も、switch...caseではなく、case...whenと書く。

出典

[編集 ]

関連項目

[編集 ]

AltStyle によって変換されたページ (->オリジナル) /