Cプログラミング入門

第15回 Chapter5 if文で条件分岐(3)

この記事を読むのに必要な時間:およそ 1.5 分

if文のネスティング

if文の中に別のif文を入れ,さらに複雑な条件判断を行うこともできます。if文や後述のfor文while文などの中に,別のif文,for文,while文などを入れることをネスティング(入れ子)と言います。ネスティングの際にはインデント(字下げ)を行い,プログラムの構造が視覚的にわかりやすいようにするとよいでしょう。

リスト5.5 if文のネスティング

if (A) {
  if (B) {
    /* Aが真,かつBが真の場合に実行される */
  } else {
    /* Aが真,かつBが偽の場合に実行される */
  }
} else {
  if (C) {
    /* Aが偽,かつCが真の場合に実行される */
  } else {
    /* Aが偽,かつCが偽の場合に実行される */
  }
}

ネスティング時のelseの注意

複数のif文がネスティングしている場合,elseの使用には注意が必要です。elseは文法上,直前のifにかかることになっているため,場合によってはelseが意図しないifと結び付いてしまうことがあります。

たとえば,リスト5.6のelseは,最初のif(A)に対応するものとして書いたつもりです。

リスト5.6 if(A)~elseのつもり

if (A)
  if (B) {
    /* Aが真,かつBが真の場合に実行される */
  }
else {
    /* Aが偽の場合に実行されるつもり */
}

しかしこのelseは,リスト5.7のように,if(B)に対するelseと解釈され,結果的にプログラムの動作は意図したとおりにはなりません。

リスト5.7 実際にはこう解釈される

if (A) {
  if (B) {
    /* Aが真,かつBが真の場合に実行される */
  } else {
    /* Aが真,かつBが偽の場合に実行される */
  }
}

この問題の原因は,if(A)の直後の{ }を省略してif(B)を続けてしまったことにあります。正しくはリスト5.8のように{ }を省略しないで書くことです。このように記述すれば,elseはif(A)に対するelseと解釈されるようになります。

リスト5.8 elseの対応のために{ }を省略しないで書く

if (A) {
  if (B) {
    /* Aが真,かつBが真の場合に実行される */
  }
} else {
    /* Aが偽の場合に実行される */
}

else if による複数の場合分け

たとえば,変数iの値が1だった場合,2だった場合,3だった場合…でそれぞれ別の処理をしたい場合は,リスト5.9のように else if を使って必要なだけそれぞれの条件を記述します。最後のelseのあとは,変数iの値が1でも2でも3でもない場合,となります。

リスト5.9 else_if.c

#include <stdio.h>

int
main()
{
  int i;

  /* i = 1; */
  i = 2;
  /* i = 3; */
  /* i = 4; */

  if (i == 1) {
      printf("i == 1\n");
  } else if (i == 2) {
      printf("i == 2\n");
  } else if (i == 3) {
      printf("i == 3\n");
  } else {
      printf("i != 1 && i != 2 && i != 3\n");
  }

  return 0;
}

図5.3 else_if(リスト5.9)の実行例

$ gcc -O2 -o else_if else_if.c
$ ./else_if
i == 2
$

なお,C言語の文法上に「else if」という制御文があるわけではありません「else if」と記述すると,文法上はあくまでelseに続いて別のif文がネスティングされているものと解釈されます。したがって,前述のelse_if.c(リスト5.9)をネスティングどおりにインデントすると,リスト5.10のようになります。

リスト5.10 else_if_nest.c

#include <stdio.h>

int
main()
{
  int i;

  /* i = 1; */
  i = 2;
  /* i = 3; */
  /* i = 4; */

  if (i == 1) {
      printf("i == 1\n");
  } else {
    if (i == 2) {
        printf("i == 2\n");
    } else {
      if (i == 3) {
          printf("i == 3\n");
      } else {
          printf("i != 1 && i != 2 && i != 3\n");
      }
    }
  }

  return 0;
}

しかし,これでは繁雑でわかりにくいため,elseのあとにif文が1つのみ続く場合はリスト5.9(else_if.c)のように「else if」と記述するのです。この場合,elseのあとの{ }は省略していることになります。これは,{ }を省略した方がよいという例外のひとつと言えます。

著者プロフィール

山森丈範(やまもりたけのり)

「C言語はアセンブラを触っているうちに自然に覚えてしまった」というプログラマ。C言語とのかかわり上,OSは専らUNIXを使用。C言語のプログラムでは,いつもLinux/FreeBSD/Solarisすべてで動くことを気に留めている。C言語と同様に移植性の高いシェルスクリプトにも思い入れが深く,著書に『シェルスクリプト基本リファレンス』がある。

著書

コメント

コメントの記入