1

I have the following code call it code#1

Scanner keyboard = new Scanner(System.in);
String s = keyboard.nextLine();
int x = keyboard.nextInt();
double y = keyboard.nextDouble();
System.out.println("String: "+s);
System.out.println("Double: "+y);
System.out.println("Int: "+x);

If I enter

Hello World
12.1
12 

The output will be

String: Hello World
Double: 12.1
Int: 12

However, If I rearrange my code, call it code#2, as

Scanner keyboard = new Scanner(System.in);
int x = keyboard.nextInt();
double y = keyboard.nextDouble();
String s = keyboard.nextLine();
System.out.println("String: "+s);
System.out.println("Double: "+y);
System.out.println("Int: "+x);

and I enter

12
12.1

the compiler skips the string input and outputs

String:
Double: 12.1
Int: 12 

This is odd to me. I was taught compilers always read from top to bottom. I imagine the compiler reads code#2 as

int x = keyboard.nextInt();

first and waits for the user to enter an integer so it can assign it to x. Then reads

double y = keyboard.nextDouble();

waiting for the user to enter a double so it can be assigned to y. It then finally reads

String s = keyboard.nextLine();

and waits for the user to enter a string so it can assign it to s. In fact, to me, this how the compiler read code#1 and the output is desired. This seems like a subtle difference, rearranging the variables, but then why are the outputs so different?

Andy Thomas
  • 78,842
  • 10
  • 93
  • 142
Diehardwalnut
  • 288
  • 2
  • 7
  • You change the order of which value you ask for first and you expect it to work the same way? I'm missing something here... – Juan Mendes Sep 30 '15 at 19:36
  • You're also confusing the _compiler_, which parses the source code and produces a binary, with the _runtiime_, which executes the code (note the "runtime" could be the physical cpu, as in a C program, but for Java it's the JVM). If I wrote a compiler that read the source file from the end to the start, it would (should) have no effect on the _order of execution_. – Stephen P Sep 30 '15 at 22:38

2 Answers2

4

It's not the compiler. And it's not the order of variable declarations. It's the order you read from the input stream.

In the second case, you read an int, a double, and a line. And this is exactly what it does.

 int x = keyboard.nextInt();       // Reads "12"
 double y = keyboard.nextDouble(); // Reads "12.1"
 String s = keyboard.nextLine();   // Reads the remainder of the "12.1" line.

As a side issue, note that the "next line" in the input is the remainder of the "12.1" line after "12.1" is read. This is described in more detail in the question "Scanner is skipping nextLine() after using next(), nextInt() or other nextFoo() methods".

Community
  • 1
  • 1
Andy Thomas
  • 78,842
  • 10
  • 93
  • 142
1

I'm writing this quickly so sorry if I have mistakes or am unclear. Just let me know.

The issue here is the Scanner, not the compiler. The scanner reads text that it has access to in the manner in which you request it to do so.

When you use the nextLine() method, you are asking the Scanner to read from the current location of the cursor to the end of the line OR get a new line of text if there is no current text being referenced to.

get new text from the keyboard since there is no text currently in the Scanner object. Then read the whole text that was received from the keyboard and return it as a String to the caller. Since the whole line was read, the Scanner assumes you don't need it anymore if you call a new next***() method.

String s = keyboard.nextLine(); 

get new text from the keyboard since there is no text currently in the Scanner object.Then read the first text that is parsable as an int from the text received from the keyboard and return it as an int to the caller. The problem is, this is basically what the Scanner sees when you input text "12.1\n". As you know, the "\n" is a symbol for a return (like pushing enter to get to a new line). This means that your Scanner's cursor is now at the position right after the int you entered but still has the "\n" to read.

Example: "12.1*\n" //the * indicates the position of the cursor

int num = keyboard.nextInt();

get new text [/code] So when we now call nextLine() again, it will read the rest of the current line. Not requiring any input from the user because the Scanner still had text to read.

s = keyboard.nextLine();

For a beginner, simply add a keyboard.nextLine() after each nextInt/Double/etc to finish reading the line. I am not saying that this is the "right" way to do things but for a beginner it is perfect.

String s = keyboard.nextLine();
int num = keyboard.nextInt();
//read to end of Scanner object's text to "reset" it
keyboard.nextLine();
//get text normally
s = keyboard.nextLine();
sauv0168
  • 97
  • 8