Pergunta

Estou usando o seguinte 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.");
    }
}

No entanto, se eu inserir um 'w', ele me dirá "Você digitou uma entrada inválida.Tente novamente." e então entrará em um loop infinito mostrando o texto "Especifique um número inteiro entre 0 e 5:Você inseriu uma entrada inválida.Tente novamente."

Por que isso está acontecendo?O programa não deveria esperar que o usuário insira e pressione Enter cada vez que chegar à instrução:

if (in.hasNextInt())
Foi útil?

Solução

Em seu último else Bloco, você precisa limpar o 'W' ou outra entrada inválida do scanner. Você pode fazer isso ligando next() no scanner e ignorando seu valor de retorno para jogar fora essa entrada inválida, como segue:

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

Outras dicas

O problema era que você não avançou no Scanner após a entrada problemática. A partir de hasNextInt() documentação:

Retorna true Se o próximo token na entrada deste scanner puder ser interpretado como um int valor no Radix padrão usando o nextInt() método. O scanner não avança em nenhuma entrada.

Isso é verdade para todos hasNextXXX() Métodos: eles retornam true ou false, sem avançar o Scanner.

Aqui está um trecho para ilustrar o 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!
        }
    }

Você descobrirá que este programa entrará em um loop infinito, perguntando int, please! repetidamente.

Se você descomentar o sc.next() declaração, então fará o Scanner Passe o token que falha hasNextInt(). O programa imprimiria:

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

O fato de que um falhou hasNextXXX() A verificação não ignora a entrada é intencional: permite que você realize verificações adicionais nesse token, se necessário. Aqui está um exemplo 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());
        }
    }

Se você executar este programa, ele produzirá o seguinte:

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

Esta afirmação de Ben S. sobre a chamada não bloqueadora é falsa:

Além disso, o hasNextInt () não bloqueia. É a verificação que não é bloqueadora para ver se uma próxima chamada futura pode obter entrada sem bloquear.

... embora eu reconheça que o documentação pode ser facilmente interpretado para dar essa opinião, e o próprio nome implica que deve ser usado para esse fim. A citação relevante, com ênfase adicionada:

Os próximos métodos () e hasnext () e seus métodos complementares do tipo primitivo (como NextInt () e HasNextInt ()) Primeiro pule qualquer entrada que corresponda ao padrão delimitador e depois tente retornar o próximo token. Tanto o HasNext quanto os próximos métodos podem bloquear a espera por mais informações. Se um método HasNext blocos não tem conexão se o próximo método associado será bloqueado ou não.

É um ponto sutil, com certeza. Ou dizendo "ambos a Hasnext e os próximos métodos ", ou" HasNext () e Next () "teriam implícito que os métodos complementares agiriam de maneira diferente. Mas, visto que estão em conformidade com a mesma convenção de nomenclatura (e a documentação, é claro), é razoável Espere que eles agem da mesma forma, e hasNext ()diz claramente que pode bloquear.

META NOTA: Isso provavelmente deve ser um comentário para a postagem incorreta, mas parece que, como um novo usuário, só posso postar essa resposta (ou editar o wiki que parece ser preferido para alterações sistematizadas, não as de substância).

Variáveis ​​de sinalização são muito propensas a erros para serem usadas.Use controle de loop explícito com comentários.Também, hasNextInt() não bloqueia.É a verificação sem bloqueio para ver se um futuro next a chamada pode obter entrada sem bloqueio.Se você quiser bloquear, use o nextInt() método.

// 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top