teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

inM\.csvファイルが空の場合のプログラム終了方法について追記しました

2016/03/21 12:43

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -134,3 +134,67 @@
134
134
  ```
135
135
 
136
136
  切り捨てと、四捨五入では、<<< >>> でマークした所に違いがありますが、どちらも期待している答えとは違いますね。仕様について、確認してもらえないでしょうか?
137
+
138
+ ---
139
+
140
+ **2016年3月21日 追記**
141
+
142
+ > ②inM.csvファイルが空の場合エラー表示して通常終了したい
143
+ > のですが次の処理に進んでしまいます。
144
+
145
+ 回答が遅くなりました。
146
+
147
+ いまのプログラムは以下のような構造になっていますので、
148
+
149
+ ```
150
+ public static void main(String[] args) {
151
+
152
+ boolean emptyflgM = true; //inM判定マスタファイル空判定フラグ
153
+
154
+ // ... 省略 ...
155
+
156
+ fileError1:
157
+ try {
158
+ while ((stM = brM.readLine()) != null) {
159
+ emptyflgC = false;
160
+
161
+ // ... inM ファイルの読み込み
162
+ }
163
+
164
+ if (emptyflgM) {
165
+ System.err.println("inM.csvファイルは空です。");
166
+ break fileError1;
167
+ }
168
+
169
+ } catch(IOException e){
170
+ // ...
171
+ } finally {
172
+ // ...
173
+ }//finally
174
+
175
+ // ... 次の処理
176
+
177
+ }
178
+ ```
179
+
180
+ 「inM.csvファイルは空です」を表示して、try 文から break しても、たしかに、次の処理と書かれた部分は実行されてしまいます。
181
+
182
+ エラー表示後、プログラムを正常終了させたいということなので、`System.exit(0)` を呼ぶのが良いと思います。`break flieError` と書く代わりに、`System.exit(0)` と書くと、(main メソッドを最後まで実行した時と同じように)Java仮想マシンの終了処理が行われ、プログラムが終了します。
183
+
184
+ - [System.exit(int) の解説](http://docs.oracle.com/javase/jp/8/docs/api/java/lang/System.html#exit-int-)
185
+
186
+ 引数の `0` は、正常終了を表します。ただ、このように入力ファイルに不備がある場合は、`0` 以外の値を返すことで、異常終了を表すのが一般的です。
187
+
188
+ 今回のように、`try` 〜 `catch` 〜 `finally` の中から `System.exit(0)` を呼んだ場合、`finally` の部分もちゃんと実行されます。また、もっと大きなプログラムを書いていて、何らかの終了処理を行いたい時は、shutdown hook というものを設定することで、`System.exit(int)` を呼んだ時に、その処理を実行することができます。
189
+
190
+ なお、今回のプログラムだと、`System.exit(0)` ではなく、単に `return` と書いて、main メソッドから早期に抜け出す方法も使えます。ただ、この方法は応用がきかないので、おすすめはしません。今後、Java を学んでいくと、メソッドを分割するとか、クラスを分けるなどといった、プログラムを構造化することが必ず必要になります。そういう構造になってくると、inMファイルの読み込みも、main とは別のメソッドで行われるようになり、単にそのメソッドから `return` するだけでは、Java仮想マシンを終了させることができません。
191
+
192
+ さらに、今後学習していくなかで、エラー処理の方法についても調べてみてください。大きくわけて、2つの方法があります。
193
+
194
+ 1. エラーをメソッドからの戻り値で表す。例えば、Result といった名前のクラスを作り、メソッドが返す値を Resultオブジェクトにする。メソッドがエラーなく終了した時は、Resultオブジェクトに値(例:inM.csvファイルの内容)を格納して返す。エラーが起こった時は、Resultオブジェクトにエラーの内容を示す値を格納して返す。
195
+
196
+ 2. エラーを例外(Exception) で表す。例えば、`EmptyFileException` というような名前の例外クラスを作り、エラーが起こった時は、`throw new EmptyFileException()` というようにして例外を投げる。
197
+
198
+ Java は少し古い言語で、1の方法で呼び出し側(値を受け取った側)の処理が簡潔に書けないという問題があります。2は Java でエラー処理を行う中心的なやりかたですが、あまり例外を増やすと、プログラムの流れが分かりにくくなるという問題があります。
199
+
200
+ Java に慣れたら、1のような処理を簡潔に書ける、最近の言語もぜひ並行して学んでください。たとえば、Java で学んだ知識を活かせる、Scala という言語がおすすめです。

4

誤字を修正しました

2016/03/21 12:43

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -74,7 +74,7 @@
74
74
  if (masterM[0][1].equals("○")) {
75
75
  ```
76
76
 
77
- でも、これを直して試してみたのですが、期待した答えにならないかったですねぇ。うーん、仕様か期待している答えのどちらかが間違っているような気がします。
77
+ でも、これを直して試してみたのですが、期待した答えにならないかったですねぇ。うーん、仕様か、あるいは、期待している答えのどちらかが間違っているような気がします。
78
78
 
