第12週目演習

下準備

テストドライバの導入

第12回目分のテストドライバを導入する。以下の手順で行う。

  1. ダウンロード のページを開く (ここをクリック)
  2. プロジェクト「java20XX」にある「test」の左側の「+」をクリック
  3. ツリーが展開されるので「install-libraries.xml」を右クリック
  4. 「実行(R)」にマウスカーソルを合わせる
  5. 「1 Ant ビルド」をクリック
  6. 「コンソール」タブに"BUILD SUCCESSFUL"と表示されれば成功
  7. eclipseの画面でプロジェクト「java20XX」を右クリック
  8. メニューが表示されるので、「更新」あるいは「最新表示」をクリック
  9. "week12.zip" をデスクトップなどにダウンロード
  10. eclipseの画面でプロジェクト「java20XX」を右クリック
  11. メニューから「インポート(I)」を選択
  12. 「インポート」ウィンドウが表示されるので、「Zip ファイル」を選択
  13. 「次へ(N)」をクリック
  14. 宛先フォルダー(L): が「java20XX」になっていることを確認
  15. From zip file: の右側にある「参照(R)...」あるいは 「ブラウズ(R)...」をクリック
  16. ファイルダイアログが表示されるので、ダイアログ内に表示されたダウンロードしたファイルをダブルクリック
  17. 前の画面に戻るので、From zip file: のエリアに正しいパスが入力されていることを確認
  18. フォルダ「/」の左にチェックがついていることを確認 (ついていなければチェックボックスをクリック)
  19. 「警告を出さずに既存リソースを上書き」にチェックがついていることを確認 (上書きしたくないファイルがある場合はチェックを外す)
  20. 「終了 (F)」をクリック

第12週目テストドライバの導入に成功すると、java20XX プロジェクトの test フォルダに j1.lesson12.xml というファイルが作成される。

パッケージの作成

過去の演習を参考にして、「j1.lesson12」というパッケージを作成する。

文字列を操作するプログラム

文字列を逆順に表示するプログラムを作成する。

このプログラムではコンソールに入力された文字列を逆順に表示する。

擬似コードの作成

「プログラム全体」の擬似コード

プログラム全体の擬似コードは以下のようにする。

プログラム全体
    print "文字列を入力:"
    line = コンソール入力 (文字列)
    for c = line 内のすべての文字を逆順に
        print c

骨格の作成

クラスの作成

以下の手順で、パッケージ「j1.lesson12」に「ReversePrint」クラスを作成する。

  1. 先ほど作成したパッケージ 「j1.lesson12」の上で右クリック
  2. マウスカーソルを「新規」に合わせる
  3. 「クラス」をクリック
  4. クラス名は ReversePrint とする

擬似コードの貼り付け (骨格のみ)

作成したクラスに、各擬似コードの名前を貼り付ける。ただし、「プログラム全体」ではコンソールからの入力を行っていたため、import java.io.*; も追加する。

package j1.lesson12;

import java.io.*;

public class ReversePrint {
    // プログラム全体
}

mainメソッドの作成 (骨格のみ)

擬似コード「プログラム全体」に合わせて、クラス「ReversePrint」内にpublic static void main(String[] args) から始まるメソッドを作成する。ただし、擬似コード「プログラム全体」ではコンソールからの入力を行っていたので、throws IOExceptionをつける。

全体の骨格

ここまでのプログラムの骨格は以下のようになる。

package j1.lesson12;

import java.io.*;

public class ReversePrint {
    // プログラム全体
    public static void main(String[] args) throws IOException {
    }
}

骨格テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「ReversePrint に対する骨格テスト」 を実行する。

骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「実行」ボタンをクリックする。

メッセージ 詳細
(クラス名), existence j1.lesson12 に対象のクラスが存在していない。パッケージやクラス名を確認
(メソッド名), existence 指定されたメソッドが存在しない
(メソッド名), public メソッドを作る際に public が抜けている
(メソッド名), static メソッドを作る際に static が抜けている
(メソッド名), type <T> メソッドを作る際に戻り値の型を間違えている (正しくは <T>)
(メソッド名), throws java.io.IOException メソッドを作る際に throws IOException が抜けている

