Print Friendly, PDF & Email

この記事では、弊社の新人エンジニア研修の参考にJava8を解説します。

前回は条件分岐と判定条件について解説しました。

今回は繰り返し処理について解説します。

人間だったら嫌になってしまう繰り返し処理もコンピュータにとっては何でもありません。

コンピュータの偉大さを感じる瞬間です。

ここでは、以下の3つの繰り返し処理を学びましょう。

1.while文

2.for文

3.do while文

です。

なお、繰り返し処理のことをループとも言います。

1.while文

英語のwhileには「~の間」という意味がありました。

継続条件を満たしている間は処理を繰り返すというのがwhile文です。

whileの基本構文です。

<構文>

While(継続条件式){
      文;
}

「継続条件式」がtrueなら「文」を処理する。 false ならwhile文を終了する。

という意味になります。

具体例で見てみましょう。

package chap05;

public class Example01 {

    public static void main(String[] args) {
        int i = 0;
        while (i < 3) {
            System.out.println(i);
            i++;
        }
    }
}

<結果を表示する>

0
1
2

ここでは、9行目のインクリメントに着目してください。

もしも、このインクリメントがないと、継続条件式がいつまでもtrueのままでループを抜けませんから、無限ループになってしまいます

ぜひ、無限ループも経験しておいてください。

そして、無限ループの止め方もIDEごとに異なりますので講師に教わってください。

この繰り返しの文をよく理解するためにはトレース表を埋めてみるのが一番です。

途中まで埋まったトレース表を完成させてください。(※答えは隠し文字になっています。)

 iの値i < 3 の値
6行目0-
1回目の7行目00 < 3 :true
1回目の9行目1-
2回目の7行目11 < 3 :true
2回目の9行目2-
3回目の7行目22 < 3 : true
3回目の9行目3-
4回目の7行目33 < 3 :false

ここでループを抜けています。

なお、前回使ったデバッガを使うと繰り返しの様子を見ることができます。

余談ですが、なぜ変数に"i"という文字を使っているかというと、昔のプログラミングスタイルの名残です。

興味のある方はググってください。

ただ、一時的な使い捨ての変数には短い名前がつけられる傾向があることは、知っておいて損はありません。

2.for文

先のwhile文では、ループに入る前に変数のiを初期化して、さらにループの中でこのiをインクリメントする必要がありました。

この構造を見やすく1行で表現できるのがfor文です。

まずは、イメージを掴みましょう。

while文とfor文の比較
while文とfor文の比較

基本構文です。

<構文>

for(初期化文; 継続条件式; 更新文){
   文;
}

1.ループに入る前に初期化文を一度だけ行います。

2.継続条件式がtrueなら文を実行し、falseならループを終了します。

3.更新文を実行し、2に戻ります。

for文で間違えやすいのは、「継続条件式は繰り返し処理を実行する前に判定される」ということです。

また、「更新文は繰り返し処理が終わってから実行される」こともポイントです。

初期化文 → 継続条件式 → 繰り返し処理 → 更新文 → 継続条件式 → 繰り返し処理 → 更新文、以下繰り返しという実行の順番を確実に覚えましょう

これも具体例で見てみます。

for文の複雑な構文もIDEを使うと簡単に挿入できますので講師から聞いてください。

package chap05;

public class Example02 {

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println(i);
        }
    }
}

<結果を表示する>

0
1
2

処理内容は先ほどのwhile文と同じですが、シンプルに書けているのがお分かりになると思います。

以下の図が示す通りループの制御構造が一か所にまとまっているので、繰り返したい処理ブロックが長くなっても可読性が保たれるのがfor文の良いところです。

途中まで埋まったトレース表を完成させてください。

 初期化式の値 ii < 3 の値i++の値
1回目の6行目00 < 3 :true-
2回目の6行目-(初期化は一度だけ)1 < 3 :true1
3回目の6行目-(初期化は一度だけ)2 < 3 : true2
4回目の6行目-(初期化は一度だけ)3 < 3 :false3

※答えは隠し文字になっています。

for文とwhile文のどちらを使うか迷ったらまずはfor文を使って下さい。

さらに後で学ぶ拡張for文が使える場面では拡張for文を使って下さい。

ここで少し、繰り返し処理というテーマから外れますが初学者が間違いやすい変数の有効範囲(スコープ)ということについて注意喚起です。

例えば、以下のようなプログラムはException 「例外」が出て止まってしまいます。

何が良くないのでしょうか?

package chap05;

public class Example03 {

    public static void main(String[] args) {
        for (int i = 0; i < 6; i++) {
            System.out.println(i);
        }
        System.out.println(i);
    }
}

<結果を表示する>

(一部省略)

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous tree type: <any>

