• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Dani

Dúvida básica com o scanner

10 mensagens neste tópico

Olá boa noite a todos. Estou a iniciar-me no Java e por isso estou a fazer os programas mais simples.

Daí ter escolhido um programa que o que faz é pedir o nome do utilizador e devolvê-lo:

 public static void main(String[] parametros) {

    	Scanner teclado = new Scanner(System.in);
    	
        System.out.print("Introduza o seu nome: ");
        
        String nome = teclado.nextLine();
        
        System.out.println("Olá " + nome);
    }

Acontece que se eu escolhe como nome "ola" aparece-me o seguinte na conseola:

Olá þa

Gostava de saber o porquê e maneira de o remdiar.

Obrigado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Um objecto Scanner, construído como o tens no código, o que faz é usar os bytes da stream passada e convertê-los para caracteres usando o encoding da plataforma, dessa forma, a única razão para o problema que mencionaste é o facto de estares a escrever num encoding diferente do que está a ser usado pelo Scanner ou de existirem bytes no buffer que estejam a causar problemas de conversão.

Não tenho usado o Scanner para esse tipo de código, a classe tem como objectivo o parsing de texto usando expressões regulares, o que não é o caso de uma simples leitura de texto, por isso não estou a ver como possas resolver o problema, ou até se o problema está mesmo relacionado com o que indiquei acima. Mas dado que estás a construir o objecto com uma stream de entrada, o único ponto onde vejo que possa estar o problema é no conteúdo dessa stream.

Verifica se o teu teclado está de acordo com o encoding usado pela plataforma, que deverá ser o do teu sistema operativo, se a consola onde estás a escrever os dados está também a usar o encoding certo, etc.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigado pela resposta Knitter. Não sei se é do encoding do eclipse, mas suponho que sim. Como não descobri onde se muda o enconding decidi experimentar o NetBeans. No NetBeans já não tive problemas de encoding e tudo me corre bem.

No entanto ao fazer mais um programa simples tenho novo problema:

Scanner teclado = new Scanner (System.in);

	System.out.println("Introduza o seu nome: ");
	String nome = teclado.nextLine();

	System.out.println("Introduza o seu telefone: ");
	int telefone = teclado.nextInt();

	System.out.println("Introduza o seu morada: ");
	String morada = teclado.nextLine();


	System.out.println("O nome que introduziu foi: " + nome );
	System.out.println("O telefone que introduziu foi: " + telefone );
	System.out.println("O e-mail que introduziu foi: " + morada );

O que acontece é que quando é introduzo o mail este não fica registado na variável morada. Ao fazer o debug verifico que as outras variáveis ficam bem preenchidas mas a morada fica com o valor "".

Se alguém me puder esclarecer novamente agradeço.

Só mais uma questão, como fazer um \n num System.out.println ?

Obrigado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Essa é simples de esclarecer :D, estás a ter um problema com alguns efeitos secundários de usar um Scanner, como disse antes, o Scanner é criado para fazer parsing de texto e é muito bom para isso, podemos considerar que ler dados de consola é parsing de texto, mas depois temos estes pequenos problemas :thumbsup:

O problema está no método nextLine depois do nextInt. Se leres a documentação do método nextLine, ficas a saber que o método avança para a próxima linha e devolve a linha "comida", isto é, o método vai avançando, caracter a caracter, até encontrar um caracter de mudança de linha quando o encontra, coloca um ponteiro para a posição seguinte ao delimitador, que é a linha a seguir, e devolve todo o texto que processou até chegar ao delimitador.

O nextInt não faz isso, na verdade o nextInt não consome o delimitador, ele vai ler um conjunto de caracteres que representem um inteiro, e caso tenha sucesso, devolve esse inteiro mas deixa o delimitador na stream e não muda de linha.

Resultado, se analisarmos o comportamento de teu código vemos que:

  • o primeiro nextLine obtém uma linha e consome o '\n'
  • o nextInt obtém um inteiro e não consome o '\n'
  • o segundo nextLine vai ler tudo até ao '\n', que já se encontra no buffer porque o nextInt não o removeu, resultado, o método encontra o caracter que estava à procura e não precisa de mais nada, devolver "", uma vez que só existia o delimitador, para o Scanner, isso é uma string vazia

A forma simples de resolver o problema será invocar o método nextLine logo após à invocação do nextInt, o que vai resultar no consumo dos dados que se encontram a mais dentro do buffer.

O problema que estás a ter é de que existem dados dentro do buffer que não foram lidos pelo nextInt, ao invocares o nextLine esses dados vão ser lidos, esta é uma das razões pelas quais não gosto de usar Scanner para ler dados do teclado, não é simples trabalhar com o buffer interno, para, por exemplo, remover dados que não interessam, ou  limpar o buffer.

