目次 | 索引 |
---|---|
これまで、端末エミュレータにデータを出力するには、
System.out.println(
data
);
を使ってきました。
文字列をそのまま出力するには、
data
の部分にその文字列をダブルクオート(
"
)で囲んで書き、変数の値を出力するには、そこにその変数名を書きました。
演算子
+
で結びますと、それらを混在させることができます。
/* 1*/ class IntToString { /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.println("x"); /* 5*/ System.out.println(x); /* 6*/ System.out.println("x = " + x); /* 7*/ } /* 8*/ }
b00a001@Ampere:~/java% java IntToString x 100 x = 100 b00a001@Ampere:~/java%
実は、この演算子
+
は文字列の連結です。
一方だけが文字列のときは、他方を文字列に変換して連結するという約束になっています。
System.out.println(
data
);
は、出力の後に改行します。
改行してほしくないときは、
System.out.print(
data
);
と書きます。
また、改行だけしてほしいときは、
System.out.println();
とします。
注意:
端末エミュレータへの出力は一文字ずつ行なわれるわけではなく、ある程度の文字数になるか改行があるとまとめて行なわれます。
System.out.print(
data
);
と書いてあるのに何も出力されないときは、改行
System.out.println();
を忘れていないか確認してください。
while
文前回の授業では、選択というプログラムの構成要素を紹介しました。 今日は、 反復 ( iteration )について説明します。
反復にはいくつか種類がありますが、「何々が成り立つ間、何々を繰り返す」というものが基本です。
この種の反復には
while
文を使います。
while
文は以下の形をとります。
while (condition) { statement; ... }
条件
condition
が成り立っている間、文
statement
;
...
が繰り返し実行されます。
ここで、Good morning!と10回出力するプログラムを考えます。
はじめは数え上げ方式です。
これは、変数
i
に0を代入しておき、Good morning!と一回出力するごとに
i
の値を1増やすということを、
i
の値が10未満の間繰り返すものです。
/* 1*/ class TenMornings { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 0; /* 5*/ while (i < 10) { /* 6*/ System.out.println("Good morning!"); /* 7*/ i++; /* 8*/ } /* 9*/ } /*10*/ }
b00a001@Ampere:~/java% java TenMornings Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! Good morning! b00a001@Ampere:~/java%
5行目から8行目までの
while
文は次のように実行されます。
i
の値は0。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は1。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は9。条件i < 10
が成り立つので、Good morning!と出力し、i
の値を1増やす。i
の値は10。条件i < 10
は成り立たないので、このwhile
文の実行を終える。
次はカウントダウン方式です。
これは、変数
i
に10を代入しておき、Good morning!と一回出力するごとに
i
の値を1減らすということを、
i
の値が正の間繰り返すものです。
/* 1*/ class TenMornings2 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 10; /* 5*/ while (i > 0) { /* 6*/ System.out.println("Good morning!"); /* 7*/ i--; /* 8*/ } /* 9*/ } /*10*/ }
5行目から8行目までの
while
文は次のように実行されます。
i
の値は10。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は9。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は1。条件i > 0
が成り立つので、Good morning!と出力し、i
の値を1減らす。i
の値は0。条件i > 0
は成り立たないので、このwhile
文の実行を終える。数え上げ方式とカウントダウン方式のどちらがよいかは、問題によって変わります。 数え上げ方式のほうがよく使われますが、カウントダウン方式が適切な場合もあります。
注意: 上記のプログラムで、7行目を書き忘れたとしましょう。
/* 1*/ class InfiniteMornings { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ i = 10; /* 5*/ while (i > 0) { /* 6*/ System.out.println("Good morning!"); /* 7*/ } /* 8*/ } /* 9*/ }
このプログラムを実行しますと、変数
i
の値は10のままですので、条件
i > 0
がずっと成り立ち、永遠にGood morning!と出力され続けることになります。
このような、いつまでも続く繰り返しを、
無限ループ
(
infinite loop
)とよびます。
反復を使うときは、無限ループにならないように気をつける必要があります。
なお、誤って無限ループに陥ったときは、Ctrl-Cで強制終了してください。
次のプログラムは、1+2+...+100を計算するものです。
変数
i
の値を1ずつ増加させながら、変数
sum
にそれまでの合計を格納していきます。
/* 1*/ class Summation { /* 2*/ public static void main (String[] args) { /* 3*/ int i, sum = 0; /* 4*/ i = 1; /* 5*/ while (i <= 100) { /* 6*/ sum = sum + i; /* 7*/ i++; /* 8*/ } /* 9*/ System.out.println(sum); /*10*/ } /*11*/ }
b00a001@Ampere:~/java% java Summation 5050 b00a001@Ampere:~/java%
for
文
反復の種類の中には、何らかの変数(
ループ変数
とよびます)を増加(あるいは減少)させながら繰り返すというものがあります。
for
文を用いますと、このような反復をコンパクトに書き表すことができます。
for
文は次のような形をとります。
for (statement1; condition; statement2) { statement3; ... }
まず文
statement1
が一度だけ実行されます。
そして条件
condition
が成り立っている間、文
statement3
;
...
と
statement2
が繰り返し実行されます。
while
文を使ってこの
for
文を書きますと、次のようになります。
statement1; while (condition) { statement3; ... statement2; }
for
文を用いますと、Good morning!と10回出力するプログラムは次のように書けます。
数え上げ方式については、
/* 1*/ class TenMornings3 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ for (i = 0; i < 10; i++) { /* 5*/ System.out.println("Good morning!"); /* 6*/ } /* 7*/ } /* 8*/ }
です。 カウントダウン方式は、
/* 1*/ class TenMornings4 { /* 2*/ public static void main (String[] args) { /* 3*/ int i; /* 4*/ for (i = 10; i > 0; i--) { /* 5*/ System.out.println("Good morning!"); /* 6*/ } /* 7*/ } /* 8*/ }
となります。
また、1+2+...+100を計算するプログラムは次のようになります。
/* 1*/ class Summation2 { /* 2*/ public static void main (String[] args) { /* 3*/ int i, sum = 0; /* 4*/ for (i = 1; i <= 100; i++) { /* 5*/ sum = sum + i; /* 6*/ } /* 7*/ System.out.println(sum); /* 8*/ } /* 9*/ }
for
文の中に、さらに
for
文を書くこともできます。
このような、「反復の反復」となる構造は、
多重ループ
(
nested loop
)とよばれます。
多重ループでは、ループ変数が衝突しないように注意する必要があります。
次のプログラムは、2重のループの中で、ループ変数の値を出力するものです。
ループ変数は、
i
と
j
の2つです。
この2つの変数の値がどう変化するかに注目してください。
/* 1*/ class NestedLoop { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ for (i = 0; i < 3; i++) { /* 5*/ for (j = 0; j < 4; j++) { /* 6*/ System.out.println("i = " + i + ", j = " + j); /* 7*/ } /* 8*/ } /* 9*/ } /*10*/ }
b00a001@Ampere:~/java% java NestedLoop i = 0, j = 0 i = 0, j = 1 i = 0, j = 2 i = 0, j = 3 i = 1, j = 0 i = 1, j = 1 i = 1, j = 2 i = 1, j = 3 i = 2, j = 0 i = 2, j = 1 i = 2, j = 2 i = 2, j = 3 b00a001@Ampere:~/java%
多重ループは、「長方形」のように実行されるとは限りません。 より複雑な多重ループも考えられます。
次のプログラムは、記号を使って旗のような三角形を出力するものです。 三角形の大きさは、コマンドライン引数で与えます。
/* 1*/ class FillPennant { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ int size = Integer.parseInt(args[0]); /* 5*/ for (i = 0; i < size; i++) { /* 6*/ for (j = 0; j < size - i; j++) { /* 7*/ System.out.print("*"); /* 8*/ } /* 9*/ System.out.println(); /*10*/ } /*11*/ } /*12*/ }
b00a001@Ampere:~/java% java FillPennant 5 ***** **** *** ** * b00a001@Ampere:~/java% java FillPennant 7 ******* ****** ***** **** *** ** * b00a001@Ampere:~/java%
5行目の
for
によって、
size
の値だけ行が作られます。
そして、6行目の
for
によって、
size - i
の値だけ記号が出力されます。
6行目の反復回数が、
i
の値によって変わることに注意してください。
行を追うごとに記号を減らすわけですから、ループ変数
i
をカウントダウン方式にしますと、多少分かりやすくなります。
/* 1*/ class FillPennant2 { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ int size = Integer.parseInt(args[0]); /* 5*/ for (i = size; i > 0; i--) { /* 6*/ for (j = 0; j < i; j++) { /* 7*/ System.out.print("*"); /* 8*/ } /* 9*/ System.out.println(); /*10*/ } /*11*/ } /*12*/ }
そのほかに、多重ループを「長方形」のように実行しておき、記号を出力するか否かを
i
と
j
の値に基づいて決定するという方法もあります。
記号を出力する条件は、
j < size - i
とも
i < size - j
とも書けますが、ここでは
i + j < size
とします。
また、記号を出力しない場合はスペースを出力します。
/* 1*/ class FillPennant3 { /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ int size = Integer.parseInt(args[0]); /* 5*/ for (i = 0; i < size; i++) { /* 6*/ for (j = 0; j < size; j++) { /* 7*/ if (i + j < size) { /* 8*/ System.out.print("*"); /* 9*/ } else { /*10*/ System.out.print(" "); /*11*/ } /*12*/ } /*13*/ System.out.println(); /*14*/ } /*15*/ } /*16*/ }
次のように、コマンドライン引数 r を受け取り、記号を使って「半径」 r のひし形を出力するJavaプログラムを作成してください。 r は負でない整数と仮定してください。
b00a001@Ampere:~/java% java FillDiamond 2 * *** ***** *** * b00a001@Ampere:~/java% java FillDiamond 3 * *** ***** ******* ***** *** * b00a001@Ampere:~/java%
このプログラムにはいくつかの方針が考えられます。 以下にその例を示しますが、自分で考えてもかまいません。
-r
は、
r
の正負の反転を意味する。
Math.abs(k)
で与えられる。
今日の演習5に従ってJavaプログラムを作成し、そのプログラムをkonishi@twcu.ac.jpあてにメールで提出してください。 メールには、学生番号、氏名、科目名、授業日(10/18)を明記してください。