この例外発生の原因は、変数(ローカル変数)の有効範囲は同じブロック内({}波カッコの中)というルールがあるからです。

もしも、変数iをfor文の外でも使いたい場合には、以下のように変数宣言をfor文の外(前)でします。

package chap05;

public class Example04 {

    public static void main(String[] args) {
        int i;
        for (i = 0; i < 6; i++) {
            System.out.println(i);
        }
        System.out.println(i);
    }
}

<結果を表示する>

0
1
2
3
4
5
6

スコープの問題はこれからも出てきますのでまずは言葉と概念を押さえてください。

3.ユーザー入力を受け付ける

ここで、繰り返しの話からは少し外れるのですが、ユーザーからの入力ができるようにしてみましょう。

ユーザーからの入力を受け付けるにはjava.util.Scanner(標準API)を使います。

以下は標準APIの引用です。

たとえば、次のコードを使用して、System.inから数値を読み込むことができます。

Scanner sc = new Scanner(System.in);
int i = sc.nextInt();

System.outは標準出力でした。

System.inは標準入力です。

標準入力とはお使いのパソコンのキーボードのことです。

では、先程の繰り返し処理で繰り返し回数をユーザーが入力するようにするにはどうしたらいいでしょうか?

こんな感じでできますね。

package chap05;

import java.util.Scanner;

public class Example10 {

    public static void main(String[] args) {
        
        System.out.println("何回数え上げますか?");
        
        Scanner sc = new Scanner(System.in);
        int count = sc.nextInt();
        
        int i = 0;
        while (i < count) {
            System.out.println(i);
            i++;
        }
    }
}

ここからの解説と問題演習ではこのScannerクラスの機能を使います。

4.ループを中断するbreak文

先ほど、無限ループを説明しました。

この無限ループを利用するプログラムがあります。

繰り返し回数が分からない場合に while(true) として無限ループにする方法です。

無限ループだといつまでたってもプログラムが終了しないのでは?

と思った人も多いかと思います。

ある条件のときだけ無限ループを抜けるようにします。

無限ループとよく組み合わせて使われるのがbreak文です。

break(破る)ということでループを抜けます。

前回もswitch文で使いましたね。

具体例で見てみましょう。

以下のサンプルコードはユーザが入力した数値を足していき、合計値を表示します。

ただし、-1が入力されたら終了します。

package p05;

import java.util.Scanner;

public class Example05 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = 0, sum = 0;
        while (true) {
            System.out.println("整数値を入力してください。(終了するには-1を入力)");
            n = scanner.nextInt();
            System.out.println(n + "が入力されました。");
            if (n == -1) {
                break;
            }
            sum += n;
            System.out.println("これまでの合計:" + sum);
        }
    }
}

<結果の例を表示する>

整数値を入力してください。(終了するには-1を入力)
2
2が入力されました。
これまでの合計:2
整数値を入力してください。(終了するには-1を入力)
4
4が入力されました。
これまでの合計:6
整数値を入力してください。(終了するには-1を入力)
-1


なお、
このように、繰り返しの中に(if+break)という形は頻繫に登場しますので覚えてください。

また、while (true)

のところを

for(;;)

と書いても同じ処理になりますので試してみてください。

上記の例では、(if+break)を使わずにwhile文を使って以下のよう書くことももちろんできます。

package chap05;

import java.util.Scanner;

public class Example06 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int n = 0, sum = 0;

        System.out.println("整数値を入力してください。(終了するには-1を入力)");
        n = scanner.nextInt();

        while (n != -1) {
            sum += n;
            System.out.println(n + "が入力されました。");
            System.out.println("これまでの合計:" + sum);
            System.out.println("整数値を入力してください。(終了するには-1を入力)");
            n = scanner.nextInt();
        }
    }
}

<結果の例を表示する>

整数値を入力してください。(終了するには-1を入力)
2
2が入力されました。
これまでの合計:2
整数値を入力してください。(終了するには-1を入力)
4
4が入力されました。
これまでの合計:6
整数値を入力してください。(終了するには-1を入力)
-1

しかし、(if+break)を使うと、どういう条件でループを抜けるのかということをより明確に表現できます。

ところで、(if+break)で使ったif(n == -1)というのは終了条件です。

一方、Example06のwhile(n != -1)というのは継続条件です。

前回の論理演算子のところで条件の否定について学びました。

継続条件の否定は終了条件です。

つまり、

「age < 20 はお酒が飲めない」

を否定すると

「age >= 20 はお酒が飲める」になります

このように終了条件と継続条件を相互に変換するには、不等号をひっくり返して=がなければ足し、あれば無くします

つまり、

もしも、!(sum > 1000) という条件があったとして、

この条件は (sum <= 1000) と等しく、

!(sum <= 1000) は (sum > 1000) と等しい

という論理になります。

