0

I have a question concerning stdin buffer content inspection.

This acclaimed line of code:

int c; while((c = getchar()) != '\n' && c != EOF);

deals efficiently with discarding stdin-buffer garbage, in case there is a garbage found. In case the buffer is empty, the program execution wouldn't go past it.

Is there a way of checking if there is garbage in the stdin-buffer at all (no matter if it's there by user error, typeahead or whichever reason), and executing the "fflush-replacement line" from above only in case there is a garbage found?

I'd prefer to keep it programmatically all in plain-UNIX-flavor-of standard C, without having to use special parsing tools, no yacc, bison, python, ruby, shell scripts etc., no Windows API, please.

Thanks in advance!

UPDATE:

I hope this example tells a bit more of my question:

//...
//this line should make sure stdin buffer is free from accidentally typed content
int c; while (( c = getchar()) != '\n' && c != EOF);

//this line won't show in case buffer is already clean
printf("Please enter an arbitrary number of float or symbolic values:\n");

//this line should read the real input user is being asked for
char* p = fgets(text, TEXT_SIZE, stdin);
if(p != NULL)
parse_and_process(text);
//...

The problem happens when there is no accidental input. The "garbage" is here considered anything that may stay in the buffer at the moment printf( ) prompt would appear. Is there a way of getting around the first line in case the buffer is already clean?

user3078414
  • 1,942
  • 2
  • 16
  • 24
  • 4
    The quoted lineof code removes everything from `stdin` until new-line or EOF is read. So what do you consider "*garbage*" though? – alk Feb 26 '15 at 14:27
  • Related: http://stackoverflow.com/q/13993742/694576 ? – alk Feb 26 '15 at 14:28
  • 1
    Please edit your question and add an example which demonstrates the problem. – user694733 Feb 26 '15 at 14:28
  • Thanks. I'll do my best to produce an example ASAP. – user3078414 Feb 26 '15 at 16:04
  • Everything typed before the printf is garbage. This has been asked before here: http://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c The short answer is that there is no "portable" way to do this. – caveman Feb 26 '15 at 16:44
  • Thanks, I'm well aware of stackoverflow.com/questions/7898215/… , and this is not what my question is about. All I'd like to know is if there is a way of programmatically determining if this line of code has to be executed depending on state of stdin buffer (empty or not empty)? – user3078414 Feb 26 '15 at 16:58
  • You'd like to programmatically _test_ the stdin buffer, so you can programmatically clear the stdin buffer, all the while avoiding giving the user the impression of a hung program. Close? Have you considered using a `switch(){case 1:... case n:}; state machine in conjunction with the concept of windows GetAsyncKeyState()? There are ways to do that in Linux, and it sounds like it may work for you. – ryyker Feb 26 '15 at 17:52
  • 1
    IMO, no portable way to "getting around the first line in case the buffer is already clean" other than to only call `while ((int c = getchar()) != '\n' && c != EOF);` _after_ reading data and detecting it did not end with a `'\n'`. Then `stdin` is empty for the _next_ reading. – chux - Reinstate Monica Feb 26 '15 at 17:58
  • Thanks, @ryyker, for having carefully read my question. Unfortunately, I'm nowhere near Windows, and I'm not familiar with their concepts, nor can apply them to my programs (please see tags). All I do is UNIX (including OSX-BSD-Darwin). – user3078414 Feb 26 '15 at 18:01
  • Thanks chux, but there is no guarantee the buffer will stay clean or user will accidentally type characters going back-and-forth between terminal part and GUI part of the program... – user3078414 Feb 26 '15 at 18:04
  • True, the method my comment suggests does not clean out `stdin` between the time of the previous input and "now". But to look at a higher level - is it really important to even do this? By cleaning out the buffer right before input code 1) prevents users from intentionally typing ahead. 2) prevents using re-directed input (quite useful) and 3) there is still a small window of time between flushing `stdin` and the next prompt/`fgets()`. Hmm if anything, your above code should clean `stdin` _after_ the prompt. – chux - Reinstate Monica Feb 26 '15 at 18:47
  • 1
    Thanks for your comment @chux. Unfortunately, I wouldn't have asked for this unless **really** necessary to fix. All that you mention as (1), (2) is exactly what I'm trying to prevent. My question does not exclude cleaning the stdin *after* the reading of actual user data. – user3078414 Feb 26 '15 at 19:01

