分岐処理

順次処理

変数やSystem.out.println()を用いれば、ある程度基本的な計算や画面への出漁が出来ます。しかし、プログラムとしてはいまひとつ物足りないというのも事実です。これまでやってきた処理は、プログラム中に記述された様々な処理を、その順番とおり実行するだけのものでした。こういった処理を、順次処理(じゅんじしょり)と言います。(図3-1)

分岐処理

しかし、プログラムは、順次処理だけでは出来上がりません。様々な状況に応じて、違った処理を行わなくてはなりません。例えばゲームプログラムを作っているとしたら「もし、敵に当たったらゲームオーバー」など といったような、条件に応じた処理の分岐が必要になります。こういったように、ある条件で処理の流れが変わる処理を、分岐処理(ぶんきしょり)と言います。(図3-2)

図3-1:順次処理図3-2:分岐処理
Java言語順次処理のフローチャートC言語分岐処理のフローチャート
処理が順次実行される条件によって、処理の流れが変わる

Javaでは、分岐処理を記述するための命令として、if(イフ)と、switch(スイッチ)という命令が用意されています。ここでは、それらについて解説します。

if文

サンプルプログラム

では、まず手始めに条件分岐の最も基本的な処理である、if文について学んでいくことにしましょう。ifとは、英語で、「もしも」という意味を表す単語で、「もしも~だったら、…する」といった処理を 行うために用います。まずは、以下のプログラムを実行してみてください。

Sample301.java
package day3;

public class Sample301 {

	public static void main(String[] args) {
		//標準出力
		int a = 10;	//	整数値(いろいろ変えてみましょう)
		System.out.println("a="+a);
		//  入力した値が、正の数かどうかを調べる
	    if(a > 0){
	        System.out.println("aは正の数です。");  //  正の数だった場合に実行
	    }
	}

}

プログラムを実行すると、以下のようになります。

実行結果1.(aの値が正の値の場合)
a=10
aは正の数です。

すると、上のように「aは正の数です。」と表示されて、プログラムが終わります。続いて、このサンプルの7行目を、次のように変更してみましょう。

Sample301.javaの変更点(7行目)
int a = -5;

すると、実行結果は以下のようになります。

実行結果2.(aの値が負の値の場合)
a=-5

実際に、aの値を何度か正の数や負の数にして試して見ましょう。

if文

では、なぜこのようにaの値によって結果が異なるのでしょう?条件分岐で用いる、if文の書式について説明します。if文は、次のような書式になっています。

if文の書式
if(条件式){
    処理
}

()内に入る条件式は、boolean型の値trueおよびfalseを返す演算処理です。たとえば、a==5とすると、「aが5と等しいか」という条件の比較演算です。もしもこれが正しい(真)であれば、true、正しくない(偽)ならば、falseが得られます。 なお、比較演算子は、以下のようなものがあります。いずれも、条件が正しければtrueを、正しくなければfalseを返します。(表3-1)

表3-1:比較演算子
演算子 意味 使用例
> より大きい a > 0
>= 以上 a >= 0
< より小さい a > 0
<= 以下 a <= 0
== 等しい a == 0
!= 等しくない a != 0

そして、()内の条件式がtrueのとき、{}に囲まれた処理を実行するのが、if文です。Sample301.javaでは、a>0、つまりaが0よりも大きい時に条件が成立し、{}内のprintf()文が実行されるわけです。

以上より、このプログラムが、キーボードから入力された数値が正の整数のときは「入力した値は、正の数です。」と表示され、そうでない場合は何も表示されないのです。ただ、出来ることならば、正の数以外の値が入力された時にも何らかのメッセージを表示したいものです。そこで、次はそれをできる仕組みを紹介しましょう。(図3-3)

図3-3.Sample301.javaのフローチャート
Java言語でif文の条件分岐

if~else文

サンプルプログラム

まずは、以下のプログラムを実行してみてください。

Sample302.java
package day3;

public class Sample302 {

	public static void main(String[] args) {
		//標準出力
		int a = -5;	//	整数値(いろいろ変えてみましょう)
		System.out.println("a="+a);
		//  入力した値が、正の数かどうかを調べる
	    if(a > 0){
	        System.out.println("aは正の数です。");  //  正の数だった場合に実行
	    }else{
	    	System.out.println("aは正の数ではありません。");		//	正の数ではなかった場合
	    }
	}

}

このプログラムの実行結果は、aに正の整数を代入した場合は変わりません。しかし、負の数を入力した場合は、以下のような実行結果になります。

実行結果(0および負の数をaに代入した場合)
a=-5
aは正の数ではありません。

else

ここで出現した、if~else文は、以下のような書式になっています。

if~else文の書式
if(条件式){
    処理①
}else{
    処理②
}

if文の()内の条件式が満たされた時には、処理①が実行されるのは、if文単体の時と変わりません。しかし、それ以外の場合、つまり条件式が満たされなかった場合は、else(エルス)文以下の処理②が実行されます。 したがって、このプログラムは、aが正の整数ではない、つまり、0か、負の値であるのならば、「入力した値は、正の数ではありません。」と出力されるのです。