プログラムへの変換

main メソッドの実装

先ほど作成した ReversePrint クラスの main メソッドの中身を記述する。

まずは擬似コードをコメントとして貼り付ける。

// プログラム全体
public static void main(String[] args) throws IOException {
    // print "文字列を入力:"
    // line = コンソール入力 (文字列)
    // for c = line 内のすべての文字を逆順に
        // print c
}

これを元にプログラムを作成する。

// プログラム全体
public static void main(String[] args) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
    // print "文字列を入力:"
    System.out.print("文字列を入力:");
    
    // line = コンソール入力 (文字列)
    String line = reader.readLine();
    
    // for c = line 内のすべての文字を逆順に
    for (int i = line.length() - 1; i >= 0; i--) {
        char c = line.charAt(i);
        
        // print c
        System.out.print(c);
    }
}

全体的には下記のようなプログラムにする。

package j1.lesson12;

import java.io.*;

public class ReversePrint {

    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        
        // print "文字列を入力:"
        System.out.print("文字列を入力:");
        
        // line = コンソール入力 (文字列)
        String line = reader.readLine();
        
        // for c = line 内のすべての文字を逆順に
        for (int i = line.length() - 1; i >= 0; i--) {
            char c = line.charAt(i);
            
            // print c
            System.out.print(c);
        }
    }
}

プログラムの実行

先週までと同じ手順でプログラムを実行する。

入力に "Hello world!"と与えてやると、以下のように表示される。

文字列を入力:Hello, world!
!dlrow ,olleH

機能テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「ReversePrint に対する機能テスト」 を実行する。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「実行」ボタンをクリックする。

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。

機能テストの項目

項目名 テストの内容
ABC 入力に ABC を指定してプログラムを実行

2次元配列を用いたプログラム

行列の足し算を行うプログラムを考える。

擬似コードの作成

「プログラム全体」の擬似コード

プログラム全体の擬似コードは以下のようにする。

プログラム全体
        | 0 1 2 |
    a = | 3 4 5 |
        | 6 7 8 |

        | 9 8 7 |
    b = | 6 5 4 |
        | 3 2 1 |

    c = a + b

    print c

「c = a + b」「print c」とあるが、2次元配列の加算や各要素の表示はJavaでは直接行うことはできない。次の擬似コードで詳細化する。

「add」の擬似コード

A, B, C を行列として、「C = A + B」を計算する場合、行列の各項について、 cij = aij + bij を計算してやればよい。

つまり、次のような行列の計算を考えた場合、


以下のように計算できる。


実際には行列の添え字は 0 ではなく 1 から始まるが、ここではJavaに合わせて 0 から始めている。

これを元に、「プログラム全体」で使用されている、行列の足し算の擬似コードは以下のようにする。

行列の和を計算(a,b)
    c = (a.length)x(a[0].length) の新しい2次元配列 (int[][])
    for all i in c[]
        for all j in c[i][]
            c[i][j] = a[i][j] + b[i][j]
    c を返す

「(a.length)x(a[0].length) の新しい2次元配列」はこのプログラムでは必ず 3x3 の新しい二次元配列になるが、ここでは汎用性を考えてこのような形にした。

行列の各要素を表示する擬似コード

プログラム全体の擬似コードの中に、

print c

というものがあった。しかし Javaでは System.out.print() メソッドなどを使用して配列を表示しようとすると、ID が表示されるのみで、配列内の各要素までは表示してくれない。

そこで、行列 (二次元配列) を表示するためのプログラムを作成する必要がある。

print-matrix(matrix)
    for i = 0 to matrixの長さ - 1
        for j = 0 to matrix[i]の長さ - 1
            print matrix[i][j] " "
        print 改行

骨格の作成

クラスの作成

以下の手順で、パッケージ「j1.lesson12」に「MatrixAdd」クラスを作成する。

  1. 先ほど作成したパッケージ 「j1.lesson12」の上で右クリック
  2. マウスカーソルを「新規」に合わせる
  3. 「クラス」をクリック
  4. クラス名は MatrixAdd とする

