while文

目次
  • 解説
  • 1. ループとは
  • 2. while文
問題に挑戦!
進捗を変更する




解説

1. ループとは


配列のページで使用したサンプルコードを再度見てみましょう。

    static void practiceArray() {
        int[] sellCounter = new int[3]; // 変数sellCounterをint型3つに区切る

        sellCounter[0] += 10;           // 区切った0番目に1を加算
        sellCounter[1] += 20;           // 区切った1番目に2を加算
        sellCounter[2] += 30;           // 区切った2番目に3を加算

        Logger.out(sellCounter[0]);     // それぞれの「変数」で
        Logger.out(sellCounter[1]);     // 加算した値を
        Logger.out(sellCounter[2]);     // 保持できている
    }

最後の3行で配列の各要素の中身を順番にターミナルへ出力させていますね。よく見ると、添字が0から2に増えているだけで、それ以外は全く同じ処理を繰り返しています。単純な処理ではありますが、もしもこの配列の要素数が100個の場合、この行が100行必要になってしまいます!

これを解決するのがループLoop繰り返し)処理です。while文を使用した最も単純な構造のループ処理は以下のようになりますが、絶対に実行しないでください

while (true) {
    Logger.out("止まりません");
}

これはターミナルに「止まりません」を延々と出力し続けます。キーワード「while」に続く丸括弧の中には、if文と同じように条件式を書きます。この条件式の評価結果がtrueの間、ブロック内をひたすら繰り返す、これがwhile文なのです。

さて、万一実行してしまった場合には、「Ctrl + C」でコードを中断し、「Terminate batch job (Y/N)?」に「Y」を入力して強制終了させましょう。

2. while文


先ほど再掲したサンプルコードを次のように書き直してみましょう。

    static void practiceWhile() {
        int[] sellCounter = new int[] { 10, 20, 30 }; // 宣言時代入に変更

        int counterIndex = 0;                   // 添字に使うIndex変数
        Logger.out(sellCounter[counterIndex]);  // 添字に応じた出力処理
        counterIndex++;                         // 添字を+1
        Logger.out(sellCounter[counterIndex]);  // 添字に応じた出力処理
        counterIndex++;                         // 添字を+1
        Logger.out(sellCounter[counterIndex]);  // 添字に応じた出力処理
    }

添字の部分をIndex変数に置き換えると、出力処理の行はすべて同じとなり、Index変数を増加させる処理もまた、同じコードの繰り返しとなりました。この繰り返しをwhile文を使用したループで置き換えてみましょう。

    static void practiceWhile() {
        int[] sellCounter = new int[] { 10, 20, 30 };

        int counterIndex = 0;                       // 添字に使うIndex変数
        while (counterIndex <= 2) {                 // 添字が2以下の間
            Logger.out(sellCounter[counterIndex]);  // 添字に応じた出力処理
            counterIndex++;                         // 添字を+1
        }
    }

5行目の条件式がtrueの間、6行目と7行目が繰り返されます。つまり、counterIndex0の時、1の時、2の時の3回ブロック内が実行され、3になったら9行目以降に進む流れとなります。

このメソッド内でプログラムがどう実行されるか、表に整理してみましょう。

行番号行われる処理counterIndex
1メソッド内の処理を開始する-
2int型配列の変数sellCounterを宣言し、sellCounter[0]に10、
sellCounter[1]に20、sellCounter[2]に30を代入する
-
4int型のIndex変数counterIndexを宣言し、0を代入する0
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
0
6sellCounter[0]の中身=10を出力する0
7counterIndexを1増やして1にする1
85行目に戻る(while文のルール)1
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
1
6sellCounter[1]の中身=20を出力する1
7counterIndexを1増やして2にする2
85行目に戻る(while文のルール)2
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
2
6sellCounter[2]の中身=30を出力する2
7counterIndexを1増やして3にする3
85行目に戻る(while文のルール)3
5counterIndexが2以下でないため、
条件式がfalseとなりブロックをスキップ
3
9メソッド内の処理を終了してMainメソッドに戻る-

ループ処理や複雑な条件分岐などは、このように実行される行番号処理内容、そして重要な変数の中身の状態を表に書き出してみると、読み解きやすくなります。

counterIndexの値が3になったことにより、ひたすら繰り返されるwhile文から「脱出」できていることがわかると思います。つまり、条件式に使われているIndex変数を変化させる処理を忘れてしまうと無限ループとなってしまいますので注意しましょう。

コードが整理され重複感はなくなりましたが、もうひとつ工夫をしてみましょう。条件式の中に固定で「2」を書いていましたが、「.length」で取得できる要素数未満を条件とすることで、配列の要素数に影響されないコードとなります。

    static void practiceWhile() {
        int[] sellCounter = new int[] { 10, 20, 30 };

        int counterIndex = 0;                       // 添字に使うIndex変数
        while (counterIndex < sellCounter.length) { // 添字が要素数未満の間
            Logger.out(sellCounter[counterIndex]);  // 添字に応じた出力処理
            counterIndex++;                         // 添字を+1
        }
    }