5.1回スキップするcontinue文

continueはブロック内の残りの文をスキップします。

具体例で見てみましょう。

以下のサンプルコードはユーザが入力した数値を足していき、合計値を表示します。

ただし、マイナスの数は合計せずにスキップします。

今回はfor文を使ってみましょう。

package chap05;

import java.util.Scanner;

public class Example07 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int n = 0, sum = 0;

        for (int i = 0; i < 3; i++) {
            System.out.println("整数値を入力してください。");
            n = scanner.nextInt();
            if (n < 0) {
                continue;
            }
            sum += n;
            System.out.println(n + "が入力されました。");
            System.out.println("これまでの合計:" + sum);
        }
    }
}

<結果を表示する>

整数値を入力してください。
2
2が入力されました。
これまでの合計:2
整数値を入力してください。
-1
整数値を入力してください。
2
2が入力されました。
これまでの合計:4

足し込んでいく処理を書く場所に気をつけてください。

continueでスキップされるのは、繰り返しのブロックのうちcontinue文の後ろの部分になります。

6.ループのネスト

ループ処理の中にループ処理を入れることがあります。

ループのネスト、または入れ子処理といいます

nestとは英語で「巣」という意味です。

アリの巣のように巣の中に巣があって、その中にも、、、と延々続いている様子をイメージしてください。

例えば、九九を表示することを考えてみます。

九九の計算回数はその名の通り9×9で81回ですね。

1の段は、掛けられる数(1)を固定してその数に1~9までの数を繰り返し掛けます。

2の段は、掛けられる数を1増やして(2になる)その数に1~9までの数を繰り返し掛けます。

以降同様にかけられる数は9まで繰り返し増やして処理を継続します。

つまり、繰り返しの中に繰り返しがあります。

Javaのコードでは例えば、こうなります。

package chap05;

public class Example08 {

    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                System.out.print(i + "×" + j + "=" + i * j + "\t"); //最後のタブは見やすさのため
            }
            System.out.println(""); //改行のため
        }
    }
}

<結果>

1	2	3	4	5	6	7	8	9	
2	4	6	8	10	12	14	16	18	
3	6	9	12	15	18	21	24	27	
4	8	12	16	20	24	28	32	36	
5	10	15	20	25	30	35	40	45	
6	12	18	24	30	36	42	48	54	
7	14	21	28	35	42	49	56	63	
8	16	24	32	40	48	56	64	72	
9	18	27	36	45	54	63	72	81

<図解>

ループのネストのイメージ
ループのネストのイメージ

青色の外側のループが9回まわりオレンジの内側のループが9回まわって合計81回の掛け算が行われたことが分かればループのネストはOKです。

7.do while文

最後にwhile文やfor文ほど使用頻度は高くありませんが、もう一つのループ処理の記述方法であるdo while文を簡単に見ておきましょう。

do while文の構文

<構文>

do {
    文;
} while(継続条件式);

1.まず無条件に1回、文を実行します。

2.継続条件式がtrueなら1に戻り、falseならループを抜けます。

具体例です。

package chap05;

public class Example09 {

    public static void main(String[] args) {
        int i = 0;
        do {            
            System.out.println(i);
            i++;
        } while (i < 6);
    }
}

<結果を表示する>

0
1
2
3
4
5

このように、無条件に1回、文を実行するのがdo while文です。

do while文の条件式の後には、文末ですのでセミコロンが必要です。

しかし、while文の()の後にセミコロンをつけてしまうと空文だと解釈されて、何も処理されなくなってしまいます。

初学者が犯しやすいミスなので、気をつけてください。

もっともIDEを使っていればミスを指摘してくれはしますが。

今回はJavaの繰り返し処理について見てきました。

次回は、この繰り返し処理一緒に使われることも多い配列の作成と使用を学んで変数の名前付け問題から解放されましょう。

まとめ:隣の人に正しく説明できたらチェックを付けましょう

□継続条件を満たしている間は処理を繰り返すというのがwhile文やfor文である

□for文で間違えやすいのは、「継続条件式は繰り返し処理を実行する前に判定される」、「更新文は繰り返し処理が終わってから実行される」ということである

□break文はループを中断し、continue文はループを1回スキップする

□終了条件と継続条件を相互に変換するには、不等号をひっくり返して=がなければ足し、あれば無くす

□ループ処理の中にループ処理を入れることをループのネスト、または入れ子処理という

まとめができたら、アウトプットとして演習問題にチャレンジしましょう。

問題5.繰り返し

どれだけ繰り返しても飽きることが無い。 これもコンピュータの特徴です。 今までの順次、選択(条件分岐)とこの繰り返しは構造化プログラミングという最も基本的なプロ…

【今回の復習Youtube】
 
 
 

JavaSE8の解説に戻る