擬似コードの貼り付け (骨格のみ)

作成したクラスに、各擬似コードの名前を貼り付ける。

package j1.lesson12;

public class MatrixAdd {
    // プログラム全体
    // add(a,b)
    // print-matrix(matrix)
}

mainメソッドの作成 (骨格のみ)

擬似コード「プログラム全体」に合わせて、クラス「MatrixAdd」内にpublic static void main(String[] args) から始まるメソッドを作成する。

add メソッドの作成 (骨格のみ)

擬似コード「add」に合わせて、クラス「MatrixAdd」内に「add」という名前を持ち、仮引数に (int[][], int[][]) を取るメソッドを作成する。また、メソッドの戻り値は計算後の行列を返すため、戻り値型は int[][] とする。骨格だけでよいのでメソッドの中身は return new int[0][0]; とでも書いておく。

仮引数の名前は何でもよいが、ここでは擬似コードに合わせて順に a, b としておく。

printMatrix メソッドの作成 (骨格のみ)

擬似コード「print-matrix」に合わせて、クラス「MatrixAdd」内に「printMatrix」という名前を持ち、仮引数に int[][] 型を取るメソッドを作成する。メソッドの戻り値は特にないため、戻り値型は void とする。

仮引数の名前は何でもよいが、ここでは擬似コードに合わせて matrix としておく。

全体の骨格

ここまでのプログラムの骨格は以下のようになる。

package j1.lesson12;

public class MatrixAdd {

    // プログラム全体
    public static void main(String[] args) {
    }

    // 行列の和を計算(a,b)
    public static int[][] add(int[][] a, int[][] b) {
        return new int[0][0];
    }

    // print-matrix(matrix)
    public static void printMatrix(int[][] matrix) {
    }
}

骨格テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「MatrixAdd に対する骨格テスト」 を実行する。

骨格テストを行った際に緑のバーが表示されれば、外側から見たプログラムの骨格は正しくなっている。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「実行」ボタンをクリックする。

メッセージ 詳細
(クラス名), existence j1.lesson12 に対象のクラスが存在していない。パッケージやクラス名を確認
(メソッド名), existence 指定されたメソッドが存在しない
(メソッド名), public メソッドを作る際に public が抜けている
(メソッド名), static メソッドを作る際に static が抜けている
(メソッド名), type <T> メソッドを作る際に戻り値の型を間違えている (正しくは <T>)

プログラムへの変換

add メソッドの実装

メソッド add の中身を記述する。

まずは擬似コードをコメントとして貼り付ける

// 行列の和を計算(a,b)
public static int[][] add(int[][] a, int[][] b) {
    // c = (a.length)x(a[0].length) の新しい2次元配列 (int[][])
    // for all i in c[]
        // for all j in c[i][]
            // c[i][j] = a[i][j] + b[i][j]
    // c を返す

    return new int[0][0];
}

これを元にプログラムを作成する。書き終わったら最後に入れていたダミーの return 文はいらないので削除する。

// 行列の和を計算(a,b)
public static int[][] add(int[][] a, int[][] b) {
    // c = (a.length)x(a[0].length) の新しい2次元配列 (int[][])
    int[][] c = new int[a.length][a[0].length];

    // for all i in c[]
    for (int i = 0; i < c.length; i++) {
        // for all j in c[i][]
        for (int j = 0; j < c[i].length; j++) {
            // c[i][j] = a[i][j] + b[i][j]
            c[i][j] = a[i][j] + b[i][j];
        }
    }
    // c を返す
    return c;
}

printMatrix メソッドの実装

メソッド printMatrix の中身を記述する。

まずは擬似コードをコメントとして貼り付ける

// print-matrix(matrix)
public static void printMatrix(int[][] matrix) {
    // for i = 0 to matrixの長さ - 1
        // for j = 0 to matrix[i]の長さ - 1
            // print matrix[i][j] " "
        // print 改行
}

これを元にプログラムを作成する。

