Проверка входных данных с помощью java.util.Сканер
Я беру пользовательский ввод из System.in
используя java.util.Scanner
. Мне нужно проверить входные данные для таких вещей, как:
- Это должно быть неотрицательное число
- Это должна быть буква алфавита
- ... etc
Какой лучший способ сделать это?
Переведено автоматически
Ответ 1
Обзор Scanner.hasNextXXX
методов
java.util.Scanner
имеет множество hasNextXXX
методов, которые можно использовать для проверки входных данных. Вот краткий обзор всех из них:
hasNext()
- есть ли у него вообще какой-либо токен?hasNextLine()
- есть ли у него другая строка ввода?- Для примитивов Java
hasNextInt()
- есть ли у него токен, который можно преобразовать вint
?- Также доступны
hasNextDouble()
,hasNextFloat()
,hasNextByte()
hasNextShort()
,hasNextLong()
,,, иhasNextBoolean()
- В качестве бонуса также есть
hasNextBigInteger()
иhasNextBigDecimal()
- Целочисленные типы также перегружены для указания исходного кода (например, шестнадцатеричного)
- На основе регулярных выражений
hasNext(String pattern)
hasNext(Pattern pattern)
являетсяPattern.compile
перегрузкой
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
.
Вопросы по теме
- Как использовать Scanner, чтобы принимать в качестве входных данных только допустимый int
- Как мне предотвратить выдачу сканером исключений при вводе неправильного типа? (java)
Пример 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
hasNext(String pattern)
- Возвращает,true
если следующий токен соответствует шаблону, построенному из указанной строки.java.util.regex.Pattern
Вопросы по теме
Ссылки
- Учебные пособия по Java / Основные классы / Регулярные выражения
- regular-expressions.info/Character Классы
Пример 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
в комбинации означает, что aScanner
НИКОГДА не выдаст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()
для проверки того, является ли символ буквой...