Exercício 3.14: (Employee Class) | Método nextLine não funciona após método nextDouble

3 respostas
Zignd

Olá, gostaria de uma ajuda se possivel, estou resolvendo um exercício do livro Java How to Program 9th Edition - Deitel, e me deparei com o seguinte problema: O método nextLine que foi varias vezes utilizado é ignorado durante a execução do programa após a execução de um nextDouble. Gostaria de saber porque isso está acontecendo, a propósito o compilador não está retornando nem um erro.

A ideia é a seguinte: eu crio uma classe chamada Employee e depois uma outra chamada EmployeeTest para testar suas funcionalidades.

A linha que está sendo ignorada é a 34 do arquivo EmployeeTest.java.

Employee.java

// Ex. 3.14: Employee.java

public class Employee
{
	// instance variables
	private String name;
	private String lastName;
	private double monthlySalary;
	
	// constructor
	public Employee( String nam, String las, double mon )
	{
		name = nam;
		lastName = las;
		
		if ( mon >= 0.0 )
			monthlySalary = mon;
	}
	
	// method to set the name
	public void setName( String nam )
	{
		name = nam;
	} // end method setName
	
	// method to retrieve the name
	public String getName()
	{
		return name;
	} // end method getName
	
	// method to set the lastName
	public void setLastName( String las )
	{
		lastName = las;
	} // end method setLastName
	
	// method to retrieve the lastName
	public String getLastName()
	{
		return lastName;
	} // end method getLastName
	
	// method to set the monthlySalary
	public void setMonthlySalary( double mon )
	{
		if ( mon >= 0.0 )
			monthlySalary = mon;
	} // end method setMonthlySalary
	
	// method to retrieve the monthlySalary
	public double getMonthlySalary()
	{
		return monthlySalary;
	} // end method getMonthlySalary
} // end class Employee

EmployeeTest.java

// Ex. 3.14: EmployeeTest.java

import java.util.Scanner;

public class EmployeeTest
{
	public static void main( String[] args )
	{
		Employee employee1 = new Employee( "João", "Silva", 1200.00 );
		Employee employee2 = new Employee( "Maria", "Rocha", 1500.00 );
		Scanner input = new Scanner( System.in );
		
		// employee1
		System.out.printf( "employee1\n\nName: %s\nLast Name: %s\nMonthly Salary: %.2f\n",
			employee1.getName(), employee1.getLastName(), employee1.getMonthlySalary() );
		
		System.out.println( "\nModify employee1" );
		System.out.print( "Enter the new name for employee1: " );
		employee1.setName( input.nextLine() );
		System.out.print( "Enter the new last name for employee1: " );
		employee1.setLastName( input.nextLine() );
		System.out.print( "Enter the new monthly salary for employee1: " );
		employee1.setMonthlySalary( input.nextDouble() );
		System.out.println( "\nChanges applied.\n\n" );
		System.out.printf( "employee1\n\nName: %s\nLast Name: %s\nMonthly Salary: %.2f\n",
			employee1.getName(), employee1.getLastName(), employee1.getMonthlySalary() );
		
		// employee2
		System.out.printf( "\n\nemployee2\n\nName: %s\nLast Name: %s\nMonthly Salary: %.2f\n",
			employee2.getName(), employee2.getLastName(), employee2.getMonthlySalary() );
		
		System.out.println( "\nModify employee1" );
		System.out.print( "Enter the new name for employee2: " );
		employee2.setName( input.nextLine() ); // >>>> ESTA É A LINHA IGNORADA <<<<
		System.out.print( "Enter the new last name for employee2: " );
		employee2.setLastName( input.nextLine() );
		System.out.print( "Enter the new monthly salary for employee2: " );
		employee2.setMonthlySalary( input.nextDouble() );
		System.out.println( "\nChanges applied.\n\n" );
		
		System.out.printf( "employee2\n\nName: %s\nLast Name: %s\nMonthly Salary: %.2f\n",
			employee2.getName(), employee2.getLastName(), employee2.getMonthlySalary() );
	} // end main
} // end class EmployeeTest

3 Respostas

davidbuzatto

Isso acontece pela forma que o nextDouble (nextInt tbm) funcionam. Ao invocá-los eles não vão consumir a “linha” inteira do buffer, normalmente ficando o “\n” no buffer, ai as próximas chamadas não fazem o que você pensa que irão fazer.

Por exemplo, para uma entrada (\n é o pulo de linha):

2.5\n 5.7\n

Em duas invocações a nextDouble, acontecerá o seguinte:
Ler o primeiro double até chegar no separador (espaço ou pulo de linha).
Perceba que aqui o \n ainda não foi consumido.
Ler o próximo double. Aqui todos os separadores serão descartados até chegar em um double válido, que será lido até chegar em um outro separador.
Perceba que aqui o último \n ainda vai ficar no buffer.
Está percebendo? Fica “lixo” no buffer.

Agora outro exemplo:

2.5\n bla bla bla bla bla\n 5.7\n

Lê o double (fica o separador!!!)
Na hora de dar o nextLine dá problema, pois vai achar o pulo de linha no buffer, não lendo “nada” (lendo uma String vazia na verdade).
Na hora que der o proximo nextDuble não vai achar um double, mas uma String e uma exceção será lançada (InputMismatchException), pois a entrada (o primeiro bla) não é um double.

Para resumir, o que você deve fazer é:
Se o seu Scanner só for utilizar nextInt, nextDouble, sem problema, use-os.
Se o seu Scanner for utilizar o método nextLine, você só “pode” usar o nextLine sem misturar com os outros métodos, assim você não terá problema.
Agora você pergunta: Se eu só posso utilizar o nextLine no caso acima, como que eu leio um inteiro ou um double? Simples, faça a conversão usando o Integer.parseInt() ou o Double.parseDouble() no valor retornado da linha. Note que aqui você só poderá ter entradas em linhas e não diversas entradas em uma linha só como é possível ao utilizar o nextInt ou o nextDouble, pois o espaço é um dos separadores padrão deles.

Zignd

Valeu pela resposta David, me ajudou bastante. :slight_smile:

davidbuzatto

Disponha :wink:

Criado 30 de dezembro de 2012
Ultima resposta 30 de dez. de 2012
Respostas 3
Participantes 2