Chapter 11

繰り返し処理

KeitoYuasa
KeitoYuasa
2023.02.12に更新

while文

条件式がtrueの間、繰り返し処理を行う制御構文

  • while(条件式){処理;}
No. 注意点
1 処理文が1文しかない場合は、{}を省略できる。
2 条件式は、boolean型になる式でなければいけない。
3 条件式に、while(true)と指定した場合、無限ループになってしまう。
4 条件式にwhile(false)と指定した場合(直接false指定のみ)、コンパイルエラー。処理文が実行されないので。

以下では、while文の例を示す。
int i = 15;とした場合、条件式がfalsenになるので、何も出力されずに終了する。

Training.java
class Training {
    public static void main(String[] args){
        int i = 10;
        while(i < 15){
          System.out.println(i);
          i++; //これがないと無限ループ
        }
    }
}
//出力結果:
//10
//11
//12
//13
//14

do while文

条件式がtrueの間、繰り返し処理を行う制御構文。
while文との違いは、判定の後に処理を行うか、処理の後に判定を見るかの違い。

  • do{処理;} while(条件式);
    |No.|注意点|
    |--|--|
    |1|処理文が1文しかない場合は、{}を省略できる。|
    |2|条件式は、boolean型になる式でなければいけない。|
    |3|条件式に、while(true)と指定した場合、無限ループになってしまう。|
    |4|条件式にwhile(false)と指定した場合(直接false指定のみ)、エラーにならずにdoは実行される。|

以下では、while文とdo whileb文の違いを示している。

Training.java
class Training {
    public static void main(String[] args){
        int i = 15;
        
        while(i != 15 && i == 14){
          System.out.println(i);
        }

        do{
          System.out.println(i);
          i--;
        }while(i != 15 && i == 14);
    }
}
//出力結果:
//15
//14

for文

条件式がtrueの間、繰り返し処理を行う制御構文

  • for(スタート値;継続条件;増減式){繰り返し中に実行する処理;}
  • スタート値:カウンタ変数と呼ぶ。
  • 継続条件:繰り返し処理を終わらせる条件のこと。ここがtrue場合、繰り返しを続ける。
  • 増減式:1回の繰り返し処理ごとに実行する処理。
No. 注意点
1 処理文が1文しかない場合は、{}を省略できる。
2 条件式は、boolean型になる式でなければいけない。
3 スタート値、継続条件、増減式はそれぞれ省略することができる。
4 継続条件を省略した場合、条件が常にtrueになるので無限ループになる。 そのため、継続条件は省略しないこと。
5 スタート値、継続条件を省略した場合でも;は必ずつける
繰り返し処理の順序 説明
1 継続条件がtrueの場合、以下に続く (スタート値は見ない。最初に継続条件を見る。)
2 for文ブロックの処理が実行される
3 増減式があれば実行。なければ継続条件を見る(この場合、無限ループに注意)。
4 1〜3を繰り返す。

※コードを見た方がわかりやすい

以下のコードでは、5回繰り返し処理を行っている。
インデックスは、0スタートなので繰り返し回数 = 継続条件に指定する数値+1になることに注意。

  • スタート値int i = 0をもとに継続条件i <= 4が判定される
  • 判定条件がtrueになるので、for文ブロックが実行される
  • 増減式i++が実行される(= スタート値が更新される)
  • i = 5となった時点で繰り返しを終了する
Training.java
class Training {
    public static void main(String[] args){
        for(int i = 0; i <= 4; i++){
            System.out.println(i);
        }
    }
}
//出力結果:
//0
//1
//2
//3
//4

スタート値、継続条件、増減式を省略した場合

  • スタート値、継続条件、増減式はそれぞれ省略することができる。
  • スタート値、継続条件を省略した場合でも;は必ずつけること。
  • 継続条件を省略した場合、条件が常にtrueになるので無限ループになる。 そのため、継続条件は省略しないこと。

