Java - Язык:Бесконечный цикл с использованием сканера в.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
Это заявление Бена С.о том, что неблокирующий вызов является ложным:
Кроме того, 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);