Hola.
El problema se debe a una peculiaridad que tiene la clase Scanner y que hace que siempre que en un mismo programa queramos leer datos numéricos como un int y texto en un String, tendremos problemas seguro....
El problema se debe a que los métodos de la clase Scanner que usamos para recoger datos numéricos: nextInt(), nextDouble(), nextFloat(), etc... solo recogen la parte numérica de lo que hemos tecleado.
Es decir, si yo tecleo el número 52 y pulso enter, en realidad lo que he introducido es:
52\rEse último carácter, el
\r lo genera la tecla enter, es el símbolo llamado "retorno de carro" y, en este caso, sirve para decirle al objeto Scanner que ya hemos terminado de teclear.
Pues bién, si eso se lo pasamos al método nextLine(), lo cogerá COMPLETO y generará un String. Coge también el \r, aunque no lo vemos porque es "invisible".
En fín, en este caso no hay problema.
Pero si esa entrada se la pasamos a por ejemplo el método nextInt(), este método no cogerá el \r porque no es un valor numérico, SOLO cogerá el 52 y generará un int.
Pero el \r que nextInt() ha ignorado, no desaparece, se queda en el "stream" de entrada de datos por teclado, tal que así:
\r¿Qué pasa entonces? Pues que si tras leer un valor con nextInt(), luego queremos leer otro con un nextLine().... el nextLine() se va a encontrar con que hay un
\r en el "stream" de entrada.
Y erróneamente va a pensar que es que el usuario ya ha pulsado enter, por lo tanto dará por finalizada la entrada de datos y generará un String vacío.... cuando en realidad el usuario no ha tenido la posibilidad de teclear nada.
Esto es lo que te está pasando a tí. Tu primero lees un entero para preguntar cuantos usuarios se van a introducir:
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=en.nextInt();
Esto te deja un
\r abandonado en el stream de entrada, por lo tanto, tu primer intento de leer un String, va a fracasar:
System.out.println("Ingrese el nombre de los alumnos: ");
for(int i=0;i<=nombreAlumnos.length-1;i++){
alumno=en.nextLine();
nombreAlumnos[i]=alumno;
}
Solo fallará el primero, el resto irán bien porque los nextLine() no dejan
\r abandonados...
En fin, vamos a lo importante,
¿cómo solucionar esto?Por suerte es fácil, de hecho, hay dos formas.
Una, la más sencilla, pero muy poco elegante. Es invocar un nextLine() justo después de haber leido el dato int.
Este nextLine() no se asigna a ninguna variable, simplemente "limpiará" el stream de entrada de cualquier
\r que pueda haber.
Como digo, es fácil, pero no es elegante, porque queda un poco raro ir poniendo nextLine() sin asignar en distintas partes del código.
Aunque se puede usar un comentario para aclarar el motivo:
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=en.nextInt();
en.nextLine(); //Para limpiar stream de entrada y poder leer datos String a continuacion
La segunda opción, es solo un poquito más complicada, pero es más elegante y de hecho es la más recomendable por dos motivos que indicaré después.
Consiste en usar SIEMPRE nextLine() para leer datos, tanto si queremos un String como si queremos un dato numérico.
La diferencia es que si queremos un dato numérico, tendremos que "parsearlo" (convertirlo) segun nuestra necesidad.
En este caso, lo haríamos así:
System.out.println("Ingrese la cantidad de alumnos");
cantidadDeAlumnos=Integer.parseInt(en.nextLine());
O si quisieramos leer un dato numérico con decimales:
System.out.println("Ingrese el area del rectángulo: ");
double areaRectan=Double.parseDouble(en.nextLine());
¿Por qué es la opción más recomendable?
- Como ya hemos dicho, es más elegante. No hay que aclarar nada con comentarios, es evidente con solo leer el código que estamos recogiendo un valor int, o double, o byte o lo que sea...a pesar de que usamos un nextLine()
- Cuando avances más en tu aprendizaje en Java y comiences a crear ventanitas, botones, formularios con campos de texto, etc... estos formularios SIEMPRE nos van a devolver los valores introducidos por el usuario como String, y SIEMPRE tendremos que "parsearlos" si deseamos un dato numérico.
Así que mejor ir cogiendo ya la costumbre de este proceso.
- Otros lenguajes como C#, lenguaje muy similar a Java y que seguramente algún dia querrás/tendrás que meterle mano, realiza la lectura de datos de este mismo modo: pidiendo un String al usuario para luego "parsearlo".
Así que de nuevo resultará muy útil estar acostumbrado a esta mecánica.