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

情報処理技法(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 k12x1001$ java StringPlusTest1
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
x = 100
24102a1:java1 k12x1001$

データの出力で使う 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)

do-while文

前回の授業では、繰返し文について説明しました。 その中で、繰り返しの回数がはっきりしているときにはfor文を使い、そうでないときにはwhile文を使うと言いました。

繰り返しの回数がはっきりしていない例として、レジのような計算を考えます。 つまり、整数を次々と入力してもらい、最後にその合計を出力するというプログラムです。 最後の目印として、0が入力されたら合計を出力して終了することにします。

24102a1:java1 k12x1001$ java InputTotal
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
整数を入力してください: 100
整数を入力してください: 200
整数を入力してください: 300
整数を入力してください: 0
合計は600です。
24102a1:java1 k12x1001$

次のプログラムは、while文を使った場合です。 最初に0が入力される可能性があるので、9行目と13行目の両方で、入力される値を取り出しています。

/*  1*/ import java.io.*;
/*  2*/ 
/*  3*/ class InputTotal1 { // 入力の合計1
/*  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*/         System.out.print("整数を入力してください: ");
/*  9*/         x = Integer.parseInt(br.readLine()); // 入力
/* 10*/         while (x != 0) { // 0が入力されるまで繰り返す
/* 11*/             total += x;
/* 12*/             System.out.print("整数を入力してください: ");
/* 13*/             x = Integer.parseInt(br.readLine()); // 入力
/* 14*/         }
/* 15*/         System.out.println("合計は" + total + "です。");
/* 16*/     }
/* 17*/ }

while文と似たものに、do-while文があります。 これは、条件を確認してから文の並びを実行するのではなく、文の並びを実行してから条件を確認するものです。

do-while文 の形式は、次の通りです。

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

これは、

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

と同じ意味です。

while文がその中身を一度も実行しないかもしれないのに対して、do-while文はその中身を必ず一度は実行します。 条件の成立、不成立に関わらず、1回以上繰り返す場合は、do-while文を使います。

次のプログラムは、入力の合計の計算で、do-while文を使った場合です。 while文の場合と比べて、入力される値を取り出す部分が、1か所になっています。 ただし、0が入力されても11行目が実行されるので、もし0でない数で終了を表すなら間違うことになります。

/*  1*/ import java.io.*;
/*  2*/ 
/*  3*/ class InputTotal2 { // 入力の合計2
/*  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*/         do {
/*  9*/             System.out.print("整数を入力してください: ");
/* 10*/             x = Integer.parseInt(br.readLine()); // 入力
/* 11*/             total += x;
/* 12*/         } while (x != 0); // 0が入力されるまで繰り返す
/* 13*/         System.out.println("合計は" + total + "です。");
/* 14*/     }
/* 15*/ }

break文

break文 は、繰返しを終了する文です。 具体的には、while文やdo-while文やfor文の実行中にbreak文があると、繰返しの途中でも実行が終了し、その繰返し文の次に制御が移ります。

次のプログラムは、入力の合計の計算で、break文を使った場合です。 do-while文の場合と比べて、もし0でない数で終了を表しても大丈夫です。

なお、while文の条件が true なのに注意してください。 これは、条件が成り立つことを意味し、無限ループを作るときに使います。 無限ループはプログラムとして間違っていますが、break文で終了しているので、本当の無限ループではないのです。

/*  1*/ import java.io.*;
/*  2*/ 
/*  3*/ class InputTotal3 { // 入力の合計3
/*  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 k12x1001$ java NestedLoop
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
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 k12x1001$

繰返し文の使用例(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 k12x1001$ java MultiplicationTable
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
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 k12x1001$

繰返し文を使ったアプレットの例として、パターンを描きます。 ここでは、市松模様を取り上げます。 幅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)

まず、このパターン要素を横に描きます。 ループ制御変数を 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*/ }
パターンの要素(2)
パターンの要素(2)

そして、これをさらに縦に繰り返すと出来上がりです。 ループ変数を 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*/ }

演習8

例を参考にして、2重ループを使って、パターンを描画するアプレットを作成してください。 余力のある人は、パターンを複雑にしてください。

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

レポート課題

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


参考文献


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

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