第7回
制御構造と変数(3)~switch caseによる多枝分岐

switch caseによる多枝分岐

Cには、ifの他にもswitch caseという条件分岐の構造が備わっています。先に紹介したtoromaji関数のような処理では、if~elseよりソースが分かりやすくなります。

ifよりシンプルな分岐構造

toromaji関数のようにifによる条件判断が何行も繰り返される場合、switch caseの方が向いています。switch caseの書式は以下のようになります。
switch (<値>) {
  case <値1> : <処理1>;
               break;
  case <値2> : <処理2>;
               break;
         :
  default    : <処理n>;
}
switchに続く( )内に記述された<値>を、caseに続く<値1>、<値2>……と順次比較し、両者が一致したら「:」の右側に記述された<処理>以降の処理が実行されます。

多枝分岐の構造

switch caseでは、値の一致した箇所の「:」以降、}にたどり着くまでに記述された処理がすべて実行されます。つまり、2つめのcaseで値が一致した場合、3つめや4つめのcaseで実行されるべき処理もすべて実行されてしまうのです。

それではいけないので、1つのcaseで値が一致したときに実行させたい処理の最後にbreak命令を記述し、そこから先は}の次の命令に移動するようにします。

最後に、どのcaseにも一致しない場合は、defaultに続く「:」以降の処理(<処理n>)が実行されます。

このようにswitch caseでは、比較元の変数を最初に一度記述しておけば、あとはそれをcaseに続く値と順次比較していくことができます。

ifの機能である条件判定と分岐に対して、1つの比較元から複数の処理に分岐するswitch caseを『多枝分岐』と呼びます。


VBのSelect Caseとの違い

Cのswitch caseは、Visual BasicのSelect Case構文に似ています ※2 。しかし、先述したように値の一致したcase以降の文がすべて実行されてしまう点が異なります。各caseに当てはまる処理の最後に、必ずbreak命令を記述しておきましょう。

break命令を省略すると、先にリスト1で紹介したifの連続による構造と同じで、無駄な条件判定を行ってしまいます。

また、VBのSelect Caseでは、Caseに続けて条件式を記述できますが、Cのswitch caseでは純然たる値──定数または変数しか記述できず、2つの値が『等しいかどうか』しか判定できません。この点にも注意が必要です。

CやC++とVisual Basicの両方を扱っていると、switch caseをついついselect caseなどと記述してしまうことがあります。慌て者の筆者は、今回の原稿で3も回くらい間違えました^^; みなさんもご注意を

toromaji関数をswitch caseで書く

toromaji関数をswitch caseを使って書き直すと、リスト4のようになります。

ここでは、引数cの値が母音を示す『A・I・U・E・O』のどれとも一致しなかった場合(defaultに続く処理)、記号定数“_FALSE”を返すようにしています。

そこで、toromaji関数を呼び出すmain関数も、戻り値が_FALSEだった場合にエラーメッセージを表示するよう、リスト5のように書き換えてみました。

リスト4:switch caseを使ったtoromaji関数
int toromaji(int c) {
  int retval;

  switch (c) {
    case 'A' : strcpy(str, "あ");
               retval = _TRUE;
               break;
    case 'I' : strcpy(str, "い");
               retval = _TRUE;
               break;
    case 'U' : strcpy(str, "う");
               retval = _TRUE;
               break;
    case 'E' : strcpy(str, "え");
               retval = _TRUE;
               break;
    case 'O' : strcpy(str, "お");
               retval = _TRUE;
               break;
    default  : retval = _FALSE;
  }
  return retval;
}

リスト5:switch caseを使って書き直したプログラム(ex0704.cex0704.exe)
#define _FALSE 0
#define _TRUE  !(_FALSE)

char str[4];

/* 関数の宣言 */
int toromaji(int);

int main(void)
{
  char c;

  printf("Input Charactor : ");
  scanf("%c", &c);
  if (toromaji((int)c) == _FALSE) {
    printf("ローマ字の母音を入力してください。\n");
  } else {
    printf(" --> %s\n", str);
  }
}

int toromaji(int c) {
  int retval;

  switch (c) {
    case 'A' : strcpy(str, "あ");
               retval = _TRUE;
               break;
    case 'I' : strcpy(str, "い");
               retval = _TRUE;
               break;
    case 'U' : strcpy(str, "う");
               retval = _TRUE;
               break;
    case 'E' : strcpy(str, "え");
               retval = _TRUE;
               break;
    case 'O' : strcpy(str, "お");
               retval = _TRUE;
               break;
    default  : retval = _FALSE;
  }
  return retval;
}