まだ入門書を読破していないレベルですが、モヤモヤするので質問させてください。
やりたいことは、次のようなコードで
0か1が入力されるまでひたすらdoを回したいだけなんです。
java
1import java.util.Scanner; 2import java.util.InputMismatchException; 3 4class IntBlnRensyuu { 5 public static void main(String[] args) { 6 try(Scanner stdIn = new Scanner(System.in);) { 7 8 int x; 9 do { 10 System.out.print("0=true/1=false:"); 11 x = stdIn.nextInt(); 12 } while (x < 0 || x > 1); 13 14 boolean a; 15 if (x == 0) { 16 a = true; 17 } else { 18 a = false; 19 } 20 System.out.println("論理型変数に" + a + "を代入しました"); 21 22 } catch (InputMismatchException e) { 23 System.out.println("不正な入力値です"); 24 } 25 } 26} 27
しかしながら、これだと-1や2の入力ではループしますが
『a』や『1.5』を入力すると「不正な入力値です」を表示して終了してしまいます。
不正な入力があっても尚ループさせるには、どう修正するものなのでしょうか。
入門書の序盤はどれも、こういうのを気にしたら負けのようですが
私は気になるのでよろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
catchがwhileの外にあるのが原因です。例外が起これば何があろうと(対応する例外がある)catchに飛ぶため、whileから外れてしまいます。
ループを続けるためには、whileの中でcatchする必要があります。
ただし、今使っているtry-with-resourcesでcatchすると、catchする場合標準入力が閉じられてしまうため、別のtryを入れます。
java
1 int x = -1; // あらかじめwhileの継続条件を満たす値を入れておくと安全 2 do { 3 try { 4 System.out.print("0=true/1=false:"); 5 x = stdIn.nextInt(); 6 } catch (InputMismatchException e) { 7 System.out.println("不正な入力値です"); 8 } 9 } while (x < 0 || x > 1); 10
無限ループの原因(コメントを受けて)
試してみると、
「0=true/1=false:不正な入力値です」の永久ループになってしまいました・・
自分でも試してみると、aなどの不正入力をすると無限ループ発生。
無限ループしないように工夫してスタックトレースを2回出してみるも、
Integer.parseInt()のNumberFormatExceprionと違って
Scanner#nextInt()のInputMismatchExceptionは入力が何かはスタックトレースに乗らないらしい
そこでScanner#nextIntの説明を読むとこんな文言が。
入力の次のトークンをintとしてスキャンします。次に示す方法で、次のトークンを有効なint値に変換できない場合、このメソッドはInputMismatchExceptionをスローします。変換に成功すると、スキャナは一致した入力の先に進みます。
この太字部分は、裏を返せば「変換できない場合スキャナの位置は動かない」ということではないか。
となるとどういうことが起こるか。例えば"a"を入れた場合、
- nextInt()で数値変換できないため例外発生。
- スキャナの位置は動かないため、まだ入力には"a"が残った状態になる。
- ループによりこの状態で再びnextInt()が呼ばれるため、また"a"を変換しようとして例外発生。
これが永遠に繰り返されるわけだ。
これを防ぐためには、例外発生時に変換できなかった文字を飛ばす必要がある。
java
1do { 2 try { 3 System.out.print("0=true/1=false:"); 4 x = stdIn.nextInt(); 5 } catch (InputMismatchException e) { 6 System.out.println("不正な入力値です"); 7 stdIn.next(); // 変換できなかった文字列を飛ばす 8 } 9 10} while (x < 0 || x > 1);
ただこれだと不格好なので、nextInt()を使わず文字列で読み込んでparseInt()という方法も考えられる。
java
1do { 2 try { 3 System.out.print("0=true/1=false:"); 4 x = Integer.parseInt(stdIn.next()); 5 } catch (NumberFormatException e) { 6 System.out.println("不正な入力値です"); 7 } 8 9} while (x < 0 || x > 1);
ちなみに
java
1 boolean a; 2 if (x == 0) { 3 a = true; 4 } else { 5 a = false; 6 }
ここのコードは次の1行で片づけられます。
java
1 boolean a = (x == 0);
投稿2018/02/15 15:06
編集2018/02/16 02:33総合スコア20649
0
参考までに、himejiy3さんのアプローチとは他の方法を紹介します。
Java
1import java.util.Scanner; 2import java.io.IOException; 3 4class Main { 5 static int input_1_or_0(String message, Scanner sc) throws IOException { 6 while(true) { 7 System.out.print(message); 8 String input = sc.nextLine(); 9 10 if(input.equals("0")) return 0; 11 if(input.equals("1")) return 1; // return Integer.valueOf(input); も可 12 13 System.out.println("論理型変数に" + input + "を代入しました"); 14 } 15 } 16 17 public static void main(String[] args) { 18 try(Scanner sc = new Scanner(System.in)) { 19 System.out.println( 20 input_1_or_0("0=true/1=false: ", sc) 21 ); 22 } 23 catch(IOException e) { 24 e.printStackTrace(); 25 } 26 } 27}
実行例 Wandbox
こういうときは文字列のまま扱った方が楽ですね。
投稿2018/02/15 15:19
総合スコア35658
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/16 14:24
2018/02/16 14:36
2018/02/16 14:39
0
Ctrl-D の入力にも対処してみました。
java
1import java.util.Scanner; 2 3class IntBlnRensyuu { 4 public static void main(String[] args) { 5 Scanner stdIn = new Scanner(System.in); 6 7 // 0, 1, または Ctrl-D が有力されるまで ループする。 8 // ループを抜けたときに、x には次のように設定されている。 9 // 0 (0 が入力されたとき) 10 // 1 (1 が入力されたとき) 11 // -1 (Dtrl-D が入力されたとき) 12 int x; 13 while (true) { 14 System.out.print("0=true/1=false:"); 15 16 // CTRL-D が入力されたときの処理 17 if (!stdIn.hasNext()) { 18 x = -1; 19 break; 20 } 21 String line = stdIn.nextLine().trim(); 22 if (line.equals("0") || line.equals("1")) { 23 x = Integer.parseInt(line); 24 break; 25 } 26 27 System.out.println("不正な入力値です"); 28 } 29 30 if (x == -1) { 31 System.out.println("入力が終了されました。"); 32 } else { 33 boolean a = (x == 0); 34 System.out.println("論理型変数 a に" + a + "を代入しました"); 35 } 36 } 37}
投稿2018/02/17 07:23
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/17 09:05
2018/02/17 10:11
2018/02/17 10:30 編集
2018/02/17 10:29
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/15 15:23
2018/02/15 15:55
2018/02/16 12:32