🖥️

【C言語超入門】 おまけ2 switch

に公開

https://youtu.be/9brC1Cg_sMc

四国めたん
\textcolor{pink}{四国めたん: }教師役ですわ

ずんだもん
\textcolor{lime}{ずんだもん: }生徒役なのだ

\footnotesize \textcolor{pink}{四国めたん:} 皆さん、こんにちは。四国めたんです

\footnotesize \textcolor{lime}{ずんだもん:} ずんだもんなのだ。こんにちはなのだ

\footnotesize \textcolor{pink}{四国めたん:} 今回もC言語のお勉強をしていきましょう

\footnotesize \textcolor{lime}{ずんだもん:} レッツゴーなのだ

\footnotesize \textcolor{pink}{四国めたん:} 前回は、 無条件ジャンプ についてお話ししましたわ

\footnotesize \textcolor{lime}{ずんだもん:} そうだったのだ

\footnotesize \textcolor{pink}{四国めたん:} 今回はswitchcase文についてお話ししますわ

\footnotesize \textcolor{lime}{ずんだもん:} switchcase文?

\footnotesize \textcolor{pink}{四国めたん:} はい、指定した「式」の結果に応じて、予め決めた場所にジャンプするための構文ですわ

\footnotesize \textcolor{lime}{ずんだもん:} 「式」に応じてと云うことは、if文と同じような感じか?

\footnotesize \textcolor{pink}{四国めたん:} 同じようなことは可能ですが、基本的な動作は全く異なりますわね

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} 同一に扱うプログラマーもいらっしゃいますが、しっかりと区別した方がいいですわね

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

\footnotesize \textcolor{lime}{ずんだもん:} ところで、今回も おまけ なのか?

\footnotesize \textcolor{pink}{四国めたん:} はい、基本的にswitchcase文も、できれば使ってほしくありませんわ

\footnotesize \textcolor{lime}{ずんだもん:} 使ってほしくないのに解説するのか?

\footnotesize \textcolor{pink}{四国めたん:} はい、文法として決められている以上、switchcase文が使われているプログラムも多く存在しますわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} そのようなプログラムを読んだ時に、意味が解らないのでは困ることになりますわ

\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} とくにswitchcase文は、どのように動作するかをしっかりと把握していないと、間違ってしまうもとになりますわ

\footnotesize \textcolor{lime}{ずんだもん:} 気をつけるのだ

switch ~ case

\footnotesize \textcolor{pink}{四国めたん:} まず、switchcase文は、指定した「式」の戻り値に合ったラベルにジャンプする構文ですわ

\footnotesize \textcolor{lime}{ずんだもん:} うん?条件に応じて分岐するのではないのか?

\footnotesize \textcolor{pink}{四国めたん:} 基本的にはgotoジャンプに近いと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} とりあえず具体的な形式を見てみましょう

switch (式) {
  case 値0:
    処理0
  case 値1:
    処理1
  case 値2:
    処理2
    :
    :
  default:
    処理
}

\footnotesize \textcolor{pink}{四国めたん:} まず、switchの後に「式」を括弧"()"で括って記述しますわ

\footnotesize \textcolor{lime}{ずんだもん:} ふむ

\footnotesize \textcolor{pink}{四国めたん:} この「式」の戻り値がジャンプ先のラベルとなりますわ

\footnotesize \textcolor{lime}{ずんだもん:} ラベルと云うと、本当にgotoのような感じなのだな

\footnotesize \textcolor{pink}{四国めたん:} 波括弧"{}"内では、caseに続けてラベルの代わりとなる値とコロン":"を記述しますわ

\footnotesize \textcolor{lime}{ずんだもん:} 値と云うと、数値をラベルとして使うのか?

\footnotesize \textcolor{pink}{四国めたん:} はい、ジャンプ先のラベルとしての値は、整数値かそれに準ずる、たとえば列挙子などを用いますわ

