本物のC

C の基本:分岐


条件によって処理を変える

条件式が真か偽かで処理を変えるのが条件分岐(conditional branch)であり、Cでは次の様なifによって実現されます。

if (条件式1)
条件式1が真の場合の処理
else if (条件式2)
条件式2が真の場合の処理
...
else if (条件式N)
条件式Nが真の場合の処理
else
条件式が全て偽の場合の処理

else if部分の数はいくつでもよく、else ifelseは省略可能です。また処理内容は単一の文で書いても、ブロックを用いてもよいです。

if (cond)
printf("cond is true.");
if (cond)
{
printf("cond is true.");
}

(ただし、某社の gotofail バグの様なものを防ぐ為に単文でも{ }を省略すべきでないという見方もあります。参考:「EXP19-C. if、for、while 文の本体は波括弧で囲む」、「AppleがiOS7.0.6で修正したSSLバグの簡単な解説 - Qiita」)

ラベルと無条件分岐

何も条件を付けず、必ず処理が飛ぶ様にする事もできます。

ジャンプする先はラベル(label)により指定します。

ラベル名:
何らかの文

gotoによってそのラベルへ飛ぶ事ができます。

goto ラベル名;

gotoは関数の色々な所から共通のエラー処理へ飛ばす場合や、

int some_process(void)
{
...
if (x == 0)
goto fail;
...
return 0;
fail:
fprintf(stderr, "Error!");
free_allocated_memory();
return -1;
}

深いループから抜ける場合などに有効です。

for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
if (data[i][j] == 0)
goto exit_loop;
...
}
}
exit_loop: ;

値による場合分け

switchを使うと

if (x == 1)
pattern1();
else if (x == 2)
pattern2();
else if (x == 3)
pattern3();

の様な場合分けをより簡単に書く事ができます。

switch (式)
{
case 値1 :
式が値1になる場合の処理
...
case 値2:
式が値2になる場合の処理
...
default:
どれにも当て嵌らない場合の処理
...
}

式の値に対応するcaseがあればそこへ飛び、無ければdefaultに飛びます。defaultは省略可能です。

飛んだ後は特に何もアフターケアが無く飛びっぱなしので、処理の最後にbreak;を書かないとその後のcaseも立て続けに実行されてしまいます。(フォールスルーと呼ばれます。)つまり、上のif文と同じ処理をするには

switch (x)
{
case 1:
pattern_one();
break;
case 2:
pattern_two();
break;
case 3:
pattern_three();
break;
}

と書く必要があります。