3

I have been learning Java with Oracle’s “Java A Beginner’s Guide”, and was having trouble understanding an example program from the book about the input buffer and do-while loop.

This example is about a number guessing program. It’s designed to ignore any extra characters you might enter. So if you enter ABC then push enter it will only check A.

My question is more about the input buffer, if I comment out the 2nd do-while loop that deals with ignore then run the program, it checks that single character 3 times. So if I enter a single ‘A’ then push enter it appears to check 3 times and I get the “...Sorry, you're too low” output blurb 3 times.

If I enter ‘AZ’ then push enter it seems to check 4 times, it checks A then Z then A 2 more times.


Questions:

  1. Why does it seem to always check the first character 3 times?
  2. Does the enter key assign \n to the ignore variable?
    When the 2nd do-while loop is not commented out, is this the correct sequence if you enter ABC then push enter?
    A – assigned to ch
    B- assigned to ignore
    C- assigned to ignore
    Enter key (\n) – assigned to ignore, loop exits because ignore is assigned \n

I am a bit confused if the enter key actually assigns \n to ignore? Or is it just waiting until there are no more characters to assign to ignore? The book says pushing enter causes a newline. So that do-while loop is terminated when: (ignore != '\n').

Thanks for any help!

class Guess4{
    public static void main (String args[])
        throws java.io.IOException {

            char ch, ignore, answer = 'K';

            do {
                System.out.println("I'm thinking of a letter between A and Z.");
                System.out.println("Can you guess it: ");

                //read a character
                ch = (char) System.in.read();

                /* discard any other characters in the input buffer
                do {
                    ignore = (char) System.in.read();
                } while(ignore != '\n');
                */

                if(ch == answer) System.out.println("**Right**");
                else {
                    System.out.print("...Sorry, you're ");
                    if(ch < answer) System.out.println("too low");
                    else System.out.println("too high");
                    System.out.println("Try again!\n");
                }
            } while(answer != ch);
        }
}
  • Are you sure? Three times? When I was running it, everything worked as expected: If you enter just A, you see two lines because first A is read then '\n'. For ABC, you would see 4 lines: One for each character and one for '\n'. Right before the if-clause add `System.out.println("Now checking: '" + ch + "''");` to see whats going on. – Doe Johnson Aug 06 '19 at 21:33
  • @DoeJohnson I think the reason I'm getting 3 is because I'm using command line. I tried the same code with IntelliJ and only got 2. After adding your code, the extra response strangely outputs just ''w checking: '. In the book it says pressing Enter causes a carriage return AND a line feed sequence. Is this 3rd output the carriage return? As I understand carriage return moves the cursor to its left starting point, and /n moves the cursor down one line. This might explain the strange 3rd output. Here is inputting ABC with command line (4 responses): [Imgur](https://i.imgur.com/Ri6jOg4.png) – Jim Anderson Aug 07 '19 at 03:25
  • I recommend to test theories like that in your code: `if (ch == '\r') {...}`. Keep in mind that many characters can not be identified by just printing them – Doe Johnson Aug 08 '19 at 19:41
  • thanks, it turns out the extra response I was getting was indeed from the carriage return – Jim Anderson Aug 13 '19 at 21:49

1 Answers1

0

Question 1:

(As I already wrote in my comment, I did not get 3 lines if I entered just one character, I got 2, which is correct behavior)

Your assumption that the first character is checked multiple times is wrong. For simple debugging, print the character that will be tested:

// ...
System.out.println("Now checking: '" + ch + "''");
if(ch == answer) System.out.println("**Right**");
// ...

Now, when you enter abc[enter], you will see that each character is processed individually and each of them causes the same message. Also the newline is tested.

Question 2:

You're absolutely right.

There is one important thing though: The whole point of the second do-while construct is to clear the input-stream for your next guess! That's what the comment above at least tries to point out: discard any other characters in the input buffer. Checking for the newline is just so you know you can exit the loop because one guess is limited to one line! Actually you don't even need that ignore variable at all. The character is removed from the stream by reading it. So it's about the reading itself by calling System.in.read() - you don't have to assign the result to anything.

You could replace the second do-while loop with just do {} while(System.in.read() != '\n');.

Doe Johnson
  • 1,374
  • 13
  • 34
  • thanks, this clears up a lot. I didn't realize you can assign a value like \n to a char. I responded to your comment above, but basically I'm using command line and that seems like why I'm getting the extra response/run. Here is a screenshot of entering ABC and getting 4 responses: [Imgur](https://i.imgur.com/Ri6jOg4.png). Notice the strange ''w checking: ' output I suspect might be a carriage return? (the " is actually two ' before the w). – Jim Anderson Aug 07 '19 at 04:04
  • Are you using windows? Because in windows a newline is represented by sending two escape sequences: `\r` followed by `\n`... EDIT: Just saw your comment above... – Doe Johnson Aug 08 '19 at 19:33