\footnotesize \textcolor{lime}{ずんだもん:} 列挙子も使えるのか...

\footnotesize \textcolor{pink}{四国めたん:} 当然、「式」の戻り値も整数値か列挙子などである必要がありますわね

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

\footnotesize \textcolor{pink}{四国めたん:} ちなみに「ラベルへのジャンプ」なので、たとえばcase 値0:にジャンプ後は、処理0、処理1、処理2...と、全ての処理が実行されますわ

\footnotesize \textcolor{lime}{ずんだもん:} えぇっ、caseと次のcaseに挟まれた部分の処理のみが実行されるのではないのか!?

\footnotesize \textcolor{pink}{四国めたん:} ちがいますわね

\footnotesize \textcolor{pink}{四国めたん:} その辺りが 条件分岐 ではなく、ラベルへのジャンプとした理由ですわ

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

\footnotesize \textcolor{pink}{四国めたん:} なお、caseで指定された値以外が「式」の戻り値になった場合には、default:にジャンプしますわ

\footnotesize \textcolor{lime}{ずんだもん:} default:がない場合はどうなるのだ?

\footnotesize \textcolor{pink}{四国めたん:} もし、default:もない場合には、switch文をスキップして、次の処理に移りますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} とりあえず実例を見てみましょう

#include <stdio.h>
#include <conio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    switch (c) {
      case 'a':
        printf("aが入力されました\n");
      case 'b':
        printf("bが入力されました\n");
      case 'c':
        printf("cが入力されました\n");
      default:
        printf("abc以外が入力されました\n");
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

\footnotesize \textcolor{pink}{四国めたん:} キーボードから1文字ずつ入力して、\fcolorbox{blue}{lightgray}{a}, \fcolorbox{blue}{lightgray}{b}, \fcolorbox{blue}{lightgray}{c}の場合には出力され、それ以外は「abc以外が入力されました」と出力されますわ

\footnotesize \textcolor{lime}{ずんだもん:} ラベルには'a', 'b', 'c'のように文字を指定しているのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、以前にもお話ししましたが、char型の文字は整数と同じですから...

\footnotesize \textcolor{lime}{ずんだもん:} 覚えているのだ

\footnotesize \textcolor{pink}{四国めたん:} そして、\fcolorbox{blue}{lightgray}{z}を入力するとプログラムを終了しますわ

\footnotesize \textcolor{lime}{ずんだもん:} うむ

\footnotesize \textcolor{pink}{四国めたん:} それでは実行して、キーボードから\fcolorbox{blue}{lightgray}{b}を入力してみましょう

3行出力

\footnotesize \textcolor{lime}{ずんだもん:} 「bが入力されました」、「cが入力されました」、「abc以外が入力されました」と表示されたのだ

\footnotesize \textcolor{pink}{四国めたん:} なお「式」の部分を少し変更して、ラベルに整数を使うことも可能ですわ

#include <stdio.h>
#include <conio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    switch (c - 'a') {
      case 0:
        printf("aが入力されました\n");
      case 1:
        printf("bが入力されました\n");
      case 2:
        printf("cが入力されました\n");
      default:
        printf("abc以外が入力されました\n");
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

3行出力2

\footnotesize \textcolor{pink}{四国めたん:} ちなみに、ずんだもんさんは「bが入力されました」とだけ表示されると期待しましたか?

\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} ですが、switch文は「式」の戻り値をラベルとしてジャンプするだけなので、ジャンプ先以降の処理は全て実行されるのですわ

\footnotesize \textcolor{lime}{ずんだもん:} そうだったのだ

\footnotesize \textcolor{pink}{四国めたん:} この点は非常に重要で、忘れがちな点でもありますわ

\footnotesize \textcolor{lime}{ずんだもん:} じゅうぶん、注意するのだ

\footnotesize \textcolor{pink}{四国めたん:} この性質を利用して、「式」の異なる戻り値に対して、同じ位置にジャンプさせることもできますわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} とりあえず実例を見てみましょう

