プログラムの流れの繰り返し
for文
定型的な繰り返しの制御を、while文よりも簡潔に実現する for文について説明していきます。
for文
読み込んだ個数だけ * を表示するプログラムをwhile文ではなく、for文(for statement)と呼ばれる文によって書き換えたものを以下に示します。
//PutAsteriskFor.java
//読み込んだ個数だけ*を表示
import java.util.Scanner;
public class PutAsteriskFor {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.print("何個*を表示しますか?:");
int n = stdIn.nextInt();
for(int i = 0; i < n; i++){
System.out.print('*');
}
System.out.println();
stdIn.close();
}
}
プログラムはwhile文よりも短くなります。for文に慣れるとwhile文よりも直観的に分かりやすいものとなります。
for文とwhile文は相互に置き換えることができます。以下の図は、同等に書いた各文になります。
for文のプログラムの流れは以下のようになります。
- まず、前処理ともいうべきAが評価、実行されます。
- 継続条件であるBの制御式がtrueである限り、文が実行されます。
- 文の実行後は、後始末的な処理あるいは次の繰り返しのための準備としてCが評価、実行されます。
for文の各部に関する細かい規則などを以下に示します。
A for初期化部
Aには変数を置くことができます。ここで、宣言する変数はそのfor文の中でのみ使用できます。異なるfor文で同一名の変数を使用するには、各for文毎に宣言が必要です。
B 式(制御式)
B部も省略できます。省略した場合、繰り返しの継続判定は常にtrueとみなされます。この後で学習するbreak文やreturn文をループ本体中で実行しない限り、永遠に繰り返す無限ループになります。
C for 更新部
複数の式をコンマで区切っておくこともできます。何も行うことが無ければ、Cも省略可能です。
フローチャート
ここでは、フローチャートとその記号について解説します。
- 流れ図の記号
問題の定義、分析、解法の図的表現である流れ図=フローチャート(flowchart)と、その記号は以下の規格で定義されています。
JIS X0121「情報処理用流れ図・プログラム網図・システム資源図記号」
- プログラム流れ図(program flowchart)
プログラム流れ図は、以下に示す記号で構成されます。
実際に行う演算を示す記号、制御の流れを示す線記号、プログラム流れ図を理解し、かつ作成するために便宜を与える特殊記号。
- データ(data)
媒体を指定しないデータを表します。
- 処理(process)
任意の種類の処理機能を表します。例えば、情報の値、形、位置を変えるように定義された演算、もしくは演算群の実行、または、それに続くいくつかの流れの方向の1つを決定する演算もしくは演算群の実行を表します。
- 定義済み処理(predefined process)
サブルーチンやモジュールなど、別の場所で定義された1つ以上の演算又は命令群からなる処理を表します。
- 判断(decision)
1つの入り口と複数の択一的な出口を持ち、記号中に定義された条件の評価に従って、唯一の出口を選ぶ判断機能、またはスイッチ形の機能を表します。想定される評価結果は、経路を表す線の近くに書きます。
- ループ端(loop limit)
2つの部分から構成され、ループの始まりと終わりを表します。記号の2つの部分には、同じ名前を用います。ループの始端記号または、ループの終端記号の中に初期化・増分・終了条件を表記します。
- 線(line)
制御の流れを表します。流れの向きを明示する必要がある時は、矢先を付けなければなりません。
- 端子(terminator)
外部環境への出口、または外部環境からの入り口を表します。例えばプログラムの流れの開始もしくは終了を表します。
この他に、並列処理や破線などの記号があります。
奇数の列挙
まずは、整数値を読み込んで、その整数値以下の正の奇数1,3,5,… を表示するプログラムを作りましょう。
//Odd.java
//読み込んだ整数値以下の奇数を表示
import java.util.Scanner;
public class OddNo {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.print("整数値:");
int n = stdIn.nextInt();
for(int i = 1; i <= n; i += 2){
System.out.println(i);
}
stdIn.close();
}
}
for文の中で i += 2 で使っているのは、右オペランドの値を左オペランドに加える複合代入演算子になります。変数 i に 2 を繰り返しの度に増やしていきます。
約数の列挙
次に読み込んだ整数値のすべての約数を表示するプログラムを作りましょう。
//Measure.java
//読み込んだ整数値の約数を全て表示
import java.util.Scanner;
public class Measure {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.print("整数値:");
int n = stdIn.nextInt();
for(int i = 1; i <= n; i++){
if(n % i == 0)
System.out.println(i);
}
stdIn.close();
}
}
まず、変数nに整数値を読み込みます。続くfor文では、変数 i の値を1からnまでインクリメントします。n を i で割った余剰が0ならば、i は n の約数であると判断できます。
複数変数の同時制御
これまでのプログラムのfor文は、1つの変数の値を元にして繰り返しを制御するものでした。for文では、複数の変数を同時に制御することも可能です。例が以下のようになります。
//For2var.java
//読み込んだ整数値と各値との差を表示
import java.util.Scanner;
public class For2var {
public static void main(String[] args){
Scanner stdIn = new Scanner(System.in);
System.out.print("整数値:");
int n = stdIn.nextInt();
for(int i = 1, j = n-1; i <= n; i++, j--){
System.out.println("数字" + i + "との差は" + j);
}
stdIn.close();
}
}
プログラムの流れを確認しましょう。まず、最初に整数値 n に読み込みます。 2つの変数 i と j を宣言して、それぞれ 1 と n – 1 で初期化します。i の値をインクリメントする傍ら、j の値をデクリメントします。i の値は1ずつ増加し、j の値は1ずつ減少します。i <= nが成立しなくなると、繰り返しは終了します。