if 文・関係/論理演算子

if 文・関係/論理演算子

条件によって処理を分岐させる if 文と、条件を判断するための式について。
サイト全体の目次

稿


稿

if 文・関係/論理演算子

このセクションのソース

/*01*/ #include <stdio.h>
/*02*/ 
/*03*/ main()
/*04*/ {
/*05*/   int x1;
/*06*/   int x2;
/*07*/ 
/*08*/   printf("2数の大小を比べます。\n");
/*09*/   printf("整数を入力してください\n");
/*10*/   printf("数1 -> ");    scanf("%d", &x1);
/*11*/   printf("数2 -> ");    scanf("%d", &x2);
/*12*/ 
/*13*/   if(x1 == x2)
/*14*/     printf("2数は同じ値で:す。\n");
/*15*/   else if(x1 > x2)
/*16*/     printf("数1 の方が大きいです。\n");
/*17*/   else
/*18*/     printf("数2 の方が大きいです。\n");
/*19*/ 
/*20*/   return 0;
/*21*/ }

list-2.1.1-13

if 文は「もし~ならば・・・せよ。」というふうに処理の流れを制御する制御文です。書式は

if(条件式) 実行文;

の形で、 (*1) 「条件式」が「~」の部分、「実行文」が「・・・」の部分に相当し、条件が満たされていれば実行文が実行させる仕組みです。基本的に実行文は一つしか書くことができません。もし複数の実行文を書きたい場合は次のようにブロックを使用します。
if(x1 == x2){
	printf("2数は同じ値です。\n");
	printf("2数の合計は %d です。\n", x1 + x2);
}else if(x1 > x2){
	printf("数1 の方が大きいです。\n");
	printf("2数の合計は %d です。\n", x1 + x2);
}else{
	printf("数2 の方が大きいです。\n");
	printf("2数の合計は %d です。\n", x1 + x2);
}

C言語はフリーフォーマットですので、list-2.1.1 のように実行文を次の行に書いてもかまいません。

list-2.1.1-15

else 文は if 文とセットで使います。「もし~ならば・・・せよ。そうでなければXXXせよ。」という制御で、「そうでなければXXXせよ。」の部分が else 文に相当します。書式は

if(条件式) 実行文;
else 実行文;

です。

この行の「else if」は制御文と言うわけではなく、else の実行文が if 文になっているにすぎません。しかし、このようにすることで「もし~ならば・・・せよ。そうでなくてOOOならばXXXせよ」という処理を行うことができます。この例では意味的な視点から上述のように書きましたが、文法的な視点から書けば

if(x1 == x2)
	printf("2数は同じ値で:す。\n");
else
	if(x1 > x2)
		printf("数1 の方が大きいです。\n");
	else
		printf("数2 の方が大きいです。\n");

のようになります。実際にプログラミングする際は意味的な視点から見た、list-2.1.1 のような記述がほとんどです。また、この例からお気づきかもしれませんが if 文の中に if 文を入れる(ネスとさせる)こともできます。
if(x1 == x2){
    printf("2数は同じ値です。\n");
    if(x1 > 100){
        printf("また、2数は100より大きいです。");
    }
}

list-2.1.1-13

if 文の条件式には「ゼロ」または「非ゼロ」の値を記述し、「ゼロ」の状態を偽(false)と言い、「非ゼロ」の状態を真(true)と言い、両方あわせて真偽値と言います。if の条件式が 真(true) なら実行文が実行され、条件式が 偽(false) なら実行文は実行されず、else があればそちらへ処理が移ります。

if(0) 実行文; /* 実行文は常に実行されない */
if(1) 実行文; /* 実行文は常に実行される */

なお、C99ではゼロの代わりに「false」、非ゼロの代わりに「true」と記述することができます。

しかし条件式に数値を直接書いていたのでは if の意味がありません。そこで下表のような、二つの値を比較し、その結果を真偽値(ゼロ or 非ゼロ)で返す演算子があります。

等値演算子
x == yx と y が等しい。「=」がひとつでないことに注意。
x != yx と y が等しくない。「=!」ではダメ。
関係演算子
x < yx が y より小さい。
x <= yx が y 以下。「=<」ではダメ。
x >= yx が y 以上。「=>」ではダメ。
x > yx が y より大きい。

たとえば、「x == y」では x と y の値が等しければ true となり、非ゼロに置き換わります。なお、等値演算子と関係演算子をあわせて関係演算子ということがあります。

等値・関係演算子と一緒に良く使われるのが下表の論理演算子です。

論理演算子
真偽値1 || 真偽値2「真偽値1」または「真偽値2」の少なくとも一方が true のとき true
真偽値1 && 真偽値2「真偽値1」と「真偽値2」の両方が true のとき true

