C言語編 第11章 処理の流れを分岐させる

先頭へ戻る

このエントリーをはてなブックマークに追加

この章の概要

この章の概要です。

分岐構造

これまでのプログラムは、main関数から始まり、順番に下の方へ流れていき、main関数の終了とともに終わるという一直線のものばかりでした。 これは最も基本的な処理構造であり、順次構造と呼ばれることがあります。

順次構造に対して、処理を途中で2方向以上に切り分ける構造を、分岐構造あるいは選択構造と呼びます。 C言語で、分岐構造を作るためには if というキーワードを使います(他の方法もあります)。

最小の if文

最も小さい if文の構造は次のようになります。

if( 条件式 )
	条件を満たす場合に実行する処理;

「条件式」は、例えば「変数num の値が 10 より大きいとき」とか「変数num1 と変数num2 の値が同じとき」といったようなものです。 もちろん日本語で書くことはできないので、C言語では次のように関係演算子を使います。

関係演算子 意味
< 左辺が右辺より小さい
> 左辺が右辺より大きい
<= 左辺が右辺以下
>= 左辺が右辺以上
== 左辺と右辺が同じ
!= 左辺と右辺が同じでない

「左辺と右辺が同じ」ときに、イコール記号を2つつなげて書くことに注意して下さい。 イコール記号1つだけでは代入の意味になってしまいます。 また、「以上・以下」という言葉には「イコール」が含まれていることにも注意して下さい。 なお、文字列の一致を調べる場合には特別の方法が必要です。これは後で説明します

最小の if文の形式では、条件式を満たしたときにだけ、その直後の文を実行します。 条件式が満たされなければ、直後の文は無視して、その先へ進みます。 なお、「if( 条件式 )」の行末にセミコロンは付かないことに注意して下さい。

では、実際に if文を使ったプログラムを見てみましょう。

#include <stdio.h>

int main(void)
{
	char str[40];
	int num;
	
	puts( "整数を入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%d", &num );

	if( num >= 100 )
		printf( "100以上\n" );	/* 変数num が 100以上であれば、ここが実行される */

	puts( "終了します。" );		/* ここは常に実行される */

	return 0;
}

実行結果:

整数を入力して下さい。
100
100以上
終了します。

2回実行して、100以上の値と、100未満の値とを入力して動作を確認してみてください。

ここで、「if( num >= 100 )」という条件の反対を考えてみましょう。 「num の値が 100以上」の反対なので「num の値が 100以下」と考えがちですが、違います。正しくは「num の値が 100未満」です。 先ほど書いたように「以上・以下」には「イコール」が含まれていますから、 「以上」は「未満」に、「以下」は「より大きい」に置き換えないと、反対の意味にはなりません。

複数の文を実行させたいとき

最小の if文の形式では、条件を満たしたときに実行できる文は1つだけです。 2つ以上の文を実行させる場合には、次の形式を取ります。

if( 条件式 ){
	条件を満たす場合に実行する処理1;
	条件を満たす場合に実行する処理2;
	 :
}

このように { と } を使って、複数の文を囲むと、この部分はブロック(複合文)になります。 { と } の内側は、字下げ(インデント)を行って、読みやすくするのが一般的です。

