初心者入門レベルの【Javaの勉強】制御構文(分岐・繰り返し)を使った処理
2020/04/02
さて今回は、Javaの制御構文の勉強をしましょう。
制御構文というのはプログラムの流れを制御するもので、大きく分けて「逐次実行」「分岐」「繰り返し」の3つがあります。
まず一番単純な「逐次実行」ですが、これはプログラムの上から順に処理をしていくだけなので、特に説明の必要は無いでしょう。
次の「分岐」は条件によって処理の流れが変わるもので、「ある条件では処理Aを実行し、それ以外では処理Bを実行する」というように条件判断によって実行する処理を変える仕組みです。
そして「繰り返し」は、指定した回数や特定の条件に従って、プログラムの一部を繰り返して処理する仕組みのことです。
分岐処理
Javaでは分岐処理に、「if文」と「switch文」を使います。
if文
まずは「if文」ですが、基本的には以下のように記述します。
if (条件式) {
条件式が「true」のときに実行する処理
}
ここでの条件式は「true」か「false」の「boolean値」を持つもので、それ以外だとエラーになりますが、条件式が「true」のときに「{}」のブロック内の処理が実行されます。
それでは「if文」のプログラムの例として、以下の“運勢プログラム”を作ってみましょう。
public class Fortune01 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 3); //0から2までの整数に変換
if (fortune == 0) {
System.out.println("今日の運勢は・・・大吉です!");
}
}
}
このプログラムは、まず「Mathクラスのrandomメソッド」で「double型」の0以上1未満の乱数を生成しています。
そしてこれに3をかけて「int型」にキャストすることで、この乱数を0から2までの整数に変換しています。
その次の行が、今回注目の「if文」による制御構文になっています。
この「if文」の条件式には比較演算子の「==」を使っていますが、比較演算子には以下のようなものがあります。
演算子 | 呼び名 | 使用例 | 意味 |
---|---|---|---|
== | イコール演算子 | x == y | xとyが等しいときはtrue、等しくないときはfalseを返す。 |
!= | 不等号演算子 | x != y | xとyが等しいときはfalse、等しくないときはtrueを返す。 |
< | 小なり演算子 | x < y | xがyより小さいときはtrue、xがyと等しい、あるいはyより大きいときはfalseを返す。 |
> | 大なり演算子 | x > y | xがyより大きいときはtrue、xがyと等しい、あるいはyより小さいときはfalseを返す。 |
<= | 以下演算子 | x <= y | xがyより小さい、あるいはyと等しいときはtrue、xがyより大きいときはfalseを返す。 |
>= | 以上演算子 | x >= y | xがyより大きい、あるいはyと等しいときはtrue、xがyより小さいときはfalseを返す。 |
つまりここでは、変数「fortune」が0のときに“今日の運勢”を表示するようになっているわけですね。
さらにこのプログラムを以下のように変更して、ほかの運勢も表示するようにしてみましょう。
public class Fortune02 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 3); //0から2までの整数に変換
if (fortune == 0) {
System.out.println("今日の運勢は・・・大吉です!");
} else {
System.out.println("今日の運勢は・・・吉です!");
}
}
}
ここで「else文」が出てきましたが、このプログラムは変数「fortune」の値が0のときは“大吉”を表示して、それ以外のとき(つまり「fortune」の値が1または2)のときは“吉”を表示するようになっています。
つまり「else文」の処理には、「if文」の条件式が成立しないときに実行される処理を記述するということです。
続けて「else if文」も使って、以下のようにプログラムを変更してみましょう。
public class Fortune03 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 10); //0から9までの整数に変換
if (fortune == 0) {
System.out.println("今日の運勢は・・・大吉です!");
} else if (fortune < 4) {
System.out.println("今日の運勢は・・・吉です!");
} else {
System.out.println("今日の運勢は・・・小吉です!");
}
}
}
これは上から順に、変数「fortune」の値が0のとき、「fortune」の値が0ではなく4より小さい(つまり「fortune」の値が1から3の)とき、それら以外(つまり「fortune」の値が4から9)のときというように評価されます。
また「else if文」は連続して複数記述することもできるので、「else文」にはそれまでのすべての「if文」と「else if文」の条件式が成立しないときに実行される処理を記述することになります。
それでは複数の「else if文」を使って、もっと運勢を増やしてみましょう。
public class Fortune04 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 10); //0から9までの整数に変換
if (fortune == 0) {
System.out.println("今日の運勢は・・・大吉です!");
} else if (fortune == 1 || fortune == 2) {
System.out.println("今日の運勢は・・・吉です!");
} else if (fortune >= 3 && fortune <= 6) {
System.out.println("今日の運勢は・・・中吉です!");
} else if (fortune == 7 || fortune == 8) {
System.out.println("今日の運勢は・・・小吉です!");
} else {
System.out.println("今日の運勢は・・・凶です!");
}
}
}
ここで新しく出てきたのが「||」と「&&」という記号ですが、これらは「ショートサーキット(短絡評価)演算子」と呼び、以下のような働きをします。
演算子 | 呼び名 | 使用例 | 意味 |
---|---|---|---|
&& | 論理積演算子 | x && y | xとyのどちらもtrueの場合はtrue、それ以外の場合はfalseを返す。 |
|| | 論理和演算子 | x || y | xとyのどちらか、あるいは両方がtrueの場合はtrue、それ以外の場合はfalseを返す。 |
また「ショートサーキット(短絡評価)演算子」は条件式を左から評価していって、条件式全体が成立するかどうか判断できたときに評価を中断してそれ以降の評価をしないという働きをします。
つまり
fortune == 1 || fortune == 2
という条件式の場合、まず「fortune == 1」を評価してこれが成立した(「fortune」が1の)場合、条件式全体も成立すると判断できるので、そこで評価を中断して「fortune == 2」の方は評価しないということです。
「ショートサーキット(短絡評価)演算子」は「論理演算子」の仲間で、これら以外の「論理演算子」は「ビット論理演算子」と呼んで、以下のものがあります。
演算子 | 呼び名 | 使用例 | 意味 |
---|---|---|---|
& | 論理積演算子 | x & y | xとyがboolean型のときはショートサーキット演算子の論理積と同じ。両方が整数型のときはビットごとのANDの値を返す。 |
| | 論理和演算子 | x | y | xとyがboolean型のときはショートサーキット演算子の論理和と同じ。両方が整数型のときはビットごとのORの値を返す。 |
^ | 排他的論理和演算子 | x ^ y | xとyがboolean型でかつxとyが異なる値の場合はtrue、xとyが同じ場合はfalseを返す。両方が整数型のときはビットごとのXORの値を返す。 |
! | 論理否定演算子 | !x | xがtrueの場合はfalse、falseの場合はtrueを返す。 |
swith文
今回の“運勢プログラム”のように条件に整数を使ったり、または文字を使った条件分岐には、「switch文」も利用できます。
例として、“運勢プログラム”を「switch文」を使って書き換えてみましょう。
public class Fortune05 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 10); //0から9までの整数に変換
switch (fortune) {
case 0:
System.out.println("今日の運勢は・・・大吉です!");
break;
case 1:
case 2:
System.out.println("今日の運勢は・・・吉です!");
break;
case 3:
case 4:
case 5:
case 6:
System.out.println("今日の運勢は・・・中吉です!");
break;
case 7:
case 8:
System.out.println("今日の運勢は・・・小吉です!");
break;
default:
System.out.println("今日の運勢は・・・凶です!");
}
}
}
「switch文」は、まず評価の対象となる式を「()」(かっこ)の中に記述し、その後ろに「{}」(中かっこ)でブロックを作ります。
ブロックの中で「case」というキーワードの後ろに、上で「()」内に指定した式が取り得る値を記述し、式がこの値に一致したときに実行する処理をその下に記述します。
「case」は複数続けて書くことができて、どれかが一致すればその下の処理が実行されるという意味になります。
処理の下に書かれた「break文」は、ここで「switch文」のブロックを抜けるために書かれたものです。
これを忘れて書かないと、成立した「case」の下の処理を実行しても「switch文」のブロックを抜けずに、そのまま処理が下へ続いてしまうので注意が必要です。
ちなみに「switch文」で評価の対象となる式は、「byte型」「short型」「int型」「char型」、そしてそれらをオブジェクト化したラッパークラスである「Byte」「Short」「Integer」「Character」、もしくは「String」のいずれかでなければなりません。
繰り返し処理
続いて繰り返し処理ですが、Javaではループして繰り返す処理には「for文」「while文」「do - while文」を使います。
for文
まずは「for文」ですが、以下のような形になります。
for (初期化処理; 条件式; 更新処理) {
繰り返し実行する処理
}
「初期化処理」は最初に1度だけ実行しておく処理で、繰り返し処理の前処理のようなものにあたります。
「更新処理」は「繰り返し実行する処理」を実行するたび、つまりループが1回りした後で実行される処理です。
「条件式」は「if文」のときと同じく「boolean型」で、「初期化処理」の後と「更新処理」の実行のたびに評価されます。
この「条件式」の値が成立つまり「true」である間は「繰り返し実行する処理」を実行しつづけ、「false」になったらループを抜けて終了します。
ここでサンプルプログラムとして、以下の幸運度プログラムを作って見ましょう。
public class Fortune06 {
public static void main(String[] args) {
double rnd = Math.random(); //乱数の生成
int fortune = (int)(rnd * 10) + 1; //1から10までの整数に変換
System.out.println("10% 50% 100%");
System.out.println("┏━━━━━━━━┓");
for (int i = 0; i < fortune; i++) {
System.out.print("■");
}
System.out.print("\n今日の幸運度は");
System.out.print(fortune);
System.out.print("0%です!");
}
}
幸運度というのは私が勝手に作ったんですが、幸運の度合いを10%から100%の確立で表すものです。
このプログラムでは、その幸運度を「■」の数で表すようにしてみました。
ここでは「初期化処理」が「int i = 0」で条件式が「i < fortune」、「更新処理」が「i++」になっています。
つまり「i = 0」から始めて、「System.out.print("■");」を実行するたびに変数「i」が1だけ増えて(インクリメントされて)いきます。
その次に「i < fortune」が評価されて、「true」の場合つまり変数「i」が変数「fortune」よりも小さければループ処理が続き、「false」の場合つまり変数「i」が変数「fortune」以上になったとき処理が終了します。
「fortune」は1から10までの値をとりますから、このループの処理も1回から10回のいずれかの回数だけ実行されることになります。
結果として「System.out.print("■");」の処理が1回から10回の間で実行され、「■」が1個から10個並ぶわけです。
なお、「for文」の「初期化処理」「条件式」「更新処理」は省略することができますが、「;」(セミコロン)は省略できません。
「条件式」を省略した場合、その評価値は常に「true」であると判断されます。
また、「初期化処理」「更新処理」は「,」(カンマ)でつないで複数書くこともできます。
while文
次に「while文」についてですが、以下のように記述します。
while (条件式) {
繰り返し実行する処理
}
Javaでは「for文」を使えば、どんなループ処理も記述できますが、この「while文」を使ったほうがシンプルに書ける場合もありますので憶えておきましょう。
また似ている構文として「do - while文」がありますが、こちらは次のように記述します。
do {
繰り返し実行する処理
} while (条件式)
「do - while文」は「while文」と違って、ループ処理を実行した後で「条件式」を評価するところにあります。
ですから最初から「条件式」の値が「false」である場合でも、必ず「繰り返し実行する処理」が1度は実行されることになります。
つまり「while文」では1度も処理が実行されない可能性がありますが、「do - while文」は最低でも1度は処理が実行されるということです。
break文とcontinue文
最後に繰り返しの処理を中断する、「break文」と「continue文」についてふれておきましょう。
「break文」は、例えば次のプログラムのように「for文」に「if文」を組み合わせてループから抜ける場合に使用します。
public class LoopTest01 {
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
int j = i * i
if (j > 30) break;
System.out.print(i + ":");
System.out.print(j + "\t");
}
}
}
これは1から10の整数を二乗して、それが30を越えたときにループを抜ける仕組みになっているので、実行結果は以下のようになります。
>java LoopTest01
1:1 2:4 3:9 4:16 5:25
このようにループが1つのときは単純ですが、「break文」はそれが含まれるループだけを抜けるので、ループが入れ子になっている場合は注意が必要です。
もしも、入れ子になっているときに「break文」が含まれるループよりも外へ抜けたい場合は、次のプログラムのように「ラベル」を使います。
public class LoopTest02 {
public static void main(String[] args) {
firstLoop:
for (int i = 1; i < 10; i++) {
for (int j = 1; j < 10; j++) {
int k = i * j;
if (k > 20) break firstLoop;
System.out.print(i + ":");
System.out.print(j + ":");
System.out.print(k + "\t");
}
System.out.println("");
}
}
}
「ラベル」というのはループに名前を着ける仕組みで、このプログラムでは一番外側のループに「firstLoop」という名前でラベルが付けられています。
「ラベル」は変数名と同じ規約で名前をつけて、最後に「:」(コロン)を付けることで「ラベル」であることを示します。
このプログラムでは1から9までで1ずつ増分する2つの変数をかけて、その値が20を越えたときに「break firstLoop;」によってラベル「firstLoop」のループを抜けるようになっており、実行結果は以下のようになります。
>java LoopTest02
1:1:1 1:2:2 1:3:3 1:4:4 1:5:5 1:6:6 1:7:7 1:8:8 1:9:9
2:1:2 2:2:4 2:3:6 2:4:8 2:5:10 2:6:12 2:7:14 2:8:16 2:9:18
3:1:3 3:2:6 3:3:9 3:4:12 3:5:15 3:6:18
続いて「continue文」ですが、これはループ中にそこで処理を中断して、次のループの値に処理を続ける働きをします。
例として以下のプログラムでは、変数「i」が5のときに処理を中断して、以降の処理を行わないままに変数「i」を6にしてループを続ける仕組みになっています。
public class LoopTest03 {
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
if (i == 5) continue;
System.out.print(i + "\t");
}
}
}
このプログラムの実行結果は次のようになり、変数「i」が5のときには「System.out.print(i + "\t");」の行が実行されていないことが分かります。
>java LoopTest03
1 2 3 4 6 7 8 9
また「continue文」でも同様に、以下のプログラムのように「ラベル」を使って処理を外側のループの次の値まで飛ばすようなことも可能です。
public class LoopTest04 {
public static void main(String[] args) {
firstLoop:
for (int i = 1; i < 5; i++) {
System.out.println("");
for (int j = 1; j < 10; j++) {
if (j == 5) continue firstLoop;
System.out.print(i + ":" + j + "\t");
}
}
}
}
このプログラムでは、変数「j」が5になったときに以降の処理を実行せずに、処理を変数「i」の次の値まで飛ばしているので、実行結果は以下のようになります。
>java LoopTest04
1:1 1:2 1:3 1:4
2:1 2:2 2:3 2:4
3:1 3:2 3:3 3:4
4:1 4:2 4:3 4:4
まとめ
今回は、分岐の制御構文を使った処理として「if文」と「switch文」、そして繰り返しの制御構文を使った処理として「for文」「while文」「do-while文」「break文」「continue文」を勉強しました。
これらはプログラムの流れをコントロールするために必須の構文なので、しっかりと理解しておくことが必要です。
と言っても、それほど複雑な内容ではないので、特に難しくはなかったですね。
それでは、今回はここまでです。
《 【Javaの勉強】一覧 》