C言語の基本|else if文の使い方

条件は上から順にチェック。else if文を使って、たくさんの選択肢から最適な処理を1つだけ選ぼう。

if~else文を使うと、条件に応じて処理を2つに分けられます。しかし、実際のプログラムでは、3つ以上の結果に分けたい場面もよくあります。

たとえば、バッテリー残量によって次のように案内を変える場合です。

  • 残量が十分なら、そのまま使用できる
  • 少し減っていたら、充電を勧める
  • 残りわずかなら、早めの充電を警告する
  • ほとんど残っていなければ、すぐに充電を求める

このような多分岐を表現するときに使うのがelse if文です。

if~else if~elseの条件は上から順番に評価されます。そして、最初に真になったブロックだけが実行されます。一度処理が決まると、それより下の条件は評価されません。

図1:else if文による多分岐の流れ

この図から分かること

ifの条件が偽だった場合にだけ、次のelse ifが調べられます。else ifも偽なら、さらに次の条件へ進みます。

途中で真になる条件が見つかると、そのブロックを実行して多分岐全体から抜けます。それより下に書かれた条件は評価されません。

if~else if~elseの基本構文

else if文を使った多分岐は、次のように記述します。

if (条件式1) {
    文1;
} else if (条件式2) {
    文2;
} else if (条件式3) {
    文3;
} else {
    文4;
}

処理の流れは次のとおりです。

  1. 条件式1を評価する
  2. 条件式1が真なら文1を実行する
  3. 条件式1が偽なら条件式2を評価する
  4. 条件式2が真なら文2を実行する
  5. 条件式2も偽なら条件式3を評価する
  6. すべての条件式が偽ならelseの文4を実行する

else ifは必要な数だけ追加できます。一方、最初のifは1つだけで、elseは最後に1つだけ記述します。

記述位置役割
最初のif最初に調べる条件を書く
途中のelse if前の条件が偽だった場合に調べる
最後のelseどの条件にも当てはまらない場合を受け持つ

最初に真になったブロックだけが実行される

else if文で特に大切なのは、複数の条件が真になり得る場合でも、実行されるブロックは最初の1つだけという点です。

たとえば、batteryに85が入っているとします。

  • battery >= 80は真
  • battery >= 50も真
  • battery >= 20も真

数値だけを見ると3つの条件を満たしています。しかし、最初のbattery >= 80が真になった時点で処理が決まるため、それより下の条件は評価されません。

この動きによって、1つの値を重複させずに分類できます。

バッテリー残量によって案内を変える

次のプログラムでは、入力されたバッテリー残量を4段階に分類します。

バッテリー残量表示する案内
80以上残量は十分
50以上80未満余裕がある
20以上50未満充電を勧める
20未満すぐに充電する
バッテリー残量を4段階に分類するプログラム

ファイル名:8_6_1.c

#include <stdio.h>

int main(void)
{
    int battery;

    printf("バッテリー残量(%%)を入力してください > ");
    scanf("%d", &battery);

    if (battery >= 80) {
        printf("バッテリー残量は十分です。\n");
    } else if (battery >= 50) {
        printf("まだ余裕がありますが、使用後の充電がおすすめです。\n");
    } else if (battery >= 20) {
        printf("残量が少なくなっています。早めに充電してください。\n");
    } else {
        printf("残量がほとんどありません。すぐに充電してください。\n");
    }

    return 0;
}
実行結果の例

バッテリー残量に85を入力した場合は、最初のifが真になります。

バッテリー残量(%)を入力してください > 85
バッテリー残量は十分です。

60を入力すると、最初の条件は偽ですが、2番目の条件が真になります。

バッテリー残量(%)を入力してください > 60
まだ余裕がありますが、使用後の充電がおすすめです。

35を入力すると、上から3番目の条件が最初の真になります。

バッテリー残量(%)を入力してください > 35
残量が少なくなっています。早めに充電してください。

10を入力すると、すべての条件が偽になるためelseが実行されます。

バッテリー残量(%)を入力してください > 10
残量がほとんどありません。すぐに充電してください。
プログラムの詳しい解説

最初の条件では、バッテリー残量が80以上であるかを調べています。

if (battery >= 80)

85を入力した場合、この条件が真になります。最初のブロックを実行した後は、残りのelse ifやelseへ進みません。

最初の条件が偽だった場合は、次の条件が評価されます。

else if (battery >= 50)

