その他の制御文

プログラムは通常上から順に実行していくが,以下のような構文要素により 実行の順番を制御することができるということを扱ってきた.
条件分岐文
if文,if-else文
繰り返し文
for文,while文,do 文
メソッド呼び出し
メソッドからのリターン
return 文
ここでは,それ以外の制御文を紹介する.

break文とcontinue文

for文,while文などの繰り返し文でプログラムを書いていると,以下のよう なことを書きたくなってくることがある. 繰り返し部分の途中で繰り返しを終了するためにあるのが,break文である. 下のように使う.
プログラム

// コマンドラインに数字列を引数に与えて,>0の間加算して表示する
class SumArgs{
  public static void main(String[] args){
    int sum=0,num;
    int i;
     // 文字列の配列 argsの要素数は args.length
    for(i=0;i< args.length;i++){
       // 文字列からintへの変換
      num=Integer.parseInt(args[i]);
       // 0以下の時は,break文によってfor文から抜ける.
      if(num<=0) break;
       // sumにnumの値を足し込む
      sum=sum+num;
    }
     // 表示する
    System.out.println("sum="+sum);
  }
}
実行例

dell.tanaka.ecc.u-tokyo.ac.jp% java SumArgs 20 30 0 40
sum=50
dell.tanaka.ecc.u-tokyo.ac.jp% java SumArgs 20 30 40
sum=90
一方,残りの繰り返し部分を飛ばすために用意されているのが continue文で ある.例を見てみる.
// コマンドラインに数字列を引数に与えて,>0の時は平方根を加算して表示する
class SqrtSum{
  public static void main(String[] args){
    double sum=0.0;
    int i,num;
     // 文字列の配列 argsの要素数は args.length
    for(i=0;i< args.length;i++){
       // 文字列からintへの変換
      num=Integer.parseInt(args[i]);
       // 0以下の時は,以下の文は実行しない
      if(num<=0) continue;
       // sumにnumの平方根の値を足し込む
      sum=sum+Math.sqrt(num);
    }
    System.out.println("sum="+sum);
  }
}

実行例

