第5回
制御構造と変数(1) if~条件判断と分岐の基本

論理演算子による複合条件の判定

ifでは常に1つの条件しか判定できません。複雑な条件を調べるには、2つの条件式を1つにまとめる必要があります。

ifで2つの条件を調べる

ここまでの段階では、入力された値が0以上かどうかしか調べていません。1桁の整数に限定するには、さらに『9以下かどうか』も調べる必要があります。そこで、リスト3のように2段階の構造を作ってみました。

if (num >= 0)として変数numの値が0以上だったら、続けてif (num <= 9)として変数numの値が9以下であるか調べます。この式が真だったら、numの値は『0以上9以下』ということになるので、計算結果を表示します。

if (num <= 9)が偽だったら、numの値は「0以上ではあるけれど、さらに10以上である」ことになるので、「9以下の数字を入力してください」というメッセージを表示します。

if (num >= 0)が偽の場合はnumが0未満なので、「0以上の数字を入力してください」というメッセージを表示します。

このように、ifの中にifを重ねる入れ子構造が作れます。これによって、複雑な条件判定と分岐の構造が実現できます。

リスト3:入力された値が0~9でなければメッセージを表示するプログラム(標準的なCのソース)
#include <stdio.h>

int	main(void)
{
  int num;

  printf("Input number : ");
  scanf("%d", &num);

  if (num >= 0) { ------------ numの値が0以上のとき以下を実行
    if (num <= 9) { ---------- さらに9以下のときに以下を実行
      printf("%d * 10 = %d\n", num, num * 10);
      return (0);
    } else { ----------------- 9より大きければ以下を実行
      printf("9以下の数字を入力してください。\n");
      return (-1);
    }
  } else { ------------------- 0より小さければ以下を実行
    printf("0以上の数字を入力してください。\n");
    return (-1);
  }
}

2つの条件の関係を調べる

ifの入れ子は確かに複雑な条件を判定できますが、ソースが複雑になって読み取るのが難しくなります。ここで設定している『numの値が0以上9以下』のような条件は、2つの条件式
num >= 0 と num <= 9
とを連続して調べれば、ソースはもっと単純になります。2つの条件式を連続して調べるには、条件式を論理演算子で結びます。論理演算子は左辺と右辺に論理値(真または偽)を返す式を置き、それぞれの関係を判定して真または偽を返す演算子で、関係演算子とも呼ばれます。表2を参照してください。

これを用いれば、『numの値が0以上9以下』という条件は次のように記述できます。
if ((num >= 0) && (num <= 9))
       (a)           (b)

表2:論理演算子の種類と機能
演算子 機能
&& 左辺式と右辺式が共に真のとき真を返す~AND(論理積)
|| 左辺式と右辺式のどちらか一方(または両方)が真のとき真を返す~OR(論理和)
! 続く式の反対(式が真なら偽、偽なら真)を返す~NOT(否定)

ソースを書き直す

&&は論理積と呼ばれ、左辺式と右辺式の両方が真のとき、式全体が真となる演算子です。日本語では「~かつ~」と表現される関係です。||はどちらか一方または両方が真のときに真を、両方が偽の場合は偽を返します。日本語では「~または~」と表現される関係です。

!は上の2つとは違って1つの式(または値)の前に付けられ、その評価を否定(反転)します。式が真または偽の論理値を返す場合は、その反対(真なら偽、偽なら真)を返します。式が論理値でない場合は、その値以外のすべてが真となります。

先にTRUEという記号定数を定義するため、値が0のFALSEを否定する形で、以下のような記述を紹介しました。
#define TRUE !0
これは、先にFALSEを0と定義していれば、以下のようにしても同じです。
#define FALSE 0
#define TRUE !FALSE
上の式では条件式(a)と条件式(b)とを&&で結んでいるため、2つの式が共に真──numの値が0以上(a)でありなおかつnumの値が9以下である──場合に真となります。論理演算子を使って書き直すと、ソースはリスト4のようになります。

リスト4:論理演算子を使って条件式をシンプルにした(標準的なCのソース)
#include <stdio.h>

int	main(void)
{
  int num;

  printf("Input number : ");
  scanf("%d", &num);

  if ((num >= 0) && (num <= 9)) { ---- numが0~9なら以下を実行
    printf("%d * 10 = %d\n", num, num * 10);
    return (0);
  } else { ----------------- そうでなければ以下を実行
    printf("0~9までの数字を入力してください。\n");
    return (-1);
  }
}

あとがき


hiropの『ちょっと気になる専門用語』~《式》

今回紹介したifでは、変数の値がある値より大きいか、または小さいかなどを調べるために『条件式』を用いました。

一般の感覚では、式とは
10 × 100
のような計算式や
10 × 100 = 1000
のように計算式とその答を等号(=)で結んだもの(計算の解答)を思い浮かべます。が、プログラミングでは、値を返す命令はすべて『式』と呼ばれます。従って、
getchar(c);
のような関数の呼び出しも式です。また、広義には値を返さない(void型の)関数の呼び出しも式と呼びます。

算術演算子を使った、
num * 100
のような記述はもちろん式ですが、今回紹介した比較演算子による値の比較も「真または偽」を返す式となります。さらに
10 * 100
のようにわざわざ計算しなくても結果が分かっている式も、結果が0以外なら真、結果が0なら偽──という形で判定される論理式です。

また、
ans = num * 100;
という具合に、計算式の結果を変数に代入する式の場合、代入後の変数の値が0以外なら真、0なら偽と判定される論理式になります。