Как мне не дать Сканеру генерировать исключения, если введен неправильный тип?

Вот пример кода:

import java.util.Scanner;
class In
{
    public static void main (String[]arg) 
    {
    Scanner in = new Scanner (System.in) ;
    System.out.println ("how many are invading?") ;
    int a = in.nextInt() ; 
    System.out.println (a) ; 
    } 
}

Если я запускаю программу и даю ей int лайк 4, тогда все идет хорошо.

С другой стороны, если я отвечу too many это не смеется над моей забавной шуткой. Вместо этого я получаю это (как и ожидалось):

Exception in thread "main" java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:819)
    at java.util.Scanner.next(Scanner.java:1431)
    at java.util.Scanner.nextInt(Scanner.java:2040)
    at java.util.Scanner.nextInt(Scanner.java:2000)
    at In.main(In.java:9)

Есть ли способ заставить его игнорировать записи, которые не являются целочисленными, или вывести сообщение "Сколько вторгаются?" Я хотел бы знать, как сделать оба этих.

3 ответа

Решение

Вы можете использовать один из многих hasNext* методы, которые Scanner имеет для предварительной проверки.

    if (in.hasNextInt()) {
        int a = in.nextInt() ; 
        System.out.println(a);
    } else {
        System.out.println("Sorry, couldn't understand you!");
    }

Это мешает InputMismatchException даже не быть брошенным, потому что вы всегда убедитесь, что он будет соответствовать, прежде чем читать его.


java.util.Scanner API

  • boolean hasNextInt(): Возврат true если следующий токен на входе этого сканера можно интерпретировать как значение int в основании по умолчанию, используя nextInt() метод. Сканер не продвигается дальше любого ввода.

  • String nextLine(): Продвигает этот сканер за пределы текущей строки и возвращает пропущенный ввод.

Имейте в виду разделы, выделенные жирным шрифтом. hasNextInt() не проходит мимо какого-либо ввода. Если он вернется true, вы можете продвинуть сканер, позвонив nextInt(), который не бросит InputMismatchException,

Если он вернется false, то вам нужно пропустить мимо "мусора". Самый простой способ сделать это, просто позвонив nextLine() вероятно дважды, но хотя бы один раз.

Почему вам может понадобиться nextLine() дважды это следующее: предположим, что это введенный ввод:

42[enter]
too many![enter]
0[enter]

Допустим, сканер находится в начале этого ввода.

  • hasNextInt() правда, nextInt() возвращается 42; Сканер сейчас как раз перед первым [enter],
  • hasNextInt() ложно, nextLine() возвращает пустую строку, секунду nextLine() возвращается "too many!"; Сканер сейчас сразу после второго [enter],
  • hasNextInt() правда, nextInt() возвращается 0; Сканер сейчас как раз перед третьим [enter],

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

        Scanner in = new Scanner (System.in) ;
        System.out.println("Age?");
        while (!in.hasNextInt()) {
            in.next(); // What happens if you use nextLine() instead?
        }
        int age = in.nextInt();
        in.nextLine(); // What happens if you remove this statement?

        System.out.println("Name?");
        String name = in.nextLine();

        System.out.format("[%s] is %d years old", name, age);

Допустим, вход:

He is probably close to 100 now...[enter]
Elvis, of course[enter]

Тогда последняя строка вывода:

[Elvis, of course] is 100 years old

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

Первый шаг, который извлекает данные из System.in, не должен быть в состоянии сбоя, поэтому он должен прочитать его как строку в переменную, а затем преобразовать эту строковую переменную в int. Если конверсия не удалась, отлично - распечатайте ошибку и продолжайте.

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

Всегда полезно, чтобы ваше приложение выдавало ошибку, когда возникает ошибка, а не способы ее предотвращения.

Одна из альтернатив - обернуть код внутри try {...}catch {...} блок для InputMismatchException, Вы также можете обернуть код внутри while цикл, чтобы иметь Scanner продолжайте подсказывать, пока не будет выполнено определенное условие.

Другие вопросы по тегам