以下では、スタート値、増減式を省略した例を示す。

Training.java
class Training {
    public static void main(String[] args){
        int i = 0;

        //スタート値を省略
        for(; i < 5; i++){
          System.out.println(i);
        }

        //増減式を省略
        for(int i2 = 0; i2 < 5;){
          System.out.println(i2);
          i2++; //これがないと無限ループ
        }
    }
}
//出力結果:
//0
//1
//2
//3
//4
//0
//1
//2
//3
//4

for文 ()内のルール

No. 注意点
1 スタート値は文にしなければいけない。変数を指定した場合は、コンパイルエラー。
2 スタート値には、変数の宣言式ではない式を2つ指定することが可能。カンマで区切る。
3 スタート値には、変数の宣言式は1つのみ指定できる。それ以上はコンパイルエラー。
4 増減式も複数の式をカンマ区切りで指定できる。
5 スタート値、継続条件を省略した場合でも;は必ずつけること。でないとコンパイルエラー。
//1の例
int i = 0;
for(i; i > 5; i++){} //コンパイルエラー
for(i += 1; i > 5; i++){} //ok

//2の例
int i2 = 0; int i3 = 0;
for(i2++, i3++; i2 + i3 > 5; i2++){} //ok

//3の例
for(int i4 = 0, int i5 = 0; i4 + i5 > 5; i4++){} //コンパイルエラー
for(int i6 = 0, i7 = 0; i6 + i7 > 5; i6++){} //ok(i7は宣言式ではないため)

//4の例
for(int i8 = 0, i9 = 0; i8 + i9 > 5; i8++, i9++){} //ok

//5の例
for(;;){} //ok(無限ループになる)
for(){} //コンパイルエラー

配列の繰り返し処理(シンプル)

for文を使って、配列の要素を出力してみる。

Training.java
class Training {
    public static void main(String[] args){
        int[] arr = {1, 2, 3, 4, 5};

        for (int i = 0; i <= 4; i++){
            System.out.println(arr[i]);
        }
    }
}
//出力結果:
//1
//2
//3
//4
//5

for文を使って、配列の要素を全て足し合わせて出力してみる。

Training.java
class Training {
    public static void main(String[] args){
        int[] arr = {1, 2, 3, 4, 5};
        int sum = 0;

        for (int i = 0; i <= 4; i++){
            sum += arr[i];
        }
        System.out.println(sum);
    }
}
//出力結果:
//15

配列の繰り返し処理(拡張for文を使った楽な方法)

  • 拡張for文:配列やコレクションの要素を順に取り出したい時に使用できる。楽な記述方法。
  • for(要素格納変数の宣言 : 配列名){処理;}
No. 注意点
1 処理文が1文しかない場合は、{}を省略できる。
2 要素格納変数のデータ型は、配列、またはコレクションの要素のデータ型に合わせる必要がある。でないとコンパイルエラー。(varを使うと楽になる)
3 また、要素格納変数のデータ型がdoubleで、配列の要素がint型の場合、自動で型変換が行われるため問題ない。その逆はキャストはできない。
4 要素を全て取り出すと、for文を終了する。
Training.java
class Training {
    public static void main(String[] args){
        char[] c_arry = {'a', 'b', 'c'};

        for(char c : c_arry){
          System.out.println(c);
        }
    }
}
//出力結果:
//a
//b
//c

以下では、ローカル変数型推論のvarを用いて要素格納変数と要素のデータ型の差分を無くしている。
変数cには、varがついているので、データ型を自動でセットしてくれる。

Training.java
class Training {
    public static void main(String[] args){
        double[] c_arry = {1., 2., 3.};

        for(var c : c_arry){
          System.out.println(c);
        }
    }
}
//出力結果:
//1.0
//2.0
//3.0

break文

繰り返し処理を終了させる文。(if文とセットで使われる)

