• Post Reply Bookmark Topic Watch Topic
  • New Topic

Removal of Carriage return / newline with do-while loop questions

 
Simon Penders
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So i am a beginner in Java and learning from a book. I understand how a do-while loop works. It runs at least one time, and the condition is tested at the bottom. If it's false, the loop ends. Now i have a question about a little part in the following code:



The book explains this: Here is why this loop is needed: As explained earlier, System.in is line buffered—you have to
press ENTER before characters are sent. Pressing ENTER causes a carriage return and a line feed
character to be generated. These characters are left pending in the input buffer. This loop
discards those characters by continuing to read input until neither is present.

I googled for an hour, looked in video's but could not find an in depth answer. I tested the program without the loop, and then it prints "Sorry you're wrong' two times. I understand that when i choose a letter and press enter, a carriage return and newline character is also created. I don't really understand how this loop prevents that these unwanted characters are used. It's this loop:



So in example, i press the letter S. I give an enter. So if i am understanding correctly, the System.in.read receives: S, \n, \r. Three characters. So, the S is not a \n or \r, so the while loop won't run again right? Then it goes to the else part. But how is the pending in the input stream, the \n and \r removed? I don't get the order of the program, can somebody explain this with more detail?
 
Tony Docherty
Saloon Keeper
Posts: 3137
72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch.

First thing always format your code, it makes it so much easier to read. Look at how much better a formatted version of your code (with the addition of a few curly braces and blank lines) looks.


The book explains this: Here is why this loop is needed: As explained earlier, System.in is line buffered—you have to
press ENTER before characters are sent. Pressing ENTER causes a carriage return and a line feed
character to be generated.

This statement is not necessarily correct, different operating systems add different line end characters.

To answer your question, that's a non-intuitive piece of code and I wouldn't recommend writing code this way because, as you have discovered, it's very hard to work out how it works.

The best way to see what is happening is to add the following line immediately after the line which reads a char from std in.

Basically the first time you enter an input it gets the entered char and continues through the rest of the code. If you entered the wrong char the code loops back to the read statement which then reads the next char which on a Windows system will be a CR which causes the inner while loop to loop around and read the next char which on a Windows system will be a LF which causes the inner while loop to loop around and read the next char. There isn't any more chars in the input buffer so the call blocks waiting for an input.
 
Simon Penders
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you so much for your answer, you are my hero. Sorry for the code layout, new to this forum So if i am understanding correctly, it works like this:

System.in.read reads my S
I press Enter
carriage return and newline are also pending in input stream
S is not == to \n or \r, so code will continue
S is not == to answer, so i get the message that i am wrong and too high part
S is not equal to k, which is true in the while loop, code runs from the top again
Now System.in.read reads the \r, while loop condition true, it loops
Now System.in.read reads the \n, while loop condition true, it loops
Now System.in.read reads nothing anymore, so it's waiting for another input.

Correct thinking?
 
Tony Docherty
Saloon Keeper
Posts: 3137
72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes that's correct except for the first line, the call to read doesn't read anything until Enter is pressed. Once Enter is pressed the line of input including the end of line markers is passed to the input buffer and read removes and returns the first character in buffer.
 
Simon Penders
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony Docherty wrote:Yes that's correct except for the first line, the call to read doesn't read anything until Enter is pressed. Once Enter is pressed the line of input including the end of line markers is passed to the input buffer and read removes and returns the first character in buffer.


Thank you so much, you made me happy I was wondering about this for day's.
 
Campbell Ritchie
Marshal
Posts: 52516
118
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does yuor book recommend you use System.in.read? I think that is a dreadful method. I would use a Scanner; a simple way to use it is
Scanner has various nextXXX methods but no nextChar method, so next().charAt(0), which returns the first char in the first non‑whitespace token, is the nearest you will find.
Just as Tony has told you about read(), you will notice nothing until you push the enter key.
 
Simon Penders
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Does yuor book recommend you use System.in.read? I think that is a dreadful method. I would use a Scanner; a simple way to use it is
Scanner has various nextXXX methods but no nextChar method, so next().charAt(0), which returns the first char in the first non‑whitespace token, is the nearest you will find.
Just as Tony has told you about read(), you will notice nothing until you push the enter key.


No, the book does not mention the Scanner method unfortunately.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!