{ を行末に書く人や、{ だけで1行使って書く人がいますが、意味はまったく同じです。 こういうのは、その人のスタイルの問題であり、双方の利点・欠点を議論しても大抵徒労に終わります。

ブロックは、複数の文をまとめた一塊になりますが、中身が1つの文だけでも良く、それどころか中身が空でも問題はありません。 そのため、先ほどの最小の if文の形式をやめて、常に { と } を使う形式で書いて構いません。 最小の if文の形式は、後から新たな文を追加しようとすると問題になりやすく、バグの原因にもなりやすいものです。 { と } を書かない方が簡単に書けるという考え方もありますが、安全な方法を優先して採用すべきなのは明らかです。 とはいえ、{ と } を書かない人が多いのも事実なので、他人のプログラムを読むためにも、{ と } が省略されている場合があることは知っておく必要があります。

先ほどのサンプルプログラムを、{ と } を使って書きなおすと、次のようになります。

#include <stdio.h>

int main(void)
{
	char str[40];
	int num;
	
	puts( "整数を入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%d", &num );

	if( num >= 100 ){
		puts( "100以上" );	/* 変数num が 100以上であれば、ここが実行される */
	}

	puts( "終了します。" );		/* ここは常に実行される */

	return 0;
}

実行結果:

整数を入力して下さい。
100
100以上
終了します。

条件を満たさないとき

条件を満たさないときにのみ行う処理も記述できます。 この場合、次の形式を取ります。

if( 条件式 ){
	条件を満たす場合に実行する処理;
}
else{
	条件を満たさない場合に実行する処理;
}

新たに else というキーワードを導入し、この直後に、条件を満たさない場合の処理を記述します。 先ほどと同様、{ と } は中身が1文だけならば省略できますが、やはり省略すべきではありません。

これまでのサンプルプログラムを改造して、100未満のときには「100未満」と表示されるようにしてみます。

#include <stdio.h>

int main(void)
{
	char str[40];
	int num;
	
	puts( "整数を入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%d", &num );

	if( num >= 100 ){
		puts( "100以上" );	/* 変数num が 100以上であれば、ここが実行される */
	}
	else{
		puts( "100未満" );	/* 変数num が 100以上でなければ、ここが実行される */
	}

	puts( "終了します。" );		/* ここは常に実行される */

	return 0;
}

実行結果:

整数を入力して下さい。
99
100未満
終了します。

先へ進む前に少し脱線して…。 このサンプルプログラムでは、100 という数値が何度か登場します。 こういう同じ意味の同じ値は、1か所にまとめましょう。

#include <stdio.h>

int main(void)
{
	char str[40];
	int num;
	int base = 100;		/* 基準値 */

	puts( "整数を入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%d", &num );

	if( num >= base ){
		printf( "%d以上\n", base );	/* 変数num が基準値以上であれば、ここが実行される */
	}
	else{
		printf( "%d未満\n", base );	/* 変数num が基準値以上でなければ、ここが実行される */
	}

	puts( "終了します。" );		/* ここは常に実行される */

	return 0;
}

実行結果:

整数を入力して下さい。
99
100未満
終了します。

こうすると、基準となる 100 を別の値に変えることが非常に簡単になりますね。

ここでは、変数base を使っていますが、本当は #define(第24章)や、 enum(第50章)を使うのが一般的でしょう。 しかし、変数を使う方法でも、十分な効果があります。

if文のネスト

「条件を満たす場合の処理」あるいは「条件を満たさない場合の処理」に、更に if文を書くこともできます。 この場合、if文の中に if文があるような形であり、こういう入れ子になった構造をネストといいます。 例えば、次のように書きます。

#include <stdio.h>

int main(void)
{
	char str[40];
	int num;
	
	puts( "整数を入力して下さい。" );
	fgets( str, sizeof(str), stdin );
	sscanf( str, "%d", &num );

	if( num >= 0 ){
		if( num % 2 == 0 ){
			puts( "正の偶数です。" );
		}
		else{
			puts( "正の奇数です。" );
		}
	}
	else{
		puts( "負の値は対象外です。" );
	}

	return 0;
}

実行結果:

整数を入力して下さい。
77
正の奇数です。

入力された値が正の値なら、更に偶数と奇数に応じて分岐しています。 このような構造が理解できるようになると、出来ることの幅が広がりそうですね。

せっかくなので、偶数と奇数の判定方法も理解しておきましょう。 2 で割った余りを調べれば、偶数と奇数を判定できます。余りがなければ偶数です

文字列の比較

文字列が一致しているかどうか調べる場合、普通に == を使うことはできません。 なぜ出来ないのかを現時点で説明することは困難なのでやめておきますが、とにかくできません。 できないといいながら、実際に次のようなプログラムを書くことは出来てしまいます。

#include <stdio.h>

int main(void)
{
	char str[6] = "Hello";

	if( str == "Hello" ){
		puts( "一致しています。" );
	}
	else{
		puts( "一致していません。" );
	}

	return 0;
}

実行結果:

一致していません。

こういう書き方はできるのですが、実行結果を見ればわかるように、一致していないと判定されてしまいます。 文字列を比較するための正しい方法は、専用の標準ライブラリ関数を使うことです。

#include <stdio.h>
#include <string.h>

int main(void)
{
	char str[6] = "Hello";

	if( strcmp( str, "Hello" ) == 0 ){
		puts( "一致しています。" );
	}
	else{
		puts( "一致していません。" );
	}

	return 0;
}

実行結果:

一致しています。

strcmp関数は、引数に2つの文字列を渡し、それらを比較します。 2つの文字列が一致していれば 0 を返し、1つ目の方が小さければ負数を、1つ目の方が大きければ 0 より大きい値を返します。 ここで「小さい・大きい」というのは、辞書順で早く登場する文字が小さいという意味合いになります。 なお、strcmp関数を使うには、「#include <string.h>」という新たな行が必要になります

strcmp関数を使って比較を行えば、一致判定を正しく行えます。 一致しているかどうかを調べるなら「== 0」のように比較する必要があることに注意して下さい。 これは、strcmp関数の戻り値が 0 かどうかを調べている訳です。


練習問題

問題@ 標準入力から整数を受け取り、その数が3の倍数かどうか判定するプログラムを作成して下さい。

問題A 標準入力から2つの整数を受け取り、除算を行うプログラムを作成して下さい。 割る数として 0 が入力されたとき、実行時エラーを避け、結果を 0 とするようにして下さい。

問題B 2つの int型の引数を持ち、大きい方の値を返すような関数を作成して下さい。 同様に、小さい方の値を返すような関数も作成して下さい。


解答ページはこちら

参考リンク

更新履歴

'2015/8/22 リンク先が間違っていたので修正。

'2009/3/17 「この章の概要」を追加。

'2009/2/28 新規作成。



前の章へ

次の章へ

C言語編のトップページへ

Programming Place Plus のトップページへ