今まで、"x = 100"のようにデータを出力するときは、
System.out.print
と
System.out.println
を組み合わせて使ってきました。
/* 1*/ class StringPlusTest1 { // printとprintlnを組み合わせる /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.print("x = "); /* 5*/ System.out.println(x); /* 6*/ } /* 7*/ }
24102a1:java1 k16x1001$ java StringPlusTest1 x = 100 24102a1:java1 k16x1001$
データの出力で使う
System.out.println(
データ
);
や
System.out.print(
データ
);
の「
データ
」の所では、文字列や変数などを演算子
+
で結ぶことができます。
/* 1*/ class StringPlusTest2 { // 文字列と整数を連結する /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.println("x = " + x); // 連結 /* 5*/ } /* 6*/ }
実は、この演算子
+
は文字列の連結です。
一方だけが文字列のときは、他方を文字列に変換して連結するという約束になっています。
整数と整数の足し算も
+
なので、混乱しそうなら、括弧を使ってください。
「ターミナル」に"OK"と出力するには、
System.out.println("OK");
と書きました。 では、ダブルクオート(")も出力するにはどうすればよいでしょうか。 正解は、
System.out.println("\"OK\"");
です。
文字列
\"
がダブルクオートの代りになるように、直接扱いにくい文字の代りとなる文字列を、
エスケープ・シーケンス
(
escape sequence
)とよびます。
Javaのエスケープ・シーケンスは以下の通りです。
ここで、タブとは一定のきざみ(たいていは8文字単位)の位置まで設けられる間隔のことです。
データを表のような形式で出力するときに役に立ちます。
\b
|
バックスペース |
\t
|
タブ |
\n
|
改行 |
\f
|
フォームフィード |
\r
|
復帰 |
\"
|
ダブルクオート |
\'
|
シングルクオート |
\\
|
バックスラッシュ |
注意:
記号
\
は、場合によってバックスラッシュになったり円記号になったりします。
エスケープ・シーケンスが使えないときは、バックスラッシュと円記号を入れ替えてみてください。
以下は、
System.out.println
で改行する代わりに、エスケープ・シーケンスで改行する例です。
/* 1*/ class StringPlusTest3 { // エスケープ・シーケンスで改行する /* 2*/ public static void main (String[] args) { /* 3*/ int x = 100; /* 4*/ System.out.print("x = " + x + "\n"); // 改行する /* 5*/ } /* 6*/ }
前回の授業では、繰返し文を紹介しました。 何回繰り返すか分かっているときはfor文、分かっていないときは while文 ( while statement )を使うと説明しました。 今日はwhile文を使います。
while文の形式は以下のとおりです。
while (条件) { 文; ... }
これで、「 条件 」が成り立っている間、「 文 」 ... が繰り返し実行されます。 while文の実行の流れは以下のとおりです。
例えば、OKと10回出力するプログラムをwhile文で書くと、次のようになります。 10回繰り返す仕組みはfor文と同じで、変数 i が10未満の間、OKの出力と i の増加を繰り返します。
/* 1*/ class WhileTest { // while文のテスト /* 2*/ public static void main (String[] args) { /* 3*/ int i = 0; /* 4*/ while (i < 10) { // i<10の間繰り返す /* 5*/ System.out.println("OK"); /* 6*/ i++; /* 7*/ } /* 8*/ } /* 9*/ }
24102a1:java1 k16x1001$ java WhileTest OK OK OK OK OK OK OK OK OK OK 24102a1:java1 k16x1001$
while文は、「 文 」 ... を実行する前に「 条件 」を確認します。 したがって、「 条件 」によっては「 文 」 ... が1回も実行されないことがあります。 次のプログラムでは、最初から成り立たない条件( i ≠0)を与えることよって、1回もOKと出力しません。
/* 1*/ class WhileTest2 { // while文のテスト2 /* 2*/ public static void main (String[] args) { /* 3*/ int i = 0; /* 4*/ while (i != 0) { // 最初から成り立たない /* 5*/ System.out.println("OK"); /* 6*/ } /* 7*/ } /* 8*/ }
24102a1:java1 k16x1001$ java WhileTest2 24102a1:java1 k16x1001$
最初から成り立たない条件の反対で、永久に成り立つ条件を与えると、今度は永久に繰り返してしまいます。 永久に繰り返す繰返しを、 無限ループ ( infinite loop )と呼びます。 もし、プログラムが無限ループに陥ったら、controlキーを押しながらCキーを押して、プログラムを強制終了してください。
while文は「 文 」 ... を実行する前に「 条件 」を確認しますが、「 文 」 ... を実行した後で「 条件 」を確認するという繰返し文もあります。 それが、 do-while文 ( do-while statement )です。
do-while文の形式は以下のとおりです。
do { 文; ... } while (条件);
「 条件 」が成り立っている間、「 文 」 ... が繰り返し実行されることはwhile文と同じですが、do-while文は「 文 」 ... を実行した後で「 条件 」を確認します。 do-while文の実行の流れは以下のとおりです。
do-while文を使っても、10回OKと出力するプログラムが書けます。
/* 1*/ class DoWhileTest { // do-while文のテスト /* 2*/ public static void main (String[] args) { /* 3*/ int i = 0; /* 4*/ do { /* 5*/ System.out.println("OK"); /* 6*/ i++; /* 7*/ } while (i < 10); // i<10の間繰り返す /* 8*/ } /* 9*/ }
24102a1:java1 k16x1001$ java DoWhileTest OK OK OK OK OK OK OK OK OK OK 24102a1:java1 k16x1001$
while文は「 文 」 ... を1回も実行しないかもしれないのに対して、do-while文は少なくとも1回は実行します。 以下のように、最初から成り立たない条件( i ≠0)を与えても、1回だけOKと出力します。
/* 1*/ class DoWhileTest2 { // do-while文のテスト2 /* 2*/ public static void main (String[] args) { /* 3*/ int i = 0; /* 4*/ do { /* 5*/ System.out.println("OK"); /* 6*/ } while (i != 0); // 最初から成り立たない /* 7*/ } /* 8*/ }
24102a1:java1 k16x1001$ java DoWhileTest2 OK 24102a1:java1 k16x1001$
while文は「 文 」 ... を実行する前に「 条件 」を確認し、do-while文は「 文 」 ... を実行した後で「 条件 」を確認します。 では、「 文 」 ... を実行している途中で「 条件 」を確認するには、どうしたらよいでしょうか。 これは、 break文 ( break statement )を使うとできます。
break文は、for文やwhile文、do-while文の中で使い、break文を実行すると、繰返しを途中で終了します。
break文の典型的な使い方は、while文の「 条件 」をtrue(成り立つ)にして無条件に繰り返し、その中のif文で「 条件 」を確認して、break文で繰返しを途中で終了するというものです。
このパターンで10回OKと出力するプログラムを書くと、次のようになります。
/* 1*/ class BreakTest { // break文のテスト /* 2*/ public static void main (String[] args) { /* 3*/ int i = 0; /* 4*/ while (true) { // 無条件に繰り返す /* 5*/ if (i >= 10) { /* 6*/ break; // 途中で繰返しを終了 /* 7*/ } /* 8*/ System.out.println("OK"); /* 9*/ i++; /* 10*/ } /* 11*/ } /* 12*/ }
24102a1:java1 k16x1001$ java BreakTest OK OK OK OK OK OK OK OK OK OK 24102a1:java1 k16x1001$
繰返しの回数が問題になる例として、レジのような計算を考えます。 つまり、整数を次々と入力してもらい、最後にその合計を出力するというプログラムです。 最後の目印として、0が入力されたら合計を出力して終了することにします。
24102a1:java1 k16x1001$ java InputTotal 整数を入力してください: 100 整数を入力してください: 200 整数を入力してください: 300 整数を入力してください: 0 合計は600です。 24102a1:java1 k16x1001$
繰返しの回数が分からないので、for文は使わず、while文を使うかdo-while文を使うか考えます。 入力を求める部分は、必ず1回は実行するので、do-while文が良さそうです。 一方、合計を計算する部分は、1回も実行しないかもしれないので、while文が良さそうです。 結局、どっちもどっちなので、while文で無条件に繰り返し、break文で繰返しを途中で終了することにします。
/* 1*/ import java.io.*; /* 2*/ /* 3*/ class InputTotal { // 入力の合計 /* 4*/ public static void main (String[] args) throws IOException { /* 5*/ InputStreamReader isr = new InputStreamReader(System.in); /* 6*/ BufferedReader br = new BufferedReader(isr); /* 7*/ int x, total = 0; /* 8*/ while (true) { // 無条件に繰り返す /* 9*/ System.out.print("整数を入力してください: "); /* 10*/ x = Integer.parseInt(br.readLine()); /* 11*/ if (x == 0) { /* 12*/ break; // 途中で繰返しを終了 /* 13*/ } /* 14*/ total += x; /* 15*/ } /* 16*/ System.out.println("合計は" + total + "です。"); /* 17*/ } /* 18*/ }
繰返しの繰返し、すなわち、繰返し文の中にさらに繰返し文を書くこともできます。 このような繰返しを、 2重ループ ( nested loop )と呼ぶことがあります。 3重ループやそれ以上も考えられます。
一般的に、2重ループではループ変数を2つ用意します。 変数が i と j ならば、 i を外側のループ変数とし、 j を内側のループ変数とします。
次のプログラムは、出力を4回繰り返すことを3回繰り返すものです。 変数 i と j がどのように変化するかを見てください。
/* 1*/ class NestedLoop { // 2重ループ /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ for (i = 0; i < 3; i++) { // 3回繰り返す /* 5*/ for (j = 0; j < 4; j++) { // 4回繰り返す /* 6*/ System.out.println("i = " + i + ", j = " + j + "."); /* 7*/ } /* 8*/ } /* 9*/ } /* 10*/ }
24102a1:java1 k16x1001$ 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. 24102a1:java1 k16x1001$
繰返し文の使用例として、九九の表を作成します。 九九の表は、2重ループを使うと、うまく作れます。 ループ変数 i と j を、1から9まで変化させればよいのです。
/* 1*/ class MultiplicationTable { // 九九の表 /* 2*/ public static void main (String[] args) { /* 3*/ int i, j; /* 4*/ for (i = 1; i <= 9; i++) { // 9回繰り返す /* 5*/ for (j = 1; j <= 9; j++) { // 9回繰り返す /* 6*/ System.out.print(i + "*" + j + "=" + i * j + "\t"); /* 7*/ } /* 8*/ System.out.println(); // 改行 /* 9*/ } /* 10*/ } /* 11*/ }
24102a1:java1 k16x1001$ java MultiplicationTable 1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9 2*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18 3*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27 4*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 24102a1:java1 k16x1001$
繰返し文を使ったアプレットの例として、パターンを描きます。 ここでは、市松模様を取り上げます。 幅300ピクセル、高さ200ピクセルのアプレットに、一辺20ピクセルの正方形を敷き詰めます。
一見、繰返しでは描けないように見えますが、以下のパターン要素を縦横に繰り返し描けばできます。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class Checkers1 extends Applet { // 市松模様1 /* 5*/ public void paint (Graphics g) { /* 6*/ g.setColor(Color.white); /* 7*/ g.fillRect(0, 0, 20, 20); /* 8*/ g.fillRect(20, 20, 20, 20); /* 9*/ g.setColor(Color.black); /* 10*/ g.fillRect(20, 0, 20, 20); /* 11*/ g.fillRect(0, 20, 20, 20); /* 12*/ } /* 13*/ }
まず、このパターン要素を横に描きます。 ループ変数を j とし、 j を1増加させるごとに横に40ピクセルずらします。 最後が少しはみ出ますが、アプレットではみ出た描画は単に表示されないだけなので問題ありません。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class Checkers2 extends Applet { // 市松模様2 /* 5*/ public void paint (Graphics g) { /* 6*/ int j; /* 7*/ for (j = 0; j < 8; j++) { // 8回繰り返す /* 8*/ g.setColor(Color.white); /* 9*/ g.fillRect(40 * j, 0, 20, 20); /* 10*/ g.fillRect(40 * j + 20, 20, 20, 20); /* 11*/ g.setColor(Color.black); /* 12*/ g.fillRect(40 * j + 20, 0, 20, 20); /* 13*/ g.fillRect(40 * j, 20, 20, 20); /* 14*/ } /* 15*/ } /* 16*/ }
そして、これをさらに縦に繰り返すと出来上がりです。 ループ変数を i とし、 i を1増加させるごとに縦に40ピクセルずらします。
/* 1*/ import java.applet.*; /* 2*/ import java.awt.*; /* 3*/ /* 4*/ public class Checkers3 extends Applet { // 市松模様3 /* 5*/ public void paint (Graphics g) { /* 6*/ int i, j; /* 7*/ for (i = 0; i < 5; i++) { // 5回繰り返す /* 8*/ for (j = 0; j < 8; j++) { // 8回繰り返す /* 9*/ g.setColor(Color.white); /* 10*/ g.fillRect(40 * j, 40 * i, 20, 20); /* 11*/ g.fillRect(40 * j + 20, 40 * i + 20, 20, 20); /* 12*/ g.setColor(Color.black); /* 13*/ g.fillRect(40 * j + 20, 40 * i, 20, 20); /* 14*/ g.fillRect(40 * j, 40 * i + 20, 20, 20); /* 15*/ } /* 16*/ } /* 17*/ } /* 18*/ }
例を参考にして、2重ループを使って、パターンを描画するアプレットを作成してください。 余力のある人は、より複雑なパターン(ギンガム・チェックやタータン・チェックなど)にしてください。
今日の演習8の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(11月18日)を明記してください。