Java:使用Scanner in.hasNextInt()的无限循环

时间:2009-11-25 02:25:53

标签: java loops java.util.scanner infinite

我使用以下代码:

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 个答案:

答案 0 :(得分:18)

在上一个else区块中,您需要清除扫描仪中的“w”或其他无效输入。您可以通过调用扫描程序上的next()并忽略其返回值来丢弃该无效输入,如下所示:

else
{
      System.out.println("You have entered an invalid input. Try again.");
      in.next();
}

答案 1 :(得分:10)

问题是你没有提前Scanner超过有问题的输入。来自hasNextInt()文档:

  

如果使用true方法将此扫描仪输入中的下一个标记解释为默认基数中的int值,则返回nextInt()扫描仪不会超过任何输入。

所有hasNextXXX()方法都是如此:它们会返回truefalse,而不会推进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

答案 2 :(得分:4)

Ben S.关于非阻塞呼叫的陈述是错误的:

  

此外,hasNextInt()不会阻止。这是非阻塞检查,以查看未来的下一个呼叫是否可以在不阻塞的情况下获得输入。

...虽然我确实认识到documentation很容易被误读以表达这种观点,而这个名称本身意味着它将被用于此目的。相关报价,重点补充:

  

next()和hasNext()方法及其原始类型的伴随方法(例如nextInt()和hasNextInt())首先跳过与分隔符模式匹配的任何输入,然后尝试返回下一个标记。 hasNext和next方法都可能阻止等待进一步输入。 hasNext方法块是否与其关联的下一个方法是否会阻塞无关。

确实,这是一个微妙的观点。无论是说“两个 hasNext和next方法”,还是“Both hasnext()和next()”都暗示伴随方法的行为会有所不同。但是看到它们符合相同的命名约定(当然还有文档),期望它们的行为相同是合理的,hasNext() 明确表示它可以阻止。

Meta注意:这应该是对不正确帖子的评论,但似乎作为一个新用户我只能发布这个答案(或者编辑似乎更适合于sytlistic变化的wiki,而不是那些实质内容)

答案 3 :(得分:1)

标记变量太容易使用。使用带注释的显式循环控制。此外,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);