爪哇:使用 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”,它会告诉我“您输入了无效的输入。再试一次。”然后它将进入无限循环,显示文本“指定 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
此有关非阻断-调用语句由Ben S.是假:
另外,hasNextInt()不会阻塞。这是无阻塞的检查,看是否有未来的下一个呼叫可能不阻塞获取输入。
...虽然我不承认,文档很容易被误读给这个意见,名字本身就意味着它被用于此目的。相关报价,与加上强调:
在next()和hasNext()方法的和它们的基本类型companion方法(如nextInt()和hasNextInt())强>首先跳过与分隔符模式匹配的任何输入,然后尝试返回下一个标记。的两者hasNext和next方法可以阻塞等待进一步的输入。强> hasNext方法是否嵌段具有到其相关联下一个方法是否将阻止任何连接。
这是一个微妙的点,可以肯定的。无论是说“无论是的 hasNext和next方法”或“两者hasnext()和next()”会暗示伴侣的方法将采取不同。但看到他们都遵循相同的命名约定(和文档,当然),它的合理期待他们的行为是相同的,的 hasNext() 明确地说,它可以阻断。
元注:这也许应该是不正确的信息的评论中,但似乎作为一个新的用户,我只能发布这个答案(或编辑,这似乎是首选sytlistic变化维基,而不是那些物质)
标志变量使用起来太容易出错。使用带有注释的显式循环控制。还, 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);