Estoy usando los Scanner
métodos nextInt()
y nextLine()
para leer la entrada.
Se parece a esto:
System.out.println("Enter numerical value");
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string");
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)
El problema es que después de ingresar el valor numérico, input.nextLine()
se omite el primero y input.nextLine()
se ejecuta el segundo , de modo que mi salida se ve así:
Enter numerical value
3 // This is my input
Enter 1st string // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string // ...and this line is executed and waits for my input
Probé mi aplicación y parece que el problema radica en el uso input.nextInt()
. Si lo elimino, ambos string1 = input.nextLine()
y string2 = input.nextLine()
se ejecutan como quiero que sean.
java
io
java.util.scanner
blekione
fuente
fuente
Respuestas:
Esto se debe a que el
Scanner.nextInt
método no lee el carácter de nueva línea en su entrada creada al presionar "Enter", por lo que la llamada aScanner.nextLine
regresa después de leer esa nueva línea .Encontrará un comportamiento similar cuando use
Scanner.nextLine
afterScanner.next()
o cualquierScanner.nextFoo
método (excepto élnextLine
mismo).Solución alterna:
Haga una
Scanner.nextLine
llamada después de cada unoScanner.nextInt
oScanner.nextFoo
consuma el resto de esa línea, incluida la nueva líneaO, mejor aún, lea la entrada
Scanner.nextLine
y conviértala al formato adecuado que necesita. Por ejemplo, puede convertir a un entero utilizando elInteger.parseInt(String)
método.fuente
try-catch
, porque seInteger.parseInt
lanzaNumberFormatException
cuando se le pasa un argumento no válido. Aprenderá sobre la excepción más adelante. Por ejemplo: -Integer.parseInt("abc")
. No quieres que "abc" se convierta a int ¿verdad?Scanner#hasNextFoo
cheque de antemano en lugar de un try-catch, pero eso también funciona.El problema está en el método input.nextInt () : solo lee el valor int. Entonces, cuando continúe leyendo con input.nextLine (), recibirá la tecla "\ n" Enter. Entonces, para omitir esto, debe agregar input.nextLine () . Espero que esto esté claro ahora.
Pruébalo así:
fuente
nextLine
, pero todavía necesito una explicación de este comportamientoEs porque cuando ingresa un número y luego presiona Enter,
input.nextInt()
consume solo el número, no el "final de línea". Cuando seinput.nextLine()
ejecuta, consume el "final de línea" aún en el búfer desde la primera entrada.En cambio, use
input.nextLine()
inmediatamente despuésinput.nextInt()
fuente
Parece que hay muchas preguntas sobre este problema con
java.util.Scanner
. Creo que una solución más legible / idiomática sería llamarscanner.skip("[\r\n]+")
para eliminar los caracteres de nueva línea después de llamarnextInt()
.EDITAR: como @PatrickParker señala a continuación, esto causará un bucle infinito si el usuario ingresa cualquier espacio en blanco después del número. Vea su respuesta para un mejor patrón para usar con skip: https://stackoverflow.com/a/42471816/143585
fuente
Lo hace porque
input.nextInt();
no captura la nueva línea. puedes hacer como los otros propuestos agregando uninput.nextLine();
debajo.Alternativamente, puede hacerlo al estilo C # y analizar una nextLine a un entero de esta manera:
Hacer esto funciona igual de bien y le ahorra una línea de código.
fuente
TL; DR Uso
scanner.skip("\\R")
antes de cadascanner.newLine()
llamada, que se ejecuta después de:scanner.next()
scanner.next*TYPE*()
método.Cosas que necesitas saber:
el texto que representa pocas líneas también contiene caracteres no imprimibles entre líneas (los llamamos separadores de línea) como
"\r"
)"\n"
)cuando está leyendo datos desde la consola, le permite al usuario escribir su respuesta y cuando termina necesita confirmar de alguna manera ese hecho. Para hacerlo, el usuario debe presionar la tecla "enter" / "return" en el teclado.
Lo importante es que esta clave, además de garantizar la colocación de los datos del usuario en la entrada estándar (representada por la
System.in
cual se leeScanner
), también envía separadores de línea dependientes del sistema operativo (como para Windows\r\n
) después de ella.Entonces, cuando le pide al usuario un valor como
age
, y el usuario escribe 42 y presiona enter, la entrada estándar contendrá"42\r\n"
.Problema
Scanner#nextInt
(y otros métodos) no permite que ScannerScanner#nextType
consuma estos separadores de línea. Los leeráSystem.in
(¿de qué otra manera Scanner sabría que no hay más dígitos del usuario que representen unage
valor que no sean espacios en blanco?) Que los eliminará de la entrada estándar, pero también almacenará en caché esos separadores de línea internamente . Lo que debemos recordar es que todos los métodos de escáner siempre escanean a partir del texto almacenado en caché.Ahora
Scanner#nextLine()
simplemente recopila y devuelve todos los caracteres hasta que encuentre separadores de línea (o final de la secuencia). Pero dado que los separadores de línea después de leer el número de la consola se encuentran inmediatamente en la memoria caché de Scanner, devuelve una cadena vacía, lo que significa que Scanner no pudo encontrar ningún carácter antes de esos separadores de línea (o al final de la secuencia).Por cierto,
nextLine
también consume esos separadores de línea.Solución
Así que cuando se quiere pedir el número y luego por toda la línea, evitando que cadena vacía como resultado de
nextLine
, o biennextInt
memoria caché de escáneresnextLine
,skip("\\R")
oskip("\r\n|\r|\n")
dejar que el escáner omita la parte que coincida con el separador de línea (más información sobre\R
: https://stackoverflow.com/a/31060125 )nextInt
(ninext
, ni ningúnnextTYPE
método) en absoluto. En su lugar, lea los datos completos línea por línea usandonextLine
y analice los números de cada línea (suponiendo que una línea contenga solo un número) al tipo apropiado comoint
viaInteger.parseInt
.Por cierto : los métodos pueden omitir delimitadores (de forma predeterminada, todos los espacios en blanco, como tabulaciones, separadores de línea), incluidos los almacenados en caché por el escáner, hasta que encuentren el siguiente valor que no sea delimitador (token). Gracias a eso por entrada como código
Scanner#nextType
"42\r\n\r\n321\r\n\r\n\r\nfoobar"
podrá asignar adecuadamente
num1=42
num2=321
name=foobar
.fuente
En lugar de
input.nextLine()
usarinput.next()
, eso debería resolver el problema.Código modificado:
fuente
Si desea leer cadenas e ints, una solución es usar dos escáneres:
fuente
scanner.nextLine()
debería funcionar.Si desea escanear entradas rápidamente sin confundirse con el método nextLine () de la clase Scanner, use el escáner de entrada personalizado para ello.
Código:
Ventajas:
Métodos :
Uso:
ScanReader sc = new ScanReader(System.in);
3. Importar clases necesarias:import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. Lanza IOException desde tu método principal para manejar la excepción 5. Usa los métodos provistos. 6. DisfrutaEjemplo:
fuente
Para evitar el problema, use
nextLine();
inmediatamente después,nextInt();
ya que ayuda a limpiar el búfer. Cuando presionaENTER
elnextInt();
botón no captura la nueva línea y, por lo tanto, omite elScanner
código más tarde.fuente
sc.nextLine()
es mejor en comparación con el análisis de la entrada. Porque el rendimiento sabio será bueno.fuente
Supongo que llego bastante tarde a la fiesta ...
Como se indicó anteriormente, llamar
input.nextLine()
después de obtener su valor int resolverá su problema. La razón por la cual su código no funcionó fue porque no había nada más que almacenar desde su entrada (donde ingresó el int) enstring1
. Voy a arrojar un poco más de luz sobre todo el tema.Considere nextLine () como el extraño entre los métodos nextFoo () en la clase Scanner. Tomemos un ejemplo rápido. Digamos que tenemos dos líneas de código como las siguientes:
Si ingresamos el valor a continuación (como una sola línea de entrada)
El valor de nuestra
firstNumber
ysecondNumber
variable se convierte en 54 y 234 respectivamente. La razón por la que esto funciona de esta manera es porque un nuevo avance de línea ( es decir, \ n ) NO SE genera automáticamente cuando el método nextInt () toma los valores. Simplemente toma el "próximo int" y sigue adelante. Esto es lo mismo para el resto de los métodos nextFoo () excepto nextLine ().nextLine () genera un nuevo avance de línea inmediatamente después de tomar un valor; esto es lo que @RohitJain quiere decir al decir que el nuevo avance de línea se "consume".
Por último, el método next () simplemente toma la cadena más cercana sin generar una nueva línea; Esto lo convierte en el método preferencial para tomar cadenas separadas dentro de la misma línea.
Espero que esto ayude. ¡Feliz codificación!
fuente
Use 2 objetos de escáner en lugar de uno
fuente
fuente
si espero una entrada no vacía
utilizado en el ejemplo anterior:
fuente
En uno de mis casos de uso, tuve el escenario de leer un valor de cadena precedido por un par de valores enteros . Tuve que usar un " for / while loop " para leer los valores. Y ninguna de las sugerencias anteriores funcionó en este caso.
Usando en
input.next()
lugar deinput.nextLine()
solucionado el problema. Espero que esto pueda ser útil para aquellos que se enfrentan a situaciones similares.fuente
Use este código, solucionará su problema.
fuente
Como los
nextXXX()
métodos no leennewline
, exceptonextLine()
. Podemos omitirnewline
después de leer cualquiernon-string
valor (int
en este caso) usandoscanner.skip()
lo siguiente:fuente
¿Por qué no usar un nuevo escáner para cada lectura? Como abajo. Con este enfoque no enfrentarás tu problema.
fuente
Scanner
para evitar pérdidas de memoria. ¿Perdiendo el tiempo?nextInt()
no consumirá la nueva línea, independientemente de si está en una "nueva"Scanner
o ya usada.