Problema de iniciante com a classe Scanner.

1. Problema de iniciante com a classe Scanner.

rob
robgeek

(usa Debian)

Enviado em 30/05/2018 - 11:31h

Bom dia!

Sou iniciante em Java e estou tentando aprender a classe Scanner, mas tem algumas coisas que não consigo entender:
Considerem o código abaixo:
import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

while(true) {
if(scanner.hasNextInt()) {
System.out.println("valor digitado: " + scanner.nextInt());
break;
}
else {
System.out.println("digite um numero inteiro");
}
}

}
}


1- Por que ele está bloqueando e esperando um entrada em scanner.hasNextInt() sendo que na documentação não diz que ele vai bloquear?
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#hasNextInt--

2- Por que ele está entrando em loop infinito quando eu digito um caracter ou número com ponto(número float/double)? Parece que scanner.hasNextInt() só bloquea esperando uma entrada do teclado na primeira vez e depois não espera mais. Não estou entendendo isso.

3- Como eu faço para arrumar isso? Eu quero que ele fique pedindo para o usuário digitar um número inteiro até que ele realmente digite e então termine.


  


2. Re: Problema de iniciante com a classe Scanner.

Perfil removido
removido

(usa Nenhuma)

Enviado em 30/05/2018 - 13:47h

1) Ele não está bloqueando em "scanner.hasNextInt()", mas sim em "new Scanner(System.in)";

2) O scanner é inicializado em "new Scanner(System.in)". Quando você digita o valor, ele entra no loop com o mesmo valor sempre.

3) Isso parece ser algum exercício, então não vou te dar a solução. Apenas entenda que é em "new Scanner(System.in)" que ele bloqueia e só vai adiante quando um valor é digitado, por isso é que deve ficar dentro do loop.

Ps.: não se esqueça de fechar o scanner.


3. Re: Problema de iniciante com a classe Scanner.

rob
robgeek

(usa Debian)

Enviado em 30/05/2018 - 17:54h

Olha, eu acho que ele para ali sim. Veja o código abaixo:
import java.util.Scanner;

public class Test {
public static void main(String[] args) {
System.out.println("teste-01");
Scanner scanner = new Scanner(System.in);

System.out.println("teste-02");
while(true) {
System.out.println("teste-03");
if(scanner.hasNextInt()) {
System.out.println("teste-04");
System.out.println("valor digitado: " + scanner.nextInt());
break;
}
else {
System.out.println("digite um numero inteiro");
}
System.out.println("teste-05");
}

}
}

A saída é:
teste-01
teste-02
teste-03
5 // número que eu digitei
teste-04
valor digitado: 5

Portanto você pode ver que ele passa do "new Scanner(System.in)" e para no if.

Não é exercício, mas ok. A gente já passou desse conteúdo na faculdade, mas o professor explicou isso aí meio "por cima". Ele deu o método todo pronto, parecido com esse que eu postei, e indiretamente falou:
- Façam assim que funciona.

Então estou tentando refazer eu mesmo, mas empaquei nessa parte.



4. Re: Problema de iniciante com a classe Scanner.

Perfil removido
removido

(usa Nenhuma)

Enviado em 30/05/2018 - 20:19h

Ele bloqueia exatamente onde falei, por isso ele deve estar dentro do loop e por isso seu código não funciona.

Faça isso:

do {
System.out.println("digite um numero inteiro");
Scanner scanner = new Scanner(System.in);

if(scanner.hasNextInt()) {
System.out.println("valor digitado: " + scanner.nextInt());
break;
}

} while (true);


Dica: nunca use saídas de texto para testar pois elas podem facilmente te enganar. Ao invés disso, use um depurador de código.


5. Re: Problema de iniciante com a classe Scanner.

Paulo Dias
di4s

(usa XUbuntu)

Enviado em 06/06/2018 - 17:06h

hcabzlus escreveu:

Ele bloqueia exatamente onde falei, por isso ele deve estar dentro do loop e por isso seu código não funciona.

Faça isso:

do {
System.out.println("digite um numero inteiro");
Scanner scanner = new Scanner(System.in);

if(scanner.hasNextInt()) {
System.out.println("valor digitado: " + scanner.nextInt());
break;
}

} while (true);


Dica: nunca use saídas de texto para testar pois elas podem facilmente te enganar. Ao invés disso, use um depurador de código.


Oi pessoal.

Hcabzlus, desculpe, mas eu acredito que isso não está correto.

A parada ( para leitura do stdin ) não ocorre na linha:


Scanner scanner = new Scanner(System.in);


Também acho que instanciar o scanner dentro do loop é uma má prática... Dessa forma, você cria diversos objetos da classe Scanner de forma desnecessária.

Robgeek, penso que a parada ocorre porquê você criou o Scanner passando o System.in, que é, de forma genérica, a entrada padrão, na maioria das vezes, o teclado... Quando você chama o método hasNextInt(), sem ter feito nenhuma leitura antes, a entrada padrão precisa ser lida para só depois ser avaliada...

Veja que usando um arquivo para criar o Scanner essa parada não acontece:


import java.util.*;
import java.io.*;

public class Teste {

public static void main(String[] args) throws Exception {

Scanner scanner = new Scanner( new File( "numeros" ));

while(true) {
if(scanner.hasNextInt()) {
System.out.println("valor digitado: " + scanner.nextInt());
break;
}
else {
System.out.println("digite um numero inteiro");
}
}
}
}


Você pode criar o arquivo "numeros" com o seguinte comando no terminal :


echo {1..100} > numeros


Já o fato de acorrer um loop quando um caractere é digitado, penso que seja porquê não é feita nenhuma leitura quando o método hasNextInt() retorna false, ou seja, o caractere continua lá e o retorno continua sendo false, veja:


public static void main(String[] args) {
System.out.println("teste-01");
Scanner scanner = new Scanner(System.in);

System.out.println("teste-02");
while(true) {
System.out.println("teste-03");


Na próxima linha o método hasNextInt() é chamado e espera uma entrada. Se essa entrada for do tipo int, é retornado true senão, é retornado false.

if(scanner.hasNextInt()) {
System.out.println("teste-04");
System.out.println("valor digitado: " + scanner.nextInt());
break;
}


Se você digita um char ou um float, o retorno é false e a execução vai para o bloco else...

Nesse bloco, nenhuma leitura com Scanner acontece e o while é executado novamente, onde o método hasNextInt() é chamado outra vez e avalia o mesmo char ou float que foi inserido na primeira interação... Como o retorno desse método vai ser sempre false, a execução nunca entra no bloco if onde está a instrução break.


else {
System.out.println("digite um numero inteiro");
}
System.out.println("teste-05");
}

}



Veja que limpando( fazendo a leitura de uma linha com o Scanner ) no bloco else, o loop não acontece:



import java.util.*;
import java.io.*;

public class Teste {

public static void main(String[] args) throws Exception {

Scanner scanner = new Scanner( new InputStreamReader(System.in) );

while(true) {

if(scanner.hasNextInt()) {
System.out.println("valor digitado: " + scanner.nextInt());
break;
}
else {
//usado para limpar
scanner.nextLine();

System.out.println("digite um numero inteiro");
}
}

}
}



Linux Professional Institute - LPIC-1
Novell Certified Linux Administrator - CLA
Oracle Certified Associate, Java SE Programmer - OCA

http://twitter.com/p4ulodi4s
http://www.prminformatica.com.br/






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts