88078


Java初心者です。  
現在、年齢をScannerに打ち込み、InputMismatchExceptionが起きた場合、"あなたの年齢を打ってください。"とエラーが起きなくなるまで出力を繰り返したいです。

以下のようなコードを作成し、InputMismatchExceptionが起きた場合、"年齢を打ってください" と例外が起きなくなるまで出力したいです。  
このような場合にはどのようにコードにすいればよいでしょうか？

また、この場合はdo-while文か、for文、どちらを使えばいいでしょうか？

読みづらくて申し訳ございません。

**現状のコード:**

[code]

    import java.util.Scanner;
    
    public class Main{
        public static void main (String[] args){
            Scanner sc = new Scanner(System.in);
    
            try{
                System.out.print("年齢を打ってください:");
                int age = sc.nextInt();
    
                System.out.println("あなたは " + age + "歳です。!");
            }catch(Exception e){
                System.out.println("あなたの年齢を打ってください。");
            }
    
        }
    
[/code]


CC BY-SA 4.0
2022-03-28T17:21:26.310
88076
2022-03-29T00:22:38.767
2022-03-29T00:22:38.767
3060
51596
question
java
例外が起きた場合、例外が起きなくなるまで処理を繰り返したい

[code]

    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            while (true) {
                try {
                    System.out.print("年齢を打ってください:");
                    int age = sc.nextInt();
    
                    System.out.println("あなたは " + age + "歳です。!");
                    break;
                } catch (InputMismatchException e) {
                    sc.nextLine();
                    System.out.println("あなたの年齢を打ってください。");
                }
            }
        }
    }
    
[/code]

以下、質問コードとの差分を説明していきます。

まず、正しい入力が行われるまで延々質問を繰り返す処理は無限ループ `while(true){...}` で実現しています。

> do-whileか、for文か、どちらを使えばいいでしょうか？

`do{...}while(true);` や `for(;;){...}`
でも同じように無限ループを実現でき、どれを使っても構わないですし、どれが最も良い、というようなものも特にありません。  
(強いて言うと、 `do{...}while(true);` は、最後の `true` を見ないと無限ループであることが分からないのに対し、他の2つは最初の
`while(true)`, `for(;;)` を見た時点で無限ループであることが分かるので、何を意図したコードなのかが分かりやすくはあると思います)

次に、正常に入力値から年齢を取得でき、"あなたはxx歳です。!" と出力した後に、 `break;` で無限ループを抜けています。

最後に、`InputMismatchException` を catch したところで `sc.nextLine();` を実行しています。  
これは、[JavaDoc](https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/util/Scanner.html)にある、

>
> スキャナが`InputMismatchException`をスローするとき、ほかのメソッドを使用して取得またはスキップできるように、スキャナは例外の原因となったトークンを渡しません。

への対応です。  
`sc.nextInt();`で取得しようとしたものが実際には数字ではなかった場合、その入力値はスキャナの中に残ったままになります。  
残ったままになっていると、次回 `sc.nextInt();` を呼んだときに同じエラーになります。  
そこで、`sc.nextLine();` を呼び出し、今回の入力情報を取り除いています。

* * *

スキャナから取り出すところで例外を発生させないようにした方が、若干ですがシンプルかもしれません(ただし、発生する例外は質問文にある
`InputMismatchException` ではなくなります):

[code]

    import java.util.Scanner;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            while (true) {
                try {
                    System.out.print("年齢を打ってください:");
                    // 文字列として取得するので数字でなくても例外は発生しない
                    String text = sc.nextLine();
                    // ここで文字列を数値に変換
                    // 数値に変換できなかった場合の例外は NumberFormatException
                    // https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/Integer.html#valueOf(java.lang.String)
                    int age = Integer.valueOf(text);
    
                    System.out.println("あなたは " + age + "歳です。!");
                    break;
                } catch (NumberFormatException e) {
                    // 上の処理でスキャナから入力情報は取り除かれているので
                    // ここで sc.nextLine(); を呼び出す必要はなくなった
                    System.out.println("あなたの年齢を打ってください。");
                }
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2022-03-28T19:59:35.850
88078
2022-03-28T19:59:35.850
2808
88076
answer