2019/02/06
sponsored link
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
で、その配列の要素数を返します(「返す」というのは「評価する」と同じことで、その値に置き換わるというようなニュアンスです)。
つまり、
names.length
は、配列namesの要素数を返すので、「4」に置き換わります。そんなややこしい書き方しなくても「4」と書く方が早いようにも思いますが、配列を回す時は絶対「.length」を使うようにした方がいいです。
これで配列namesと配列scoresを通し番号0番から3番まで一つづつ進めながら4回繰り返して実行するfor文になりました。(「names.length」と「scores.length」が両方4なので動作自体はこれで問題ないですが、例としてはあまりよくなかったです申し訳ない・・。)
この配列を回す書き方を見ると、for文の繰り返しの基本形が、
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文のブロック内で宣言された変数は、そのブロック内でしか存在できません。なので一度そのブロックを抜けると消えてしまいます。
for文の繰り返しでもう一度そのブロック内が実行されたら、宣言&初期化からやり直しになるので、前周の値は持ち越しません。逆にブロックの外側で宣言された変数はそのブロックを抜けてもまだ値を保持していますので、こんなこと(上記の下側のプログラムの実行結果)になるんです。
この、変数を宣言する場所によって処理内容が変わってしまう仕組みはfor文に限ったことではありません。変数は、宣言された場所より内側のブロック内では生きていますが、宣言されたブロックの外側では存在できません。
変数の有効範囲(生きている範囲)をスコープと言います。宣言する場所によってその変数のスコープが決まりますので、自分で思った通りに変数を使おうと思ったらどこで宣言したらいいかをよく考えないといけません。
なんか難しい感じですが、やっているうちに分かってきますので宣言する場所を意識することだけは忘れないようにして下さい。
次はメソッドについてやります。メソッドは覚えることも多くてややこしいですが、その分メソッドを使いこなせればいろんなことができるようになりますので頑張りましょう。
今だけ→転職できなければ全額返金の「エンジニア転職保証コース」
絶対エンジニアになる!→テックエキスパート
フリーランスエンジニアの収入例を見てみる→レバテックフリーランス
コメント
大変勉強になっております。
私は超初心者で非常に助かります。
質問なのですが、このコードを最初に見たときに思ったのが、iもjも1ずつ増えていきそれを掛けるので、1×1、2×2、3×3というように9回の計算で終わることを考えてしまいました。
なぜこうならないのでしょうか
by ポチオ 2015/04/26 16:59
すみません。
最後のForInFor.javaについての質問です。
by ポチオ 2015/04/26 17:01
for文の中にfor文が入ってるからです。
落ち着いてiとjとaの値を追っていけば分かるはずですよ。
頑張って下さい!
by Nobuo@管理人 2015/04/27 08:48
ご返信ありがとうごさいます!
だいたいわかりました。
また以前の回も見直しながら理解します。
by ポチオ 2015/04/27 15:18
細かいことですが、一応書かせてもらいます。「ForInFor.java」のプログラムのforの条件式で、一つ目は上限が「9より小さい」となっているのですが、二つ目は「10以下」になっています。どちらでも良いんだとは思いますが、何も断りなくそこが変わっているのが気になるのですが…。
by 名無し 2015/07/14 16:05
すみません。書き間違えました。一つ目が「9以下」なのに、二つ目は「10より小さい」になっている、でした。
by 名無し 2015/07/14 16:08
ホントですね。
修正しておきました。ありがとうございます。
by Nobuo@管理人 2015/07/15 12:19
大変勉強になっております。質問なのですが、
a += i * j + ” “;
の部分で、aはstring型の変数ですよね? i * j の結果はどのようにして文字列に変換されているのでしょうか。
string型変数の説明をもう一度読んだのですがよく分かりませんでした。
by 権兵衛 2016/07/15 00:29
>権兵衛さん
ここを読んでみてください→ http://nobuo-create.net/stringplus/
by Nobuo@管理人 2016/07/15 09:19
返信が遅れて申し訳ありません。ご丁寧にリンクまで貼っていただき、ありがとうございます!
よくわかりました。
by 権兵衛 2016/07/19 21:29