0

I found this code that clears the input buffer, but I don't really understand how it works. Can anybody explain it in a simple way?

do{
    fgets(string,LENGTH,stdin);
} while (strlen(string) > 0 && string[strlen(string) - 1] != '\n');
Barmar
  • 741,623
  • 53
  • 500
  • 612
Gio Bur
  • 15
  • 6
  • 2
    It just keeps calling `fgets()` until it gets an input that ends with newline. So that will read everything up to the next newline. – Barmar Nov 12 '21 at 00:56
  • 2
    What part of it don't you understand? – Barmar Nov 12 '21 at 00:56
  • 2
    And consuming everything through the next newline may be a reasonable thing to want to do, but I wouldn't characterize it as "clears the input buffer". – John Bollinger Nov 12 '21 at 00:58
  • Related: [How to clear input buffer in C?](https://stackoverflow.com/questions/7898215), [Using fflush(stdin)](https://stackoverflow.com/questions/2979209), [What is the use of fflush(stdin) in c programming?](https://stackoverflow.com/questions/18170410) – Steve Summit Nov 12 '21 at 01:01
  • @Barmar what I don't get is why it doesn't ask for input once for every loop, if fgets() gets called every time. – Gio Bur Nov 12 '21 at 01:08
  • Because `fgets()` reads from the input buffer. If there's data in the buffer that hasn't been read, `fgets()` doesn't need to wait for the user to type anything. – Barmar Nov 12 '21 at 01:10
  • This is typically used after `scanf()`, because it stops reading from the buffer as soon as the format operators are satisfied. – Barmar Nov 12 '21 at 01:11
  • @JohnBollinger It does what the non-standard `fflush(stdin)` does -- it clears the rest of the input line from the buffer. – Barmar Nov 12 '21 at 01:12
  • @Barmar ahh now I understand! thanks for clearing that up for me... I am a newbie and it shows! – Gio Bur Nov 12 '21 at 01:16
  • No, @Barmar, it does not. If there is more than one line in the input buffer then `fgets()` reads only the first. If there is less than one full line in the input buffer (and `string` is large enough) then it reads more input from the source, possibly blocking until it can do so. On those implementations that support `fflush(stdin)`, on the other hand, the effect is usually to drop everything from the buffer without reading anything further from the source, regardless of buffer contents. – John Bollinger Nov 12 '21 at 01:21

2 Answers2

0

while (strlen(string) > 0 && string[strlen(string) - 1] != '\n');. So, do fgets while the length of string is larger than 0 (that is, while there are characters waiting in the input stream) AND ALSO while the end of the string does not equal newline. If the end of the input equals newline, stop. I am not sure why this code does not go ahead and eat up the newline while it is at it, but it is safe because all standard reading functions ignore the intial newline. @barmar had a good suggestion though (Because fgets() reads from the input buffer. If there's data in the buffer that hasn't been read, fgets() doesn't need to wait for the user to type anything.) But they differ in whether or not they ignore the trailing newline (generated when you press ENTER). fgets keeps the trailing newline, but gets strips it off.

ADBeveridge
  • 650
  • 3
  • 15
  • [Read why the `gets` function is dangerous](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – ADBeveridge Nov 12 '21 at 03:05
0

It's a misnomer to say that it "clears the input buffer". What it does is advance to the next line of input.

The code is a do/while loop. It assumes a char array called string that is at least LENGTH in size.

The body of the loop reads as much of a line as it can, up to LENGTH - 1 characters:

fgets(string,LENGTH,stdin);

The return value from fgets() is ignored - this is a bug, because it can mean that string is not assigned to in a failure case (such as EOF) and we could loop forever.

The condition of the loop checks to see whether we have read up to the end-of-line. There's a test that the string has at least one character (which it will if fgets() was successful) and then compares the last character to a newline:

while (strlen(string) > 0 && string[strlen(string) - 1] != '\n')

If we see a newline, then fgets() has read the rest of the line; if not, it read LENGTH-1 characters from a longer input line, and there's still input to consume, so continue looping.


Fixed version:

while (fgets(string, LENGTH, stdin) && string[strlen(string) - 1] != '\n')
    ;

Simpler alternative:

scanf("%*[^\n]%*c");

Note that in both cases, any stream error will remain, to be detected on the next attempt at input.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103