Вопрос-ответ

Validating input using java.util.Scanner [duplicate]

Проверка входных данных с помощью java.util.Сканер

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


  • Это должно быть неотрицательное число

  • Это должна быть буква алфавита

  • ... etc

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

Переведено автоматически
Ответ 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's 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 какие-либо входные данные вперед!,,, Вы обнаружите, что если вы опустите эту строку из фрагмента, то это приведет к бесконечному циклу при недопустимом вводе!

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


  • Если вам нужно пропустить ввод "мусора", который не проходит ваш 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
false

(логическое значение) false
бла

(Строка) бла

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's not a vowel!");
sc.next();
}
String vowel = sc.next();
System.out.println("Thank you! Got " + vowel);

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


Пожалуйста, введите гласную в нижнем регистре!

5

Это не гласная!
z

Это не гласная!
e

Спасибо! Есть


В регулярных выражениях в качестве строкового литерала 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) конструктору, есть также Scanner(java.io.File) среди прочих.


Краткие сведения


  • Scanner предоставляет богатый набор функций, таких как hasNextXXX методы проверки.

  • Правильное использование hasNextXXX/nextXXX в комбинации означает, что a Scanner НИКОГДА не выдаст InputMismatchException/NoSuchElementException .

  • Всегда помните, что hasNextXXX это не продвигает Scanner ни один ввод дальше.

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

  • Наконец, даже если вы не планируете использовать расширенные функции регулярных выражений, имейте в виду, какие методы основаны на регулярных выражениях, а какие нет. Любой Scanner метод, принимающий String pattern аргумент, основан на регулярных выражениях.

    • Совет: простой способ превратить любой String шаблон в буквальный - это использовать Pattern.quote его.


Ответ 2

Вот минималистичный способ сделать это.

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

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

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;
}
Ответ 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() для проверки того, является ли символ буквой...

java