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行目が繰り返されます。つまり、counterIndexが0の時、1の時、2の時の3回ブロック内が実行され、3になったら9行目以降に進む流れとなります。
このメソッド内でプログラムがどう実行されるか、表に整理してみましょう。
行番号 | 行われる処理 | counterIndex |
---|---|---|
1 | メソッド内の処理を開始する | - |
2 | int型配列の変数sellCounterを宣言し、sellCounter[0]に10、 sellCounter[1]に20、sellCounter[2]に30を代入する | - |
4 | int型のIndex変数counterIndexを宣言し、0を代入する | 0 |
5 | counterIndexが2以下であるため、 条件式がtrueとなりブロック内に入る | 0 |
6 | sellCounter[0]の中身=10を出力する | 0 |
7 | counterIndexを1増やして1にする | 1 |
8 | 5行目に戻る(while文のルール) | 1 |
5 | counterIndexが2以下であるため、 条件式がtrueとなりブロック内に入る | 1 |
6 | sellCounter[1]の中身=20を出力する | 1 |
7 | counterIndexを1増やして2にする | 2 |
8 | 5行目に戻る(while文のルール) | 2 |
5 | counterIndexが2以下であるため、 条件式がtrueとなりブロック内に入る | 2 |
6 | sellCounter[2]の中身=30を出力する | 2 |
7 | counterIndexを1増やして3にする | 3 |
8 | 5行目に戻る(while文のルール) | 3 |
5 | counterIndexが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);
}