ラベル付きbreak文とラベル付きcontinue文

7.7 ラベル付きbreak文とラベル付きcontinue文

 前節で解説したbreak文とcontinue文は、その文が含まれる直近のループ文を抜けたり先頭に戻ったりすることができます。しかし、多重ループをしていた場合、内側のループ文ではなく、外側のループ文からも抜けたい場合がでてくるかもしれません。
 このようなときに使用するのがラベルです。

7.7.1 ラベル付きbreak文

 まず、通常のbreak文を多重ループで使用した場合の動きを説明します。

 上記のように、内側のfor文は抜けても、外側のfor文を抜けることはできません。
 一方、ラベル付きbreak文を使うと、そのラベルの付いたfor文まで一気に抜けることが出来ます。

 ラベルは任意の名前に「:(コロン)」を付けて明示します。
 ループ文の直前にラベルを付けると、ラベル付きbreak文はそのループ文全体から抜けます。
 上の例では二重ループの場合を示していますが、ループが何重であっても、指定したラベル名が付いたループ文全体から抜けることができます。

7.7.2 ラベル付きbreak文を使ったプログラム

 ラベルの無いbreak文を含む二重ループのfor文と、ラベル付きのbreak文を含む二重ループのfor文を、実際にプログラムを作成して比較してみましょう。

① ソース・フォルダー      :myproj_intro/src
② パッケージ          :jp.co.f1.intro.ch7
③ 名前             :BreakLabel
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

➢ BreakLabel.java

1package jp.co.f1.intro.ch7;
2 
3public class BreakLabel {
4 
5    public static void main(String[] args) {
6 
7        myLabel:for(int i = 1; i <= 3; i++) {
8            System.out.println("外側のループ" + i + "回目開始");
9 
10            for(int j = 1; j <= 5; j++) {
11                System.out.println("    内側のループ" + j + "回目開始");
12                if(j == 2) {
13                    System.out.println("        「ラベル付きbreak!」");
14                    break myLabel;
15                }
16                System.out.println("    内側のループ" + j + "回目終了");
17            }
18            System.out.println("外側のループ" + i + "回目終了");
19            System.out.println();
20 
21        }
22        System.out.println("プログラム終了");
23 
24    }
25 
26}

実行結果

解説

 このプログラムには、二重ループのfor文があります。外側のfor文には「myLabel」というラベルが付けられています。
 内側のループの内部処理である12~15行目に、if文が1つ記述されています。if文の条件は、内側のfor文のカウンタ変数jが2であることです。if文の条件が満たされた場合、13行目でメッセージを表示し、14行目のbreak文で「myLabel」というラベルのfor文から抜けます。
 ラベルの無いbreak文の場合は、break文を記述したところから一番近い繰り返し文である内側のfor文から抜けます。しかし、今回のプログラムのbreak文はラベル名を記述しているので、同じラベルが付いている外側のfor文から抜けます。
   7: myLabel:for(int i = 1; i <= 3; i++) {
   8:    System.out.println("外側のループ" + i + "回目開始");
   10:    for(int j = 1; j <= 5; j++) {
   11:          System.out.println(" 内側のループ" + j + "回目開始");
   12:          if(j == 2) {
   13:                System.out.println(" 「ラベル付きbreak!」");
   14:                break myLabel;
   15:          }
   16:          System.out.println(" 内側のループ" + j + "回目終了");
   17:    }
   18:    System.out.println("外側のループ" + i + "回目終了");
   19:    System.out.println();    21: }

 ・ どのような順番でプログラムが動いているのか。
 ・ どの時点で12行目のif文の条件式が満たされるのか。
 ・ その次にどんな動きをするのか。
この3点について確認しながら、次のフロー図 7.7.1を見て、プログラムの流れを追ってみて下さい。

図 7.7.1 : BreakLabelのフローチャート


7.7.3 ラベル付きcontinue文

 続いて、ラベル付きcontinue文の概要を見ていきます。
 今回も、まずは通常のcontinue文で多重ループを使用した場合の動きを説明します。下に示すcontinue文の流れを見てください。


 このように、通常のcontinue文では内側のfor文の先頭に処理が戻ります。
 一方、ラベル付きcontinue文の場合は、下に示すように、ラベルの付いたfor文の先頭まで一気に処理が戻ることになります。
 多重ループのネストの階層の深さに依存しないところは、ラベル付きbreak文と同じです。

7.7.4 ラベル付きcontinue文でwhile文を制御するプログラム

 キーボードから入力した値と、それまで入力された複数の値の合計値を出力するプログラムを作成していきましょう。continue文を使ってwhile文を制御します。

① ソース・フォルダー      :myproj_intro/src
② パッケージ          :jp.co.f1.intro.ch7
③ 名前             :ContinueLabel
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる

➢ ContinueLabel.java

1package jp.co.f1.intro.ch7;
2 
3import java.util.Scanner;
4 
5public class ContinueLabel {
6 
7    public static void main(String[] args) {
8 
9        Scanner sin = new Scanner(System.in);
10 
11        // 入力値を管理するための変数の宣言
12        int num;
13 
14        // 合計値を管理するための変数の宣言
15        int sum;
16 
17        Outer:while(true){
18            sum = 0;
19 
20            while(true){
21 
22                System.out.print("整数値を入力してください(終了したい場合は0を入力)>");
23                num = sin.nextInt();
24 
25                if(num == 0){
26                    System.out.println("0が入力されたので、処理を終了します。");
27                    break Outer;
28                }else if(num < 0){
29                    System.out.println("マイナス値は合計されません。");
30                    System.out.println();
31                    continue;
32                }
33 
34                sum += num;
35 
36                System.out.println("入力値は" + num + "です。");
37                System.out.println("合計値は" + sum + "です。");
38                System.out.println();
39                if(sum == 77){
40                    System.out.println("ラッキー!合計値は77です。");
41                    break;
42                }
43                else if(sum > 100){
44                    System.out.println("合計値が100を超えたのでリセットされます。");
45                    System.out.println();
46                    continue Outer;
47                }
48 
49            }
50            System.out.println("値はリセットされます。");
51        }
52 
53    }
54 
55}

