web-dev-qa-db-ja.com

スキャナーを使用して無効な入力(InputMismatchException)が原因で発生する無限ループを処理する方法

だから、私はこのコードの一部で立ち往生しています:

import Java.util.InputMismatchException;
import Java.util.Scanner;

public class ConsoleReader {

    Scanner reader;

    public ConsoleReader() {
        reader = new Scanner(System.in);
        //reader.useDelimiter(System.getProperty("line.separator"));
    }

    public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                num = reader.nextInt();

                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");
            } 
        }
        return num;
    }
}

そしてこれが私の出力です:

整数を挿入します。
無効な値です!
整数を挿入:
無効な値です!
...

35
mateusmaso

javadoc によると:

スキャナーがInputMismatchExceptionをスローすると、スキャナーは例外の原因となったトークンを渡さないため、他の方法で取得またはスキップできます。

つまり、次のトークンがintではない場合、InputMismatchExceptionがスローされますが、トークンはそのまま残ります。したがって、ループの次の反復で、reader.nextInt()は同じトークンを再度読み取り、例外を再度スローします。必要なのはそれを使い切ることです。 catch内にreader.next()を追加して、トークンを消費します。トークンは無効であり、破棄する必要があります。

...
} catch (InputMismatchException e) {
    System.out.println("Invalid value!");
    reader.next(); // this consumes the invalid token
} 
59
samitgaur

私がやろうとしていることは、Scanner.nextLine()を使用して行全体を読み取ることです。次に、返された文字列を読み取る別のスキャナーを作成します。

String line = reader.nextLine();
Scanner sc = new Scanner(line);

これにより、サンプル関数は次のようになります。

  public int readInt(String msg) {
        int num = 0;
        boolean loop = true;

        while (loop) {
            try {
                System.out.println(msg);
                String line = reader.nextLine();
                Scanner sc = new Scanner(line);
                num = sc.nextInt();   
                loop = false;
            } catch (InputMismatchException e) {
                System.out.println("Invalid value!");

            } 
        }
        return num;
    }

このようにして、入力を取得するスキャナーと検証を行うスキャナーが1つずつあるので、正しい形式の入力を入力した場合にリーダーが気にする必要はありません。

0
cohensh

While-doのガードは「ループ」変数です。

コードが割り当てループに到達する前にスローされる例外自体は、falseです。正確には、前のステートメントで例外がスローされます。num= reader.nextInt();

例外がスローされると、 'loop'変数の値は 'true'ですが、コードはジャンプしてブロックをキャッチし、while-doを繰り返します。このwhile-doは決して停止しません。これは、次の反復で再び例外がスローされ、ジャンプして再びブロックをキャッチするためです。

このwhile-doを終了するには、while-doを次のような別の論理的なもので保護する必要があります。

  1. リーダーが非INT文字を取得したときに終了します
  2. EOF時に終了

これは、catchブロックまたは他のいくつかの行で実行できます。ただし、正確な解決策は仕様によって異なります。

0
Hendra Jaya

これを試すこともできます:

   public int readInt(String msg) {
        int num = 0;
        try {
            System.out.println(msg);
            num = (new Scanner(System.in)).nextInt();
        } catch (InputMismatchException e) {
            System.out.println("Invalid value!");
            num = readInt(msg);
        } 
        return num;
    }
0
jerjer
package nzt.nazakthul.app;

import Java.util.*;

public class NztMainApp {

    public static void main(String[] args) {
    ReadNumber readObj = new ReadNumber();
    readObj.readNumber();
    }

}

class ReadNumber {
int no;

    int readNumber() {
    Scanner number = new Scanner(System.in);
    int no=0;
    boolean b=true;
    do {

        try {
            System.out.print("Enter a number:\t");
            no = number.nextInt();
        } catch (InputMismatchException e) {
            System.out.println("No Number");
            //e.printStackTrace();

            b=false;
        }

    }

    while (b);
    return no;

    }

}

個人的には、BufferedReaderとInputStreamReaderを使用して文字列を読み取り、数値であるかどうかを確認していますが、スキャナーを使用するとコードが少なくなります。コードがチェックされ、正常に実行されます。

0
user3220849