79
79
  ちなみに、整数の除算は小数点以下切り捨てですが、浮動小数点型(double)の除算の場合は、小数点以下四捨五入や、繰上げも選べます。以下のようなコードを追加して、結果が、outA.csv、outB.csvのどちらになるかやってみましたが、整数除算の場合と、浮動小数点除算(四捨五入)のどちらの場合でも、答えが合わないです。
80
80
 
@@ -88,7 +88,7 @@
88
88
  int intQ = intA / intC;
89
89
  boolean intEven = intQ % 2 == 0;
90
90
  int intMIndex = intEven ? 1 : 0;
91
- String intOut = masterM[intMIndex][1].equals("yes") ? "outA" : "outB";
91
+ String intOut = masterM[intMIndex][1].equals("") ? "outA" : "outB";
92
92
 
93
93
  System.out.format("%d: int ---- A: %4d, C: %4d, Q: %4d, even(%d): %s ==> %s%n",
94
94
  i, intA, intC, intQ, intQ, intEven, intOut);
@@ -99,7 +99,7 @@
99
99
  int doubleRoundedQ = (int)Math.round(doubleQ);
100
100
  boolean doubleEven = doubleRoundedQ % 2 == 0;
101
101
  int doubleMIndex = doubleEven ? 1 : 0;
102
- String doubleOut = masterM[doubleMIndex][1].equals("yes") ? "outA" : "outB";
102
+ String doubleOut = masterM[doubleMIndex][1].equals("") ? "outA" : "outB";
103
103
 
104
104
  System.out.format("%d: double - A: %2.2f, C: %2.2f, Q: %2.2f, even(%d): %s ==> %s%n",
105
105
  i, doubleA, doubleC, doubleQ, doubleRoundedQ, doubleEven, doubleOut);

3

誤字を修正しました

