aspose file tools*
The moose likes I/O and Streams and the fly likes Loop & System.in.read weirdness! Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » I/O and Streams
Bookmark "Loop & System.in.read weirdness!" Watch "Loop & System.in.read weirdness!" New topic
Author

Loop & System.in.read weirdness!

Ender Everett
Greenhorn

Joined: Mar 31, 2001
Posts: 19
Sorry, this will be a long post, perhaps...
I have run into a few strange issues with using loops and System.in.read(). I am getting multiple passes on loops that should only get one pass before any input (or at least they sure look like they should only be getting one pass to me...).
I will give three of my code examples and maybe someone can tell me why I'm getting such strange output.
first, this example, a simple for loop that is going to loop and ask for input until the correct character (in this case, "S") is entered:

OK, I would be expecting output something along these lines...

But instead I get this!!!

If I press ENTER it loops twice, not once, before prompting me again. If I enter a wrong character, it loops thrice! Why is this? How can I prevent it?
Here is another example of odd output in a somewhat similar program.

OK, this one does a very similar thing. Three loops when I press a character, two loops if I press enter.
Now something that confuses me a little more, but also makes me wonder if it is line buffered input is this program, which works just fine:

OK, this one gives me PERFECTLY normal output. Only one prompt and one pass per entry. Nothing weird here. In this one I added an exclusion for line feeds and carriage returns. I suspect these are the culprits in AnnoyingForProg and AnnoyingDWhileProg, but I am not 100% certain. Could some Java guru give me a hand here and explain what's going on?
Thanks a million, and again, sorry for the excessively long post.
-Ender
[This message has been edited by Ender Everett (edited June 01, 2001).]


Don't sweat the petty stuff, just pet the sweaty stuff.
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
This is NOT too long. It was just long enough to completely and clearly explain the situation.
Well, there seems to be some overhead associated with the InputStream, and that overhead is exactly 2 statements long.
If you hit enter - you loop 2 times.
If you enter 1 char - you loop 1 + 2 times.
If you enter 2 char - you loop 2 + 2 times.
If you enter 3 char - you loop 3 + 2 times. Etc.
However if you enter the required character - it terminates immediately, so the overhead is AFTER the char read.
That would support your theory that the 2 extra loops are for the slash and command in \n or \r.
However, since this is basically an IO question, I will move it over to that forum and see what kind of answers you get there.

"JavaRanch, where the deer and the Certified play" - David O'Meara
Bryan Fagan
Greenhorn

Joined: Feb 26, 2001
Posts: 17
Ender:
Your program is working correctly. Since this is a console application, every time you hit enter it prints the character entered plus the carriage return and line feed. For example, if you entered 'S' and hit return, it would look like this:
S\r\n
So, your suspicions were correct. It was the '\r' and '\n' that caused your problem.
When you were hitting a character your program logged three passes. One for the character 'S', one for the carriage return '\r', and, finally, one for the line feed '\n'.
I took your code and altered it a bit.
You simply make sure you are processing only the chars you are interested in and ignore the rest. I saw that you did this in some of your other code. See the code below:
// Begin irritating program # 1
import java.io.*;
class AnnoyingForProg
{
public static void main(String args[]) throws java.io.IOException
{
int i = 0;
char c;
System.out.println("Press S to stop.");

while( ( c = ( char )System.in.read() ) != 'S' )
{
if( (c >= 'a' && c <= 'z' ) | | ( c >= 'A' && c <= 'Z' ) )
{
i++;
System.out.println("Pass # " + i);
}
}
}
}// End first irritating prog.
Looks like you are already on the right track.
Happy programming!!
-Bryan

OK, I would be expecting output something along these lines...

But instead I get this!!!

If I press ENTER it loops twice, not once, before prompting me again. If I enter a wrong character, it loops thrice! Why is this? How can I prevent it?
Here is another example of odd output in a somewhat similar program.

OK, this one does a very similar thing. Three loops when I press a character, two loops if I press enter.
Now something that confuses me a little more, but also makes me wonder if it is line buffered input is this program, which works just fine:

OK, this one gives me PERFECTLY normal output. Only one prompt and one pass per entry. Nothing weird here. In this one I added an exclusion for line feeds and carriage returns. I suspect these are the culprits in AnnoyingForProg and AnnoyingDWhileProg, but I am not 100% certain. Could some Java guru give me a hand here and explain what's going on?
Thanks a million, and again, sorry for the excessively long post.
-Ender
[This message has been edited by Ender Everett (edited June 01, 2001).][/b]
</BLOCKQUOTE>
[This message has been edited by Bryan Fagan (edited June 03, 2001).]
[This message has been edited by Bryan Fagan (edited June 03, 2001).]
Ender Everett
Greenhorn

Joined: Mar 31, 2001
Posts: 19
Bryan,
Thanks a lot! The code you modified gave me one more thing to think about (not a very important thing). You mentioned that to keep the extra cycle problem in check, just have the loop cycle when it recieves a character within a range that I'm looking for.
You used:

I use:

It gives me two thoughts...
1 - Perhaps your filter is more robust, since you would be ignoring numbers, spaces, or really anything that could possibly be outside of the range of characters that the game was intended to play and analyze. Mine will accept and analyze anything that isn't a \n or \r (sorry, I'm using a Japanese keyboard, so i can't do the proper backslash unless i disable it... it works fine, though).
2 - Which evaluation cycle is more efficient? In a program as trivial (well, just plain useless, really) as this, it doesn't really matter, and I like your method a little more, since it targets only the letters I want to analyze. But just for the sake of the language, which one is more efficient?
Thanks again!
[This message has been edited by Ender Everett (edited June 05, 2001).]
Ender Everett
Greenhorn

Joined: Mar 31, 2001
Posts: 19
Nevermind, I played around a bit with your

and it is incredibly slick... especially from the output end! Cool, it doesn't cycle at ALL unless it is a character. I didn't see that when i first read through, since I was in do-while mental mode. (^_^)
Thanks again!
Bryan Fagan
Greenhorn

Joined: Feb 26, 2001
Posts: 17
Ender:
Glad to hear that this is making since to you. I love it when I finally figure something out and a big light just hits me. It's the best.
Happy Programming.
-Bryan
Originally posted by Ender Everett:
[B]Nevermind, I played around a bit with your

and it is incredibly slick... especially from the output end! Cool, it doesn't cycle at ALL unless it is a character. I didn't see that when i first read through, since I was in do-while mental mode. (^_^)
Thanks again![/B]

 
jQuery in Action, 2nd edition
 
subject: Loop & System.in.read weirdness!