21

次のコードを使用しています。

while (invalidInput)
{
    // ask the user to specify a number to update the times by
    System.out.print("Specify an integer between 0 and 5: ");

    if (in.hasNextInt())
    {
        // get the update value
        updateValue = in.nextInt();

        // check to see if it was within range
        if (updateValue >= 0 && updateValue <= 5) 
        { 
            invalidInput = false; 
        } 
        else 
        {
            System.out.println("You have not entered a number between 0 and 5. Try again.");
        }
    } else
    {
        System.out.println("You have entered an invalid input. Try again.");
    }
}

ただし、「w」を入力すると、「無効な入力が入力されました。再試行してください」と表示されます。そして、「0 から 5 までの整数を指定してください: 無効な入力が入力されました。再試行してください。」というテキストを表示する無限ループに入ります。

なぜこうなった?プログラムは、ステートメントに到達するたびにユーザーが入力してEnterキーを押すのを待つべきではありませんか:

if (in.hasNextInt())
4

4 に答える 4

27

最後のelseブロックでは、スキャナからの「w」またはその他の無効な入力をクリアする必要があります。これを行うには、次のように Scanner を呼び出しnext()、その戻り値を無視して無効な入力を破棄します。

else
{
      System.out.println("You have entered an invalid input. Try again.");
      in.next();
}
于 2009-11-25T02:47:27.907 に答える
11

Scanner問題は、問題のある入力を過去に進めなかったことです。hasNextInt()ドキュメントから:

メソッドを使用して、このスキャナの入力の次のトークンをデフォルトの基数の値trueとして解釈できるかどうかを返します。スキャナは入力を超えて進みません。intnextInt()

これはすべてのhasNextXXX()メソッドに当てはまりtrueます。falseScanner

問題を説明するためのスニペットを次に示します。

    String input = "1 2 3 oops 4 5 6";
    Scanner sc = new Scanner(input);
    while (sc.hasNext()) {
        if (sc.hasNextInt()) {
            int num = sc.nextInt();
            System.out.println("Got " + num);
        } else {
            System.out.println("int, please!");
            //sc.next(); // uncomment to fix!
        }
    }

このプログラムは無限ループに入り、int, please!繰り返し尋ねます。

sc.next()ステートメントのコメントを外すとScanner、失敗したトークンを通過しますhasNextInt()。次に、プログラムは次のように出力します。

Got 1
Got 2
Got 3
int, please!
Got 4
Got 5
Got 6

失敗したhasNextXXX()チェックが入力をスキップしないという事実は意図的なものです。これにより、必要に応じてそのトークンに対して追加のチェックを実行できます。説明する例を次に示します。

    String input = " 1 true foo 2 false bar 3 ";
    Scanner sc = new Scanner(input);
    while (sc.hasNext()) {
        if (sc.hasNextInt()) {
            System.out.println("(int) " + sc.nextInt());
        } else if (sc.hasNextBoolean()) {
            System.out.println("(boolean) " + sc.nextBoolean());
        } else {
            System.out.println(sc.next());
        }
    }

このプログラムを実行すると、次のように出力されます。

(int) 1
(boolean) true
foo
(int) 2
(boolean) false
bar
(int) 3
于 2010-05-04T05:20:00.803 に答える
4

非ブロッキング呼び出しに関する Ben S. の次の声明は誤りです。

また、 hasNextInt() はブロックしません。将来の次の呼び出しがブロックせずに入力を取得できるかどうかを確認するのは、非ブロック チェックです。

...とはいえ、この意見を述べるためにドキュメントを簡単に読み違える可能性があることは認識しており、名前自体は、この目的のために使用されることを暗示しています。強調を加えた関連する引用:

next() メソッドと hasNext() メソッド、およびそれらのプリミティブ型のコンパニオン メソッド (nextInt() や hasNextInt() など)は、最初に区切り文字パターンに一致する入力をスキップしてから、次のトークンを返そうとします。hasNext メソッドと next メソッドの両方が、さらなる入力を待つことをブロックする場合があります。hasNext メソッドがブロックするかどうかは、関連する next メソッドがブロックするかどうかとは関係ありません。

確かに、それは微妙な点です。「 hasNext と next メソッド両方」または「hasext() と next() の両方」と言うと、コンパニオン メソッドの動作が異なることを暗示していました。しかし、それらが同じ命名規則 (そしてもちろんドキュメント) に準拠していることを考えると、それらが同じように動作すると期待するのは合理的であり、hasNext() は明らかにブロックできることを示しています。

メタノート: これはおそらく間違った投稿へのコメントであるはずですが、新しいユーザーとして、私はこの回答しか投稿できないようです (または、実質的な変更ではなく体系的な変更に適していると思われる wiki を編集します)。

于 2011-03-22T18:48:26.090 に答える
2

フラグ変数を使用するとエラーが発生しやすくなります。代わりに、コメント付きの明示的なループ制御を使用してください。また、hasNextInt()ブロックしません。next将来の呼び出しがブロックせずに入力を取得できるかどうかを確認するのは、非ブロック チェックです。ブロックしたい場合は、nextInt()メソッドを使用してください。

// Scanner that will read the integer
final Scanner in = new Scanner(System.in);
int inputInt;
do {  // Loop until we have correct input
    System.out.print("Specify an integer between 0 and 5: ");
    try {
        inputInt = in.nextInt(); // Blocks for user input
        if (inputInt >= 0 && inputInt <= 5)  { 
            break;    // Got valid input, stop looping
        } else {
            System.out.println("You have not entered a number between 0 and 5. Try again.");
            continue; // restart loop, wrong number
         }
    } catch (final InputMismatchException e) {
        System.out.println("You have entered an invalid input. Try again.");
        in.next();    // discard non-int input
        continue;     // restart loop, didn't get an integer input
    }
} while (true);
于 2009-11-25T02:45:04.120 に答える