「Java/基礎/反復処理」の版間の差分

削除された内容 追加された内容
構成を変更。while文の説明を追加
1 行
== for文による反復処理 ==
他の多くのプログラミング言語と同様、Javaにも、反復処理のための構文があります。
簡単なサンプルを用意しましたので見てみましょう。このプログラムも、実用的な意味はありません。
 
他の多くのプログラミング言語同様、Javaにも、処理の流れをコントロールする構文が用意されています。
public class Main {
条件分岐や反復処理の構文です。
このページでは反復処理(ループ)を採り上げます。
さっそくサンプルを見てみましょう。
 
 
== 反復処理の例 ==
次のサンプルは、一応Hello worldの日本語版(のつもり)です。
Hello world同様、実用的な意味は全くありませんが、反復処理を使っています。
 
class JapaneseHelloWorld {
public static void main(String[] args) {
char[] msg = "世界よ今日こんにちは".toCharArray();
<b>for (int i = 0; i < msg.length; i++) {</b>
System.out.println(msg[i]);
<b>}</b>
}
}
 
上の例は'''for文'''と呼ばれる構文を使った例です(4行目にキーワード「<tt>for</tt>」があることに注意してください)。
<tt>javac</tt>でコンパイルし、<tt>java</tt>コマンドで実行してみましょう。
コンパイルして実行してみましょう。
 
$ <span style="font-weight:bold">javac MainJapaneseHelloWorld.java</span>
$ <span style="font-weight:bold">java MainJapaneseHelloWorld</span>
 
 
一応“縦書き”でメッセージが表示されます(コマンドの行頭に出てくる「<tt>$</tt>」の文字は、プロンプトを表しています)。同様の表示結果になれば成功です。
 
 
<div style="padding: 10px; background-color: rgb(244, 240, 240); font-size: small;"><b>参考:文字コードについて</b><br/>
 
<div style="padding: 10px; background-color: rgb(244, 240, 240); font-size: small;"><b>参考:文字コードについて</b>
 
今回のサンプルには「世界よ今日こんにちは」という文字が出てきました。
こうした、いわゆる“2バイト文字”を使う際、文字コードの問題が起こる場合もあります。
 
たとえば、WindowsやMac OS Xなどの環境で、このソースコードを「[[w:UTF-8|UTF-8]]」という文字コードで保存したとします。この場合でも、コンパイルは成功するかもしれません。しかし、実行結果は正しく表示されないと思います。
これは、WindowsやMac OS Xなどの環境下では、ソースコードが「[[w:Shift_JIS|Shift-JIS]]」という文字コードで書かれているという前提で動くになっているからです(Windowsの場合、厳密には「[[w:Microsoftコードページ932|MS932]]」と呼ばれて文字コードです)。
 
ソースコードを規定値以外の文字コードで保存した場合は、使用した文字コードをコンパイル時に指定するようにします。たとえば次の例は「UTF-8」を指定している場合です。
 
$ <b>javac -encoding UTF-8 MainJapaneseHelloWorld.java</b>
 
システムによっては、問題はコンパイルだけとは限りません。
たとえば、Mac OS X 10.4の標準のターミナルはUTF-8をサポートしています。
ですからもちろん日本語の表示も可能なのですが、実際には1つ問題があります。
というのも、Javaが規定しているMac OS X環境下Javaは、デフォルトの文字コードShift-JISと規定しているからです。
すなわち、JavaプログラムはターミナルにShift-JISで出力しますが、
ターミナルはそれをUTF-8で解釈しようとしてしまうのです。
 
表示結果を正しくするためには、次のようにしてプログラムを実行します。
 
$ <b>java -Dfile.encoding=UTF-8 MainJapaneseHelloWorld</b>
</div>
 
 
このプログラム、まず「世界次の今日は」とい文字列を<tt>char</tt>型の配列変換して変数<tt>msg</tt>に代入し、書くこともできます。
そしてその配列の要素を1つずつ取り出して表示しています。配列要素を取り出す際に、今回のテーマである'''反復処理'''を行っています。
 
class JapaneseHelloWorld {
public static void main(String[] args) {
char[] msg = "世界よこんにちは".toCharArray();
int i = 0;
<b>while (i < msg.length) {</b>
System.out.println(msg[i]);
i++;
<b>}</b>
}
}
 
こちらは'''while文'''を使った書き方です。
=== 構文と処理の流れ ===
さらに次のような書き方もできます。
反復処理を行っている部分を見てみましょう。
 
class JapaneseHelloWorld {
for (int i = 0; i < msg.length; i++) {
public static void main(String[] args) {
System.out.println(msg[i]);
char[] msg = "世界よこんにちは".toCharArray();
int i = 0;
<b>do {</b>
System.out.println(msg[i]);
<b>} while (++i < msg.length);</b>
}
}
 
こで'''fordo-while文'''と呼ばれる構文が使われています。この構文は次のような書式になっています。
 
またさらには、JDK 5.0 以降を使っている場合、次のような書き方も可能です。
for (<i>初期処理</i>; <i>反復条件</i>; <i>継続処理</i>) {
これが最もシンプルな書き方です。
<i>繰り返す処理</i>
 
class JapaneseHelloWorld {
public static void main(String[] args) {
for (char c: "世界よこんにちは".toCharArray()) {
System.out.println(c);
}
}
}
 
反復処理を紹介する導入として、カタログ的にいくつかの書き方を紹介しました(もっとも、この例のように配列要素を取り出したい場合は、通常for文が適していると言えるでしょうけれども)。
for文では、次のように処理が進みます。
 
以降、詳しく見ていくことにしましょう。
#「<b><i>初期処理</i></b>」に書かれた処理が実行される
 
#「<b><i>反復条件</i></b>」に書かれた条件に合っているかどうか判定される
 
#* <b>条件に合っていた場合:</b>
== 反復条件によく使われる比較演算子 ==
#*#「<b><i>繰り返す処理</i></b>」に書かれた処理が1回実行される
それぞれの構文について詳しく説明する前に、共通する要素について説明しておきます。
#*#「<b><i>継続処理</i></b>」に書かれた処理が実行される
#*# 2(「<b><i>反復条件</i></b>」の判定)に戻る
#* <b>条件に合っていなかった場合:</b>
#*# 反復処理を終了する
 
反復処理では、必ず反復条件が指定されます。
反復処理は、反復条件を満たしている間だけ続き、条件を満たさなくなると処理を抜けます。
 
反復条件は、しばしば'''比較演算子'''というものを使って表現されます。
=== 比較演算子 ===
比較演算子は、数学の記号によく似ています。
「反復条件」は、しばしば比較演算子を使って表現されます。よく使われる比較演算子には、たとえば次のものがあります。
反復条件でよく使われる比較演算子には、たとえば次のものがあります。
 
{| class="wikitable"
89 ⟶ 122行目:
|-
! <tt> &gt; </tt>
| 数学の &gt; と同様。左辺の値が右辺の値よりも大きい場合に真
|-
! <tt> &gt;= </tt>
| 数学の ≧ と同様。左辺の値が右辺の値よりも大きいか、もしくは等しい場合に真
|-
! <tt> &lt; </tt>
| 数学の &lt; と同様。<tt>&gt;</tt>の逆。左辺の値が右辺の値より小さい場合に真
|-
! <tt>&lt;=</tt>
| 数学の ≦ と同様。左辺の値が右辺の値よりも小さいか、もしくは等しい場合に真
|-
! <tt>==</tt>
| 左辺の値と右辺の値が等しい場合に真
|-
! <tt>!=</tt>
| <tt>==</tt>の逆。左辺の値と右辺の値が等しくない場合に真
|-
|}
 
下の2つ(「<tt>==</tt>」と「<tt>!=</tt>」)よりも、上の4つのほうが優先順位が高いことが知られています。
たとえば次のコード片を見てみましょう。
System.out.println(<span style="font-weight:bold; color:#ff0000;">'a' &gt; 'b' == 'Z' &gt; 'a'</span>);
「<tt>'a' &gt; 'b' == 'Z' > 'a'</tt>」の部分は次の順序で評価されることになります。
# <tt>'a' > 'b'</tt>
# <tt>'Z' > 'a'</tt>
#「1の結果」<tt>==</tt>「2の結果」
 
 
ちなみに、一般的な環境では「1の結果」も「2の結果」もfalseですから、3は「<tt>false == false</tt>」の比較になり、結果はtrueということになります。
== for文 ==
 
 
=== 構文と処理の流れ ===
for文の書式はおおよそ次のとおりです。
 
for (<i>初期処理</i>; <i>反復条件</i>; <i>継続処理</i>) {
<i>繰り返す処理</i>
}
 
処理の進み方は以下のとおりです。
 
#「<i>初期処理</i>」に書かれた処理が実行される
#「<i>反復条件</i>」に書かれた条件に合っているかどうか判定される
#* <b>条件に合っていた場合:</b>
#*#「<i>繰り返す処理</i>」に書かれた処理が1回実行される
#*#「<i>継続処理</i>」に書かれた処理が実行される
#*# 2(「<i>反復条件</i>」の判定)に戻る
#* <b>条件に合っていなかった場合:</b>
#*# 反復処理を終了する
 
なお、<i>繰り返す処理</i>は、単文であればブロック(<tt>{ }</tt>)を外すこともできます。
たとえば次のように書きます。
 
for (int i = 0; i < msg.length; i++) System.out.println(msg[i]);
 
 
155 ⟶ 200行目:
 
処理の流れを思い描くことができましたか。
処理の流れをイメージすることは、慣れないうちは少し骨が折れる作業かもしれません。
しかし、落ち着いて考えれば至極簡単なことです。
慣れるまでは、何度かじっくり考えて、考え方のパターンを把握するように努めてみてください。
 
 
167 ⟶ 212行目:
for (int y = 1; y <= 9; y++) {
for (int x = 1; x <= 9; x++) {
String rbuf = String.valueOfformat("%dx%d=%2d ", x, y, x * y);
System.out.print(x + "x" + y + " =" + rbuf);
<span style="color:#0000ff;">for (int i = 0; i < 3 - r.length(); i++) {</span>
<span style="color:#0000ff;"> System.out.print(" ");</span>
<span style="color:#0000ff;">}</span>
}
System.out.println();
181 ⟶ 223行目:
処理の流れを追うことができますか?
 
これができれば、反復処理の基本はほぼマスターできたと言えるだろうと思います。
 
なお、青い文字の部分は、単純に出力結果の整形にもfor文を使ったというだけですから、ここではあまり注目する必要はありません。
代わりに注目すべきは、変数<tt>x</tt>と<tt>y</tt>に関するfor文の流れです。
ここが把握できていれば、とりあえず繰り返し処理の基本はマスターしたと言ってよいでしょう。
 
 
=== 拡張for文 ===
J2SEJDK 5.0以降では'''拡張for文'''を使うことができます。
冒頭で掲げた例のうち
拡張for文がどのようなものかは、一から文章で説明するよりも、サンプルを見たほうが理解が早いでしょう。
 
public class MainJapaneseHelloWorld {
public static void main(String[] args) {
for (char c: "世界よ今日は".toCharArray()) {
199 ⟶ 238行目:
}
 
 
このサンプルは、冒頭のサンプルと同等の処理を、拡張for文で表現したものです。
が拡張for文を使った例です。
繰り返しになりますが、「<tt>"世界よ今日は".toCharArray()</tt>」は、<tt>char</tt>型の配列を返します。
 
ですからこの場合、
この例では配列を使っていますので、それに合わせて書式を紹介すると、
 
for (<b><i>配列要素の型 変数名</i></b>: <b><i>配列</i></b>) {
207 ⟶ 247行目:
}
 
という形になっていることがわかります。
こうすると、「<b><i>変数名</i></b>」で示した変数に、「<b><i>配列</i></b>」で示した配列の各要素が自動的に代入されるのです。
 
 
なお、'''この例では配列を使って説明していますが、拡張for文が使えるのは配列だけではありません'''。(少し先取りした内容になりますが)おそらく本格的にJavaプログラミングをするようになれば、配列よりもコレクションフレームワークを多用するようになるでしょう。従来、for文でコレクションの各要素にアクセスするには、わざわざ<tt>Iterator</tt>を取得し、for構文内で<tt>next()</tt>や<tt>hasNext()</tt>メソッドを呼び出していましたが、拡張for文を使えば、こうした手間が一気に省けてシンプルに表現できます。
 
<div style="padding: 10px; background-color: rgb(244, 240, 240); font-size: small;"><b>参考:</b>
 
なお、'''この例では配列を使って説明していますが、拡張for文が使えるのは配列だけではありません'''。(少し先取りした内容になりますが)おそらく本格的にJavaプログラミングをするようになれば、配列よりも'''コレクションフレームワーク'''を多用するようになるでしょう。拡張for文は、そうしたコレクションフレームワークにも配列同様の考え方で適用することができます。
</div>
 
 
 
== while文 ==
 
=== 構文と処理の流れ ===
while文の書式は次のとおりです。
 
while (<i>反復条件</i>) {
<i>繰り返す処理</i>
}
 
処理の進み方は次のとおりです。
 
#「<i>反復条件</i>」に書かれた条件に合っているかどうか判定される
#* <b>条件に合っていた場合:</b>
#*#「<i>繰り返す処理</i>」に書かれた処理が1回実行される
#*# 1(「<i>反復条件</i>」の判定)に戻る
#* <b>条件に合っていなかった場合:</b>
#*# 反復処理を終了する
 
for文同様、一番最初の反復条件の判定が偽となれば、<i>繰り返す処理</i>は一度も実行されません。
 
=== ファイルの読み込みの例 ===
while文はfor文よりも機能が少なく、シンプルな構造です。
ループカウンタが不要な反復処理などで使われることが多いかもしれません。
 
たとえば、次の例は、引数で指定されたテキストファイルを読み込んで表示するサンプルです。
 
import java.io.*;
class CatLike {
public static void main(String[] args) throws IOException {
for (String fn: args) {
BufferedReader in = new BufferedReader(new FileReader(fn));
String line = null;
<b>while ((line = in.readLine()) != null) {</b>
System.out.println(line);
<b>}</b>
}
}
}
 
このようにファイルやデータベースからデータを読み込むような処理は、while文が使われることの多い例と言えるかもしれません。
 
 
<div style="padding: 10px; background-color: rgb(244, 240, 240); font-size: small;"><b>参考:</b>
 
もっとも、上記の処理もfor文を使ってたとえば
 
import java.io.*;
class CatLike {
public static void main(String[] args) throws IOException {
String line = null;
for (String fn: args)
for (BufferedReader in = new BufferedReader(new FileReader(fn));
(line = in.readLine()) != null; )
System.out.println(line);
}
}
 
というふうに書くこともできます。
どちらを使うかは、基本的に好みの問題です。
</div>