Проверка ввода с помощью java.util.Scanner

Я беру ввод пользователя с System.in с помощью java.util.Scanner. Мне нужно проверить вход для таких вещей, как:

  • Это должно быть неотрицательное число
  • Это должно быть алфавитная буква
  • ... и т.д.

Какой лучший способ сделать это?

Ответы

Ответ 1

Обзор методов Scanner.hasNextXXX

java.util.Scanner имеет много методов hasNextXXX, которые могут использоваться для проверки ввода. Вот краткий обзор всех из них:

Scanner способен к большему, включенному тем, что он основан на регулярном выражении. Важной особенностью является useDelimiter(String pattern), которая позволяет определить, какой шаблон разделяет ваши токены. Существуют также методы find и skip, которые игнорируют разделители.

Следующее обсуждение будет поддерживать регулярное выражение как можно более простым, поэтому фокус остается на Scanner.


Пример 1: Проверка положительных целых чисел

Вот простой пример использования hasNextInt() для проверки положительного int на входе.

Scanner sc = new Scanner(System.in);
int number;
do {
    System.out.println("Please enter a positive number!");
    while (!sc.hasNextInt()) {
        System.out.println("That not a number!");
        sc.next(); // this is important!
    }
    number = sc.nextInt();
} while (number <= 0);
System.out.println("Thank you! Got " + number);

Вот пример сеанса:

Введите положительное число!
пять
Это не число!
-3
Введите положительное число!
5
Спасибо! Получил 5

Заметьте, насколько проще Scanner.hasNextInt() использовать по сравнению с более подробными try/catch Integer.parseInt/NumberFormatException комбо. По контракту a Scanner гарантирует, что если он hasNextInt(), то nextInt() мирно предоставит вам int и не будет бросать никаких NumberFormatException/InputMismatchException/NoSuchElementException.

Связанные вопросы


Пример 2: Несколько hasNextXXX на одном и том же токене

Обратите внимание, что вышеприведенный фрагмент содержит инструкцию sc.next() для продвижения Scanner до тех пор, пока не будет hasNextInt(). Важно понимать, что ни один из методов hasNextXXX не продвигает Scanner мимо любого ввода!. Вы обнаружите, что если вы опустите это line из фрагмента, затем он перейдет в бесконечный цикл на недопустимом вводе!

Это имеет два следствия:

  • Если вам нужно пропустить вход "мусор", который не прошел тест hasNextXXX, вам необходимо заранее продвинуть Scanner (например, next(), nextLine(), skip и т.д.)).
  • Если один тест hasNextXXX завершился с ошибкой, вы все равно можете проверить, возможно ли это hasNextYYY!

Здесь приведен пример выполнения нескольких тестов hasNextXXX.

Scanner sc = new Scanner(System.in);
while (!sc.hasNext("exit")) {
    System.out.println(
        sc.hasNextInt() ? "(int) " + sc.nextInt() :
        sc.hasNextLong() ? "(long) " + sc.nextLong() :  
        sc.hasNextDouble() ? "(double) " + sc.nextDouble() :
        sc.hasNextBoolean() ? "(boolean) " + sc.nextBoolean() :
        "(String) " + sc.next()
    );
}

Вот пример сеанса:

5
(int) 5
ложь
(boolean) false
бла
(String) blah
1.1
(двойной) 1.1
100000000000
(длинный) 100000000000
выход

Обратите внимание, что порядок испытаний имеет значение. Если a Scanner hasNextInt(), то это также hasNextLong(), но это не обязательно true наоборот. Чаще всего вы хотите сделать более конкретный тест перед более общим тестом.


Пример 3: Проверка гласных

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

Scanner sc = new Scanner(System.in);
System.out.println("Please enter a vowel, lowercase!");
while (!sc.hasNext("[aeiou]")) {
    System.out.println("That not a vowel!");
    sc.next();
}
String vowel = sc.next();
System.out.println("Thank you! Got " + vowel);

Вот пример сеанса:

Введите гласный, в нижнем регистре!
5
Это не гласный!
г
Это не гласный!
е
Спасибо! Получил e

В regex, как строковый литерал Java, шаблон "[aeiou]" - это так называемый "класс символов"; он соответствует любой из букв a, e, i, o, u. Обратите внимание, что это тривиально, чтобы сделать вышеупомянутый тест нечувствительным к регистру: просто укажите такой шаблон регулярного выражения на Scanner.

Ссылки API

Связанные вопросы

Ссылки


Пример 4. Использование двух Scanner сразу

Иногда вам нужно сканировать строки за строкой, с несколькими токенами на линии. Самый простой способ сделать это - использовать два Scanner, где второй Scanner принимает nextLine() из первого Scanner в качестве входного. Вот пример:

