第9講・STEP 02

for文と配列とスコープ

for文の使い方はなんとなく掴めましたでしょうか?配列とfor文を組み合わせると非常に効果的な使い方ができます。配列を一つずつ処理していくのは、for文が得意とする使い方の一つです。

for文と配列

この非常に有用な「配列をfor文で回す」という感覚を身につける為に、前々回に配列を使って作ったScoresクラスを改造したいと思います。
 Scoresクラスはこんなのでした。

Scores.java

public class Scores {
    public static void main(String[] args) {
        int[] scores = new int[]{80, 65, 70, 95};

        System.out.println("Aさんの点数:" + scores[0] + "点");
        System.out.println("Bさんの点数:" + scores[1] + "点");
        System.out.println("Cさんの点数:" + scores[2] + "点");
        System.out.println("Dさんの点数:" + scores[3] + "点");
    }
}

「System.out.println("○さんの点数:" + scores[○] + "点");」というようによく似た処理が4回繰り返されています。ここをfor文を使ってスマートに書き換えましょう。

前回の2のn乗を計算するプログラムでは「answer = answer * 2;」を繰り返すだけだったのですが、この場合、繰り返しとは言うものの一回一回微妙に違いますよね?

名前も違うし、scores[ ]の連番も違います。繰り返しの1回目はscores[0]を、2回目はscores[1]を・・、と配列の連番を進めながら繰り返すようにします。

for文で回す?

まずは名前の方もfor文で回す為に、配列にします。どうせならAさんBさんじゃなくて、青木さんと飯田さんと上田さんと江藤さんにしておきます。別に誰でもいいんですが。。

Scores.java

public class Scores {
    public static void main(String[] args) {
        String[] names = new String[]{"青木", "飯田", "上田", "江藤"};
        int[] scores = new int[]{80, 65, 70, 95};

        System.out.println(names[0] + "さんの点数:" + scores[0] + "点");
        System.out.println(names[1] + "さんの点数:" + scores[1] + "点");
        System.out.println(names[2] + "さんの点数:" + scores[2] + "点");
        System.out.println(names[3] + "さんの点数:" + scores[3] + "点");
    }
}

さあ、これをfor文で書き換えると、

Scores.java

public class Scores {
    public static void main(String[] args) {
        String[] names = new String[]{"青木", "飯田", "上田", "江藤"};
        int[] scores = new int[]{80, 65, 70, 95};

        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i] + "さんの点数:" + scores[i] + "点");
        }
    }
}

こうなります。

for文の( )の中の初期設定パートで宣言・初期化した「i」を実行文の中でも使うことで、ブロック内実行の1回目は配列の通し番号0番、2回目は通し番号1番・・、と言う風に配列を回しながら繰返しを実行できるわけです。

それとfor文の( )の中の実行条件のパートが「i < names.length」こんなことになってますが、

配列名.length

で、その配列の要素数を取得できます。lengthは配列が持つフィールドで、names.length という式を評価すると、その値が得られます。メソッドの呼び出しではないので、後ろに( )は付けません。

つまり、

Scores.java

names.length

は、配列namesの要素数を返すので、「4」に置き換わります。そんなややこしい書き方しなくても「4」と書く方が早いようにも思いますが、配列の全要素を順に処理するときは「.length」を使うと、要素数が変わっても繰り返し回数を手直しせずに済みます。

これで配列namesと配列scoresを通し番号0番から3番まで一つずつ進めながら4回繰り返して実行するfor文になりました。

この配列を回す書き方を見ると、要素数が5の配列を先頭から最後まで処理する場合に、

for(int i=1; i<=5; i++)

ではなく、

for(int i=0; i<5; i++)

にする理由がよく分かるのではないでしょうか?iを1から始めてしまうと、配列の通し番号も1から始めてしまうことになりますからね。

for文の入れ子とスコープ

最後にちょっとした応用問題。

for文の中にfor文が入っているやつです。ここまでの講座の内容をちゃんと理解できていたら、何を出力しようとしているのか読めるはずです。

ForInFor.java

public class ForInFor {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            String a = "";
            for (int j = 1; j <= 9; j++) {
                a += i * j + " ";
            }
            System.out.println(a);
        }
    }
}

さてこれを実行したら何が出力されるでしょうか??ポイントは入れ子になっているfor文のブロック(どこを繰り返すのか?)をよく見ることと、ころころ変わっていく「i」と「j」の値を常に追いかけて把握しておくことです。「i」が1、「j」が1とかメモしながら読んだらよく分かると思います。あと、変数aはStringですのでそこのところ注意して読んで下さい。

「a += i * j + " "」は、
「a = a + (i * j + " ")」の省略形ですよ。「i * j」が数値として計算されてから文字列に変換されて連結されます。ちなみにi*jの後に足している「" "」これはスペースです。

答えが分かったらぜひ、実行して答え合わせをしてみてください。

このプログラムを読めた人は、次のを見て下さい。

ForInFor.java

public class ForInFor {
    public static void main(String[] args) {
        String a = "";
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= 9; j++) {
                a += i * j + " ";
            }
            System.out.println(a);
        }
    }
}

「String a = "";」の位置が、for文のブロックの中から外に変わっただけなのですが、これだと思ったように出力されません。

このプログラムの実行結果を見れば、for文のブロック内で宣言された変数と、ブロックの外で宣言された変数の動きの違いがよく分かると思います。

ここでfor文のブロック内に宣言したaは、その宣言からブロックの終わりまで名前を使えます。ブロックの外からaを読み出すことはできません。

for文の繰り返しでもう一度そのブロック内が実行されたら、この例では String a = ""; が毎回実行されるので、前周の値は持ち越しません。逆にブロックの外側で宣言された変数はそのブロックを抜けてもまだ値を保持していますので、こんなこと(上記の下側のプログラムの実行結果)になるんです。

この、変数を宣言する場所によって処理内容が変わってしまう仕組みはfor文に限ったことではありません。今回のようなブロック内のローカル変数は、宣言した場所からそのブロックの終わりまで、内側のブロックも含めて名前を使えますが、宣言したブロックの外側では使えません。

変数名を使える範囲をスコープと言います。宣言する場所によってその変数のスコープが決まりますので、自分で思った通りに変数を使おうと思ったらどこで宣言したらいいかをよく考えないといけません。

なんか難しい感じですが、やっているうちに分かってきますので宣言する場所を意識することだけは忘れないようにして下さい。

次はメソッドについてやります。メソッドは覚えることも多くてややこしいですが、その分メソッドを使いこなせればいろんなことができるようになりますので頑張りましょう。

目次へ

質問・コメント

読み込み中

この記事についての質問や、学習して気づいたことをお寄せください。

コメントを書く

投稿フォームを準備しています。

コメントと一緒に公開される名前です。
3,000文字以内。パスワードなどの個人情報は書き込まないでください。

コメントは送信後すぐに公開されます。

この記事のコメント

旧サイトに寄せられたコメントも当時の投稿内容のまま掲載しています。現在の記事では変更している内容や、旧環境についてのやり取りも含まれます。

コメントを読み込んでいます。