等値・関係演算子、論理演算子の使用例を.に示すので、参考にしてください。また、これらの演算子は「 ( )」で優先順位を決めてやれば複数組み合わせることができます。

/*** パターン1 ***/
if(0){
    /* 絶対に実行されない */
}

/*** パターン2 ***/
if(1){
    /* 必ず実行される */
}

/*** パターン3 ***/
if(-3){
    /* 必ず実行される */
}

/*** パターン4 ***/
x = 0;
if(x){    /* if(0) と同じ */
    /* 実行されない
}

/*** パターン5 ***/
x = 1;
if(x){    /* if(1) と同じ */
    /* 実行される */
}

/*** パターン6 ***/
x = 1; y = 2;
if(x > y){    /* 条件を満たしていないので if(0) と同じ */
    /* 実行されない */
}

/*** パターン7 ***/
x = 2; y = 1;
if(x > y){    /* 条件を満たしているので if(1) と同じ */
    /* 実行される */
}

/*** パターン8 ***/
if(x1 == x2){    /* x1 と x2 が等しい時に真 */
    printf("2数は同じ値です。\n");
}

/*** パターン9 ***/
if(x1 == x2 || x1 < x2){    /* x1 と x2 が等しいか x1 のほうが小さいときに真 */
    printf("x1 は x2 と同じか、小さいです。\n");
}
	

コラム

演算子の優先順位

今までにいろいろな演算子が出てきましたが、ひとつの式にいくつもの演算子が使われている場合はどうなるのでしょう。これらの演算子にはどう順序でこれらのを評価していくか、演算順位が決まっています。ちょうど、数学で「+」や「-」よりも、「*(乗算)」「/(除算)」の方が優先順位が高いのと同じですね。今までに出てきていないものも含めて、これらの優先順位をまとめておくので参考にして下さい。

() [] -> .
! ~ ++ -- * & (type) sizeof (「*」は間接演算子)
* / %
+ -
<< >>
< <= >= >
== !=
& (「&」はビットごとの論理演算子)
^
|
&&
||
? :
= += -= *= /= %= &= ^= |= <<= >>=
,

上のほうが優先順位が高く、同じ行のものは同レベル順位。同レベル順位の場合、一般には結合規則に従って「左から右」
へ順に評価されます。ただし、上から2行目と下から2,3行目の結合規則は「右から左」です。結合規則については「左から右」、「右から左」などと書いてありますが、普通は「左から順に計算されていく」と思っていれば問題ありません。あやふやな場合や明確に書きたいときは「( )」でくくってしまいましょう。

練習問題

問題-2.1.1

生まれた年(西暦)を入力すると、その年の干支が出るようにしてください。
参考1:
2000年はたつ年です。
参考2:
(十二支の順)ねずみ / うし / とら / うさぎ / たつ / へび / うま / ひつじ / さる / とり / いぬ / いのしし

問題-2.1.2

二つの float 型で割る数と割られる数を入力すると、その計算結果を出す割り算プログラムを作ってください。ただし、割り算には「0 で割ることはできない」という制約があります。そこで、割る数として 0 が入力された時は「0 で割ってはいけません」というメッセージを表示するようにしてください。また、この問題では比較演算子を使ってはいけません。

問題-2.1.3

キーボードから 3 つの整数を入力し、これを小さい順に並べ替えて表示させてください。

練習問題回答例

問題-2.1.1

#include <stdio.h>

main()
{
	int year;

	printf("今年は何年ですか? -> ");
	scanf("%d", &year);

	/* 入力された年を12で割った余りを使い、干支を判別します。 */
	year = year % 12;

	/* 2000 割る 12 の余りが 8 であることから、余りが 8 の
	年は たつ 年と分かります。 */
	if(year == 8){
		printf("あなたは たつ 年生まれです。\n");
	}else if(year == 9){
		printf("あなたは へび 年生まれです。\n");
	}else if(year == 10){
		printf("あなたは うま 年生まれです。\n");
	}else if(year == 11){
		printf("あなたは ひつじ 年生まれです。\n");
	}else if(year == 0){
		printf("あなたは さる 年生まれです。\n");
	}else if(year == 1){
		printf("あなたは とり 年生まれです。\n");
	}else if(year == 2){
		printf("あなたは いぬ 年生まれです。\n");
	}else if(year == 3){
		printf("あなたは いのしし 年生まれです。\n");
	}else if(year == 4){
		printf("あなたは ねずみ 年生まれです。\n");
	}else if(year == 5){
		printf("あなたは うし 年生まれです。\n");
	}else if(year == 6){
		printf("あなたは とら 年生まれです。\n");
	}else{
		printf("あなたは うさぎ 年生まれです。\n");
	}

	return 0;
}

問題-2.1.2

if 文の条件式が非ゼロならば実行されることを利用します。

#include <stdio.h>

main()
{
	float a, b, y;
	printf("[割られる数] [割る数]:");
	scanf("%f%f", &a, &b);

	/* b が非ゼロなら計算する */
	if(b){
		y = a / b;
		printf("答えは %.2f です。\n", y);
	}else{
		printf("割る数は 0 であってはいけません。\n");
	}

	return 0;
}

問題-2.1.3

データの個数が 3 個しかないことに着目して全てのパターンを調べる強引な手法

#include <stdio.h>

main()
{	
	int x1, x2, x3;	/* 読み込んだ値を入れる */
	int y1, y2, y3;	/* 小さい順に入れる */

	printf("三つの整数を入力してください -> ");
	scanf("%d%d%d", &x1, &x2, &x3);

	/* セット1
	x1 がもっとも小さいときの処理 */
	if(x1 <= x2 && x1 <= x3){
		y1 = x1;
		if(x2 <= x3){	/* さらに x2 と x3 を比較 */
			y2 = x2;
			y3 = x3;
		}else{
			y2 = x3;
			y3 = x2;
		}
	}

	/* セット2
	x2 がもっとも小さいときの処理 */
	if(x2 <= x1 && x2 <= x3){
		y1 = x2;
		if(x1 <= x3){	/* さらに x1 と x3 を比較 */
			y2 = x1;
			y3 = x3;
		}else{
			y2 = x3;
			y3 = x1;
		}
	}

	/* セット3
	x3 がもっとも小さいときの処理 */
	if(x3 <= x1 && x3 <= x2){
		y1 = x3;
		if(x1 <= x2){	/* さらに x1 と x2 を比較 */
			y2 = x1;
			y3 = x2;
		}else{
			y2 = x2;
			y3 = x1;
		}
	}
	/* 以上の比較で「<」とせずに「<=」としたのは、値が同じ場合にその二つを
	入れ替えても同じこと、という理屈のため。逆に「<」としてしまった場合、
	値が同じ場合の処理も加えなければいけない。そうでないと例えば値が
	「x1 = 1」「x2 = 1」「x3 = 2」の時、
	(x1 < x2 && x1 < x3)
	(x2 < x1 && x2 < x3)
	(x3 < x1 && x3 < x2)
	のいずれにも当てはまらなくなってしまう */

	printf("小さい順に並べ替えました -> %d %d %d\n", y1, y2, y3);

	return 0;
}

並んだデータを最初から順に見ていき、隣同士を比較して逆順なら入れ替える手法(バブルソートという)。

#include <stdio.h>

main()
{
	int x1, x2, x3, tmp;

	printf("三つの整数を入力してください -> ");
	scanf("%d%d%d", &x1, &x2, &x3);

	/* 1 サイクル目 */
	if(x1 > x2){	/* 最初の二つを比較 */
		tmp = x1;	/* 二つの値を入れ替えるとき、片方の値を */
		x1 = x2;	/* tmp に退避させておかねばならない */
		x2 = tmp;
	}

	if(x2 > x3){
		tmp = x2;
		x2 = x3;
		x3 = tmp;
	}
	/* ここまでが 1 サイクル目。この時点で並びの最後には
	もっとも大きな値が入っているはず */

	/* 2 サイクル目 */
	if(x1 > x2){
		tmp = x1;
		x1 = x2;
		x2 = tmp;
	}
	/* ここまでが 2 サイクル目 */

	printf("小さい順に並べ替えました -> %d %d %d\n", x1, x2, x3);

	return 0;
}

補足:バブルソートの例

3 5 1 2 4 という並びがあったとする。[]で示された二つの値を比較

1 サイクル目
	[3] [5] 1 2 4 → 3 5 1 2 4
	3 [5] [1] 2 4 → 3 1 5 2 4
	3 1 [5] [2] 4 → 3 1 2 5 4
	3 1 2 [5] [4] → 3 1 2 4 5
この時点で並びの最後は最も大きな値になっている

2 サイクル目
	[3] [1] 2 4 5 → 1 3 2 4 5
	1 [3] [2] 4 5 → 1 2 3 4 5
この例では 2 サイクル目で並び終わったが、あとは
これの繰り返しである


読み込み中・・・
10秒待っても表示が変わらない場合、次の理由が考えられます。
・Javascript が無効になっています。
・検索エンジンのキャッシュを見ています。
サイトホームへ / 上位ページへ / ページトップへ / PAROFトレンドショッピングへ
Copyright (C) 2010 totobon all right reserved.