// print-matrix(matrix)
public static void printMatrix(int[][] matrix) {
    // for i = 0 to matrixの長さ - 1
    for (int i = 0; i < matrix.length; i++) {
        // for j = 0 to matrix[i]の長さ - 1
        for (int j = 0; j < matrix[i].length; j++) {
            // print matrix[i][j] " "
            System.out.print(matrix[i][j]);
            System.out.print(" ");
        }
        // print 改行
        System.out.println();
    }
}

add メソッドのテスト

余裕があれば、add に対する単体テストを作成せよ。もし時間が無い場合は、次のようにmainメソッド内にテスト用のコードを書いて実行してみること。

public static void main(String[] args) {
    int[][] testPattern = {{1,2,3},{4,5,6},{7,8,9}};
    int[][] testResult = add(testPattern, testPattern);
    printMatrix(testResult);
}

main メソッドの実装

続けて、先ほど作成した MatrixAdd クラスの main メソッドの中身を記述する。

まずは擬似コードをコメントとして貼り付ける。

// プログラム全体
public static void main(String[] args) {
    // ... | 0 1 2 |
    // a = | 3 4 5 |
    // ... | 6 7 8 |

    // ... | 9 8 7 |
    // b = | 6 5 4 |
    // ... | 3 2 1 |

    // c = a + b

    // print c
}

これを元にプログラムを作成する。

// プログラム全体
public static void main(String[] args) {
    // ... | 0 1 2 |
    // a = | 3 4 5 |
    // ... | 6 7 8 |
    int[][] a = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };

    // ... | 9 8 7 |
    // b = | 6 5 4 |
    // ... | 3 2 1 |
    int[][] b = { { 9, 8, 7 }, { 6, 5, 4 }, { 3, 2, 1 } };

    // c = a + b
    int[][] c = add(a, b);

    // print c
    printMatrix(c);
}

全体的には下記のようなプログラムにする。

package j1.lesson12;

public class MatrixAdd {

    // プログラム全体
    public static void main(String[] args) {
        // ... | 0 1 2 |
        // a = | 3 4 5 |
        // ... | 6 7 8 |
        int[][] a = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } };

        // ... | 9 8 7 |
        // b = | 6 5 4 |
        // ... | 3 2 1 |
        int[][] b = { { 9, 8, 7 }, { 6, 5, 4 }, { 3, 2, 1 } };

        // c = a + b
        int[][] c = add(a, b);

        // print c
        printMatrix(c);
    }

    // 行列の和を計算(a,b)
    public static int[][] add(int[][] a, int[][] b) {
        // c = (a.length)x(a[0].length) の新しい2次元配列 (int[][])
        int[][] c = new int[a.length][a[0].length];

        // for all i in c[]
        for (int i = 0; i < c.length; i++) {
            // for all j in c[i][]
            for (int j = 0; j < c[i].length; j++) {
                // c[i][j] = a[i][j] + b[i][j]
                c[i][j] = a[i][j] + b[i][j];
            }
        }
        // c を返す
        return c;
    }

    // print-matrix(matrix)
    public static void printMatrix(int[][] matrix) {
        // for i = 0 to matrixの長さ - 1
        for (int i = 0; i < matrix.length; i++) {
            // for j = 0 to matrix[i]の長さ - 1
            for (int j = 0; j < matrix[i].length; j++) {
                // print matrix[i][j] " "
                System.out.print(matrix[i][j]);
                System.out.print(" ");
            }
            // print 改行
            System.out.println();
        }
    }
}

プログラムの実行

先週までと同じ手順でプログラムを実行する。

プログラムの実行に成功すると、以下のように表示される。

9 9 9 
9 9 9 
9 9 9 

機能テスト

ここまでの作業をCtrl+Sを押して保存し、コンパイルを行う (保存時に自動で行われる)。ここでエラーが発生していたら文法エラーなので見直す。

「MatrixAdd に対する機能テスト」 を実行する。

赤いバーが表示された場合、メッセージを元にプログラムを見直すこと。修正を行い、Ctrl+Sで保存した後に「実行」ボタンをクリックする。

メッセージ 詳細
期待された結果と異なります 出力された結果が期待された値と異なる。

機能テストの項目

項目名 テストの内容
testRun プログラムを実行