プログラミングをする際に、数値や数式、文字列を繰り返し用いるシーンは多く見られます。
基本のループ(繰り返し)処理として、for文とwhile文があります。
まずはfor文について学んでいきましょう。
for文の書き方
for文は、カウンタと呼ばれるループ処理を制御する変数を使って、次のような形式で書きます。
for(カウンタの初期値; ループ処理の条件式; 増減式){
/*
* 実行する処理
*/
}
( )内の3つの要素は、それぞれ以下の役割を持ちます。
- カウンタの初期値 – はじめの値
- ループ処理の条件式 – どのような条件のもとループ処理をおこなうか
- 増減式 – 処理1回ごとに、値をいくつ増やしたり減らしたりするか
次のfor文の処理を実際に書いて、具体的に見ていきましょう。
「com.cmps.forWhile」パッケージを作成し、「ForWhile」クラスを作成して下さい。
作成後、以下のソースを記入してください。
public static void main(String[] args) {
/*
* パターン1,最も基本的なfor文
*/
//for構文の基本形
for(int i = 0; i < 5; i++) {
System.out.println(i);
}
}
結果は「01234」と表示されたと思います。ではその内容を解説していきます。
for(int i = 0; i < 5; i++){では、for文で繰り返す条件を指定しています。
- i = 0; では、for文のカウンタ変数iの初期値を0で設定しています。
- i < 5; では、ループ処理の条件式は、変数iが5より小さい間繰り返すという意味です。
5より小さくなくなったとき、処理を行わなくなります。 - i++ では、増減式で処理1回ごとに1を加算する意味で、i = i + 1 またはi += 1 と同義です。
上記のことから今回のfor文は「0からスタートし(初期値)、5より小さい値まで(条件)、1ずつ足して(増減)、処理を繰り返す」ということを示します。
図で表すと以下のようになります。


値を変えてfor文の動きを確認していきましょう。
今度はfor文をこのように変えましょう。
for(int i = 0; i <= 5; i++) {
System.out.println(i);
}
今度の結果は「012345」と表示されたと思います。先ほどは変数iが5より小さい間繰り返すという意味でしたが
今回は変数iが5以下の間繰り返すという意味になります。
次はfor文をこのように変えましょう。
for(int i = 2; i <= 5; i++) {
System.out.println(i);
}
今度の結果は「2345」と表示されたと思います。先ほどは変数iのカウンタの初期値を0で設定でしたが
今回は変数iのカウンタの初期値を2で設定したため「2」からスタートしたのです。
続いて、for文をこのように変えましょう。
for(int i = 5; i >= 1; i--) {
System.out.println(i);
}
今度の結果は「54321」と表示されたと思います。
今回はi++ではなくi–-のため、加減式で処理1回ごとに1を減算する意味となるため、このような結果になります。
ちなみに、増減式は++または–以外の書き方も可能です。 i = i + 1 や、i = i + 2 や、i += 50 でも問題ありません。
上の例だと、下記のように書いても同じ結果になります。
for(int i = 5; i >= 1; i -= 1) {
System.out.println(i);
}
while文の書き方
まず書き方の前にwhile文とfor文の違いですが、ざっくり言えば、2つの違いはこのようになります。
- 繰り返し回数を優先的に指定したい場合はfor文
- 条件を優先的に繰り返したい場合はwhile文
それでは書き方を見ていきましょう、while文は条件式に合っている(真である)間中ずっと処理を繰り返すもので、次のような形式で書きます。
初期値
while(条件式){
/*
* 実行する処理
*/
増減式;//増減式はwhileの閉じブロックの直前に書く
}
条件式、増減式とは、それぞれこのような意味を持ちます。
- 条件式 – どういう条件のところまでループ処理をおこなうか
- 増減式 – 処理一回ごとに、値をいくつ増やしたり減らしたりするか
次のwhile文処理を実際に書いて、具体的に見ていきましょう。
int i = 0;
while(i < 5){
System.out.println(i);
i++;
}
結果は「01234」と表示されたと思います。これはfor文の最初で書いた処理をwhile文に置き換えたものとなります。
while文の条件に合致した場合、{}中の実行する処理が動きます。
全ての処理が終わったらwhile( 条件 )まで処理が戻り、再度条件が一致するかを確認します。
気を付けてほしいのは、条件が必ず合致する処理を書いてしまうと無限ループが始まってしまうため、注意が必要です。
例えば、while( true )と記載して実行すると、条件が常にtrueで合致するため、処理が延々と続きます。
もちろんfor文でも同じように無限ループを起こす可能性があります。
for文とwhile文の使い分けをきちんと理解するのは難しい部分もあるため、ここでは深く解説を行いませんが、
ここでは次のことだけ覚えておくといいでしょう。
- for文は、繰り返す回数が大事なので、はじまりから終わりまでの数値を把握するために、( )内には初期値・条件式・増減式をすべて書く。
- while文は、回数は気にせず、繰り返すにあたっての条件が大事なので、( )内には条件式のみでOK。
無限ループとは
while文は無限ループに特に気をつけなければなりません。
無限ループとはその名の通りで、while文の特性上、while文の条件式に実現不可能な式や
増減式の書き忘れにより条件式の条件に一生たどり着けないなどになってしまうと無限ループが起きてしまいます。
しかし、この処理は決しておこなってはいけません。
なぜなら、半永久的に実行されるということは、処理が終わらないため、
プログラムに負荷が掛かりクラッシュしてしまうからです。
※補足:break関数を用いて行為的に無限ループを起こすことはあります。
do-while文(補足) ※こういうものもあるんだ程度で大丈夫です。
先ほどのwhile処理では条件に合致するかを確認してから処理を実行する、という順番でループを行っていましたが、
先に処理を行ってから条件を確認する、という記載方法も可能です。
このwhile構文はdo-while構文といわれています。
while構文との明確な違いは条件に合致していなくても必ず処理が実行される、という点にあります。
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
/*
* パターン1,条件に合致する場合
*/
System.out.println("パターン1の場合");
int a = 0;
//do while構文、どんな条件だったとしても必ず1回は実行する。
do {
//aの2乗をlistの中に格納していく。
list.add(a * a);
//格納した結果をコンソールに出力する
//出力結果が見やすくなるようにif条件で成形してみる
if(a < 9) {
System.out.println(" " + (a + 1) + "回目の処理:\t" + list.get(a) );
} else {
System.out.println((a + 1) + "回目の処理:\t" + list.get(a) );
}
a++;
} while (a < 50);
/*
* パターン2,条件に合致しない場合
*/
System.out.println();
System.out.println("パターン2の場合");
//aを一度初期化
a = 0;
do {
list.add(a * a);
if(a < 9) {
System.out.println(" " + (a + 1) + "回目の処理:\t" + list.get(a) );
} else {
System.out.println((a + 1) + "回目の処理:\t" + list.get(a) );
}
a++;
} while (a == 0);
}
do-while構文は以下の構文で記載します。
do {
// 処理する内容
} while (処理を実行するかの条件)
この構文では、doの処理が先に実行される、whileの条件を確認する、条件通りならdoの処理を再度実行するを繰り返し行っています。
条件が合致していなくても必ず1回は実行される、
という挙動は、パターン1よりパターン2の方が必ず1回は実行するイメージがつきやすいでしょう。
パターン2の処理では、(whileの処理)を処理を行った後で実施するため、最初に処理された「1回目の処理:0」が出力されています。 ただし、条件を見た時に合致しない条件であるため、処理はそこで完了しています。
ループ処理の終了とスキップ(break、continue)
for,while文などのループ処理を途中で中止させることができる break、continue について解説します。
まず、breakとcontinueの違いを以下に示します。
- breakは、ループ自体をその時点で終了させる。break以降のループ処理は実行されない。
- continueは、現在の繰り返しループ の残りの処理をスキップし、次のループを続行する。
実際の処理でも確認してみましょう。
//break
for(i = 1; i < 4; i++){
if(i == 2) break;
System.out.println(i+"回目");
}
出力結果は(1回目)のみです。if(i == 2) break;より以降の処理は全て実行されません。
//continue
for(i = 1; i < 4; i++){
if(i == 2) continue;
System.out.println(i+"回目");
}
出力結果は(1回目3回目)になりましたね。
if(i == 2) continue;でこの時だけ処理がスキップされ、i == 3のループは継続し実行されています。
breakとcontinueは記述する箇所によっても動きが変わります。違いを理解して使っていきましょう。
ネストによる2重のループ
if文でもネスト(=構文の中に構文が入った入れ子構造)を扱いましたが、for文、while文でももちろん可能です。
基本的にどの構文同士をネストしても問題ありません。
for文のネストの例を見てみましょう。
// ネスト
for (int a = 0; a < 2; a++) {
System.out.println("外側:" + a);
for (int b = 0; b < 2; b++) {
System.out.println("・内側:" + b);
}
}
カウンタaによる外側のループの中で、bによる内側のループが回っています。
丁寧に追うと、a=0のときに内側のループが回り(b=0、b=1)、
内側のループが終わると外側のループが回りa=1になり、再度内側のループが回る、といった流れです。
プログラムが上から下に順に実行されることと、ループの動きを丁寧に追えば単純な話です。
練習問題
「com.cmps.forWhile」パッケージ内に「ForWhileQuestion」クラスを作成して下さい。
※各問題について、for文とwhile文の両方で実装しましょう。
問1: 100ずつ増える100~1000までの繰り返しを行いましょう。
問2: 30~0まで1ずつ減る繰り返しを行いましょう。
問3: 下記のように出力しましょう。
外側:0
・内側:0
・内側:1
・内側:2
外側:1
・内側:0
・内側:1
・内側:2
外側:2
・内側:0
・内側:1
・内側:2
