Home > OS >  C - Can't correctly clear stdin before fgets
C - Can't correctly clear stdin before fgets

Time:10-04

I'm having troubles cleaning the stdin. It's a complex topic for which i searched all over the internet. I found many answers, but none helped me.

I will provide a little example program of what happens, and what behaviour i would want.

This is a program that waits for 3 seconds, then starts printing whatever i write.

int main(int argc, char *argv[]){

char message[100] = {};
printf("Wait 3 seconds before you can write!\n");

sleep(3);

printf("Start writing!\n");
while (1) {
    while (fgets(message, 100, stdin) != NULL) {
      printf("You wrote: %s\n", message);
    }
}

}

My problem is: if i write things on the terminal while my program is sleeping, then the fgets() will print those things i wrote. It's not what i would like. The correct behaviour should be that everything you wrote while sleeping should be discarded. Of course, the problem is that the things i previously wrote are still in the buffer.

This is an output example:

Wait 3 seconds befoure you can write!
hi
i don't want to wait

Start writing!
You wrote: hi
You wrote: i don't want to wait

To clear the stdin buffer, many mentioned using fflush(stdin) (while many others told this is an incorrect use of fflush, since it is used for stdout). Many others mentioned using this kind of function:

void clear_stdin() {
  int c;
  do {
    c = getchar();
  }   while (c != EOF && c != '\n');
}

But this doesn't help me like it should. It only clear the first string i wrote on the terminal. I don't know how the stdin's buffer is implemented, but given its behaviour with this code, i think every time i write and press enter, it appends '\n', but also a EOF. In my mind, EOF should be AT THE END of all the buffer. So, probably i have to change some conditions in my while, but i don't know what.

Using this function in my code:

int main(int argc, char *argv[]){

char message[100] = {};
printf("Wait 3 seconds before you can write!\n");

sleep(3);

clear_stdin();

printf("Start writing!\n");

while (1) {
    while (fgets(message, 100, stdin) != NULL) {
      printf("You wrote: %s\n", message);
    }
}

}

And this is its output:

Wait 3 seconds befoure you can write!
hi
i don't want to wait

Start writing!
You wrote: i don't want to wait

Sorry for the wall of text. I tried giving you every bit of information possible. How can i totally clear the buffer?

CodePudding user response:

For Windows and Linux

#ifdef _WIN32

  #include <windows.h>

  void clear_stdin()
  {
    FlushConsoleInputBuffer( GetStdHandle( STD_INPUT_HANDLE ) );
  }

  void sleep( unsigned timeout_ms )
  {
    Sleep( timeout_ms );
  }

#else

  #include <termios.h>
  #include <unistd.h>

  void clear_stdin()
  {
    tcflush( 0, TCIFLUSH );
  }

  void sleep( unsigned timeout_ms )
  {
    usleep( timeout_ms * 1000 );
  }

#endif

That should do it.

[edit] Added a sleep function for both systems for you too

CodePudding user response:

You can turn off buffering using setvbuf(stdin, NULL, _IONBF, 0); before sleeping and active it again using setvbuf(stdin, NULL, _IOLBF, BUFSIZ); after waking up.

  •  Tags:  
  • c
  • Related