Java: бесконечный цикл с использованием сканера.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())
4 ответов
В прошлом else
блок, вам нужно очистить " w " или другой недопустимый вход от сканера. Вы можете сделать это, позвонив next()
на сканере и игнорируя его возвращаемое значение, чтобы выбросить этот недопустимый ввод следующим образом:
else
{
System.out.println("You have entered an invalid input. Try again.");
in.next();
}
проблема заключалась в том, что вы не продвигали Scanner
мимо проблемного ввода. От hasNextInt()
документы:
возвращает
true
если следующий маркер во вводе этого сканера может быть интерпретирован какint
значение по умолчанию radix с помощью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 связи с тем, будет ли его связанный следующий метод блокировать.
Это тонкий момент, чтобы быть уверенным. Либо говоря: "оба the hasNext и next методы", или "оба hasnext () и next ()" подразумевали бы, что сопутствующие методы будут действовать по-разному. Но поскольку они соответствуют одному и тому же соглашению об именах (и документации, конечно), разумно ожидать, что они действуют одинаково, и hasNext() ясно говорит, что может блокировать.
Meta Примечание: это, вероятно, должен быть комментарий к неправильному сообщению, но кажется, что как новый пользователь я могу только опубликуйте этот ответ (или отредактируйте wiki, который, по-видимому, предпочтителен для sytlistic изменений, а не для существа).
переменные флага слишком подвержены ошибкам. Вместо этого используйте явный элемент управления loop с комментариями. Кроме того,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);