Как я могу сбросить непрочитанные данные из очереди ввода tty в системе UNIX?

Моя программа должна читать только один символ со стандартного ввода, поэтому я использую read(0, buffer, 1). Но если пользователь вставляет более одного символа, они остаются в некотором буфере, и когда я снова вызываю read, они все еще там.

Итак, как я могу отбросить эти символы? Я хочу, чтобы при повторном вызове read буфер заполнялся новым символом, а не старыми.

Пример: У меня есть read(0, buffer, 1), и пользователь пишет abcde. Мой буфер содержит (и это правильно), но затем я вызываю read(0, buffer, 1) снова, и я хочу, чтобы следующий символ, написанный пользователем, теперь, а не ранее написанный b.

Ответ 1

Когда ваша программа хочет начать чтение символов, она должна слить буфер существующих символов, а затем ждать, чтобы прочитать символ.

В противном случае он будет читать последний введенный символ, а не последний символ, введенный после этого.

Естественно, вам не нужно ничего делать с прочитанными символами; но вам нужно их прочитать.

Ответ 2

Ответ POSIX tcflush(): очистить не передаваемые выходные данные, нечитаемые входные данные или и то, и другое. Существует также tcdrain(), который ожидает вывода, которую нужно передать. Они были в POSIX, поскольку был стандарт POSIX (1988 для пробной версии), хотя я не помню, чтобы когда-либо их использовали напрямую.

Пример программы

Скомпилируйте этот код, чтобы получившаяся программа была вызвана 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;
}

Пример диалога

$ ./tcflush
abc
a
def
d
$

Похоже, что доктор заказал. Без второго tcflush() оболочка жалуется, что не может найти команду ef. Вы можете поместить tcflush() перед первым чтением, если хотите. Это не было необходимо для моего простого тестирования, но если бы я использовал sleep 10; ./tcflush, а затем набрал вперед, это изменило бы его.

Протестировано на RHEL 5 Linux на машине x86/64, а также в Mac OS X 10.7.4.