Sign in to follow this  
nilkn

Java Scanner Vagueness

Recommended Posts

I'm needing to do some console work in Java, but I can't seem to figure out the general behavior of the Scanner class, and the Java documentation is vague. What, exactly, do the the Scanner.hasNext() and Scanner.hasNextDouble() methods do? If hasNextDouble() is called once and then nextDouble() is called, it waits for the user to enter input and checks if the input string could be interpreted as a double. Investigation reveals that, if hasNextDouble() is called repeatedly in an infinite loop, as long as the user enters a double, it will block at the next iteration, but if the user enters anything that's not a double, it will never block again. In this case, the hasNext() method must be used. It successfully makes the program wait for input at each iteration of the loop. But then is the method name not completely vacuous? If it waits for the user to enter input, obviously it will always return true. The name therefore implies there are circumstances under which it will not wait for the user to enter input, but what are these? I don't know, and the documentation doesn't seem to know either; it merely states that "this method may block while waiting for input to scan." And why does it block in this case and not others? Thanks in advance.

Share this post


Link to post
Share on other sites
I think whether or not the Scanner blocks is dependant on whether or not the source you give it blocks. For example if you pass in System.in then the scanner will block and wait for user input. Alternatively if you give it a File or String, which don't block, then neither will the Scanner.

Share this post


Link to post
Share on other sites
This is all using System.in as the input stream to the Scanner object, and it still demonstrates the behavior above.

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
This is all using System.in as the input stream to the Scanner object, and it still demonstrates the behavior above.


The specific behaviour you're seeing is precisely because the stream is System.in. And the Java documentation is being as precise as it can be, without going into details about what streams are, which are beyond the scope of class documentation. You are supposed to understand this stuff already. :) So let's take a closer look:

Quote:
Original post by nilkn
I'm needing to do some console work in Java, but I can't seem to figure out the general behavior of the Scanner class, and the Java documentation is vague.

What, exactly, do the the Scanner.hasNext() and Scanner.hasNextDouble() methods do? If hasNextDouble() is called once and then nextDouble() is called, it waits for the user to enter input and checks if the input string could be interpreted as a double. Investigation reveals that, if hasNextDouble() is called repeatedly in an infinite loop, as long as the user enters a double, it will block at the next iteration, but if the user enters anything that's not a double, it will never block again.


Because there is data, but that data is not a double. It doesn't throw that data away, because you might want to use it for something else. It doesn't block, because it can tell right away that the upcoming data isn't a double, because it already sees that data.

Quote:
In this case, the hasNext() method must be used. It successfully makes the program wait for input at each iteration of the loop. But then is the method name not completely vacuous? If it waits for the user to enter input, obviously it will always return true.


If the input comes from somewhere that could be entered by the user, then yes. Sort of. At the DOS command prompt, for example, a control-Z character fed to the program is interpreted as the "end of file" for the standard input. Similarly control-D under Linux.

Quote:
The name therefore implies there are circumstances under which it will not wait for the user to enter input, but what are these?


When the underlying data source already has data available.

Consider that a DOS or Linux console will normally line buffer the user's input. This is very useful: it allows, for example, for the user to edit input with the backspace key. If you received every character as the user typed it, you would have to do that processing yourself (cancelling ASCII 8 against the previous character, in a way that is clever enough to handle multiple backspaces and also backspacing past the beginning of the line).

If your program asks for doubles in a loop, and the user types three valid doubles separated by spaces, and then hits return, the loop will execute three times before it has to block again. This is because the whole line of text because available to be "scanned" at once, so hasNextDouble() is able, three times, to find a double (and also to know that the available data isn't merely the prefix of a double that the user isn't finished typing yet).

Share this post


Link to post
Share on other sites
Thanks for the information, Zahlman.

Quote:
Original post by Zahlman
You are supposed to understand this stuff already. :)


I'm a tad rusty with console I/O, as you can tell. Further, I've never done any sort of console work in Java before, nor have I used the Scanner class before, so I'm just getting used to its behavior using different sorts of input streams.

I did some more investigation into the behavior of hasNextDouble() because what you said initially didn't mean much to me.

The following is an example that illustrates the idea I was describing in the original post:


Scanner keyboard = new Scanner(System.in);
boolean inputValid = false;
double num = 0.0;

while (!inputValid)
{
if (keyboard.hasNextDouble())
{
num = keyboard.nextDouble();
inputValid = num > 0;
}
}



This code should demonstrate the mentioned behavior. It turns out that hasNextDouble() never advances past any input, and nextDouble() does. So, if the user enters 'a', for example, then hasNextDouble() will return false, nextDouble() won't be called, and the scanner will not advance beyond the 'a', so that at the next iteration of the loop the character 'a' will be processed again, and the whole process will repeat, resulting in an infinite loop.

[Edited by - nilkn on September 17, 2008 12:41:30 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
I did some more investigation into the behavior of hasNextDouble() because what you said initially didn't mean much to me.

The following is an example that illustrates the idea I was describing in the original post:

*** Source Snippet Removed ***

This code should demonstrate the mentioned behavior. It turns out that hasNextDouble() never advances past any input, and nextDouble() does. So, if the user enters 'a', for example, then hasNextDouble() will return false, nextDouble() won't be called, and the scanner will not advance beyond the 'a', so that at the next iteration of the loop the character 'a' will be processed again, and the whole process will repeat, resulting in an infinite loop.


Er, yes; that's exactly as advertised, and as I thought I described. The reason the has() functions exist is so you can "look before you leap". Because they don't leap, you have to do something before looking again, if you expect to see anything different.

Share this post


Link to post
Share on other sites
Yes, it is what you described. Your initial explanation was a bit general for my taste; hence, "what you said initially didn't mean much to me." The prior post was the result of my applying it to the specific situation at hand.

I can see, of course, exactly what you meant in retrospect, but sometimes it's hard to make such a leap without a practical connection first. You should keep in mind that I've never, in my life, used Java's methods for console I/O, nor have I done much with console I/O in general in any language. I have much programming experience, but it's not in this area.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this