2016/03/18 12:07

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -40,7 +40,7 @@
40
40
  if (isHanNum(numC[i]) == false) {
41
41
  ```
42
42
 
43
- のところですが、`numC[i]` とすると、長さ2の String配列がってきてしまうので、たしかに型の不一致となります。以下のように、String配列の各要素を一つずつチェックしてください。
43
+ のところですが、`numC[i]` とすると、長さ2の String配列がってくるので、たしかに型の不一致となります。以下のように、String配列の各要素を一つずつチェックしてください。
44
44
 
45
45
  ```java
46
46
  if (!isHanNum(numC[i][0]) || !isHanNum(numC[i][1])) {

2

誤字を修正しました

2016/03/18 12:04

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -37,7 +37,7 @@
37
37
  > 出来ません。
38
38
 
39
39
  ```java
40
- if (isHanNum(numC[i])) {
40
+ if (isHanNum(numC[i]) == false) {
41
41
  ```
42
42
 
43
43
  のところですが、`numC[i]` とすると、長さ2の String配列が帰ってきてしまうので、たしかに型の不一致となります。以下のように、String配列の各要素を一つずつチェックしてください。

1

質問①と②について追記しました

2016/03/18 12:03

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -22,4 +22,115 @@
22
22
 
23
23
  あと、変数 `sum` ですが、この言葉には「合計」と言う意味があるので、割り算の商を格納するのには、ちょっと紛らわしい名前です。例えば、`quotient` としてはどうでしょうか?
24
24
 
25
- プログラムの内容を詳しく見てないので、他にも間違いがあるかもしれませんが、とりあえず、いま出ているエラーについて気づいたことは、これで全部です。
25
+ プログラムの内容を詳しく見てないので、他にも間違いがあるかもしれませんが、とりあえず、いま出ているエラーについて気づいたことは、これで全部です。
26
+
27
+ ---
28
+
29
+ ---
30
+ **2016年3月18日 質問①と②について追記**
31
+
32
+ ③は説明が長くなりそうなので、後で(明日?)書きます。
33
+ 取り急ぎ、①と②について回答しますね。
34
+
35
+ > ①数値化出来るかどうかをisHanNum(String s)メソッドを使用
36
+ > したいのですが、配列の要素だと型の不一致でコンパイル
37
+ > 出来ません。
38
+
39
+ ```java
40
+ if (isHanNum(numC[i])) {
41
+ ```
42
+
43
+ のところですが、`numC[i]` とすると、長さ2の String配列が帰ってきてしまうので、たしかに型の不一致となります。以下のように、String配列の各要素を一つずつチェックしてください。
44
+
45
+ ```java
46
+ if (!isHanNum(numC[i][0]) || !isHanNum(numC[i][1])) {
47
+ ```
48
+
49
+ ---
50
+ > ②除算した結果を偶数か奇数で判断したいのですが。int同士だと
51
+ > 小数点以下切り捨てなので、すべてが偶数になってしまいます。
52
+
53
+ たしかに小数点以下切り捨てですが、でも、偶数だけでなく、奇数になることもあります。
54
+
55
+ まず、以下のところに間違いがあることに気づきました。
56
+
57
+ ```java
58
+ if (quotient % 2 == 0) { // 偶数かどうかを確認
59
+ if (masterM[1][0].equals("○")) {
60
+ // ...省略...
61
+
62
+ } else {
63
+ if (masterM[0][0].equals("○")) {
64
+ ```
65
+
66
+ `masterM` の2番目のインデックスが違います。正しくは以下のようになります。
67
+
68
+ ```java
69
+ if (quotient % 2 == 0) { // 偶数かどうかを確認
70
+ if (masterM[1][1].equals("○")) {
71
+ // ...省略...
72
+
73
+ } else {
74
+ if (masterM[0][1].equals("○")) {
75
+ ```
76
+
77
+ でも、これを直して試してみたのですが、期待した答えにならないかったですねぇ。うーん、仕様か期待している答えのどちらかが間違っているような気がします。
78
+
79
+ ちなみに、整数の除算は小数点以下切り捨てですが、浮動小数点型(double)の除算の場合は、小数点以下四捨五入や、繰上げも選べます。以下のようなコードを追加して、結果が、outA.csv、outB.csvのどちらになるかやってみましたが、整数除算の場合と、浮動小数点除算(四捨五入)のどちらの場合でも、答えが合わないです。
80
+
81
+ ```java
82
+ for (int i = 0; i < numC.length; i++) {
83
+
84
+ if (stA.equals(numC[i][0])) { // 入力の値と計算Cのキーの値の一致確認
85
+
86
+ int intA = Integer.valueOf(stA);
87
+ int intC = Integer.valueOf(numC[i][1]);
88
+ int intQ = intA / intC;
89
+ boolean intEven = intQ % 2 == 0;
90
+ int intMIndex = intEven ? 1 : 0;
91
+ String intOut = masterM[intMIndex][1].equals("yes") ? "outA" : "outB";
92
+
93
+ System.out.format("%d: int ---- A: %4d, C: %4d, Q: %4d, even(%d): %s ==> %s%n",
94
+ i, intA, intC, intQ, intQ, intEven, intOut);
95
+
96
+ double doubleA = Double.parseDouble(stA);
97
+ double doubleC = Double.parseDouble(numC[i][1]);
98
+ double doubleQ = doubleA / doubleC;
99
+ int doubleRoundedQ = (int)Math.round(doubleQ);
100
+ boolean doubleEven = doubleRoundedQ % 2 == 0;
101
+ int doubleMIndex = doubleEven ? 1 : 0;
102
+ String doubleOut = masterM[doubleMIndex][1].equals("yes") ? "outA" : "outB";
103
+
104
+ System.out.format("%d: double - A: %2.2f, C: %2.2f, Q: %2.2f, even(%d): %s ==> %s%n",
105
+ i, doubleA, doubleC, doubleQ, doubleRoundedQ, doubleEven, doubleOut);
106
+
107
+ quotient = Integer.valueOf(stA) / Integer.valueOf(numC[i][1]);
108
+ ```
109
+
110
+ **結果:**
111
+ (出力されたものは、桁が揃っておらず見づらかったので、編集して読みやすくしてます)
112
+
113
+ ```
114
+ 9: int ---- A: 10, C: 2, Q: 5, even(5): false ==> outA
115
+ 9: double - A: 10.00, C: 2.00, Q: 5.00, even(5): false ==> outA
116
+ 8: int ---- A: 9, C: 1, Q: 9, even(9): false ==> outA
117
+ 8: double - A: 9.00, C: 1.00, Q: 9.00, even(9): false ==> outA
118
+ 7: int ---- A: 8, C: 3, Q: 2, even(2): true ==> outB <<<
119
+ 7: double - A: 8.00, C: 3.00, Q: 2.67, even(3): false ==> outA >>>
120
+ 6: int ---- A: 7, C: 2, Q: 3, even(3): false ==> outA <<<
121
+ 6: double - A: 7.00, C: 2.00, Q: 3.50, even(4): true ==> outB >>>
122
+ 5: int ---- A: 6, C: 1, Q: 6, even(6): true ==> outB
123
+ 5: double - A: 6.00, C: 1.00, Q: 6.00, even(6): true ==> outB
124
+ 4: int ---- A: 5, C: 3, Q: 1, even(1): false ==> outA <<<
125
+ 4: double - A: 5.00, C: 3.00, Q: 1.67, even(2): true ==> outB >>>
126
+ 3: int ---- A: 4, C: 2, Q: 2, even(2): true ==> outB
127
+ 3: double - A: 4.00, C: 2.00, Q: 2.00, even(2): true ==> outB
128
+ 2: int ---- A: 3, C: 1, Q: 3, even(3): false ==> outA
129
+ 2: double - A: 3.00, C: 1.00, Q: 3.00, even(3): false ==> outA
130
+ 1: int ---- A: 2, C: 3, Q: 0, even(0): true ==> outB <<<
131
+ 1: double - A: 2.00, C: 3.00, Q: 0.67, even(1): false ==> outA >>>
132
+ 0: int ---- A: 1, C: 2, Q: 0, even(0): true ==> outB <<<
133
+ 0: double - A: 1.00, C: 2.00, Q: 0.50, even(1): false ==> outA >>>
134
+ ```
135
+
136
+ 切り捨てと、四捨五入では、<<< >>> でマークした所に違いがありますが、どちらも期待している答えとは違いますね。仕様について、確認してもらえないでしょうか?