2 Answers2

0

This acclaimed line of code:

int c; while((c = getchar()) != '\n' && c != EOF);

deals efficiently with discarding stdin-buffer garbage

No. This is just reading character until newline character is found or EOF is reached. I don't get what garbage you are talking about.

So by doing this you are consuming the newline character that is left in the stdin buffer. This is one of the ways of flushing the buffer.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Gopi
  • 19,784
  • 4
  • 24
  • 36
  • Why "No"? It refers to exactly what? – alk Feb 26 '15 at 14:31
  • @alk what is been considered as garbage is not known so I said the actual meaning of the code .. If newline is considered garbage then YES :) – Gopi Feb 26 '15 at 14:33
  • Ah .. - so you mean a confusing question deserves a confusing answer ...? ;-> – alk Feb 26 '15 at 14:35
  • @alk No confusing question needs a clear answer which says what the actual line of code is doing and leave the rest to OP .. – Gopi Feb 26 '15 at 14:36
  • As I have said it deals efficiently with what's left in the buffer. All I'd like to know is how to get around this line if the stdin buffer is empty? Hope I've made myself clear now. – user3078414 Feb 26 '15 at 15:45
  • @user3078414 Just allow this line to be there as it is of no harm it is being used to flush the buffer and if the buffer is empty this code will not do any harm – Gopi Feb 26 '15 at 15:50
  • Thanks, Gopi, but sorry, this is exactly where the problem is. In case user made no previous mistaken input, the printf( ) statement won't show at all, and that's the harm it'll do - it'll give an impression of a hanging program, until user presses the "enter" key (which produces the newline to get consumed), enabling the program to continue... – user3078414 Feb 26 '15 at 17:06
0

Edit to respond to OP comment.

You need to specify what is garbage. Only then can you (or anyone else) determine what input is valid.

Once you have determined that, you can write a routine that quietly consumes user input with the category of garbage until some non-garbage input is detected.

The conio.h header used in C programming on Windows (not Unix) contains functions for console input/output. Some of the most commonly used functions of conio.h are clrscr, getch, getche, kbhit etc.

Following is an example from here that illustrates how you might run a loop that consumes input until non-garbage appears over the keyboard... (in this case, it is written to work with escape key, using an adaptation of conio functions, but you can adapt it for your purposes)

   do
   {
      ch = _getch();
      ch = toupper( ch );

      if (ch != 27) {
         _cputs( "CHARACTER: " );
         _putch( ch );
         _putch( '\r' );    // Carriage return
         _putch( '\n' );    // Line feed
      }

   } while( ch != 27 ); 

Original post
This does not answer Is there a way of checking if there is garbage in the stdin-buffer, but it addresses how to make sure it is clear...
Add one additional line to make it clear to the user how to begin, and because of your original code, it will result in clearing the buffer of any garbage, or unintended input before user is directed to enter additional values...:...

    ...
    printf("hit <return> to begin");
    while ( (c = getchar()) != '\n' && c != EOF );
    printf("Please enter an arbitrary number of float or symbolic values:\n");    
    ...
Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Thanks, but this is exactly what I hope to avoid. It's part of a larger program which has at least 50 similar interactive situations (used very frequently) and I can't afford having to start each of them by displaying the sentence you have suggested to me in good faith. – user3078414 Feb 26 '15 at 17:12
  • Thanks for your reply. Garbage **is** whatever stays in the buffer at the moment `while ( (c = getchar()) != '\n' && c != EOF );` gets executed. There is no "non-garbage" before user consciously acting upon `printf( )` statement. The problem is that a clean buffer causes a hanging `while( )` until `'\n'` condition is met. – user3078414 Feb 26 '15 at 18:11