Validar entrada usando java.util.Scanner
validation (6)
Descripción general de los métodos de Scanner.hasNextXXX
java.util.Scanner
tiene muchos métodos hasNextXXX
que se pueden usar para validar la entrada. Aquí hay una breve descripción de todos ellos:
-
hasNext()
- ¿tiene algún token? -
hasNextLine()
- ¿tiene otra línea de entrada? - Para primitivos de Java
-
hasNextInt()
- ¿tiene un token que se puede analizar en unint
? - También están disponibles
hasNextDouble()
,hasNextFloat()
,hasNextByte()
,hasNextShort()
,hasNextLong()
yhasNextBoolean()
- Como bonificación, también tiene
hasNextBigInteger()
yhasNextBigDecimal()
- Los tipos integrales también tienen sobrecargas para especificar radix (por ejemplo, hexadecimal)
-
- Basado en expresiones regulares
-
hasNext(String pattern)
-
hasNext(Pattern pattern)
es la sobrecarga dePattern.compile
-
Scanner
es capaz de más, habilitado por el hecho de que está basado en expresiones regulares. Una característica importante es useDelimiter(String pattern)
, que le permite definir qué patrón separa sus tokens. También hay métodos de find
y skip
que ignoran los delimitadores.
La siguiente discusión mantendrá la expresión regular tan simple como sea posible, por lo que el foco permanece en el Scanner
.
Ejemplo 1: Validación de resultados positivos
Aquí hay un ejemplo simple de usar hasNextInt()
para validar el int
positivo de la entrada.
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);
Aquí hay una sesión de ejemplo:
Por favor ingrese un número positivo!
cinco
¡Eso no es un número!
-3
Por favor ingrese un número positivo!
5
¡Gracias! Tengo 5
Tenga en cuenta qué tan fácil es usar Scanner.hasNextInt()
en comparación con el más detallado NumberFormatException
try/catch
Integer.parseInt
/ NumberFormatException
combo. Por contrato, un Scanner
garantiza que si tiene hasNextInt()
, nextInt()
le dará pacíficamente esa int
, y no arrojará ninguna NumberFormatException
/ InputMismatchException
/ NoSuchElementException
.
Preguntas relacionadas
- Cómo usar Scanner para aceptar solo int válido como entrada
- ¿Cómo evito que un escáner arroje excepciones cuando se ingresa el tipo incorrecto? (Java)
Ejemplo 2: Múltiple hasNextXXX
en el mismo token
Tenga en cuenta que el fragmento de arriba contiene una sc.next()
para avanzar en el Scanner
hasta que hasNextInt()
. ¡Es importante darse cuenta de que ninguno de los métodos de hasNextXXX
avanzar el Scanner
allá de cualquier entrada! Encontrarás que si omites esta línea del fragmento, ¡entraría en un ciclo infinito en una entrada no válida!
Esto tiene dos consecuencias:
- Si necesita omitir la entrada "basura" que falla su prueba de
hasNextXXX
, entonces necesita avanzar elScanner
una forma u otra (por ejemplo,next()
,nextLine()
,skip
, etc.). - Si uno
hasNextXXX
pruebahasNextXXX
falla, ¡ aún puede probar si tal vez tienehasNextYYY
!
Aquí hay un ejemplo de realizar múltiples pruebas de 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()
);
}
Aquí hay una sesión de ejemplo:
5
(int) 5
falso
(booleano) falso
paja
(Cuerda) bla
1.1
(doble) 1.1
100000000000
(largo) 100000000000
salida
Tenga en cuenta que el orden de las pruebas es importante. Si un Scanner
hasNextInt()
, también hasNextLong()
, pero no es necesariamente true
al revés. En la mayoría de los casos, querrá hacer la prueba más específica antes de la prueba más general.
Ejemplo 3: Validar vocales
Scanner
tiene muchas funciones avanzadas compatibles con expresiones regulares. Aquí hay un ejemplo de usarlo para validar vocales.
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);
Aquí hay una sesión de ejemplo:
Por favor, introduzca una vocal, minúscula!
5
¡Eso no es una vocal!
z
¡Eso no es una vocal!
mi
¡Gracias! Tengo e
En regex, como un literal de cadena Java, el patrón "[aeiou]"
es lo que se llama una "clase de caracteres"; coincide con cualquiera de las letras a
, e
, i
, o
, u
. Tenga en cuenta que es trivial hacer que la prueba anterior no distinga entre mayúsculas y minúsculas: simplemente proporcione dicho patrón de expresiones regulares al Scanner
.
Enlaces API
-
hasNext(String pattern)
- Devuelvetrue
si el siguiente token coincide con el patrón construido a partir de la cadena especificada. -
java.util.regex.Pattern
Preguntas relacionadas
Referencias
- Tutoriales de Java / Clases esenciales / Expresiones regulares
- regular-expressions.info/Character Classes
Ejemplo 4: uso de dos Scanner
a la vez
Algunas veces necesita escanear línea por línea, con múltiples tokens en una línea. La forma más fácil de lograr esto es usar dos Scanner
, donde el segundo Scanner
toma la nextLine()
del primer Scanner
como entrada. Aquí hay un ejemplo:
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);
}
Aquí hay una sesión de ejemplo:
Dame un montón de números en una línea (o ''salir'')
3 4 5
Suma es 12
10 100 millones de dólares
Suma es 110
¿esperar lo?
Suma es 0
salida
Además del constructor Scanner(String)
, también hay Scanner(java.io.File)
entre otros.
Resumen
-
Scanner
proporciona unhasNextXXX
conjunto de características, como los métodoshasNextXXX
para la validación. - El uso adecuado de
hasNextXXX/nextXXX
en combinación significa que unScanner
NUNCA lanzará unaInputMismatchException
/NoSuchElementException
. - Recuerde siempre que
hasNextXXX
no hace avanzar elScanner
allá de cualquier entrada. - No sea tímido para crear un
Scanner
múltiple si es necesario. DosScanner
simples a menudo son mejores que unScanner
demasiado complejo. - Finalmente, incluso si no tiene planes de utilizar las funciones avanzadas de expresiones regulares, tenga en cuenta qué métodos están basados en expresiones regulares y cuáles no. Cualquier método de
Scanner
que tome un argumento deString pattern
está basado en expresiones regulares.- Sugerencia : una manera fácil de convertir cualquier
String
en un patrón literal esPattern.quote
it.
- Sugerencia : una manera fácil de convertir cualquier
Esta pregunta ya tiene una respuesta aquí:
Estoy tomando la entrada del usuario de System.in
usando java.util.Scanner
. Necesito validar la entrada para cosas como:
- Debe ser un número no negativo
- Debe ser una letra alfabética
- ... etc
¿Cuál es la mejor manera de hacer esto?
Aquí hay una forma minimalista de hacerlo.
System.out.print("Please enter an integer: ");
while(!scan.hasNextInt()) scan.next();
int demoInt = scan.nextInt();
Lo que he intentado es que primero tome la entrada de enteros y compruebe si es negativo o no, si es negativo, entonces, de nuevo, tome la entrada
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);
Aquí, primero debe tomar la entrada de caracteres y verificar si el usuario le dio carácter o no, si no más que tomar la entrada de caracteres
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);
Para comprobar Cadenas de letras puede usar expresiones regulares, por ejemplo:
someString.matches("[A-F]");
Para comprobar los números y detener el bloqueo del programa, tengo una clase bastante simple que puede encontrar a continuación, donde puede definir el rango de valores que desea. Here
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;
}
Si está analizando datos de cadena desde la consola o similar, la mejor manera es usar expresiones regulares. Lea más al respecto aquí: http://java.sun.com/developer/technicalArticles/releases/1.4regex/
De lo contrario, para analizar un int de una cadena, intente Integer.parseInt(string) . Si la cadena no es un número, obtendrá una excepción. De otro modo, puede realizar sus controles sobre ese valor para asegurarse de que no sea negativo.
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!");
}
Para obtener una cadena de sólo caracteres, probablemente sería mejor que recorriera cada carácter buscando los dígitos, utilizando, por ejemplo, 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;
}
}
¡Buena suerte!
Una idea:
try {
int i = Integer.parseInt(myString);
if (i < 0) {
// Error, negative input
}
} catch (NumberFormatException e) {
// Error, not a number.
}
También hay, en la biblioteca commons-lang , la clase CharUtils que proporciona los métodos isAsciiNumeric()
para verificar que un personaje sea un número, y es isAsciiAlpha()
para verificar que el personaje sea una letra ...