【Java】ループ文

#ループ文
##ループ文とは
ループ処理の主な機能は、 指定された回数分や特定の条件下にある間、処理を実行し続けること です。

Javaにおいては、for文、while文という繰り返し文の構文が用意されていて、Javaに携わる上では頻繁に使用する機能になります。

## for文
ループカウンタなどを使用して、**定められた回数だけ同じ処理を繰り返したいとき**に使用します。
ループカウンタと、添え字による配列要素へのアクセスは非常に相性がいいため、**配列の中身を単純に１つ１つ参照する場合などによく使用されます。**

###for文の書き方
書き方はこちらです。

```
for (ループカウンタ初期化; 継続条件; ループカウンタ更新) {
    繰り返し行う処理
}
```
よく使われる内容として、配列の中を全部表示する方法があります。
下記の場合、**配列の番号**と**配列の値**をそれぞれ出力する方法です。

```java
        String[] type = { "ほのお", "みず", "くさ", "いわ", "でんき", "どく", "エスパー", "じめん" };

        // 配列arrの中身を全て表示する
        for (int i = 0; i < type.length; i++) {
            System.out.println("type[" + i + "]  " + type[i]);
        }
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/830ae15f-71ca-fd43-6096-2d7ee24f4e9d.png)

###for文の使用するケースについて
このあとのwhile文と使うケースの違いについてですが、
主に**繰り返す回数が明確な場合に使用**します。例を上げると

- 九×九のマス目を作成する。
- fizz buzzでよくある「1〜100の間の数字で」といった条件がある場合

などかと思います。

##while文
ほかにwhile文という構文があり、書き方がこちら。

```
while (継続条件) {
    処理
}
```

サンプル文であまり見ないパターンであるものの、-5から5までの数を出力するプログラムです。
※コード内にも書きましたが **`i++`を記述しないと無限ループになるため注意！**

```java
// 変数の初期化
int i = -5;

// 1から10までの数字を出力
while (i <= 5) {
System.out.println(i);
i++; // この記述をしないと無限ループになる！
}
```

whileを使った簡単な計算プログラムがこちらになります。

```java
package practice_project;
import java.util.Scanner;

public class Practice1 {
    public static void main(String[] args) {
        int inputNum;       // ユーザが入力する値
        int sum = 0;        // 合計値（最初は0からスタート）

        // ユーザ入力読み込みオブジェクトを生成
        Scanner scanner = new Scanner(System.in);

        // 初回の数値入力
        System.out.print("数値入力（-1で終了）：");
        inputNum = scanner.nextInt();

        // ユーザから「-1」が入力されるまで、入力された数値をsum変数に加算
        while (inputNum != -1) {
            // 入力値をsumに加算
            sum += inputNum;

            // ２回目以降の数値入力
            System.out.print("数値入力（-1で終了）：");
            inputNum = scanner.nextInt();
        }

        // 合計値を表示
        System.out.println("入力された数値の合計は " + sum);

    }
}
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/21789664-28b6-cac6-bc19-f086daec4b75.png)

###while文の使用するケースについて
for文と使うケースの違いについてですが、
**繰り返す回数が定まらない(前もって分からない)場合に使用します。**

- ユーザーのストップなどの入力値を受け取るまでは処理を繰り返す、といったような処理を行う場合
- 電卓のように、答えが出るまで計算を続ける場合。

などかと思います。

##do-while文
do-while文はwhile文と同様、括弧内の継続条件を満たしている間、処理を繰り返します。
書き方はこちら。

```
do {
    処理
} while (継続条件);
```
記述を見るとピンとくるかもですが、**forやwhileは前判定**であるのに対し、**do-whileは後判定**であるという違いがあります。

この後ろ判定のループでは、まず最初にループ内の処理を１回実行してから、継続条件の判定を行います。
つまり、forやwhileは 0回以上の繰り返し処理 、do-whileは 1回以上の繰り返し処理 で使用します。

