Scanner nextInt(), вызывающий бесконечную ошибку внутри цикла

Следующий код выводит бесконечные ошибки, когда пользователь вводит не число.

Scanner scn = new Scanner(System.in);
System.out.println("Enter the number: ");   
int n = 0;  
while(true){
    try {
        n = scn.nextInt();
    } catch (Exception e) {
        e.printStackTrace();
        continue;
    }
    break;
}

Я ожидаю, что код ждет нового ввода, когда пользователь вводит не число.

Ответ 1

Из Javadoc,

Когда сканер генерирует исключение InputMismatchException, сканер не передает маркер, вызвавший исключение, так что его можно получить или пропустить другим способом.

В вашем случае scn.nextInt() должен вызвать исключение InputMismatchException. Но токен не передается (другими словами, входной токен висит там, чтобы быть переданным Сканером). Поэтому на следующей итерации цикла scn.nextInt() снова читает тот же токен и снова выдает исключение, что приводит к бесконечному циклу.

Если вы проверяете значение CharBuffer (HeapCharBuffer?) Внутри объекта Scanner, оно по-прежнему содержит ввод, введенный вами в первый раз, и вызывает эту проблему. Кроме того, вы не можете явно очистить буфер сканера.

Также остерегайтесь утечек ресурсов!

Ответ 2

Я бы nextInt подальше от использования nextInt и вместо этого читал ввод как строку и пытался потом преобразовать ее

Scanner scn = new Scanner(System.in);
System.out.println("Enter the number: ");   
int n = 0;  
while(true) {
    String input = scn.nextLine();

    try {
        n = Integer.valueOf(input);
        break;
    } catch (Exception e) {
        System.out.println( input + " is not a valid number. Try again.");
    }
}
System.out.println("You entered " + n);

Ответ 3

Быстрая починка

try {
    n = scn.nextInt();
} catch(Exception e) {
    e.printStackTrace();
    scn.nextLine(); // <-- add this to move to the next line
    continue;
}

Ответ 4

Моя версия:

public class IsNumber {
    public static void main(String o[]) {
        Scanner scn = new Scanner(System.in);
        System.out.println("Enter the number: ");   
        String str = null;
        do{
            str = scn.next();
            if(isInteger(str))
                break;
        }while(true);

        System.out.println("Number Entered: " + Integer.parseInt(str));
        scn.close();
    }

    private static boolean isInteger(String s) {
        try { 
            Integer.parseInt(s); 
        } catch(Exception e) { 
            return false; 
            }
        return true;
    }
}

Ответ 5

В вашем примере кода вы continue внутри блока catch {}. Это запустит цикл снова, потому что вы запустите цикл на неопределенный срок. В цикле проверяется тот же вход, что и раньше, потому что сканер снова будет использовать тот же вход, поэтому он снова выдаст исключение.

Это в основном происходит:

  1. Сканер получает не целое число.
  2. Исключение брошено.
  3. Продолжение встречается.
  4. Проверьте условие цикла, которое является истинным, поэтому цикл запускается снова.
  5. Вернуться к шагу 1.

Вы можете получить входные данные в виде строки и позже убедиться, что это на самом деле число.