Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java ask me to hit Enter again?

I've been racking my brain for a while trying to understand how Scanner works. So here's the code:

Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String p = sc.nextLine();
System.out.println(s);
System.out.println(p);
System.out.println(sc.hasNextLine());

What I expect:

Love is good  <- press ENTER
Love is blind <- press ENTER
Love is good  <- output
Love is blind <- output
false

What I have:

Love is good   <- I press ENTER
Love is blind  <- I press ENTER
Love is good   <- output
Love is blind  <- output
<- press ENTER
true <- output

What I do not understand:

  1. Instead of immediate printing this line - System.out.println(sc.hasNextLine()); - it makes me to press ENTER again
  2. It prints true instead of false while there no more lines or symbols

What I have read: I have read a dozen of stackoverflow answers about using hasNextLine() after nextInt() and about how nextInt() does not consume the final symbol in the line but I don't understand why, even though I don't use nextInt() in here, I still need to press ENTER one more time and why hasNextLine() is true.

like image 972
alekscooper Avatar asked Jan 17 '16 09:01

alekscooper


People also ask

Why do I have to press Enter twice in Java?

The second ENTER is needed because the program executes aaa = kb. nextLine() and you have to put in something. But I'm not sure where you really want the "Would you like to play again" question, the kb. nextLine() , and the test for "n" .

How do I reopen a Java system?

It is not possible to reopen System.in , System. out or System. err . The underlying native streams are file descriptors that are connected to other processes, or to files whose identity your application cannot discern.

What does nextLine return in Java?

The nextLine() method of the java. util. Scanner class scans from the current position until it finds a line separator delimiter. The method returns the String from the current position to the end of the line.


4 Answers

Instead of Scanner use BufferedReader like so:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String s = reader.readLine();
        String p = reader.readLine();
        System.out.println(s);
        System.out.println(p);      
        System.out.println(reader.ready());
    }
}

For more reading into the matter, look here and here. As a rule of thumb, when you need parsing stuff (like nextInt) use Scanner, otherwise stick to BufferedReader. BufferedReader is a lot faster than Scanner too.

As for why you got that troublesome behavior, see the javadoc for Scanner.

The part that applies in your particular case is:

A scanning operation may block waiting for input.

What this means in your case is: after the first two lines are read by Scanner, the Scanner was waiting for input, caused by its method call sc.hasNextLine(). Then when Enter was hit, it got an input (hence it prints true, according to docs it returns true when there is input). As after the method call sc.hasNextLine() there are no more executable lines in your program, the program ends, giving the illusion that it required two enter hits.

like image 84
Sнаđошƒаӽ Avatar answered Oct 10 '22 05:10

Sнаđошƒаӽ


From the Scanner documentation (emphasis by me):

public boolean hasNextLine()

Returns true if there is another line in the input of this scanner. This method may block while waiting for input. The scanner does not advance past any input.

What's probably happening is that hasNextLine is blocking because it's waiting for input, which you give by pressing enter.

like image 30
Arc676 Avatar answered Oct 10 '22 04:10

Arc676


First of all you are using Scanner declared to System.in so this means you are asking .in to check if their is any more value so it waits for the user to input something and after you press enter it is obvious that it returns true.

So if you want to check s or p declare Scanner like this:

Scanner sc = new Scanner(s);

or

Scanner sc = new Scanner(p);

then check for sc.hasNextLine(); this should return false as much I know but for user input I would recommend to create another Scanner variable and then take values from the user and use sc for your hasNextline() thing.

I hope the very first logic helps you.

like image 10
Rohan Gill Avatar answered Oct 10 '22 04:10

Rohan Gill


You are asking for three lines of input!

Standard input always has one more line coming until you close the terminal. On a Unix system, you can probably press Ctrl+D at the end, and it will return flase (= input closed).

The program would behave as expected if you had a finite input. But interactive input: how does the program know the user does not intend to input Shakespeare next?

The function hasNextLine() will wait for new input to arrive (or for the signal that there cannot be new input). This function is not for "did the user already input another line" but instead means "wait for the next line". So for practical purposes, hasNextLine() is equivalent to "is the user input still connected, and could it eventually contain another line".

Why do you need that last line? Just remove it!

like image 9
Has QUIT--Anony-Mousse Avatar answered Oct 10 '22 04:10

Has QUIT--Anony-Mousse