0

i was using a macro i created to clear the buffer after a scanf, but i was told it is not a good idea for "Many reasons". Could you explain me why and how should i clean it? I know that using fflush(stdin) is a very bad idea since it's not defined.

This is the macro i was using:

#define CLEAR_BUFFER do { c = getchar(); } while (c != '\n' && c != EOF);

And also, another question: in the "real world" is scanf used? And if yes, how do people clean the buffer?

Thanks

Tommy4
  • 21
  • 2
  • If you're having issues with spaces or newlines left over after reading something, you can put a space before the `%d`, `%f` or similar to get rid of them, e.g. `scanf(" %d",x)` – humodz Nov 22 '14 at 13:24
  • For user input, use `fgets()` which gets the data and deals with line buffered input streams well. – pmg Nov 22 '14 at 13:32
  • 1
    @pmg for robust code, fgets also needs cleanup as the line may exceed the buffer size – M.M Nov 22 '14 at 14:00
  • @humodz "... put a space before the %d..." is **not** needed. `"%d"` will consume optional leading white-space even without a preceding `" "` in the format. This applies to all `scanf()` specifiers except `"%c"`, `"%n"`, `"%["`. – chux - Reinstate Monica Nov 22 '14 at 20:25
  • What is "*bad*" with this is the name. I'd call it at least something like `CLEAR_STDIN`? – alk Nov 23 '14 at 14:47

1 Answers1

8

The idea is good although the execution could be improved:

#define CLEAR_BUFFER() do { int ch; while ( (ch = getchar()) != EOF && ch != '\n' ) {} } while (0)

Your version didn't declare c and can be used incorrectly.

If you're not familiar with do...while(0), see here.

Even better than both of these would be to write a function:

void clear_buffer(void)
{
    int ch; while ( (ch = getchar()) != EOF && ch != '\n' ) {} 
}

You could make this return bool if you're interested to distinguish whether EOL occurred or there was an error (but the calling code could check feof(stdin) || ferror(stdin) to find that out anyway).

In C99 this could be an inline function although that's not a huge problem if you are in C90 and make it non-inline.


For the second part of the question: I never use scanf, and I clean the buffer in the way I just described. Others may do it differently of course, this is more a question of personal preference.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • I'd rather have `clear_buffer()` return `ch` ... so that the calling code can easily detect `EOF`. – pmg Nov 22 '14 at 13:29
  • Is it a bad idea to use `%*c` to knock off the newline after fetching the required input? – Gopi Nov 22 '14 at 13:33
  • I prefered the original `do while` approach, seemed more readable to me. – Karoly Horvath Nov 22 '14 at 13:33
  • @KarolyHorvath the original doesn't declare `c` so it needs some work anyway – M.M Nov 22 '14 at 13:35
  • @MattMcNabb If the purpose of this loop is it fetch newline or EOF can't we just use `%*c` in the scanf() along with the format specifier? – Gopi Nov 22 '14 at 13:36
  • @Gopi that only reads one character (at best - it has other problems too) whereas this version reads all characters up to the end of the line – M.M Nov 22 '14 at 13:39
  • @MattMcNabb: not sure what you wanted to say with that. if we have to modify it, let's make it also more complicated? I was talking about your `while` loop. – Karoly Horvath Nov 22 '14 at 13:39
  • @MattMcNabb Agree ! OP wanter to know how buffer is cleaned using scanf()? So i thought without this loop any input needs to be read using scanf() and the buffer should be cleaned using %*c. Just checking – Gopi Nov 22 '14 at 13:43
  • @MattMcNabb +1 Cool!! There was a other part to it asking `in the "real world" is scanf used? And if yes, how do people clean the buffer?` Was just checking about that – Gopi Nov 22 '14 at 13:47
  • @KarolyHorvath I don't think that (pseudocode) `while(x=y) {}` is more complicated than `do { x } while (y)` ... matter of opinion of course. See also [C FAQ](http://c-faq.com/stdio/stdinflush2.html) – M.M Nov 22 '14 at 13:47