実行結果

解説

 このプログラムは、7.6.4で作成したContinueStatement.javaを発展させたものです。二重ループのwhile文に加えて、if – else if文とif文がそれぞれ1つずつ記述されています。今回のプログラムでは、合計値が100を超えるか77になると数値がリセットされるという機能が追加されました。
 インデントが深いので、少し複雑に見えますが、43行目以外は、これまで学習した文法です。実行される順序を整理しながら、ゆっくりと流れを追っていきましょう。

 まず9行目では、数値を入力するための準備をしています。そして12行目は、入力した数値を入れる変数です。15行目は、入力された数値を足した合計を格納する変数です。
   9: Scanner sin = new Scanner(System.in);
   12: int num;
   15: int sum;

 17~47行目がwhile文の二重ループです。2つのwhile文はどちらも無限ループ処理ですが、外側のwhile文には「Outer」という名前のラベルが付いています。
 内側のwhile文で主な処理を行っています。実行中は合計値が77になるか100を超えた場合以外は内側の処理をループします。
   17: Outer:while(true){
   18:    sum = 0;
   20:    while(true){
   22:          System.out.print("整数値を入力してください(終了したい場合は0を入力)>");
   23:          num = sin.nextInt();
   25:          if(num == 0){
   26:                 System.out.println("0が入力されたので、処理を終了します。");
   27:                 break Outer;
   28:          }else if(num < 0){
   29:                 System.out.println("マイナス値は合計されません。");
   30:                 System.out.println();
   31:                 continue;
   32:          }
   34:          sum += num;
   36:          System.out.println("入力値は" + num + "です。");
   37:          System.out.println("合計値は" + sum + "です。");
   38:          System.out.println();
   39:          if(sum == 77){
   40:                 System.out.println("ラッキー!合計値は77です。");
   41:                 break;
   42:          }
   43:          else if(sum > 100){
   44:                 System.out.println("合計値が100を超えたのでリセットされます。");
   45:                 System.out.println();
   46:                 continue Outer;
   47:          }
   49:    }
   50:    System.out.println("値はリセットされます。");
   51: }

 17行目からは、「Outer」という名前のラベルがついた外側のwhile文に入ります。ループに入ると、変数sumに0を代入します。
   17: Outer:while(true){
   18: sum = 0;

 そして、20行目で内側のwhile文に入ります。条件式がtrueと指定されているため、breakか外側のループへ抜けるラベル付きcontinueが実行されることでこのループを抜けなければなりません。
   20: while(true){

 次に、ユーザーからの数値の入力を求めます。22行目で数値の入力を促すメッセージを表示し、23行目で実際に入力を求め、その数値を変数numに代入します。
   22: System.out.print("整数値を入力してください(終了したい場合は0を入力)>");
   23: num = sin.nextInt();

 25~32行目はif – else if文です。
 25行目のif文では、もし入力された数値が0だった場合に外側のループから抜けます。その場合、while文を抜けた次の52行目から実行されますが、その後の処理が何もないのでプログラムも終了します。
 28行目は、「num < 0」の条件式です。25行目の条件式である「num == 0」に当てはまらなかった場合に判定されます。そして、29、30行目でメッセージの表示と改行が行われた後、31行目のcontinueで20行目の内側のwhile文の条件式へジャンプします。
   25:    if(num == 0){
   26:          System.out.println("0が入力されたので、処理を終了します。");
   27:          break Outer;
   28:    }else if(num < 0){
   29:          System.out.println("マイナス値は合計されません。");
   30:          System.out.println();
   31:          continue;
   32:    }

 34行目は、変数sumに、入力された数値である変数numを足しています。
 そして、36~37行目で、入力された数値と現在の合計値を表示しています。
   34:    sum += num;
   36:    System.out.println("入力値は" + num + "です。");
   37:    System.out.println("合計値は" + sum + "です。");
   38:    System.out.println();

 39~47行目はif – else if文です。
 39行目のif文は、変数sumが77と等しかったら40、41行目の処理が実行されるという記述です。40行目でメッセージを表示し、breakで内側のwhile文から抜けます。抜けた場合は、内側のwhile文の終端である49行目の次の行の50行目が実行されます。51行目は外側のwhile文の終端なので、17行目に戻ります。
 39行目の「sum == 77」に当てはまらず、43行目の「sum > 100」の条件式が成立する場合は、44~46行目の処理が実行されます。45、46行目でメッセージ表示や改行を行います。46行目はラベル付きcontinueです。「Outer」という名前のラベルの付いたループ文である外側のwhile文の最初の17行目にジャンプします。
   39:    if(sum == 77){
   40:          System.out.println("ラッキー!合計値は77です。");
   41:          break;
   42:    }
   43:    else if(sum > 100){
   44:          System.out.println("合計値はが100を超えたのでリセットされます。");
   45:          System.out.println();
   46:          continue Outer;
   47:    }
   49:  }
   50:  System.out.println("値はリセットされます。");
   51: }

 このプログラムの処理の流れは、図 7.7.2のフローチャートを参照して下さい。

ポイント

 ・ break文やcontinue文で、直近のループ文より外側のループ文まで処理の流れを制御するには、ラベルを使う。

図 7.7.2 : ContinueLabelのフローチャート



NEXT>> 7.8 本章のまとめ

f