O seguinte código dá a volta ao problema:

Scanner teclado = new Scanner (System.in);

System.out.println("Introduza o seu nome: ");
String nome = teclado.nextLine();

System.out.println("Introduza o seu telefone: ");
int telefone = teclado.nextInt();		
teclado.nextLine(); //Linha adicionada para remover o '\n' que está no buffer e que causa problemas.
System.out.println("Introduza o seu morada: ");
String morada = teclado.nextLine();

System.out.println("O nome que introduziu foi: " + nome );
System.out.println("O telefone que introduziu foi: " + telefone );
System.out.println("O e-mail que introduziu foi: " + morada );

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Muito obrigado knitter, a tua ajuda tem sido fundamental nestes primeiros passos no Java  :P

De agora em diante tenho de me habituar a ler a API.

Só mais duas questões. Estava à procura de um livro para me iniciar no Java e pareceu-me que o TIJ era o mais indicado, concordas, ou recomendas outro?

Que usas em vez do Scanner?

Obrigado mais uma vez

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Existem vários tipos de streams de leitura, depende do que se pretende por isso não te posso dar uma alternativa directa ao Scanner, até porque ler dados da consola como estás a fazer não é comum, isso são coisas que se fazem quando estamos a aprender, mas na realidade têm uma utilidade limitada.

Assim, desde que percebas porque é que esses problemas existem e saibas como os resolver, neste momento serve, depois podes aprender mais sobre streams, mas uma coisa de cada vez :P

Sim, ler a API é uma das coisas que se deve fazer sempre, a documentação do Java é bastante boa e está acessível no IDE que está a usar de forma bastante simples.

O TIJ é um bom livro no sentido em que te ensina a linguagem e o paradigma de Programação Orientada a Objectos, não quer dizer que outros livros não o façam, mas eu nunca encontrei um que o fizesse do mesmo modo que o TIJ. Mas neste caso é complicado, porque cada um de nós se adapta melhor a tipos de livros diferentes e formas de ensinar diferentes, eu gostei bastante desse livro.

Outro que uso para tirar dúvidas sempre que elas aparecem é o Java Tutorial, do qual podes fazer download gratuitamente, http://java.sun.com/docs/books/tutorial/. Podes usar o link que está na lateral direita, "Really Big Index", que te mostra um índice mais útil :P

Devo avisar que o Java Tutorial é algo que está em constante alteração e de tempos a tempos surgem alguns erros no tutorial. Além disso, o tutorial, por ser criado pela Sun, usa em muitos exemplos a tecnologia standard do Java mas disponível apenas no JDK da Sun, ou outras ferramentas desenvolvidas sub o patrocínio da Sun, como é o caso do NetBeans IDE.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem tenho uma nova dúvida  :down:

Eu queria fazer um exercício "clássico" que consiste em dado um certo input pelo utilizador o programa contar o número de espaços, linhas e palavras. O problema reside no facto de não encontrar um método para ignorar o \n, ou seja no máximo consigo fazer a contagem para apenas uma linha. Já tentei mudar o delimitador e também não consegui.

Será que alguém me consegue ajudar? Obrigado desde já

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem tenho uma nova dúvida  :down:

Eu queria fazer um exercício "clássico" que consiste em dado um certo input pelo utilizador o programa contar o número de espaços, linhas e palavras. O problema reside no facto de não encontrar um método para ignorar o \n, ou seja no máximo consigo fazer a contagem para apenas uma linha. Já tentei mudar o delimitador e também não consegui.

Será que alguém me consegue ajudar? Obrigado desde já

Se estiveres a guardar o input numa string, podes usar o metodo chatAt(i) para percorrer cada caracter na string e ir contando.

Se o input for um ficheiro usas o metodo hasNext() do scanner num while para percorrer todas as linhas e contá-las, e por cada linha usas o charAt(i) para contar o resto.

Pelo menos assim rapidamente é a solução que encontro.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigado pela resposta Conde.

Pois a forma de fazer também consegui fazer.

Até agora consigo contar palavras e espaços, o problema está na forma de contar linhas. Isto porque pelo o que vi o Scanner não permite receber várias linhas, era este problema que estava a tentar solucionar.

Cumps

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Os métodos que estás a usar do Scanner não permitem que contes várias linhas, isto porque o input termina com um "enter" e isso é apenas uma linha. Estou a supor que estás a usar código parecido com o que mostraste anteriormente, e dessa forma não será possível.

Se estiver enganado, e não estiveres a ler o input como indicaste acima, o Scanner poderá servir, depende da forma como pretendes contar as linhas, mas uma forma simples é contares quantos nextLine() ocorrem, isso dá-te o número de linhas.

Se puderes mostrar algum código dava mais jeito para saber como estás a fazer e aí tentar responder de acordo com o teu trabalho.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora