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

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

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

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

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.

Другие вопросы по тегам