Scanner sc = new Scanner(System.in);
System.out.println("Give me a bunch of numbers in a line (or 'exit')");
while (!sc.hasNext("exit")) {
    Scanner lineSc = new Scanner(sc.nextLine());
    int sum = 0;
    while (lineSc.hasNextInt()) {
        sum += lineSc.nextInt();
    }
    System.out.println("Sum is " + sum);
}

Вот пример сеанса:

Дайте мне кучу чисел в строке (или "exit" )
3 4 5
Сумма составляет 12
10 100 млн. Долларов

Сумма составляет 110
ждать, что? Сумма 0
Выход

В дополнение к Scanner(String) constructor, также Scanner(java.io.File) и др.


Резюме

  • Scanner предоставляет богатый набор функций, таких как hasNextXXX методы для проверки.
  • Правильное использование hasNextXXX/nextXXX в комбинации означает, что Scanner будет НИКОГДА не вывести InputMismatchException/NoSuchElementException.
  • Всегда помните, что hasNextXXX не продвигает Scanner мимо любого ввода.
  • Не стесняйтесь создавать несколько Scanner, если это необходимо. Два простых Scanner часто лучше, чем один сложный Scanner.
  • Наконец, даже если у вас нет планов использовать расширенные функции регулярного выражения, имейте в виду, какие методы основаны на регулярных выражениях, а какие нет. Любой метод Scanner, который принимает аргумент String pattern, основан на регулярном выражении.
    • Совет: простой способ превратить любой String в литеральный шаблон - Pattern.quote it.

Ответ 2

Для проверки строк для букв вы можете использовать регулярные выражения, например:

someString.matches("[A-F]");

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

    public int readInt(String prompt, int min, int max)
    {
    Scanner scan = new Scanner(System.in);

    int number = 0;

    //Run once and loop until the input is within the specified range.
    do 
    {
        //Print users message.
        System.out.printf("\n%s > ", prompt);

        //Prevent string input crashing the program.
        while (!scan.hasNextInt()) 
        {
            System.out.printf("Input doesn't match specifications. Try again.");
            System.out.printf("\n%s > ", prompt);
            scan.next(); 
        }

        //Set the number.
        number = scan.nextInt();

        //If the number is outside range print an error message.
        if (number < min || number > max)
            System.out.printf("Input doesn't match specifications. Try again.");

    } while (number < min || number > max);

    return number;
}

Ответ 3

Здесь минималистский способ сделать это.

System.out.print("Please enter an integer: ");
while(!scan.hasNextInt()) scan.next();
int demoInt = scan.nextInt();

Ответ 4

Одна идея:

try {
    int i = Integer.parseInt(myString);
    if (i < 0) {
        // Error, negative input
    }
} catch (NumberFormatException e) {
    // Error, not a number.
}

В commons-lang библиотека CharUtils класс, который предоставляет методы isAsciiNumeric(), чтобы проверить, что символ является числом, и isAsciiAlpha(), чтобы проверить, что символ является буквой...

Ответ 5

Если вы разбираете строковые данные с консоли или аналогичные, лучший способ - использовать регулярные выражения. Подробнее об этом читайте здесь: http://java.sun.com/developer/technicalArticles/releases/1.4regex/

В противном случае, чтобы проанализировать int из строки, попробуйте Integer.parseInt(строка). Если строка не является числом, вы получите исключение. Кроме того, вы можете выполнить свои проверки на это значение, чтобы убедиться, что оно не является отрицательным.

String input;
int number;
try
{
    number = Integer.parseInt(input);
    if(number > 0)
    {
        System.out.println("You positive number is " + number);
    }
} catch (NumberFormatException ex)
{
     System.out.println("That is not a positive number!");
}

Чтобы получить строку только для символов, вам, вероятно, будет лучше зацикливаться на каждом символе, проверяющем цифры, используя, например, Character.isLetter(char).

String input
for(int i = 0; i<input.length(); i++)
{
   if(!Character.isLetter(input.charAt(i)))
   {
      System.out.println("This string does not contain only letters!");
      break;
   }
}

Удачи!

Ответ 6

что я пробовал, так это то, что сначала я взял целочисленный ввод и проверил, является ли его отрицательным или нет, если его отрицательный снова принимает вход

Scanner s=new Scanner(System.in);

    int a=s.nextInt();
    while(a<0)
    {
    System.out.println("please provide non negative integer input ");
    a=s.nextInt();
    }
    System.out.println("the non negative integer input is "+a);

Здесь вам нужно сначала взять ввод символа и проверить, дал ли пользователь символ или нет, если нет, а затем снова введите символ

    char ch = s.findInLine(".").charAt(0);
    while(!Charcter.isLetter(ch))
    {
    System.out.println("please provide a character input ");
    ch=s.findInLine(".").charAt(0);
    }
    System.out.println("the character  input is "+ch);