【问题标题】:How can I flush unread data from a tty input queue on a UNIX system?如何从 UNIX 系统上的 tty 输入队列中刷新未读数据?
【发布时间】:2012-06-11 22:11:46
【问题描述】:

我的程序只需要从标准输入中读取一个字符,所以我使用read(0, buffer, 1)。 但是,如果用户插入多个字符,它们会保留在某个缓冲区中,当我再次调用 read 时,它们仍然存在。

那么,我怎样才能丢弃这些字符呢? 我希望当我再次调用 read 时,缓冲区中会填充新字符,而不是旧字符。

一个例子: 我有一个read(0, buffer, 1),用户写的是abcde。我的缓冲区包含 a (这是正确的),但是我再次调用 read(0, buffer, 1) 并且我想要用户从现在开始写入的下一个字符,而不是 b 之前写的。

【问题讨论】:

    标签: c unix buffer


    【解决方案1】:

    POSIX 答案是tcflush()刷新未传输的输出数据、未读取的输入数据,或两者兼而有之。还有tcdrain() 等待输出传输。自从有 POSIX 标准(1988 年用于试用版)以来,它们就一直在 POSIX 中,尽管我不记得曾经直接使用过它们。

    示例程序

    编译此代码,因此生成的程序称为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(),shell 会抱怨找不到命令ef。如果您愿意,可以在第一次阅读之前放置tcflush()。对于我的简单测试来说这不是必需的,但如果我使用 sleep 10; ./tcflush 然后提前输入,就会有所作为。

    在 x86/64 机器上的 RHEL 5 Linux 以及 Mac OS X 10.7.4 上测试。

    【讨论】:

      【解决方案2】:

      当您的程序想要开始读取字符时,它必须耗尽现有字符的缓冲区,然后等待读取字符。

      否则,它将读取最后输入的字符,而不是现在之后输入的最后一个字符。

      当然,你不需要对读取的字符做任何事情;但是,您确实需要阅读它们。

      【讨论】:

      • 或者,当您阅读第 1 个字符时,请继续阅读,直到您获得 eof 或 EAGAIN。
      • @evilotto 虽然您的建议会给您最后输入的字符,但它确实不能解决确定最后输入的字符是在您想要捕获之前还是之后输入的问题。为确保之后输入,需要清空通道,然后捕获字符。
      • 我怎样才能耗尽现有字符的缓冲区?
      • 使用 while 循环一次读取一个字符,直到没有字符可供读取。
      猜你喜欢
      • 2014-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多