Как не дать сканеру генерировать исключения, если введен неправильный тип? - PullRequest
13 голосов
/ 23 марта 2010

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

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 ]

18 голосов
/ 23 марта 2010

Вы можете использовать один из многих 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() равен false, nextLine() возвращает пустую строку, второй nextLine() возвращает "too many!";сканер теперь находится на сразу после , второй [enter].
  • hasNextInt() равен true, 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
2 голосов
/ 23 марта 2010

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

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

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

1 голос
/ 23 марта 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...