break文

break文によるループの終了

これまでの繰り返し処理では、決められた条件がtrueである間はループ本体を実行してきました。 しかし、ループ本体の実行途中であっても、ループを強制的に終了させたいときが有ります。 それを実現するのがbreak文です。 break文は既にswitch文のところで学習しましたが、for文、while文、do〜while文による繰り返しを中断したいときにも使うことができるのです。

英語のbreakには、「破る」「中断する」という意味があります。

構文 : break文
break;

for文、while文、do〜while文などのループ本体の中でbreak文を実行すると、そのbreak文を含む一番内側のループを強制的に終了することができます。

図 7-7 : break文によるループの終了

では、早速サンプルプログラムを見てみましょう。 今回は、入力された正の整数が素数かどうかを判定するプログラムです。

素数とは、1と自分自身でしか割り切れない自然数のことでしたね。 ただし、1は素数には入れません。 素数を小さい方から順に書いていくと次のようになります。

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, ...

尚、素数に最大のものは無く、限りなく続いていくことが知られています。

BreakSample01.java
import java.io.*;

class BreakSample01 {
    public static void main(String[] args) throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("正の整数を入力してください。");
        int num = Integer.parseInt(br.readLine());
        boolean prime = true; //素数かどうかを表すboolean型の変数。最初は素数に設定
        
        for(int i = 2; i < num; i++){
            if(num % i == 0){ //1と自分自身以外の数で割り切れたら素数ではない。
                prime = false;
                break;
            }
        }
        
        if(num == 1)    //1は自分自身以外の数で割り切れないが、素数ではない。
            prime = false;
        
        if(prime)
            System.out.println("素数です。");
        else
            System.out.println("素数ではありません。");
    }
}
BreakSample01の実行結果 1
正の整数を入力してください。
1
素数ではありません。
BreakSample01の実行結果 2
正の整数を入力してください。
3
素数です。
BreakSample01の実行結果 3
正の整数を入力してください。
6
素数ではありません。

BreakSample01では、入力された正の整数はnumに代入されています。 numが素数かどうかを表すのがboolean型の変数primeです。

        boolean prime = true; //素数かどうかを表すboolean型の変数。最初は素数に設定

最終的には、numが素数ならprimeにはtrue、素数でないならfalseが代入されることになります。 しかし、numの値に関わらず、一旦は素数であると見なしているのです。

numが素数かどうかはfor文の中で判定されます。

        for(int i = 2; i < num; i++){
            if(num % i == 0){ //1と自分自身以外の数で割り切れたら素数ではない。
                prime = false;
                break;
            }
        }

num % i == 0 は「numをiで割った余りが0である。」ということで、簡単に言えば、「numはiで割り切れる。」ということです。 iの値を2からnum-1までインクリメントしながら、numがiで割り切れるかどうかをチェックしています。 もし一つでも割り切れる数が有れば、numは素数ではないので、primeにfalseを代入して、break文でループを強制的に終了させます。 どの数でも割り切れないならば、 i < num が成り立たなくなったときにループは終了します。

この時点で、primeには正しい値が入っているように思えるのですが、よく考えてみると、numが1の場合にも、primeにはtrueが入っていることになります。 1という数は確かに自分自身でしか割り切れないのですが、素数の仲間とはみなされないことになっています。 そこで、次のようにnumの値が1の場合だけは、primeをfalseに設定し直しています。

        if(num == 1)    //1は自分自身以外の数で割り切れないが、素数ではない。
            prime = false;

こうしてprimeに正しい値が設定されたところで、primeの値に応じてメッセージを出力しているのです。

表 7-7はnumの値が1の場合のfor文の流れです。 for文の条件 i < num が始めからfalseのため、ループ本体は一度も実行されず、primeの値はtrueのままとなります。

表 7-7 : BreakSample01でのfor文の流れ(1が素数かどうか判定)
繰り返し回数 iの値 i < num num % i == 0 prime i++後のiの値
1 2 false true

表 7-8はnumの値が3の場合のfor文の流れです。 for文の条件 i < num はiの値が2のときだけtrueとなり、ループ本体が一度だけ実行されますが、if文の条件 num % i == 0 がfalseのため、結局primeの値はtrueのままでループは終了することになります。

