ジャバ:Scanner in.hasNextInt() を使用した無限ループ
-
22-09-2019 - |
質問
次のコードを使用しています。
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」を入力すると、「無効な入力が行われました。Try Again.」と表示され、無限ループに入り、「0 から 5 までの整数を指定してください:」というテキストが表示されます。無効な入力をしました。もう一度やり直してください。"
なぜこうなった?プログラムは、次のステートメントに到達するたびに、ユーザーが入力して Enter キーを押すのを待つことになっているのではないでしょうか。
if (in.hasNextInt())
解決
あなたの最後のelse
ブロックでは、スキャナからの「W」またはその他の無効な入力をクリアする必要があります。あなたは無効な入力は、次のようにすることを捨ててスキャナにnext()
を呼び出し、その戻り値を無視することによってこれを行うことができます:
else
{
System.out.println("You have entered an invalid input. Try again.");
in.next();
}
他のヒント
問題は、あなたが次のステップを進めなかったことです。 Scanner
問題のある入力を過ぎてください。から hasNextInt()
ドキュメンテーション:
戻り値
true
このスキャナの入力内の次のトークンが次のトークンとして解釈できるかどうかint
を使用してデフォルトの基数の値を取得します。nextInt()
方法。 スキャナは入力を越えて先に進みません。
これはすべてに当てはまります hasNextXXX()
メソッド:彼らは戻ってきます true
または false
, を進めずに、 Scanner
.
問題を説明するためのスニペットを次に示します。
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
ベン・S.のこの声明。ノンブロッキング呼び出しについては false です。
また、hasNextInt() はブロックしません。これは、将来の次の呼び出しがブロックせずに入力を取得できるかどうかを確認する非ブロック チェックです。
...私はそれを認識していますが、 ドキュメンテーション はこの意見を伝えるものとして誤って読み取られる可能性があり、名前自体がこの目的で使用されることを暗示しています。強調を追加した関連する引用:
next() メソッドと hasNext() メソッド およびそのプリミティブ型のコンパニオン メソッド (nextInt() や hasNextInt() など) まず、区切り文字パターンに一致する入力をスキップしてから、次のトークンを返そうとします。 hasNext メソッドと next メソッドは両方とも、さらなる入力の待機をブロックする可能性があります。 hasNext メソッドがブロックするかどうかは、それに関連付けられた next メソッドがブロックするかどうかとは関係がありません。
確かにそれは微妙な点だ。どちらかと言えば「両方とも」 の hasNext と next メソッド」、または「hasnext() と next() の両方」は、関連するメソッドが異なる動作をすることを意味します。しかし、これらが同じ命名規則 (そしてもちろんドキュメント) に準拠していることから、同じように動作すると期待するのが自然です。 hasNext()明らかにブロックできると書いてあります。
メタノート:これはおそらく間違った投稿に対するコメントであるはずですが、新規ユーザーとして私はこの回答を投稿することしかできないようです(または、実質的な変更ではなく体系的な変更が好ましいと思われるwikiを編集すること)。
フラグ変数はエラーが発生しやすいため、使用できません。代わりに、コメントを含む明示的なループ制御を使用してください。また、 hasNextInt()
ブロックしません。これは、将来の可能性を確認するためのノンブロッキング チェックです。 next
call はブロックせずに入力を取得できます。ブロックしたい場合は、 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);