Thread: "clearing buffer" confusion

  1. #1
    Registered User
    Join Date
    Mar 2013
    Posts
    29

    "clearing buffer" confusion

    Hope that someone can clarify my confusion with the following common "instructional" code for clearing buffer:
    Code:
    while ( getchar() != '\n')  continue;
    As per manual,
    fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error.
    I understand that such code will 'clear' any input characters not equal to '\n', but I don't understand why, for character '\n', the while condition would not be false, and therefore the code would not proceed to 'continue;' and discard the newline character.
    I know that there must be something very simple that I'm confused about, but I just don't see it!
    Last edited by atlantis43; 01-01-2015 at 05:59 PM. Reason: typo

  2. #2
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by atlantis43 View Post
    Hope that someone can clarify my confusion with the following common "instructional" code for clearing buffer:
    Code:
    while ( getchar() != '\n')  continue;
    As per manual,
    I understand that such code will 'clear' any input characters not equal to '\n', but I don't understand why, for character '\n', the while condition would not be false, and therefore the code would not proceed to 'continue;' and discard the newline character.
    I know that there must be something very simple that I'm confused about, but I just don't see it!
    It might be more clear if written this way:
    Code:
    while ( getchar() != '\n')
    {
      continue;
    }
    If getchar() returns the newline, then the test fails and the code inside the braces (or the single line without the braces) is never executed, and the loop exits.

  3. #3
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    First of all it should be:
    Code:
    while ((ch = getchar()) != EOF && ch != '\n')
       ;
    Ie you need to check if you hit EOF or end of line (\n). The thing you're not understanding is that getchar() takes the character out of the input stream and then returns it. So when you've compared it to '\n' or EOF it's already been removed from the buffer and thus consumed

  4. #4
    Registered User
    Join Date
    Mar 2013
    Posts
    29
    Thanks for including the word "consumed", which helps make some sense of it: but the question remains as to why '\n' is "consumed" even though, in such case, the 'while' condition is false. Is this just something that is built into the way getchar() performs?
    My question applies more to examples of keyboard input (as in "menu" examples) rather than file input (as in nonpuz reply), where extraneous characters and remaining newline characters from keying 'Enter' might occupy the buffer.

  5. #5
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    The while condition is executed for each iteration of the loop. That means getchar() is executed, which removes the \n from the buffer. Then the return value of getchar() (which has now removed that character from the buffer already) is then compared to '\n' which is false (in this case). The while loop then stops, but the getchar() was still executed
    This is why you can run into problems when you use side-effects in a conditional statement (whether it be a while loop, if statement, for, etc..)
    For example:
    Code:
    char * p = "some string I got from the user\n";
    
    /* Now I want to delete that \n char */
    while (*p++ != '\n')
      ;
    *p = '\0';
    
    /* This code looks right, but I'm actually just setting the \0 at the end of the string to \0 again because when *p == '\n' I still call the p++ and increment p afterwards which then puts it at the position of the end of the string (pointing to the terminating \0) */

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The '\n' is "consumed" because getchar() removes it from input buffer, returns its value. In the while condition, the value is stored in ch (so it can be used) but, next time through the loop, that value is discarded and overwritten by the next call of getchar().

    Also look up the meaning of the "continue" keyword in C. Essentially, within a loop construct, it jumps to the end of the loop body. When the only statement within a while loop is a "continue" statement, it just goes back and evaluates the loop condition again.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Registered User
    Join Date
    Mar 2013
    Posts
    29
    Quote Originally Posted by grumpy View Post
    The '\n' is "consumed" because getchar() removes it from input buffer, returns its value. In the while condition, the value is stored in ch (so it can be used) but, next time through the loop, that value is discarded and overwritten by the next call of getchar().

    Also look up the meaning of the "continue" keyword in C. Essentially, within a loop construct, it jumps to the end of the loop body. When the only statement within a while loop is a "continue" statement, it just goes back and evaluates the loop condition again.
    Oh, enlightenment!
    getchar() is consuming all chars remaining in buffer, but continue; only applies for chars other than '\n'. Thanks to all for your aid.

  8. #8
    Registered User
    Join Date
    Mar 2013
    Posts
    29
    Quote Originally Posted by rstanley View Post
    It might be more clear if written this way:
    Code:
    while ( getchar() != '\n')
    {
      continue;
    }
    If getchar() returns the newline, then the test fails and the code inside the braces (or the single line without the braces) is never executed, and the loop exits.
    Now that I understand, I see how appropriate your post was. I guess I'm just a bit slow.

  9. #9
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by atlantis43 View Post
    Now that I understand, I see how appropriate your post was. I guess I'm just a bit slow.
    I do agree with the code to check for EOF, but I wanted to answer your initial question first. I probably could have been more thorough in my explanation. It can be simplified to:
    Code:
    while ((ch = getchar()) != EOF && ch != '\n');
    The braces and the continue can be replaced with a single semi-colon.

    I like many others, have created this as a function, and have placed it in my personal library of functions, that don't exist in the standard library. Then I can call this and others in any application I create in the future. Don't reinvent the wheel every time you create a new application! ;^)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-08-2014, 08:12 PM
  2. Replies: 7
    Last Post: 12-04-2014, 09:28 PM
  3. "Filtering" a buffer(a std::deque here)-Which method is better?
    By manasij7479 in forum C++ Programming
    Replies: 1
    Last Post: 07-10-2011, 08:55 PM
  4. "itoa"-"_itoa" , "inp"-"_inp", Why some functions have "
    By L.O.K. in forum Windows Programming
    Replies: 5
    Last Post: 12-08-2002, 08:25 AM
  5. "CWnd"-"HWnd","CBitmap"-"HBitmap"...., What is mean by "
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 12-04-2002, 07:59 AM