10

My program has to read just ONE character from the standard input, and so I use read(0, buffer, 1). But if the user insert more than one single character, they remain in some buffer and when I call a read again they are still there.

So, how can I discard these characters? I want that when I call a read again, the buffer is filled with the new character, not with the old ones.

An example: I've a read(0, buffer, 1) and the user writes abcde. My buffer contains a (and it's right), but then I call read(0, buffer, 1) again and I want the next character written by the user from now, and not the b written before.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
JustTrying
  • 592
  • 4
  • 9
  • 23

2 Answers2

22

The POSIX answer is tcflush(): flush non-transmitted output data, non-read input data, or both. There is also tcdrain() which waits for output to be transmitted. They've been in POSIX since there was a POSIX standard (1988 for the trial-use version), though I don't recall ever using them directly.

Example program

Compile this code so the resulting program is called tcflush:

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

int main(void)
{
    char buffer[20] = "";

    read(0, buffer, 1);
    printf("%c\n", buffer[0]);
    tcflush(0, TCIFLUSH);
    read(0, buffer, 1);
    printf("%c\n", buffer[0]);
    tcflush(0, TCIFLUSH);
    return 0;
}

Example dialog

$ ./tcflush
abc
a
def
d
$

Looks like what the doctor ordered. Without the second tcflush(), the shell complains that it can't find a command ef. You can place a tcflush() before the first read if you like. It wasn't necessary for my simple testing, but if I'd used sleep 10; ./tcflush and then typed ahead, it would make a difference.

Tested on RHEL 5 Linux on an x86/64 machine, and also on Mac OS X 10.7.4.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
5

When your program wants to start reading characters, it must drain the buffer of existing characters and then wait to read the character.

Otherwise, it will read the last character entered, not the last character entered after right now.

Naturally, you do not need to do anything with the read characters; but, you do need to read them.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • alternately, when you read the 1 character, keep reading until you get eof or EAGAIN. – evil otto Jun 07 '12 at 20:07
  • @evilotto While your suggestion will give you the last inputted character, it really won't solve the problem of deciding if the last inputted character was inputted before you wanted to capture or afterwards. To make sure it was inputted afterwards, you need to drain the channel, and then capture the character. – Edwin Buck Jun 07 '12 at 20:13
  • And how can I drain the buffer of existing characters? – JustTrying Jun 07 '12 at 20:37
  • 1
    With a while loop that reads one character at a time, until no characters are available to be read. – Edwin Buck Jun 07 '12 at 20:38