2行目で代入している要素の数をいろいろ変更して、その結果を確認してみてください。

問題

確認問題


確認問題1

次のコードの中で、while文の使い方が正しく、
変数aの値が最終的に5となる構文はどれか。

実践問題


(1)VSCodeを起動し、ヘッダーメニューの「ファイル」>「フォルダーを開く...」から、「workspace_java_basic」プロジェクトを開いてください。
(2)workspace_java_basic」プロジェクトの「net.digskill
パッケージの「ArrayAndLoop.java」を開いてください。
※無い場合は「配列」を先に学習しましょう。
(3)ArrayAndLoop」クラス内に次のサンプルコードのメソッドをコピー&ペーストし、
mainから呼び出せるようにして、「F5」で実行できることを確認してください。
(4)コメント行に記された各問題文に対し、答えとなるプログラムコードを
問題文の次の空白行以降に書き込みまたは書き換えて
、「F5」で実行してください。
    static void questionWhile() {
        // (問1)空白行にString型の配列変数arrayQ1を作成し、
        // 「あ」「い」「う」「え」「お」の5つの要素を代入してください。
        // 続けてwhile文によるループ処理を作成し、
        // 変数displayQ1にすべて結合させてください。
        String displayQ1 = "";

        Logger.out(displayQ1);

        // (問2)空白行にwhile文によるループ処理を作成し、
        // arrayQ1から「あ」「う」「お」のみを
        // 変数displayQ2に結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ2 = "";

        Logger.out(displayQ2);

        // (問3)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ3にarrayQ1の中身を逆順ですべて結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ3 = "";

        Logger.out(displayQ3);

        // (問4)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ4にarrayQ1の中身の内、
        // 「え」のみを除いて逆順で結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ4 = "";

        Logger.out(displayQ4);
    }
実行結果例を表示
[2020/12/31 12:34:56.789] あいうえお
[2020/12/31 12:34:56.789] あうお
[2020/12/31 12:34:56.789] おえういあ
[2020/12/31 12:34:56.789] おういあ

正解


(問1)正解を表示
String[] arrayQ1 = new String[] { "あ", "い", "う", "え", "お" };
int idxQ1 = 0;
while (idxQ1 < arrayQ1.length) {
    displayQ1 += arrayQ1[idxQ1];
    idxQ1++;
}

(問2)正解を表示
int idxQ2 = 0;
while (idxQ2 < arrayQ1.length) {
    displayQ2 += arrayQ1[idxQ2];
    idxQ2 += 2;
}

(問3)正解を表示
int idxQ3 = arrayQ1.length - 1;
while (idxQ3 >= 0) {
    displayQ3 += arrayQ1[idxQ3];
    idxQ3--;
}

(問4)正解を表示
int idxQ4 = arrayQ1.length - 1;
while (idxQ4 >= 0) {
    if (!arrayQ1[idxQ4].equals("え")) {
        displayQ4 += arrayQ1[idxQ4];
    }
    idxQ4--;
}

正解プログラムコード全文を表示
    static void questionWhile() {
        // (問1)空白行にString型の配列変数arrayQ1を作成し、
        // 「あ」「い」「う」「え」「お」の5つの要素を代入してください。
        // 続けてwhile文によるループ処理を作成し、
        // 変数displayQ1にすべて結合させてください。
        String displayQ1 = "";
        String[] arrayQ1 = new String[] { "あ", "い", "う", "え", "お" };
        int idxQ1 = 0;
        while (idxQ1 < arrayQ1.length) {
            displayQ1 += arrayQ1[idxQ1];
            idxQ1++;
        }
        Logger.out(displayQ1);

        // (問2)空白行にwhile文によるループ処理を作成し、
        // arrayQ1から「あ」「う」「お」のみを
        // 変数displayQ2に結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ2 = "";
        int idxQ2 = 0;
        while (idxQ2 < arrayQ1.length) {
            displayQ2 += arrayQ1[idxQ2];
            idxQ2 += 2;
        }
        Logger.out(displayQ2);

        // (問3)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ3にarrayQ1の中身を逆順ですべて結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ3 = "";
        int idxQ3 = arrayQ1.length - 1;
        while (idxQ3 >= 0) {
            displayQ3 += arrayQ1[idxQ3];
            idxQ3--;
        }
        Logger.out(displayQ3);

        // (問4)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ4にarrayQ1の中身の内、
        // 「え」のみを除いて逆順で結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        String displayQ4 = "";
        int idxQ4 = arrayQ1.length - 1;
        while (idxQ4 >= 0) {
            if (!arrayQ1[idxQ4].equals("え")) {
                displayQ4 += arrayQ1[idxQ4];
            }
            idxQ4--;
        }
        Logger.out(displayQ4);
    }