Java:使用Scanner in.hasNextInt()的无限循环
我使用以下代码:
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”或其他无效输入。 您可以通过调用Scanner上的next()
并忽略其返回值来丢弃该无效输入来执行此操作,如下所示:
else { System.out.println("You have entered an invalid input. Try again."); in.next(); }
问题是你没有推进Scanner
超过有问题的输入。 来自hasNextInt()
文档:
如果使用
nextInt()
方法将此扫描器输入中的下一个标记解释为默认基数中的int
值,则返回true
。 扫描仪不会超过任何输入。
所有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()方法及其原始类型的伴随方法(例如nextInt()和hasNextInt())首先跳过与分隔符模式匹配的任何输入,然后尝试返回下一个标记。 hasNext和next方法都可能阻止等待进一步输入。 hasNext方法块是否与其关联的下一个方法是否将阻止无关。
可以肯定的是,这是一个微妙的观点。 无论是说“hasNext和next方法”,还是“hasnext()和next()”都暗示伴随方法会有不同的行为。 但是当看到它们符合相同的命名约定(当然还有文档)时,期望它们的行为相同是合理的,并且hasNext()清楚地表明它可以阻止。
元注释:这应该是对不正确的post的评论,但似乎作为一个新用户我只能发布这个答案(或编辑维基,这似乎是sytlistic变化的首选,而不是实质的那些)。
标志变量太容易使用。 使用带注释的显式循环控制。 此外, hasNextInt()
不会阻止。 这是非阻塞检查,以查看未来的next
呼叫是否可以在不阻塞的情况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);