図3-4.Sample302.javaのフローチャート
Java言語if~else文の条件分岐

else if

サンプルプログラム

ifとelseを用いた場合、ある条件が成り立つ場合と、そうでない場合の処理が書けました。しかし、実際には、条件が複数から成る場合も多く存在します。そういう時はどのようにすればよいのでしょうか?その時に役に立つのが、else if(エルスイフ)です。まずは、以下のサンプルを実行してみましょう。

Sample303.java
package day3;

public class Sample303 {

	public static void main(String[] args) {
		//標準出力
		int num = 1;					//	整数値(いろいろ変えてみましょう)
	    if(num == 1){
	        System.out.println("one");    //  numが1だった場合の処理
	    }else if(num == 2){
	    	System.out.println("two");    //  numが2だった場合の処理
	    }else if(num == 3){
	    	System.out.println("three");  //  numが3だった場合の処理
	    }else{
	    	System.out.println("不適切な値です。"); //  それ以外の値が入力された場合の処理
	    }
	}

}

実行結果1(1から3の値がnumに代入された場合)
one

7行目のnumの値を、から、2,3に変更すると、表示される値は、それぞれ「two」、「three」と変化します。ただ、それ以外の値が代入されると以下のような結果になります。

実行結果2(それ以外の値がnumに代入された場合)
不適切な値です。

else if

ifとelseだけでは、一つの条件が成り立った時と、それ以外の場合の処理しか実行できませんが、以上の結果のように、else ifを用いれば、複数の条件の場合についての場合分けが可能です。else ifを含むif文の書式は以下の通りになっています。

if~else if~else文の書式
if(条件式①){
    処理①
}else if(条件式②){
    処理②
}else{
    処理③
}

条件式①が成り立てば処理①が、条件式②が成り立てば処理②が実行され、そのどちらの条件も成り立たなければ、処理③が実行されます。なお、else ifは、ifの後に何個でも追加することができます。なので、いくつでも条件を追加することが可能です。

そのため、Sample303.javaの処理の流れを記述すると、以下のようになるのです。(図3-5)

図3-5.Sample303.javaのフローチャート
Javaでのif~else if~else文の条件分岐

複雑なif文

サンプルプログラム

つぎは、これらの知識を組みあわせて、更に複雑なifの構文を作り上げてみましょう。まずは、以下のサンプルを実行してみてください。

Sample304.java
package day3;

public class Sample304 {

	public static void main(String[] args) {
		int dice = (int)(Math.random()*7)+1;	//	1から7までの乱数を発生させる
	    //  サイコロの目を入力
		System.out.println("さいころの目:"+dice);
	    //  値が、サイコロの目の範囲内かどうかを調べる
	    if(1 <= dice && dice <= 6){
	        //  さいころの目が、偶数か、奇数かで、処理を分ける。
	        if(dice == 2 || dice == 4 || dice == 6){
	            System.out.println("丁(チョウ)です。");  //  偶数ならば丁(チョウ)
	        }else{
	        	System.out.println("半(ハン)です。");   //  奇数ならば半(ハン)
	        }
	    }else{
	    	System.out.println("範囲外の数値です。");
	    }
	}
}

このプログラムの実行すると、1から7の数が適当に発せられ、は、大きく分けて3通りに分けられます。まず一つ目が、1から6の間の偶数、つまり、2,4,6といった値を入力した場合です。 以下のように、「丁(チョウ)です。」と表示され、プログラムは終了します。

実行結果1(2,4,6が入力された場合)
さいころの目:2
丁(チョウ)です。

次に、同じく1から6の間で、今度は、1,3,5といった奇数を入力すると、「半(ハン)です。」と表示され、プログラムは終了します。

実行結果2(1,3の,5が入力された場合)
さいころの目:5
半(ハン)です。

最後に、1から6以外の整数、つまりさいころの目に該当しないような7が出ると、「範囲外の数値です。」と表示されて、プログラムが終了します。

実行結果3(範囲外の数値が入力された場合)
さいころの目:7
範囲外の数値です。

乱数

複雑なif文について説明する前に、でたらめな数を出す乱数(らんすう)という概念について説明しましょう。

プログラムにおいては、6行目の処理が、乱数の発生処理です。まず、以下のように記述すると、0からn-1までの乱数を発せさえることができます。 0からn-1までの乱数を発生させる方法

(int)(Math.random()*n);

続いて、1からnまでの乱数を発生するためには、以下のようにします。

(int)(Math.random()*n)+1;

したがって、6行目では、1から7までの乱数を発生させます。この処理は、実行させるごとに1から7までの数をでたらめに出していく処理です。

ネスト

さて、このプログラムを見ると、if文の中に、更にif文が入っています。これを、if文のネストと言います。ネストは、if文に限ったことではなく、この後紹介する繰り返し処理など でもしばしば見られる書式です。「何かの処理の中に、さらに何かの処理が入っているのがネストである」と理解すると良いでしょう。