No. 注意点
1 breakは、繰り返し処理文内または、switchのcase内で用いられる。それ以外で用いた場合はコンパイルエラー。
2 同じブロック内でbreak文の後に処理を書くことはコンパイルエラー(break後の処理は結局実行されないから文法的にアウト)
3 if文ブロック内にbreakを定義してもif文から抜けるわけではない。for文から抜ける。

以下では、i == 3になれば、繰り返し処理を終了する記述をしている。

Training.java
class Training {
    public static void main(String[] args){
        for(int i = 0; i <= 4; i++){
            if(i == 3){
                break;
		//System.out.println(i); break後に処理を書くのはコンパイルエラー
            }
            System.out.println(i);
        }
    }
}
//出力結果:
//0
//1
//2

continue文

繰り返し処理をスキップさせる文。(if文とセットで使われる)

No. 注意点
1 continueは、繰り返し処理文、switchのcase内で用いられる。それ以外で用いた場合はコンパイルエラー。
2 switchのcase文内で、continueを記述した場合、breakとは違って、対象がfor文になる。
3 同じブロック内でcontinue文の後に処理を書くことはコンパイルエラー(continue後の処理は結局実行されないから文法的にアウト)
4 if文ブロック内にcontinueを定義してもif文をスキップするわけではない。for文をスキップし、先頭に戻る。

以下では、i == 3になれば、繰り返し処理をスキップする記述をしている。

Training.java
class Training {
    public static void main(String[] args){
        for(int i = 0; i <= 4; i++){
            if(i == 3){
                continue;
                //System.out.println(i); continue後に処理を書くのはコンパイルエラー
            }
            System.out.println(i);
        }
    }
}
//出力結果:
//0
//1
//2
//4

以下では、繰り返し処理文外でcontinueを使用した例を示す。
以下は、コンパイルエラーになる。

Training.java
class Training {
    public static void main(String[] args){
        int i = 0;

        if(i == 0){
          System.out.println(i);
          continue; //コンパイルエラー
        }
    }
}

for文のネスト

  • ネスト(入れ子):あるものの中に、それと同じ種類のものが入っている構造をネスト、または入れ子構造という。
Training.java
class Training {
    public static void main(String[] args){
        for(int i = 0; i <= 2; i++){
            for(int j = 0; j <= 2; j++){
                System.out.println(i + "-" + j);
            }
        }
    }
}
//出力結果:
//0-0
//0-1
//0-2
//1-0
//1-1
//1-2
//2-0
//2-1
//2-2

ラベル

繰り返し処理文がネストしている場合、break, continue文は、内側の繰り返し処理文にのみ適用される。
外側の繰り返し処理文に適用させたい場合に、ラベルを用いる。
要は、どの繰り返し処理文に適応させたいのかを名前で識別するためのもの。

  • ラベル名: for(){for(){break ラベル名;}}
No. 注意点
1 ラベル名定義の後は、コロンを指定すること。

以下では、ラベルを用いて、外側のループをbreakしている例を示す。

Training.java
class Training {
    public static void main(String[] args){
        loop1:
        for(int i = 0; i < 3; i++){
          for(int j = 0; j < 3; j++){
            System.out.println("" + i + j);
            if(i == 1 && j == 0){
              System.out.println("外側のfor文を終了");
              break loop1;
            }
          }
        }
    }
}
//出力結果:
//00
//01
//10
//外側のfor文を終了

以下では、ラベルを用いないbreakの例を示す。
つまり、内側のループだけを終了する。

Training.java
class Training {
    public static void main(String[] args){
        for(int i = 0; i < 3; i++){
          for(int j = 0; j < 3; j++){
            System.out.println("" + i + j);
            if(i == 1 && j == 0){
              System.out.println("外側のfor文を終了");
            }
          }
        }
    }
}
//出力結果:
//00
//01
//02
//10
//外側のfor文を終了
//20
//21
//22