第 2 章 Java 言語の基本的な文法 I 5
2.26 RankEvaluation.java ( 条件分岐で成績評価 )
public class RankEvaluation {
public static void main(String[] args) { int degree = 85;
// if 文による条件分岐により以下のような出力が出るように作る
} }
あなたの成績は A でした 。
ところで、この問題の解答として以下のように書く人が結構多い。
if( degree >= 90 ) {
Systerm.out.println( "あなたの成績は S でした。" );
} else if( degree < 90 && degree >= 80 ) {
Systerm.out.println( "あなたの成績は A でした。" );
} else if( degree < 80 && degree >= 70 ) { // :
// (以下省略) えっ、何処がいけないの?
論理的には間違ってはいません。ただ、最初のif文の判定で falseとなった場合、必ずdegree < 90 は成立して いるのではないでしょうか。つまり、次の判定におけるdegree < 90の論理式は無駄だ!ということです。こうした 場合、馬鹿マジメに判定式を書くのではなく、よく考えてから簡潔な論理式を書くようにしましょう (我々は応用数学 科の学生なのだから)。
問題 2.12.11. 上の問題の条件分岐の順番を、最初にdegree >= 70から初めたときの条件分岐文を考え、それによ るプログラムRankEvaluation2.javaを作りなさい。
そして、どのランクの点数も同じ確率で発生するとしたときの分岐回数の平均値を 2つのプログラムで比較しなさい。
もしこの2つのプログラムRankEvalutionとRankEvalution2が大量のデータに対して行われるとしたら、後者 の方が(プログラムソースとしては少々見にくくなりますが)処理時間が短くなるのが予想されます。このような点も 考えながらプログラミングして下さいな。
問題 2.12.12. 以下の論理積を含むif文を、単独の (論理積を含まない)if文の入れ子として書き直しなさい。な お、condition_Aとcondition_Bはいずれもboolean型の値を返す論理式とします。そして、この論理式が短絡評 価式であることも注意して下さい。
if( condition_A && condition_B ) { System.out.println( true );
} else {
System.out.println( false );
}
最後のy += 2;がインデントされているので、ついx >= 0の場合に2つの処理が行われる、と読まれる可能性があ るからです。実際にはy +=2はxの判定に関わらず行われますよね。インデントを正しく書けば良いのでは?と思う かな。でも、この場合は以下のように書くか、
int x = 1;
int y = 2;
if( x >= 0 ) x *= 2;
y += 2;
ブロックの中かっこは中味が1つでも必ず書く!とすれば、誤解は起きないですね。
int x = 1;
int y = 2;
if( x >= 0 ) { x *= 2;
} y += 2;
2.12.6 switch 文
条件分岐する条件式が整数型もしくは文字型である場合は、もう1つ、別の書き方ができます。switch文です。た だし、switch文で使われる条件式はifでの条件式のように結果がboolean型の値となる式ではなく、整数型・文字 型もしくは文字列型となる式でないといけません。従って、「90点以上」のような範囲で場合分けするのには向いてい ません。直接、90ならどうする、80ならどうする、といった分岐になります。caseで始まる部分を「case節」と呼 びます。「defult 節」は省略することができます。
int x = 123;
switch( x % 3 ) { case 0:
// 整数 x が 3 で割り切れる場合の処理 break;
case 1:
// 整数 x が 3 で割ると1余る場合の処理 break;
default:
// 上記 2 つのケース以外の場合の処理 (この場合 3 で割ると 2 余る数) break;
}
文字型でも判定できるので、先の例の続き、学生の成績からランク評価 char型変数 rankが得られたとしましょう。
それらにより合格か否かを表示する処理をswitch文で書くと次のようになります。
switch( rank ) { case 'S':
System.out.println( "あなたは S で合格です" );
break;
case 'A':
System.out.println( "あなたは A で合格です" );
break;
case 'B':
System.out.println( "あなたは B で合格です" );
break;
case 'C':
System.out.println( "あなたは C で合格です" );
break;
default:
System.out.println( "あなたは不合格です" );
break;
}
ここで、何度も登場するbreak;について説明しましょう。この命令は、「壊す」という意味ではなく、「中断する」
という意味で使われていて、その後に続くcase 節を読み飛ばして、switchブロックの外に出る、という処理をして くれます。つまり、 rank == 'S' の場合は、S で合格と出力後break によって、switch文を抜け出します。ま た、最後のdefault節には後に続くcase節が無いので、break;を書かなくても構いません。
なお、 default 節自体が無くても構いません。その場合、それ以外のケースに合致しなかった場合は何もせずに
switch文の外へ出ることになります。
問題 2.12.13. 上のswitch文による成績処理の分岐をif文による分岐で書きなさい。
この問題のように、switch文での分岐処理はif文による分岐処理で書き直すことができます(見やすさが違いま すが)。
問題 2.12.14. 文字列の入った変数 drinkの値で次のような出力を行うswitch文を書きなさい。
• drink == "orange"なら、「オレンジジュースですね」
• drink == "apple"なら、「リンゴジュースですね」
• drink == "coffee"なら、「コーヒーですね」
• drink == "tea"なら、「紅茶ですね」
• その他の場合に、「申し訳ありません、それはご用意できません」
さて、switch 文は以下のような書き方ができます。この場合、 'S' から'B' までの case 節に何も書かれてい ません。では、rank の値の違いによりどのように処理されるでしょう。rank == 'S' の場合、case 'S': で条件 を満たし、さて処理は?というと何も無い。そして、break;も無いので、処理は単純に下に移動して、case 'A':、 case 'B':、case 'C':と通り過ぎて、"あなたは合格です"を出力、そしてbreak;でやっとswitchブロックから 抜け出すのです。rank == 'A'や、rank == 'B' の場合も同様にcase 'C':の部分まで移って出力後 break; で switchブロックの外に出ます。一方、それらでない場合 (rank=='D'ですかね)は、defalutへ飛んで"不合格で
す"を出力、break;は無いけれど終了、となります。このような幾つかの値に対して同じ処理を行うような場合にも
対応することができます。
switch( rank ) { case 'S':
case 'A':
case 'B':
case 'C':
System.out.println( "あなたは合格です" );
break;
default:
System.out.println( "あなたは不合格です" );
}
2.12.7 条件演算子
プログラムでは、条件式の真偽に応じて変数の値を切り替える処理が多く出てきます。例えば、2つの変数aとbの 大きな方を変数xに代入したいとき、if文を使えば、以下のように書けますよね。
if( a > b ) { x = a;
} else { x = b;
}
ブロックの中かっこを省略して、
if( a > b ) x = a;
else x = b;
と、まだまだ冗長ですかね。そこで、これを1つの処理として書いてしまうのが「条件演算子?:」です。その書き方 とは、
x = ( a > b ) ? a : b;
?の前に条件式を書き、それが trueになる場合の値を? の次に、falseになる場合の値をコロン:の次に書くので す。a > bをくくっている小かっこは省略できますが、無いと読みにくくなりますかね(x = a > b ? a : b;)。 省略して、x = ( a > b ? a : b );と外側に小かっこを付けるという流儀もあります。
例えば、成績degreeが60点以上なら「合格です」そうでなければ「不合格です」と出力する文を、次のようにもか けますが、どうでしょう。和田は、1行があまり長くなりそうなら条件演算子は使わないようにしています (なので、
こんなのは書かないな)。
System.out.println( "あなたは" + (degree >= 60 ? "合格" : "不合格") + "です" );
問題 2.12.15. boolean型変数isMaleには、男性なら trueが、女性ならfalseが入っているとします。条件演算 子を使ってその値から2 つの文字列”男性”と”女性”のいずれかを選んで、以下のように出力する出力文を1行で書 きなさい。
あなたは 、女性ですね 。
2.12.8 boolean 型変数の真偽判定
上の問題でも出てきましたが、if文や条件演算子の条件式の中にboolean型変数の真偽を判定することが結構出て きます。
最初に学ぶのは、繰り返しの回数が決まっている、例えばある処理を10回繰り返したい、という場合です。そうし た場合は、for文という命令で書きます。
for(int i = 1; i <= 10; i++) { // 繰り返したい処理
}
中かっこで括られた部分を forブロックと言い、この中に繰り返したい処理(複数の文でも構わない)を書きます。
forの次に続く小かっこの中に、繰り返しのカウンタについての処理を3 項目で書きます。間をセミコロンで区切っ ています(最後の命令i++にはセミコロンが無いことに注意)。小かっこの中の書き方は、次のようになります。
for(カウンタの初期化; 繰り返し条件; 処理の最後に行うカウンタの処理)
まず、「カウンタの初期化」ですが、カウンタとなる変数の宣言と初期値を与えます。カウンタはカウントできる型な らば何でも良いので、整数型・実数型・文字型のいずれかが使えます。整数型のカウンタとしては、数学でも添字によ