この条件へ到達した時点で、batteryが80未満であることはすでに分かっています。そのため、条件式にbattery < 80を追加しなくても、50以上80未満の範囲を表せます。

同じように、3番目の条件へ到達したときは、上にある2つの条件がどちらも偽になっています。

else if (battery >= 20)

この時点でbatteryは50未満なので、この条件によって20以上50未満の範囲が選ばれます。

最後のelseには条件式がありません。80以上、50以上、20以上のどれにも該当しなかった値、つまり20未満の値がelseへ進みます。

図2:入力値ごとに評価される条件の違い

この図から分かること

入力値によって、評価される条件の数が変わります。85の場合は最初の条件だけで処理が決まりますが、10の場合はすべての条件を確認してからelseへ進みます。

また、1つの条件が真になった後は、それより下の条件を調べません。たとえば85は50以上でもありますが、battery >= 50のブロックが実行されることはありません。

条件を上から書く順番が重要

else if文では、条件を書く順番が判定結果に直接影響します。

今回のプログラムは、大きな境界値から順番に並べています。

  1. battery >= 80
  2. battery >= 50
  3. battery >= 20
  4. それ以外

この順番なら、上の条件から外れるたびに対象範囲が少しずつ狭められます。

到達した条件すでに分かっていること真になった場合の範囲
battery >= 80まだ何も判定していない80以上
battery >= 5080以上ではない50以上80未満
battery >= 2050以上ではない20以上50未満
else20以上ではない20未満

広い条件を先に書くと分類に失敗する

次のように、小さい境界値から並べると意図した分類になりません。

if (battery >= 20) {
    /* 20以上の処理 */
} else if (battery >= 50) {
    /* 50以上の処理 */
} else if (battery >= 80) {
    /* 80以上の処理 */
}

batteryが85の場合、最初のbattery >= 20が真になります。その時点で処理が決まるため、battery >= 80まで到達できません。

この並びでは、50以上や80以上の値もすべて最初のブロックに入ってしまいます。

境界値を使って段階的に分類するときは、次のように並べるのが基本です。

  • 大きい値を判定する条件から書く
  • 厳しい条件から緩い条件へ並べる
  • 上の条件を通過した後の範囲を意識する

条件を並べる前に範囲を整理する

else if文を書く前に、各処理が担当する範囲を表にすると間違いを防ぎやすくなります。

分類下限上限
残量は十分80上限なし
余裕がある5080未満
残量が少ない2050未満
すぐに充電下限なし20未満

この表を上から見ると、条件式に使用する境界値の順番も分かります。

  • 最初に80以上を判定する
  • 次に50以上を判定する
  • 次に20以上を判定する
  • 残った範囲をelseで受け持つ

else if文では、上の条件が偽だったという情報を次の条件で利用できます。そのため、それぞれの条件式に上限と下限の両方を書かなくても、順番によって範囲を表現できます。

図3:正しい条件順と誤った条件順の比較

この図から分かること

大きい値から順番に調べると、85は80以上、60は50以上80未満というように正しく分類できます。

反対に20以上を最初に置くと、20以上のすべての値が最初の条件に当てはまります。そのため、50以上や80以上の条件へ進めません。

else if文では、それぞれの条件式が正しいだけでなく、条件を並べる順番も正しくなければなりません。

elseはどの条件にも当てはまらない場合を受け持つ

最後のelseには条件式を書きません。それより上にある条件がすべて偽だった場合に実行されます。

今回のプログラムでは、elseへ到達した時点で次のことが分かっています。

  • 80以上ではない
  • 50以上ではない
  • 20以上ではない

したがって、elseが担当するのは20未満の範囲です。

最後のelseを用意すると、入力値がどの条件にも当てはまらなかった場合にも処理を実行できます。どの値に対しても必ず結果を表示したい場合に便利です。

よく当てはまる条件を上に置く考え方

else if文は上から順番に条件を評価するため、上の条件ほど早く判定されます。そのため、正しい分類を保てる場合には、よく発生する条件を上に置くと、平均的な判定回数を減らせることがあります。

ただし、最初に優先するのは正しい判定です。

境界値による段階的な分類では、発生頻度だけで条件を並べ替えると、広い条件が上に来て下の条件へ進めなくなる可能性があります。まずは条件が重なるかを確認し、どの入力値も意図した1つのブロックへ進む順番を作ることが大切です。