coder008 coder008 - 2 months ago 9
Java Question

Strange output when I read from scanner

I'm trying to create a videoStore with the basic CRUD operation. For creating each movie I need to read the title, the year and the gender as below:

System.out.print("name: ");
name = in.nextLine();
System.out.print("year: ");
year = in.nextInt();
in.nextLine();
System.out.print("gender: ");
gender = in.next();


When I enter the addMovie option, I get this print on the console

(name: year:)


Can someone explain to me why it happens as above?

Here is the rest of the method:

static ArrayList<Movie> movies = new ArrayList<Movie>();
static Scanner in = new Scanner(System.in);

public static void InserirFilme() {
String name;
int year;
String gender;
boolean existe = false;
System.out.print("name: ");
name = in.nextLine();
System.out.print("year: ");
year = in.nextInt();
in.nextLine();
System.out.print("gender: ");
gender = in.next();

Movie movie = new Movie(name, year, gender);
for(Movie m: movies)
{
if(movie == m)
{
existe = true;
}
}

if(!existe)
{
movies.add(movie);
}
else
{
System.out.println("the movie already exists in the videoStore");
}
}

Answer

You run this method in loop (right?)
The first call reads input correctly, but it leaves the linebreak in System.in after the last in.next().
On next call the name: is printed, then scanner reads an empty string from System.in because the linebreak already exists here.
And after thet the year: is printed on the same line because no new linebreaks are entered.

So you just have to insert another in.nextLine() after reading gender (or genre :) )
Or use nextLine() for read genre instead of next(), because genre might have more than one word.

But there are some disadvantages with using fake nextLine() to 'eat' linebreak - there might be another text which you doesn't process. It's a bad practice - to loose the data user entered.
It is better to read all the data from line, then validate/parse it, check isn't there some extra data, and if the data is invalid show notification and let him try to enter the right value.

Here are some examples how to deal with user input manually - http://stackoverflow.com/a/3059367/1916536. This is helpful to teach yourself.
Try to generalize user input operations:

name = validatedReader.readPhrase("name: ");
year = validatedReader.readNumber("year: ");
genre = validatedReader.readWord("genre: ");

where ValidatedReader is a custom wrapper for Scanner which could use your own validation rules, and could gently re-ask user after a wrong input. It could also validate dates, phone numbers, emails, url's or so

For production purposes, it is better to use validation frameworks with configurable validation rules. There are a lot of validation frameworks for different purposes - Web, UI, REST etc...