Проверка правильности ввода с использованием java.util.Scanner
Я принимаю пользовательский ввод от System.in
используя java.util.Scanner
, Мне нужно проверить ввод для таких вещей, как:
- Это должно быть неотрицательное число
- Это должна быть буква алфавита
- ... так далее
Какой лучший способ сделать это?
6 ответов
Обзор 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);
Вот пример сеанса:
Пожалуйста, введите положительное число!
5
Это не число!
-3
Пожалуйста, введите положительное число!
5
Спасибо! Получил 5
Обратите внимание, насколько проще Scanner.hasNextInt()
использовать по сравнению с более многословным try/catch
Integer.parseInt
/ NumberFormatException
комбо. По контракту, Scanner
гарантирует, что если это hasNextInt()
, затем nextInt()
мирно даст вам это int
, и не будет бросать любой NumberFormatException
/ InputMismatchException
/ NoSuchElementException
,
Смежные вопросы
- Как использовать сканер, чтобы принимать только действительные значения int в качестве входных данных
- Как сохранить сканер от выдачи исключений при вводе неправильного типа? (Джава)
Пример 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
ложный
(логическое) ложь
вздор
(Строка) бла
1,1
(двойной) 1,1
100000000000
(длинный) 100000000000
выход
Обратите внимание, что порядок испытаний имеет значение. Если 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
Это не гласная!
е
Спасибо! Получил е
В регулярном выражении, как строковый литерал Java, шаблон "[aeiou]"
это то, что называется "класс персонажа"; это соответствует любой из букв a
, e
, i
, o
, u
, Обратите внимание, что сделать вышеуказанный тест-регистронезависимым тривиально: просто предоставьте такой шаблон регулярного выражения Scanner
,
API ссылки
hasNext(String pattern)
- возвратtrue
если следующий токен соответствует шаблону, созданному из указанной строки.java.util.regex.Pattern
Смежные вопросы
Рекомендации
- Учебные руководства по Java / Основные классы / Регулярные выражения
- регулярные выражения.info/Character Classes
Пример 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);
}
Вот пример сеанса:
Дайте мне кучу цифр в строке (или "выход")
3 4 5
Сумма 12
10 100 миллионов долларов
Сумма 110
чего ждать?
Сумма 0
выход
В дополнение к Scanner(String)
конструктор, есть также Scanner(java.io.File)
среди других.
Резюме
Scanner
предоставляет богатый набор функций, таких какhasNextXXX
методы проверки.- Правильное использование
hasNextXXX/nextXXX
в сочетании означает, чтоScanner
НИКОГДА не броситInputMismatchException
/NoSuchElementException
, - Всегда помни это
hasNextXXX
не продвигаетScanner
мимо любого входа. - Не стесняйтесь создавать несколько
Scanner
если необходимо. Два простыхScanner
часто лучше, чем один слишком сложныйScanner
, - Наконец, даже если у вас нет планов использовать расширенные функции регулярных выражений, помните, какие методы основаны на регулярных выражениях, а какие нет. любой
Scanner
метод, который принимаетString pattern
Аргумент основан на регулярных выражениях.- Совет: простой способ превратить любой
String
в буквальном смысле являетсяPattern.quote
Это.
- Совет: простой способ превратить любой
Вот минималистичный способ сделать это.
System.out.print("Please enter an integer: ");
while(!scan.hasNextInt()) scan.next();
int demoInt = scan.nextInt();
Для проверки строк на наличие букв вы можете использовать регулярные выражения, например:
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;
}
Одна идея:
try {
int i = Integer.parseInt(myString);
if (i < 0) {
// Error, negative input
}
} catch (NumberFormatException e) {
// Error, not a number.
}
В библиотеке commons-lang также есть класс CharUtils, который предоставляет методы isAsciiNumeric()
проверить, что символ является числом, и isAsciiAlpha()
чтобы проверить, что символ является буквой...
То, что я пробовал, это то, что сначала я взял целочисленный вход и проверил, является ли он отрицательным или нет, если его отрицательный, затем снова принять
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);
Если вы анализируете строковые данные из консоли или чего-либо подобного, лучше всего использовать регулярные выражения. Подробнее об этом читайте здесь: http://java.sun.com/developer/technicalArticles/releases/1.4regex/
В противном случае, чтобы проанализировать int из строки, попробуйте Integer.parseInt (string). Если строка не является числом, вы получите исключение. В противном случае вы можете выполнить проверку этого значения, чтобы убедиться, что оно не отрицательное.
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;
}
}
Удачи!