Java - Язык:Бесконечный цикл с использованием сканера в.hasNextInt()

StackOverflow https://stackoverflow.com/questions/1794281

Вопрос

Я использую следующий код:

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

Это заявление Бена С.о том, что неблокирующий вызов является ложным:

Кроме того, hasNextInt() не блокирует.Это неблокирующая проверка, чтобы увидеть, сможет ли будущий следующий вызов получить ввод без блокировки.

... хотя я признаю , что Документация это мнение легко может быть неверно истолковано, и само название подразумевает, что оно должно использоваться для этой цели.Соответствующая цитата, с добавлением акцента:

Методы next() и hasNext() и их сопутствующие методы примитивного типа (такие как nextInt() и hasNextInt()) сначала пропустите любой ввод, соответствующий шаблону разделителя, а затем попытайтесь вернуть следующий токен. Оба метода hasNext и next могут блокировать ожидание дальнейшего ввода. Блокирует ли метод hasNext, не имеет никакого отношения к тому, будет ли связанный с ним метод next заблокирован.

Конечно, это тонкий момент.Либо говоря "Оба в Методы hasNext и next", или "Оба hasnext() и next()" подразумевали бы, что сопутствующие методы будут действовать по-разному.Но поскольку они соответствуют одному и тому же соглашению об именовании (и документации, конечно), разумно ожидать, что они действуют одинаково, и hasNext() хасНекс() четко сказано, что его могут заблокировать.

Мета - заметка:вероятно, это должен быть комментарий к неправильному сообщению, но, похоже, что как новый пользователь я могу опубликовать только этот ответ (или отредактировать wiki, который, по-видимому, предпочтительнее для системных изменений, а не для изменений по существу).

Переменные флага слишком подвержены ошибкам при использовании.Вместо этого используйте явное управление циклом с комментариями.Также, 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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top