#include <stdio.h>
#include <conio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    switch (c) {
      case 'a':
      case 'b':
      case 'c':
        printf("abcが入力されました\n");
      default:
        printf("abc以外が入力されました\n");
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

abcで同じ位置

\footnotesize \textcolor{pink}{四国めたん:} この場合、キーボードの入力\fcolorbox{blue}{lightgray}{a}, \fcolorbox{blue}{lightgray}{b}, \fcolorbox{blue}{lightgray}{c}に対して、同じprintf("abcが入力されました\n");の部分に処理が移りますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

breakを使ったswitch

\footnotesize \textcolor{pink}{四国めたん:} はい、ここまでがswitch文の基本的な動作のお話しですわ

\footnotesize \textcolor{lime}{ずんだもん:} うむ

\footnotesize \textcolor{pink}{四国めたん:} ところで、ずんだもんさんは、「式」の戻り値に対してcaseのラベル毎に異なる処理がおこなわれることを期待していましたわね

\footnotesize \textcolor{lime}{ずんだもん:} その通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} 実は、ジャンプして、それ以降の処理を全て実行するような使い方は、一般的ではありませんわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} むしろ、期待した通り、if文のような 条件分岐 的な使い方のほうが一般的ですわ

\footnotesize \textcolor{lime}{ずんだもん:} ふむふむ

\footnotesize \textcolor{pink}{四国めたん:} その場合、breakを併用して、このような形式になりますわ

switch (式) {
  case 値0:
    処理0
    break;
  case 値1:
    処理1
    break;
  case 値2:
    処理2
    break;
    :
    :
  default:
    処理
    break;
}

\footnotesize \textcolor{lime}{ずんだもん:} 詳しく教えて欲しいのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、各処理の最後、次のcaseの直前にbreakを置くことで、各case後の処理が終わったら、強制的にswitch文の外にジャンプしますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} なお、default後の処理の後のbreakは、本来、必要ないのですが、様式美と云うことで入れていますわ

\footnotesize \textcolor{lime}{ずんだもん:} まぁ、全てにbreakを入れるようにしておけば、忘れる可能性が減るのだ

\footnotesize \textcolor{pink}{四国めたん:} ちなみに、このような使い方は、breakの、唯一、推奨される使い方ですわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} とりあえずサンプルプログラムを見てみましょう

#include <stdio.h>
#include <conio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    switch (c) {
      case 'a':
        printf("aが入力されました\n");
        break;
      case 'b':
        printf("bが入力されました\n");
        break;
      case 'c':
        printf("cが入力されました\n");
        break;
      default:
        printf("abc以外が入力されました\n");
        break;
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

\footnotesize \textcolor{pink}{四国めたん:} 実行してキーボードから\fcolorbox{blue}{lightgray}{b}を入力してみますわ

breakを使ったswitch

\footnotesize \textcolor{pink}{四国めたん:} 今回は「bが入力されました」とだけ表示されて、「cが入力されました」などの余計な表示はされていませんわ

\footnotesize \textcolor{lime}{ずんだもん:} breakを使わなかった時とは全然違うのだ

\footnotesize \textcolor{pink}{四国めたん:} なお、breakを伴ったswitch文は、概ねif文の 条件分岐 と同じですわ

\footnotesize \textcolor{lime}{ずんだもん:} 期待した使い方なのだ

#include <conio.h>
#include <stdio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    if (c == 'a') {
      printf("aが入力されました\n");
    } else if (c == 'b') {
      printf("bが入力されました\n");
    } else if (c == 'c') {
      printf("cが入力されました\n");
    } else {
      printf("abc以外が入力されました\n");
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

if文

\footnotesize \textcolor{lime}{ずんだもん:} お~、if文を使って同じことが可能なのだ

\footnotesize \textcolor{pink}{四国めたん:} なお、このような 条件分岐 的な使い方の場合、if文よりもswitch文を好むプログラマーもいらっしゃいますわ

\footnotesize \textcolor{lime}{ずんだもん:} どうしてなのだ?

\footnotesize \textcolor{pink}{四国めたん:} 理由としては、「if文よりもswitch文の方が速い」とか「見た目にきれい」だとかが上げられますわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} まぁ、たしかにif文よりもswitch文の方が速くなる場合があるのも事実ですわ