while文で書いた内容をdo-while文で書き換えるとこんな感じになります。

```java
package practice_project;
import java.util.Scanner;

public class Practice1 {
    public static void main(String[] args) {
        int inputNum;       // ユーザが入力する値
        int sum = 0;        // 合計値（最初は0からスタート）

        // ユーザ入力読み込みオブジェクトを生成
        Scanner scanner = new Scanner(System.in);

        // 初回の数値入力
        System.out.print("数値入力（-1で終了）：");
        inputNum = scanner.nextInt();

        // ユーザから「-1」が入力されるまで、入力された数値をsum変数に加算
        do {
            // 入力値をsumに加算
            sum += inputNum;

            // 加算値を入力
            System.out.print("加算値入力（-1で終了）：");
            inputNum = scanner.nextInt();

        } while (inputNum != -1);

        // 合計値を表示
        System.out.println("入力された数値の合計は " + sum + " です。");

    }
}
```

###do-while文の使用するケースについて
do-while文を使用する場面はそんなに多くありません。
**「最低一回は処理を行ってから繰り返しの判定を行いたい」**
という場面に遭遇したらdo-while文の使用を検討します。

##break文と continue文
繰り返し処理のfor文とwhile文では、**`break文`と`continue文`によって、ループの流れを変えることができます。**
##break文
break文を記述すると、その時点で**ループ処理から抜けます。**
for文にbreak文を組み込んだ場合の構文はこちら。

```
for (int i = 0; i < 数字; i++) {
    if (何かの条件) {
        break;      // 条件に一致したらループから抜ける
    }
}
```
例えば先程書いたのプログラムにbreakを追記し、「配列の4番目までいったら処理を止める」という内容にします。

```java
String[] type = { "ほのお", "みず", "くさ", "いわ", "でんき", "どく", "エスパー", "じめん" };

        // 配列arrの中身を全て表示する
        for (int i = 0; i < type.length; i++) {
            System.out.println("type[" + i + "]  " + type[i]);
            if (i > 3) { //配列の4番目になったら..
                break; //処理を終了する
            }
        }
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/97632919-0039-d864-40fa-24d7e69b00d6.png)

##continue文

continue文を書くと、その時点で後の処理をスキップすることが出来ます。

```
while (条件式) {
    [ある処理A]
    continue;
    [ある処理B]
}
```
こちらは「１〜10の数字を出力して3の倍数の時は 数字の処理を行わず、代わりに "3の倍数です" と出力する」プログラムです。

```java
// for文で1から20の数字を出力
        for (int i = 1; i <= 10; i++) {
            // 負の値の場合は、以降の処理をスキップ
            if (i % 3 == 0) {
                System.out.println("3の倍数");
                continue;
            }
            System.out.println(i);
        }
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/8eda3571-e32d-d670-853c-d1b6d1d0d5da.png)

##無限ループ
ループ文において、継続条件が常に真である場合、そのループは 無限ループ（永久ループ） となります。

###意図的に行う無限ループ
無限ループ は、ミスではなく意図して発生する場合があり、それは
**「繰り返す回数が決まっておらず、繰り返し処理を実行するうちに ある条件が成立したときにだけループを終了したい場合」**
などに 無限ループ を使用します。

使用する際は、**ある条件が成立したときに breakや return を実行してループやメソッド処理の ブロック を抜けるようにします**。

条件を満たすまで、無限に意識高い系ポエムを、○時〜○時の間の(乱数)分にSNS上に投稿し続けるプログラムも面白いかもしれません。

###無限ループさせるには
####for文の場合
for文の場合は、**for (;;)と記述する**と 無限ループ させることができます。
継続条件が省略されているため、判定が行われないので、 無限ループ となります。

```
// forの無限ループ
for (;;) {
    ループ中の処理
    if (ループ脱出条件) {
        break;
    }
    ループが終わったあとの処理
}
```

