C初級:if文で複数の条件を1度に判断する(論理積と論理和)

C言語初級カテゴリのロゴ画像C言語初級
スポンサーリンク

if文で数値の比較を行う方法は、10.数値の比較を行う(比較演算子)で述べました。

基本は

if( a > 10 ){
/* 実行したい処理 */
}

でいいのですが、プログラムを作っていくと複数の条件を1度に判断したいときが必ずやってきます。(たぶん)

例えば数値の範囲を判定したい場合です。

例)0~100までの数値ならOKで、それ以外はNG

こうした判定をC言語に直す場合は、要素を一つ一つ分割して考えます。
考え方としては、こんな感じです。

1.条件を「0以上」と「100以下」に分ける
2.「0以上」でなおかつ「100以下」ならOK
3.2の条件以外はNG

面倒くさいですよね!でもこれがコンピュータに与える命令の順番(すなわちプログラム)です。

これをそのままC言語プログラムで表現してみます。

サンプルプログラム hantei.c

/* hantei.c */
#include <stdio.h>
int main(void){
    int n;
    
    printf("0~100までの数値をいれてね ");
    scanf("%d", &n);
    
    if(n >= 0){
        if(n <= 100){
            printf("OK\n");
        }
    }
    else{
        printf("NG\n");
    }
    
    return 0;
}

解説
2つの条件「0以上」と「100以下」は、それぞれ n >= 0 と n <= 100 と表現できます。 このどちらの条件も成り立つというプログラムを作りたい場合、最初にどちらかの条件をif文で記述して、そのif文の処理の中にもう一つの判定を入れる方法を使って表現しています。 考え方としては、

n <= 0 が成り立つ場合、次の n <= 100 を判定する。 n <= 100 も成り立つ場合、OKと表示する。 それ以外(elseの部分)はNGと表示する。

といった感じです。

if文の中にif文がある状態です。C言語では{}(中かっこ)を使って処理のまとまりを表現していますが、この中かっこの中にさらに中かっこがある状態を入れ子状態と呼んでいます。
入れ子状態はいくつでも作ることができます。

例)

{
 {
  {

  }
 }
}

いくつでも作ることが出来ますが、あまりに深い階層にしてしまうとプログラムが見にくくなるだけでなく、ミスの原因にもなりますのでせいぜい2つくらいまでがよろしいかと思います。(経験上)入れ子が3つ以上になったら、プログラムのセンスないわ、とでも思ってください。

というわけで入れ子状態のif文を出来るだけスマートに表現したい場合は、論理積(ろんりせき)や論理和(ろんりわ)という表現を使います。

論理積A && BA と B のどちらも成り立つ場合
論理和A || BA と B のどちらか一方が成り立つ場合

上記の論理積を使うと先ほどのプログラムは以下のように記述できます。

サンプルプログラム ronriseki.c

/* ronriseki.c */
#include <stdio.h>
int main(void){
    int n;
    
    printf("0~100までの数値をいれてね ");
    scanf("%d", &n);
    
    if(n >= 0 && n <= 100){
        printf("OK\n");
    }
    else{
        printf("NG\n");
    }
    
    return 0;
}

だいぶスッキリとしたのではないでしょうか。
条件と条件を&&でつなぐだけです。

ちなみに条件はいくつでも追加できます。

例)aが1 かつ bが2 かつ cが3 の全てが成り立つ場合の判定

if( a == 1 && b == 2 && c == 3 )

これもあまり増やし過ぎるとプログラムが見にくくなりますが、使いようによっては見やすく分かりやすいプログラムが記述できます。

次は論理和を説明します。

サンプルプログラム 13if.c

/* 13if.c 判定をする(AまたはB...どちらか一方が成り立つとき) */
#include <stdio.h>
int main(void)
{
	int month;
	
	printf("何月生まれ? ");
	scanf("%d", &month);

	if(month < 1 || month > 12){			/* 1より少ない、または12より大きいとき */
		printf("そんな月ないでしょ!\n");
	}
	else{								/* それ以外 */
		printf("あっ!わたしと同じだ。\n");
	}
	
	return 0;
}

解説
生まれた月を入力させてメッセージを表示するプログラムです。
if文の条件では、月として存在しない数値(1未満または12をこえる数値)が入力されたときの判定をおこなっています。
したがって1から12までの月が入力された場合はelseの処理に移ります。

このように論理和の使い道としては、数値が範囲外である場合を判定させたいときなどに使うことができます。
論理積が記述した条件全てを満たさないと判定されないのに対して、論理和は、どれか一つの条件が合えば、といった使い方ができます。

例えば年齢が0歳または100歳の人だけが対象といった場合、

if( age == 0 || age == 100 )

といった記述ができます。

実は、先ほどの1月から12月までの範囲を指定するような判定の場合は、論理積と論理和のどちらでも記述できます。
論理和で記述されたプログラムを論理積に直してみました。

サンプルプログラム 12if.c

/* 12if.c 判定をする(AかつB...どちらも成り立つとき) */
#include <stdio.h>
int main(void)
{
	int month;
	
	printf("何月生まれ? ");
	scanf("%d", &month);

	if(month >= 1 && month <= 12){		/* 1月~12月のとき */
		printf("あっ!わたしと同じだ。\n");
	}
	else{								/* 1月~12月以外のとき */
		printf("そんな月ないでしょ!\n");
	}
	
	return 0;
}

if文の処理とelse文で行うprintf関数のメッセージ内容が入れ替わっていることに気づきましたか?
論理積で1以上かつ12以下を判定した場合、それ以外(else側)では、自然と1未満または12をこえるという判定になっている、ということです。

ですから12if.cと13if.cは同じ内容のプログラムです。
プログラマが自分で分かりやすい方を選択すればいいことになります。

論理積を2つ使って時分の判定を行うプログラムを作ってみました。

サンプルプログラム 14if.c

/*14if.c 判定をする(判定の入れ子:判定の中で判定をおこなう) */
#include <stdio.h>
int main(void)
{
	int hour, minute;
	
	printf("今朝の起床時間を教えて下さい\n");
	printf("何時? (0-12) ");
	scanf("%d", &hour);
	
	if(hour >= 0 && hour <= 12){
		printf("何分? (0-59) ");		/* hourが0~12の間のときだけ何分かを聞いてくる */
		scanf("%d", &minute);
		
		if(minute >=0 && minute <= 59){
			printf("%d時%d分ですか。", hour, minute);
			printf("アリバイはありますか?\n");
		}
		else{
			printf("時間は0~59で入力して下さいね\n");
		}
	}
	else{
		printf("時間は0~12で入力して下さいね\n");
	}

	return 0;
}

解説
最初のif文で入力された時間がが正しいか(0~12の範囲かどうか)を判定しています。
正しければ、さらに分を入力させて正しいか(0~59の範囲かどうか)を判定しています。
したがって、いずれのelse文も間違った値が入力された場合の処理となります。

論理積と論理和は他のプログラミング言語でも当然存在します。
記述方法もほぼC言語と同じですので、積極的に使ってみてください。

コメント