[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理技法(Javaプログラミング)I 第8回

目次
索引

データの入出力(2)

文字列の連結

今まで、"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*/ }

繰返し文(2)

while文

前回の授業では、繰返し文を紹介しました。 何回繰り返すか分かっているときはfor文、分かっていないときは while文 while statement )を使うと説明しました。 今日はwhile文を使います。

while文の形式は以下のとおりです。

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$
条件が成り立たないwhile文
条件が成り立たないwhile文

最初から成り立たない条件の反対で、永久に成り立つ条件を与えると、今度は永久に繰り返してしまいます。 永久に繰り返す繰返しを、 無限ループ infinite loop )と呼びます。 もし、プログラムが無限ループに陥ったら、controlキーを押しながらCキーを押して、プログラムを強制終了してください。

do-while文

while文は「 ... を実行する前に「 条件 」を確認しますが、「 ... を実行した後で「 条件 」を確認するという繰返し文もあります。 それが、 do-while文 do-while statement )です。

do-while文の形式は以下のとおりです。

do {
    ; ...
} while (条件);

条件 」が成り立っている間、「 ... が繰り返し実行されることはwhile文と同じですが、do-while文は「 ... を実行した後で「 条件 」を確認します。 do-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$
条件が成り立たないdo-while文
条件が成り立たないdo-while文

break文

while文は「 ... を実行する前に「 条件 」を確認し、do-while文は「 ... を実行した後で「 条件 」を確認します。 では、「 ... を実行している途中で「 条件 」を確認するには、どうしたらよいでしょうか。 これは、 break文 break statement )を使うとできます。

break文は、for文やwhile文、do-while文の中で使い、break文を実行すると、繰返しを途中で終了します。

break文の典型的な使い方は、while文の「 条件 」をtrue(成り立つ)にして無条件に繰り返し、その中のif文で「 条件 」を確認して、break文で繰返しを途中で終了するというものです。

break文の実行の流れ
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重ループ

繰返しの繰返し、すなわち、繰返し文の中にさらに繰返し文を書くこともできます。 このような繰返しを、 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)

繰返し文の使用例として、九九の表を作成します。 九九の表は、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ピクセルの正方形を敷き詰めます。

パターンの例(Checkers)
パターンの例(Checkers)

一見、繰返しでは描けないように見えますが、以下のパターン要素を縦横に繰り返し描けばできます。

/*  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*/ }
パターンの要素(1)
パターンの要素(1)

まず、このパターン要素を横に描きます。 これは座標 (0, 0) を基準にしていますので、座標 (0, 0)、座標 (40, 0), 座標 (80, 0), ...を基準にして繰り返し描けばよいです。 ループ変数を j とし、すべての x 座標に 40× j を足せば、パターン要素が横に描けます。 最後が少しはみ出ますが、アプレットではみ出た描画は単に表示されないだけなので問題ありません。

/*  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*/ }
パターンの要素(2)
パターンの要素(2)

そして、これをさらに縦に繰り返すと出来上がりです。 座標 (0, 0) が基準なので、座標 (0, 0)、座標 (0, 40), 座標 (0, 80), ...を基準にして繰り返し描きます。 ループ変数を i とし、すべての y 座標に 40× i を足せば、縦に繰り返せます。

/*  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*/ }

演習8

例を参考にして、2重ループを使って、パターンを描画するアプレットを作成してください。 余力のある人は、より複雑なパターン(ギンガム・チェックやタータン・チェックなど)にしてください。

パターンの例(PolkaDots)
パターンの例(PolkaDots)

レポート課題

今日の演習8の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(11月23日)を明記してください。


参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2018年11月23日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2018 Zenjiro Konishi. All rights reserved.