####while文の場合
while文の場合は、**while (true)として、継続条件に true を指定**することで 無限ループ させることができます。

```
while (true) {
    ループ中の処理
    if (ループ脱出条件) {
        break;
    }
    ループが終わったあとの処理
}
```

これは、while文の条件式に true（真） が直接指定されているため、
継続条件が false（偽） になることがないので 無限ループ となります。
for文の場合は、for (;;)と記述すると 無限ループ させることができます。
継続条件が省略されているため、判定が行われないので、 無限ループ となります。
####do-while文の場合

###無限ループのサンプルプログラム

```java
package practice_project;
import java.util.Scanner;

public class Practice1 {
    public static void main(String[] args) {
        int inputNum;       // ユーザが入力する値
        int sum = 0;        // 合計値（最初は0からスタート）

        // ユーザ入力読み込みオブジェクトを生成
        Scanner scanner = new Scanner(System.in);

        // 初回の数値入力
        System.out.print("数値入力（-1で終了）：");
        inputNum = scanner.nextInt();

        // ユーザから「-1」が入力されるまで、入力された数値をsum変数に加算
        while (inputNum != -1) {
            // 入力値をsumに加算
            sum += inputNum;

            // ２回目以降の数値入力
            System.out.print("数値入力（-1で終了）：");
            inputNum = scanner.nextInt();
        }

        // 合計値を表示
        System.out.println("入力された数値の合計は " + sum);
    }
}
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/ca1d7cdc-4b6b-360f-468e-c450eb75da09.png)

##多重ループ
ループ文の中に更にループ文を記述することを多重ループと呼びます。

##多重ループを用いて九九を作る

以前作った際にかなり手こずったのでここでもまとめてみます。
###コードと実行内容
まずは形からお見せします。for文の多重ループを用いてコードを書いているのがわかるかと思います。

```java
// 九九表を表示
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                System.out.print(i * j + " ");
            }
            System.out.println();
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/612d98ee-c4b3-6b6e-2302-e8d8556c37d6.png)

実行結果を見ると分かる通り、外側の i が１つ増加する度に、毎回内側の j が 1 から 9 まで値を変えて九九の計算をしています。
また、内側の j が 9 まで回った後、外側の i を１つ増やす直前に **`System.out.println();`**で改行を出力しています。
これにより、一つの段を表示し終わったタイミングで改行が行われることになります。

###【補足】 System.out.println();とSystem.out.print();

自分は以前このような形にする際に、
**`System.out.println();`**と
**`System.out.print();`**の使い分けができておらず、ループの内容が正しいのに出力結果が画像のように縦に出力されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/734bc285-3cf7-e59d-8042-be858022750f.png)

原因は、値の出力をすべて System.out.print **ln**と入力していたためです。

```
System.out.print(表示する内容);
System.out.println(表示する内容);
```
書き方は同じでも決定的な違いは、**改行されるかされないかです。**
当時違いがわからず、ループの書き方を調べまくっても解決できなかったのですが、原因がこいつだった過去があります。

- **println は改行される**
- **printは 改行されない**

コードと実行結果がヘラってますが、それぐらいして脳に焼き付けようと思います。

```java
        // println は改行される
        System.out.println("println は改行される");
        System.out.println("println は改行される");

        // print は改行されずにつながっていく
        System.out.print("printは改行されずにつながっていく");
        System.out.print("printは改行されずにつながっていく");
        System.out.print("printは改行されずにつながっていく");
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613675/eb8edbc7-b6bb-16eb-0884-f0018f4f22da.png)

##おわりに
ループ分は他の言語を扱っていたときも触れていましたが、色んなパターンで書いてアウトプットしていくことでやっとスキルになるのかなと思いました。
これからも更新していきます。


# 参考文献
- [Javaで文字列を出力する：print(), println()](https://uxmilk.jp/48801)