コンテンツにスキップ

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) {
    
}
else if (_tmp_ == 値2) {
    
}

………

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 ()
{
case 0:
case 1:
  // 式が0か1の時に実行
  System.Console.WriteLine("Case 0 or 1.");
  return 1;

case 2:
  System.Console.WriteLine("Case 2.");
  goto case 3: // case 3も実行

case 3:
  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)
{
    case int num when num < 0:
        Console.WriteLine($"objは負の32bit整数{num}です。");
        break;
    case string str when str.StartsWith("H"):
        Console.WriteLine($"objはHから始まる文字列{str}です。");
        break;
    case string str:
        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

[編集]

構造化された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 'Caseに複数の値を指定することができる
        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式により同様の多分岐ができる。フォールスルーはない。ラベルとして置いたものと条件値は===演算子で比較される[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と書く。

出典

[編集]

関連項目

[編集]
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy