views:

204

answers:

4

As an exercise for my Java course in Uni this morning, I had to write a small program to ask the user to input some details, then print them back. I've since finished writing it, but I ran into a strange problem along the way.

See the code below:

import java.util.Scanner;

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

        int accountId;
        String accountName;
        float accountBalance;

        System.out.println("Account ID: "); //Line 13
        accountId = keyboardIn.nextInt(); //Line 14

        System.out.println("Account name: "); //Line 16
        accountName = keyboardIn.nextLine(); //Line 17

        System.out.println("Account balance: ");
        accountBalance = keyboardIn.nextFloat();
    }
}

When this program runs, line 17 (refer to comments) is skipped; Account name: is printed, but the user is not given the opportunity to enter the information, as if that line of code was commented out. No errors are thrown. The output looks like this:

Account ID:
2
Account name:
Account balance:

However, if I switch lines 13 and 14 with 16 and 17, like as follows, the program runs fine, and no lines are skipped.

System.out.println("Account name: "); //Line 16
accountName = keyboardIn.nextLine(); //Line 17

System.out.println("Account ID: "); //Line 13
accountId = keyboardIn.nextInt(); //Line 14

Why is the line 17 being skipped in the first case, but not the second?

If it's somehow relevant, I am using JDK 6 Update 18, and TextPad 5.3.1.

+5  A: 

NextInt() merely consumes the integer value. Once the method is sure that the input being entered is a complete number it exits without consuming the characters produced your return key press. When you call NextLine() it sees the return characters in the buffer and immediately returns a zero length string.

To deal with this I recommend you always use NextLine(). Command line users are very used to the return key being the "enter value" key. Parse the results of NextLine() as an integer by using Integer.valueOf(result).

Spencer Ruport
+4  A: 

A look at the javadoc should show you why.

Scanner.nextLine() skips to the end of the current line, and returns whatever it skipped. Since the user has already input some data, this function will return what ever is left in the input stream. When you switch the order around, it doesn't yet have any input, which is why you see it ask for input.

The important part:

This method returns the rest of the current line, excluding any line separator at the end.

a_m0d
Thanks, that clears it up. I should have referred to the documentation in the first place.
Auguste
@Auguste you live and you learn! +1 for trying to do your homework and asking a reasonable question!
Lirik
+1  A: 

From this thread:

The reason it gives you trouble is because when the user enters an integer then hits enter, two things have just been entered: the integer and a "newline" which is \n.
The method you are calling, "nextInt", only reads in the integer, which leaves the newline in the input stream.
But calling nextLine() does read in newlines, which is why you had to call nextLine() before your code would work.
You could have also called next(), which would also have read in the newline.

VonC
A: 

Scanner.nextInt catches the first integer occurrence and nothing else, so it doesn't handle the new line character, which Scanner.readLine will see as its input. You could add a Scanner.next() in between which would consume the new line character, but this solution has its own downsides.

My solution would be to read all of the user's input with Scanner.readLine and parse the desired results from the Strings.

ponzao