表 7-8 : BreakSample01でのfor文の流れ(3が素数かどうか判定)
繰り返し回数 iの値 i < num num % i == 0 prime i++後のiの値
1 2 true false true 3
2 3 false true

表 7-9はnumの値が6の場合のfor文の流れです。 for文の条件 i < num はiの値が2のときtrueとなり、ループ本体が実行され、if文の条件 num % i == 0 がtrueのため、primeの値はfalseとなり、break文によってループを強制的に終了させることになります。

表 7-9 : BreakSample01でのfor文の流れ(6が素数かどうか判定)
繰り返し回数 iの値 i < num num % i == 0 prime i++後のiの値
1 2 true true false

break文を使えば、for文、while文、do〜while文を強制的に終了させることができる。

ラベル付きbreak文で多重ループを一気に抜け出す

既に述べましたように、break文はそれを含む一番内側のループを強制的に終了させます。 したがって、二重ループの内側のループ本体でbreak文を実行した場合、内側のループが終了するだけで、外側のループは終了しません。 九九の表を作るプログラム(MultipleLoopSample01A)に少し手を加えて、このことを確認してみましょう。

BreakSample02.java
class BreakSample02 {
    public static void main(String[] args) {
        int limit = 20;
        
        for(int i = 1; i <= 9; i++){
            for(int j = 1; j <= 9; j++){
                if(i * j > limit){
                    break;
                }
                System.out.printf(" %2d", i * j);
            }
            System.out.println();
        }
    }
}

BreakSample02の実行結果をスクリーンショットで見てみましょう。

図 7-8 : BreakSample02の実行結果

BreakSample02の内側のループ(列ループ)の中には、

                if(i * j > limit){
                    break;
                }

と記述されています。 九九の答えが上限であるlimitの値(20に設定されている)を超えたときは、break文が実行されて列ループが終了します。 そのため、上限を超えた場合は、その時点でその行の表示は終了します。 しかし、外側のループ(行ループ)は終了せず、改行が通常通り行われ、さらに次の行の表示へと進んでいきます。

break文は、それを含む一番内側のループを終了させるだけで、外側のループは終了させないことがお分かりいただけたでしょうか。

さて、外側のループを一気に抜け出すにはどうすればいいのでしょうか。 それにはラベル付きbreak文を使います。

例えば、for文による二重ループで、内側のループの中から外側のループの外へ一気に抜け出すには、おおよそ次のような構文でラベル付きbreak文を使います。

構文 : ラベル付きbreak文
ラベル:
    for(初期化部1; 条件1; 更新部1){
        for(初期化部2; 条件2; 更新部2){
            if(条件3){
                ...
                break ラベル;
            }
        }
    }

外側のfor文の直前に、「ラベル:」が付けられています。 こうしておくと、「break ラベル;」が実行されたときに、外側のfor文を一気に抜け出すことができます。 内側のfor文にラベルを付けることもできますが、その場合はラベル無しのbreak文と同様に、内側のfor文を抜け出すだけになります。 尚、ラベルは識別子ですので、その規則に従って決めてください。

それでは、実際にラベル付きbreak文を使ってみましょう。 次のBreakSample03はBreakSample02を少しだけ変更したものです。

BreakSample03.java
class BreakSample03 {
    public static void main(String[] args) {
        int limit = 20;

    RowLoop:
        for(int i = 1; i <= 9; i++){
            for(int j = 1; j <= 9; j++){
                if(i * j > limit){
                    System.out.println();
                    break RowLoop;
                }
                System.out.printf(" %2d", i * j);
            }
            System.out.println();
        }
    }
}

BreakSample03の実行結果は次のようになります。

図 7-9 : BreakSample03の実行結果

今回は、外側のループ(行ループ)の直前に RowLoop というラベルが付いています。 そして、九九の答えが上限を超えた場合はラベル付きbreak文が実行されます。

                if(i * j > limit){
                    System.out.println();
                    break RowLoop;
                }

ラベル付きbreak文が実行されると、行ループの外へ一気に抜け出します。 したがって、その時点で九九の表の作成は完全に終了することになります。 この場合、内側のループ(列ループ)の後の改行の処理は行われないことになるので、ラベル付きbreak文の実行前に、改行しておかなければなりません。

多重ループを一気に抜け出すには、抜け出したいループの直前にラベルを付けて、ラベル付きbreak文を実行する。