dell.tanaka.ecc.u-tokyo.ac.jp% java SqrtSum 10 20 -1 3
sum=9.366464422736836
continue文はfor文の繰り返し文を飛ばすだけで,
    for(i=0;i< args.length;i++){
の i++ は実行することに注意して欲しい.上の例は実は,
// コマンドラインに数字列を引数に与えて,>0の時は平方根を加算して表示する
class SqrtSum{
  public static void main(String[] args){
    double sum=0.0;
    int i,num;
     // 文字列の配列 argsの要素数は args.length
    for(i=0;i< args.length;i++){
       // 文字列からintへの変換
      num=Integer.parseInt(args[i]);
       // 0以下の時は,以下の文は実行しない
      if(num>0){
       // sumにnumの平方根の値を足し込む
        sum=sum+Math.sqrt(num);
      }
    }
    System.out.println("sum="+sum);
  }
}
と continueを使わずに書けるのだが,ifなどの深いところに continue文を書 く場合は,このような書き換えができないこともある.

2重3重の繰り返し文の中での,break文,continue文はその文を含む最も内側 の繰り返し文に対応する.外側に対応させる時は,あらかじめラベル付の繰り 返し文としておいて,ラベル付のbreak文,continue文を使うと良い.この例を あげる.

プログラム

// コマンドラインに数字列を引数に与えて,合成数を1つ見つけたら表示して終わる
class FindNoPrime{
  public static void main(String[] args){
    int sum=0,num;
    int i,j;
     // 外側の for 文に toploop というラベルをつける
    toploop: for(i=0;i< args.length;i++){
      num=Integer.parseInt(args[i]);
      if(num<=1) continue;
      for(j=2;j*j<=num;j++){
	if(num%j==0){
	  System.out.println("合成数"+num+"をみつけました");
	    // この break 文は外側の for 文を抜ける
	  break toploop;
	}
      }
    }
     // break で抜けなかった時の i の値は args.length になっている
    if(i==args.length)
      System.out.println("合成数は見つかりませんでした");
  }
}

実行例

dell.tanaka.ecc.u-tokyo.ac.jp% java FindNoPrime 3 7 1000 20
合成数1000をみつけました
dell.tanaka.ecc.u-tokyo.ac.jp% java FindNoPrime 3 7 5 13
合成数は見つかりませんでした
break文やcontinue文にあたる制御文を用意していない昔のプログラミング言語では,
  • ループの途中で,変数に特定の値を入れて次の終了判定時にその変数の 値をチェックする
  • goto文という,自由な場所に制御を移すことのできる構文を用意する
などの解決策が取られた.いずれもプログラムが汚くなる(複雑に絡み あっているので,スパゲティプログラムと呼ばれることがある)ので,その反 省として1970年代に構造化プログラミングという考え方が生まれた.Cも含め て現在のプログラミング言語の多くは,この考え方に基づいている(あたりま えになったので,誰も構造化プログラミングなどと言わないが).

switch文

整数値による多方向分岐をおこなうために,switch文というのが用意されて いる.実例を見てみる.
プログラム

class SwitchTest{
  public static void main(String[] args){
    int num=Integer.parseInt(args[0]);
     // numの値に応じて,「case 3」, 「case 2」, 「case 1」,「default」の
     // いずれかのラベルに分岐する
    switch(num){
     // numの値が3の時はここに飛ぶ
    case 3: 
      System.out.println("3は結構好きな数だ");
       // この break は switch文から抜けることを意味する.
      break;
     // numの値が2の時はここに飛ぶ
    case 2:
      System.out.println("2も嫌いではない");
      break;
     // numの値が1の時はここに飛ぶ
    case 1:
      System.out.println("1はそんなに好きではない");
      break;
     // numの値が1, 2, 3以外の時はここに飛ぶ
    default:
      System.out.println(num+"は好きでも嫌いでもない");
      break;
    }
  }
}

実行例

dell.tanaka.ecc.u-tokyo.ac.jp% java SwitchTest 2
2も嫌いではない
dell.tanaka.ecc.u-tokyo.ac.jp% java SwitchTest 4
4は好きでも嫌いでもない
dell.tanaka.ecc.u-tokyo.ac.jp% java SwitchTest 1
1はそんなに好きではない
このような使い方の場合は,if-else文を使って以下のように書き直すことが できる.
class SwitchTest1{
  public static void main(String[] args){
    int num=Integer.parseInt(args[0]);
    if(num==3){
      System.out.println("3は結構好きな数だ");
    }
    else if(num==2){
      System.out.println("2も嫌いではない");
    }
    else if(num==1){
      System.out.println("1はそんなに好きではない");
    }
    else{
      System.out.println(num+"は好きでも嫌いでもない");
    }
  }
}
ここで,注意するのは,switchのラベルは単なる分岐先を表すラベルなので, breakを入れないと,続けて実行してしまうことである.実際,さきほどの break文をすべて取り去ると,
プログラム

class SwitchTest2{
  public static void main(String[] args){
    int num=Integer.parseInt(args[0]);
    switch(num){
    case 3: 
      System.out.println("3は結構好きな数だ");
       // breakがないので,続けて次の文を実行する
    case 2:
      System.out.println("2も嫌いではない");
       // breakがないので,続けて次の文を実行する
    case 1:
      System.out.println("1はそんなに好きではない");
       // breakがないので,続けて次の文を実行する
    default:
      System.out.println(num+"は好きでも嫌いでもない");
    }
  }
}

実行例

dell.tanaka.ecc.u-tokyo.ac.jp% java SwitchTest2 2
2も嫌いではない
1はそんなに好きではない
2は好きでも嫌いでもない
dell.tanaka.ecc.u-tokyo.ac.jp% java SwitchTest2 1
1はそんなに好きではない
1は好きでも嫌いでもない
となってしまう.switch文で注意するのは以下の通り,
 
  • caseに続くのは定数でなくてはいけない.
     int x=100, y=100;
     switch(x){
      case y:
       System.out.println("x==yです\n");
     }
    
    などとは書けない.
  • 「switch(式)」の式は整数の式でなくてはいけない.浮動小数点,文字 列等のオブジェクト型,配列は使えない.したがって,「case 定数」の定数 部分も整数(文字定数を含む)である必要がある.
  • switch文とcontinue文は対応しない.switch文の中の continue文は switch文を含むもっとも内側の繰り返し文に対応する.繰り返し文の中に ない switch文ではエラーになる.
  • 「case 定数」で同じ定数を使ったものが1つのswitch文の中で2回以上 現れてはいけない.defaultも同様.
  • defaultのラベルがない switch文も許される.その時は,最後に defaultがあるのと同じ意味になる.

  • 授業のページに戻る