if文のネスト
if(条件式①){
    if(条件式②){
        …
    }
}

このように、if文はネストが可能ですが、二重、三重にネストをすることも可能です。ただ、あまりネストを多用すると、プログラムが複雑になり、わかりずらくなるので気をつけましょう。

論理演算子

また、次に注目したいのが、10行目および、12行目の、if文の中身です。ここでは、||や、&&が間に挟まって、複数の条件式が出ています。これらの記号は、論理演算子(ろんりえんざんし)と言い、 if文などで複数の条件を調べるときには欠かせないものです。なお、Java言語で用いられる論理演算子は、以下のとおりです(表3-2)。

表3-2:論理演算子
演算子 名称 意味 使用例 備考
& 論理積(ろんりせき) AND(アンド) a == 0 & b == 0 // aが0かつ、bが0ならば
&& a == 0 && b == 0 // aが0かつ、bが0ならば ショートカット
| 論理和(ろんりわ) OR(オア) a == 0 | a == 1 // aが0か1ならば
|| a == 0 || a == 1 // aが0か1ならば ショートカット
! 否定(ひてい) NOT(ノット) !(a == 0) // a==0でない場合、真となる

例えば、&もしくは&&は、AND(アンド)と言い、複数の条件がすべて成り立っているときに真となります。10行目の例で言うと、「変数diceの値が1以上であり、かつ6以下」ということになります。また、|または||は、OR(オア)と言い、複数の条件のうち、どれかが成り立っているときに真、ということになります。12行目の例で言うと、「変数diceが2か、4か、6であれば」ということになります。

また、1から6の範囲の数値で、2,4,6以外の値となると、必然的に残りは、1,3,5となり、これが、「半(はん)」となることから、else文での処理は、「半(ハン)です。」と表示することになります。これら一連の流れの流れを記述すると、以下のようになるのです。(図3-6)

図3-6.Sample304.javaのフローチャート
Java言語でif文のネストと、AND,ORが入ったサンプル

論理演算のショートカット

ところで、&と、&&、および|と||は、それぞれ論理積、および論理和を表すものですが、どう違うのでしょう?もう一度、表3-2.を見ると、&&よび||は、備考欄に「ショートカット」と書かれています。これはいったいどういうことでしょう?

通常、AND(論理積)は、左辺、および右辺のうちどちらかがfalseになれば、必ずその結果もfalseになります。したがって、左辺の値がfalseだと判明した時点で、この結果はfalseだと結論をつけることができます。表3-3.を見てください。③および④のケースは、左辺がわかった段階です、すぐに結論がわかります。

表3-3:AND演算
No左辺右辺演算結果
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

また、OR(論理和)の場合は、左辺、および、右辺のいずれかがtrueであれば、その結果がtrueであることがわかります。表3-4.を見てください。①および②のケースは、左辺がわかった時点で、演算結果がわかります。

表3-4:OR演算
No左辺右辺演算結果
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

このように、ANDおよび、ORは、値が固定されている場合、左辺がわかっている段階で値が判明します。このように、左辺がわかった段階で、演算結果を出すような方式が、ショートカットの方法です。

ショートカットではない演算子は、左辺、右辺の値をきちんと調べてから結果を出すため、処理スピードとしては、ショートカットのほうが速くなります。ただし、左辺の条件によって右辺の結果が変わってしまうような場合などは、ショートカットを用いるべきではありません。

switch文

サンプルプログラム

Sample303.javaのような、else ifを用いた多数に分岐する条件分岐は、値が整数値であれば、switch(スイッチ)文を用いて以下のように書くことができます。

Sample305.java
package day3;

public class Sample305 {

	public static void main(String[] args) {
		//標準出力
		int num = 1;						//	整数値(いろいろ変えてみましょう)
		switch(num){
		case 1:
	        System.out.println("one");    //  numが1だった場合の処理
	        break;
		case 2:
	    	System.out.println("two");    //  numが2だった場合の処理
	    	break;
		case 3:
	    	System.out.println("three");  //  numが3だった場合の処理
	    	break;
	    default:
	    	System.out.println("不適切な値です。"); //  それ以外の値が入力された場合の処理
	    }
	}
}

switch文は、後の()内の値によって、条件を分岐させる命令です。条件は、case(ケース)で書き、そのあとに値が来ます。最後にある、default(デフォルト)という条件は、 caseで出てきたいずれの条件にも当てはまらない場合を示しています。書式は、以下のようになります。

switch文

switch文の書式
switch(値){
    case 値①:
        処理①
        break;
    case 値②:
        処理②
        break;
    ・・・
    default:
        処理③
        break;
}

break

caseおよびswitchの後に出てくるbreak(ブレイク)というのは、処理の終了を意味します。breakがなくても、エラーにはなりませんが、そのあとの処理が続けて実行されてしまいますので、注意が必要です。

練習問題 : 問題3.