前提
行列の値が保存されているテキストファイルを読み込み(テキストファイルは入力ストリームで指定、3つのファイルがある)、その内容を二次元配列に格納するプログラムを作成しています。
テキストファイルは
3 3
0.1 0.2 0.3
0.4 0.5 0.6
0.7 0.8 0.9
のように、1行目に行、列のサイズ、2行目以降が行列の内容となっています。
//追記
プログラム実行時に、以下のようにファイルを指定します。
javau Matrix A.txt B.txt C.txt
実現したいこと
以下の例のように、33行列と指定されているのに対し、実際の行列が23であるように、指定されたサイズと入力されたサイズが異なる場合、その旨("M×Nと行列のサイズが一致しません")を出力したいです。
3 3
1 2 3
1 2 3
発生している問題・エラーメッセージ
3 3
1 2 3
1 2 3
を入力した場合は
java.lang.NullPointerException at Matrix.read(Matrix.java:49) at Matrix.main(Matrix.java:154)
3 3
1 2
1 2
1 2
を入力した場合は
java.lang.ArrayIndexOutOfBoundsException: 2 at Matrix.read(Matrix.java:51) at Matrix.main(Matrix.java:154)
と出力されます。
該当のソースコード
Java
1/** 2 プログラム:ファイルの値を読み込み二次元配列に格納する 3 二次元配列を用いて行列積、和、差を計算する 4*/ 5import java.io.*; 6import java.text.Format;/* フォーマットのため */ 7import java.text.DateFormat;/* 日付のフォーマット用 */ 8import java.util.Calendar; 9import java.text.SimpleDateFormat; 10 11public class Matrix{ 12 13 private double[][] m;//条件(1)行列をprivate名,double型のメンバ変数とする 14 private int row, col;//行サイズと列サイズをprivateなint型のメンバー変数とする 15 16 /*条件(2)Matrixクラスのコンストラクタとして、無引数のものpublic Matrix()を作成 */ 17 public Matrix(){ 18 } 19 /*条件(2)Matrixクラスのコンストラクタとして、(1)で述べた行と列を引数で与える2引数のものを作成*/ 20 public Matrix(int M, int N){ 21 this.row=M; 22 this.col=N; 23 m=new double[M][N]; 24 25 } 26 27/*条件(6):M行N列の実数データ(スペース区切り)を記述したデータ用ファイルから読み込み、Matrixクラスのオブジェクトを生成する関数。*/ 28 public Matrix read(String filename){ 29 Matrix mat=new Matrix();//ダミーオブジェクトを作成 30 try { 31 BufferedReader br = new BufferedReader(new FileReader(filename)); 32 String[] rowcol = br.readLine().split(" ");//1行目読み込み(行と列のサイズが記述されている) 33 mat.row = Integer.parseInt(rowcol[0]);//行のサイズ 34 mat.col = Integer.parseInt(rowcol[1]);//列のサイズ 35 mat.m = new double[mat.row][mat.col];//配列のサイズを指定 36 37 for (int row_read = 0; row_read < mat.row; row_read++) {//読み込む行を指定 38 if(rowcol==null){ 39 System.err.println("M×Nと行列のサイズが一致しません"); 40 System.exit(1); 41 } 42 String[] record = br.readLine().split(" "); //(row_read)行の文字列を読み込み、空白で分割 43 for (int col_read = 0; col_read < mat.col; col_read++){//読み込む列を指定 44 if(record[col_read]==null){ 45 System.err.println("M×Nと行列のサイズが一致しません"); 46 System.exit(1); 47 } 48 mat.m[row_read][col_read] = Double.parseDouble(record[col_read]);//読み込んだ値をdouble型に変換して二次元配列に格納 49 } 50 } 51 br.close(); 52 } 53 /*ファイルが存在しない場合、エラーを出力しプログラム終了 */ 54 catch (FileNotFoundException e) { 55 e.printStackTrace(); 56 System.exit(1); 57 } 58 /*フォーマットエラーの場合、エラーを出力しプログラム終了 */ 59 catch (NumberFormatException e) { 60 e.printStackTrace(); 61 System.exit(1); 62 } 63 /*stackした場合、エラーを出力しプログラム終了 */ 64 catch (IOException e) { 65 e.printStackTrace(); 66 System.exit(1); 67 } 68 69 return mat;//作成したオブジェクトを返り値とする 70 } 71 72/*条件:(5)Matrixクラスが保持するM×N行列の中身の要素をプリントするvoid型のprint()関数*/ 73 public void print(){ 74 System.out.printf("サイズ:(%d,%d)\n",row,col);//行列のサイズを出力 75 /*2重ループで行、列を指定して行列の中身を出力 */ 76 for (int i = 0; i < row; i++) { 77 System.out.print("|"); 78 for (int j = 0; j < col; j++){ 79 System.out.print(" " + (String.format("%.6f",m[i][j])));//小数点7桁目を四捨五入して出力 80 } 81 System.out.println("|"); 82 } 83 System.out.println();//改行 84 } 85 86 /*条件(3) :行列の乗算を実行し、結果を別のMatrixクラスのオブジェクトとして返す関数*/ 87 public Matrix multiply(Matrix B) { 88 /*行列A:M×K,行列B:K×NのKが一致していない場合エラー文を出力し、プログラムを終了*/ 89 if (col != B.row){ 90 System.err.print("Aの列サイズとBの行サイズが一致しません"); 91 System.exit(1); 92 } 93 Matrix D = new Matrix(row, B.col);//乗算の結果を格納するオブジェクトDを作成 94 /*3重ループで行列積を計算 */ 95 for (int i = 0; i < row; i++){ 96 for (int j = 0; j < B.col; j++) { 97 for (int k = 0; k < B.row; k++){ 98 D.m[i][j] += m[i][k] * B.m[k][j]; 99 } 100 } 101 } 102 return D;//オブジェクトDを戻り値とする 103 } 104 105 /*条件(4):Matrixクラスの2つのサイズが一致するオブジェクトに対して、要素ごとの加算(add)を行う関数*/ 106 public Matrix add(Matrix B){ 107 /*条件(D):Matrixクラスの2つのサイズが一致しない場合プログラムを終了*/ 108 if(row != B.row || col != B.col){ 109 System.err.print("行列Cと行列Dの行、列のサイズが異なります"); 110 System.exit(1); 111 } 112 Matrix E = new Matrix(row,col);//加算の結果を格納するオブジェクトEを作成 113 /*2重ループで加算を行う */ 114 for(int i=0; i<row; i++){ 115 for(int j=0; j<col; j++){ 116 E.m[i][j]=m[i][j]+B.m[i][j]; 117 } 118 } 119 return E;//オブジェクトEを戻り値とする 120 } 121 122 /*条件(4):Matrixクラスの2つのサイズが一致するオブジェクトに対して、要素ごとの減算(subtraction)を行う関数*/ 123 public Matrix sub(Matrix B){ 124 /*条件(D):Matrixクラスの2つのサイズが一致しない場合プログラムを終了*/ 125 if(row != B.row || col != B.col){ 126 System.exit(1); 127 } 128 Matrix F = new Matrix(row,col);//減算の結果を格納するオブジェクトFを作成 129 /*2重ループで加算を行う */ 130 for(int i=0; i<row; i++){ 131 for(int j=0; j<col; j++){ 132 F.m[i][j]=m[i][j]-B.m[i][j]; 133 } 134 } 135 return F;//オブジェクトFを戻り値とする 136 } 137 138 /*main文 */ 139 public static void main(String[] args){ 140 try { 141 Matrix mat=new Matrix();//条件(A):main関数から無引数のMatrixのコンストラクタを呼び出し、Matrixオブジェクトを生成する 142 /*条件(B):コマンドラインからの引数(args[])を与え、個々のファイルを読み込み、行列の中身をプリントする 143 引数が3でないときは警告文を出力し、プログラム終了*/ 144 if(args.length != 3){ 145 System.err.println("「行列データファイルは3つ与えてください」"); 146 System.exit(1); 147 } 148 Matrix A=mat.read(args[0]);//args[0]から作成した配列を配列Aとする 149 System.out.print("入力行列A,"); 150 A.print();//配列Aを出力 151 152 Matrix B=mat.read(args[1]);//args[1]から作成した配列を配列Bとする 153 System.out.print("入力行列B,"); 154 B.print();//配列Bを出力 155 156 Matrix C=mat.read(args[2]);//args[2]から作成した配列を配列Cとする 157 System.out.print("入力行列C,"); 158 C.print();//配列Cを出力 159 160 /*条件(C):3=<M,N,K=<10を満たしていない場合は警告文を出力、プログラム終了*/ 161 if(A.row<3||A.row>10||A.col<3||A.col>10||B.col<3||B.col>10){ 162 System.err.println("3=<M,N,K=<10を満たしていません"); 163 System.exit(1); 164 } 165 /*条件(C):M,N,Kがすべて同じ場合、警告文を出力、プログラム終了 */ 166 if(A.row==A.col&&A.col==B.col&&A.row==B.row){ 167 System.err.println("M,N,Kのどれか一つは他と違う値にしてください"); 168 System.exit(1); 169 } 170 /*条件(C):乗算を実行する */ 171 Matrix D=A.multiply(B); 172 System.out.print("出力 積行列 D=A×B,"); 173 D.print(); 174 175 /*条件(D):行列Cと行列Dの要素ごとの加算、結果を出力*/ 176 Matrix E=C.add(D); 177 System.out.print("出力 要素和行列 E=C+(A×B),"); 178 E.print(); 179 /*条件(D):行列Cと行列Dの要素ごとの減算、結果を出力*/ 180 Matrix F=C.sub(D); 181 System.out.print("出力 要素差行列 F=C-(A×B),"); 182 F.print(); 183 184 185 } 186 catch (Exception e) { e.printStackTrace(); } 187 } 188}
試したこと
Matrix read 内で行を読み込むたびに、nullではないか確認し、行数の不一致を検知(指定されたサイズと一致していれば、nullになる前にfor文が終了しているはずと考えました)
列数の不一致に関してはわかりませんでした。
補足情報(FW/ツールのバージョンなど)
Java バージョン8

回答2件
あなたの回答
tips
プレビュー