2009-11-25 38 views
10

estoy usando el siguiente código:.Java: Bucle infinito mediante escáner in.hasNextInt()

while (invalidInput) 
{ 
    // ask the user to specify a number to update the times by 
    System.out.print("Specify an integer between 0 and 5: "); 

    if (in.hasNextInt()) 
    { 
     // get the update value 
     updateValue = in.nextInt(); 

     // check to see if it was within range 
     if (updateValue >= 0 && updateValue <= 5) 
     { 
      invalidInput = false; 
     } 
     else 
     { 
      System.out.println("You have not entered a number between 0 and 5. Try again."); 
     } 
    } else 
    { 
     System.out.println("You have entered an invalid input. Try again."); 
    } 
} 

Sin embargo, si entro en una entrada no válida 'w' que me lo dirá "Ha introducido Intentar de nuevo " y luego entrará en un bucle infinito que muestra el texto "Especifique un número entero entre 0 y 5: ha ingresado una entrada no válida. Inténtelo de nuevo".

¿Por qué sucede esto? no es el programa supone que esperar a que el usuario introduzca y pulse ENTER cada vez que llega a la instrucción:

if (in.hasNextInt()) 
+0

¡Ya que no le has enseñado a nadie lo que es 'in', o cómo lo has construido, no hay forma de saber cómo debería comportarse! –

Respuesta

13

En su última else bloque, es necesario borrar la entrada no válida 'w' u otro desde el escáner. Usted puede hacer esto llamando next() en el escáner e ignorando su valor de retorno de tirar esa entrada no válida, de la siguiente manera:

else 
{ 
     System.out.println("You have entered an invalid input. Try again."); 
     in.next(); 
} 
2

variables de la bandera también son propensas a errores a utilizar. Use control explícito de bucle con comentarios en su lugar. Además, hasNextInt() no bloquea. Es la verificación sin bloqueo para ver si una futura llamada next podría ingresar sin bloquear. Si quiere bloquear, use el método nextInt().

// Scanner that will read the integer 
final Scanner in = new Scanner(System.in); 
int inputInt; 
do { // Loop until we have correct input 
    System.out.print("Specify an integer between 0 and 5: "); 
    try { 
     inputInt = in.nextInt(); // Blocks for user input 
     if (inputInt >= 0 && inputInt <= 5) { 
      break; // Got valid input, stop looping 
     } else { 
      System.out.println("You have not entered a number between 0 and 5. Try again."); 
      continue; // restart loop, wrong number 
     } 
    } catch (final InputMismatchException e) { 
     System.out.println("You have entered an invalid input. Try again."); 
     in.next(); // discard non-int input 
     continue;  // restart loop, didn't get an integer input 
    } 
} while (true); 
+0

¿Hay alguna razón por la que hace que el escáner sea definitivo? – Tomek

+0

este código todavía produce un bucle infinito – Tomek

+0

Lo hago definitivo ya que no cambiará. El compilador podría hacer ciertas optimizaciones debido a esto. Es un buen hábito declarar todo lo que puede ser final. El ciclo se interrumpirá cuando el usuario ingrese la entrada correcta. Solo es infinito si el usuario elige hacerlo infinito. Si lo desea, puedo editarlo para que solo permita un número determinado de reintentos. –

8

El problema era que no avanzó la Scanner más allá de la entrada problemático. De hasNextInt() documentación:

devoluciones true si el siguiente token en la entrada de este escáner puede ser interpretada como un valor int en la raíz por defecto utilizando el método nextInt(). El escáner no avanza más allá de ninguna entrada.

Esto es cierto para todos los métodos hasNextXXX(): regresan true o false, sin avanzar la Scanner.

He aquí un fragmento de ilustrar el problema:

String input = "1 2 3 oops 4 5 6"; 
    Scanner sc = new Scanner(input); 
    while (sc.hasNext()) { 
     if (sc.hasNextInt()) { 
      int num = sc.nextInt(); 
      System.out.println("Got " + num); 
     } else { 
      System.out.println("int, please!"); 
      //sc.next(); // uncomment to fix! 
     } 
    } 

Usted encontrará que este programa entra en un bucle infinito, pidiendo int, please! repetidamente.

Si descomenta la declaración sc.next(), hará que el Scanner pase el token que falla hasNextInt(). El programa se imprima:

Got 1 
Got 2 
Got 3 
int, please! 
Got 4 
Got 5 
Got 6 

El hecho de que un fallido hasNextXXX() cheque no se salta la entrada es intencional: que le permite realizar comprobaciones adicionales en esa ficha si es necesario. He aquí un ejemplo para ilustrar:

String input = " 1 true foo 2 false bar 3 "; 
    Scanner sc = new Scanner(input); 
    while (sc.hasNext()) { 
     if (sc.hasNextInt()) { 
      System.out.println("(int) " + sc.nextInt()); 
     } else if (sc.hasNextBoolean()) { 
      System.out.println("(boolean) " + sc.nextBoolean()); 
     } else { 
      System.out.println(sc.next()); 
     } 
    } 

Si ejecuta este programa, se emitiría lo siguiente:

(int) 1 
(boolean) true 
foo 
(int) 2 
(boolean) false 
bar 
(int) 3 
3

Esta afirmación de Ben S.acerca de la llamada no bloqueante es falso:

Además, hasNextInt() no bloquea. Es el control sin bloqueo para ver si una próxima llamada futura podría obtener entrada sin bloquear.

... aunque reconozco que el documentation interpretan mal fácilmente puede dar ser esta opinión, y el propio nombre implica que es para ser utilizado para este propósito. La cita relevante, con énfasis añadido:

El siguiente() y hasNext() métodos y sus métodos de compañía de tipo primitivo (como nextInt() y hasNextInt()) saltar primero cualquier entrada que coincide con el patrón de delimitador, y luego intentar devolver el siguiente token. Ambos hasNext y los siguientes métodos pueden bloquear la espera de más entradas. Si un bloque de métodos hasNext no tiene conexión a si se bloqueará o no su próximo método asociado.

Es un punto sutil, sin dudas. O decir "Ambos tiene los métodos Next y next", o "Both hasnext() y next()" implicarían que los métodos complementarios actuarían de manera diferente. Pero dado que se ajustan a la misma convención de nomenclatura (y la documentación, por supuesto), es razonable esperar que actúen de la misma manera, y hasNext() dice claramente que puede bloquear.

Nota Meta: probablemente debería ser un comentario de la publicación incorrecta, pero parece que como nuevo usuario solo puedo publicar esta respuesta (o editar la wiki que parece ser preferida para cambios sintéticos, no los de sustancia)

Cuestiones relacionadas