\footnotesize \textcolor{pink}{四国めたん:} でも、昔ならいざ知らず、現在のコンパイラやCPUでは、気にする程の差異はないと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} また、switchの方が「見た目がきれい」なのは理解はしますが、breakを忘れてバグに苦しんだりすることを考えると、あえてswitch文を勧めたいとは思いませんわ

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

複数の条件に同じ処理を

\footnotesize \textcolor{pink}{四国めたん:} ちなみに、あえてbreakを使わない部分を作って、複数の条件に同じ処理をさせることも可能ですわ

\footnotesize \textcolor{lime}{ずんだもん:} それは便利なのだ

\footnotesize \textcolor{pink}{四国めたん:} とりあえずサンプルを見てみましょう

#include <stdio.h>
#include <conio.h>

void main() {
  int c = 0;
  do {
    printf("キーボードから文字を入力して下さい\n");
    c = _getch();
    switch (c) {
      case 'a':
      case 'b':
      case 'c':
        printf("abcが入力されました\n");
        break;
      default:
        printf("abc以外が入力されました\n");
        break;
    }
  } while (c != 'z');
  printf("プログラムを終了します\n");
}

\footnotesize \textcolor{pink}{四国めたん:} 実行してキーボードから\fcolorbox{blue}{lightgray}{a}, \fcolorbox{blue}{lightgray}{b}, \fcolorbox{blue}{lightgray}{c}と入力してみますわ

abcで同じ位置2

\footnotesize \textcolor{lime}{ずんだもん:} 全てに対して「abcが入力されました」と表示されたのだ

\footnotesize \textcolor{pink}{四国めたん:} そしてbreakがあるため、以前のように「abc以外が入力されました」と云う表示はされませんわ

defaultは必須です

\footnotesize \textcolor{lime}{ずんだもん:} ところで、switch文でdefaultは必須なのか?

\footnotesize \textcolor{pink}{四国めたん:} いいえ、defaultがない場合、caseのラベルに「式」の戻り値に該当する値がなければ、そのままswitch文を抜けるだけですわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} ただ、バグを減らすという観点から、defaultは必ず記述することをお勧めしますわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} 処理が必要なければ、breakだけでもOKですわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} コメントで処理が必要ないことを明記すると、なお良いですわ

\footnotesize \textcolor{lime}{ずんだもん:} うむ

\footnotesize \textcolor{pink}{四国めたん:} これは、デフォルトの処理が必要なのに書き忘れてしまい、バグになってしまうケースが多いからですわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} また、case部分で「式」の戻り値の全てを網羅したつもりが、網羅できていなかった場合にも有用ですわね

\footnotesize \textcolor{lime}{ずんだもん:} なるほど、defaultにエラーメッセージを出力するようにしておけば、バグの発見に有効なのだ

\footnotesize \textcolor{pink}{四国めたん:} そうですわね

switchにcontinue

まとめ

\footnotesize \textcolor{pink}{四国めたん:} お疲れさまでした

\footnotesize \textcolor{lime}{ずんだもん:} おつかれさまなのだ

\footnotesize \textcolor{pink}{四国めたん:} 以上で Switch についてのお話しを終わりますわ

\footnotesize \textcolor{pink}{四国めたん:} ところで、switchcase文はifelse文とは全く異なるものですわ

\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} ifelse文は 条件分岐 ですが、switchcase文は 無条件ジャンプ に属するものと思った方がいいと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} うむ

Discussion