Pregunta

Estoy usando el siguiente código:

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 ingreso una 'w', me dirá "Ha ingresado una entrada no válida.Inténtelo 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.Intentar otra vez."

¿Por qué está pasando esto?¿No se supone que el programa debe esperar a que el usuario ingrese y presione Entrar cada vez que llega a la declaración?

if (in.hasNextInt())
¿Fue útil?

Solución

En el último bloque else, tiene que borrar la 'w' u otra entrada no válida desde el escáner. Puede hacerlo 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();
}

Otros consejos

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

  

Las devoluciones true si el siguiente token en la entrada de este escáner puede ser interpretada como un valor int en la base predeterminada utilizando el método nextInt(). El escáner no avanza más allá de cualquier 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 se quite la declaración sc.next(), entonces se hará la marcha Scanner más allá de la señal de que no hasNextInt(). El programa entonces imprimir:

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

El hecho de que un cheque hasNextXXX() fallado no pasa por alto la entrada es intencional: que le permite realizar comprobaciones adicionales en esa ficha si es necesario. Aquí hay 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 se ejecuta este programa, se dará salida a lo siguiente:

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

Esta declaración de Ben S.sobre la llamada sin bloqueo es falso:

Además, hasNextInt() no bloquea.Es la verificación sin bloqueo para ver si una próxima llamada futura podría recibir entrada sin bloquear.

...aunque sí reconozco que el documentación puede malinterpretarse fácilmente para dar esta opinión, y el nombre mismo implica que debe usarse para este propósito.La cita relevante, con énfasis añadido:

Los métodos next() y hasNext() y sus métodos complementarios de tipo primitivo (como nextInt() y hasNextInt()) primero omita cualquier entrada que coincida con el patrón delimitador y luego intente devolver el siguiente token. Tanto el método hasNext como el siguiente pueden bloquear la espera de más entradas. El hecho de que un método hasNext bloquee no tiene relación con el hecho de que su método next asociado se bloquee o no.

Es un punto sutil, sin duda.Ya sea diciendo "Ambos el hasNext y next métodos", o "Tanto hasnext() como next()" habrían implicado que los métodos complementarios actuarían de manera diferente.Pero dado que cumplen con la misma convención de nomenclatura (y la misma documentación, por supuesto), es razonable esperar que actúen de la misma manera, y tieneSiguiente()Dice claramente que puede bloquear.

Metanota:Probablemente esto debería ser un comentario a la publicación incorrecta, pero parece que como nuevo usuario solo puedo publicar esta respuesta (o editar la wiki, que parece preferirse para cambios de estilo, no para cambios sustanciales).

las variables

Flag son demasiado propenso a errores de usar. Utilice el control de lazo explícito con los comentarios en su lugar. Además, hasNextInt() hace no bloquee. Es la comprobación de no bloqueo para ver si un futuro next llamada podría obtener una entrada sin bloquear. Si desea bloquear, utilice 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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top