【问题标题】:How to make stdin file descriptor ready when pressing a key?按键时如何使标准输入文件描述符准备就绪?
【发布时间】:2019-10-16 21:47:35
【问题描述】:

我有一个用于非阻塞字符输入的自定义 _kbhit() 函数。 _kbhit() 函数使用 select() 来检查标准输入是否准备好读取。 但最后,只要我按下 RETURN,我就可以准备好标准输入。 我按任意键如何让它工作?

void set_conio_terminal_mode()
{
    struct termios new_termios;

    /* take two copies - one for now, one for later */
    tcgetattr(0, &new_termios);

    /* register cleanup handler, and set the new terminal mode */
    atexit(reset_terminal_mode);
    cfmakeraw(&new_termios);
    tcsetattr(0, TCSANOW, &new_termios);
}

int _kbhit()
{
    struct timeval tv = { 0L, 0L };
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(0, &fds);
    return select(1, &fds, NULL, NULL, &tv);
}

static char _getch(void) {
    int r;
    unsigned char c;
    if ((r = read(0, &c, sizeof(c))) < 0) {
        return r;
    } else {
        return c;
    }
}

int main( int argc, char *argv[] )
{
    set_conio_terminal_mode();
    while (1) {
        if (_kbhit()) {
            inputbuffer[inputlen] = _getch();
            if (inputbuffer[inputlen] >= 0x20 && inputbuffer[inputlen] < 0x7F) {
                putchar(inputbuffer[inputlen]);
                inputlen++;
            }
        }
    }
}

我预计这段代码会输出回显,但在我按下 RETURN 后它会输出整个字符串。

【问题讨论】:

  • 我非常接近解决方案。但我认为它是标准输入中的缓冲,但问题是标准输出中的缓冲。
  • 函数:read() 返回 ssize_t,而不是 unsigned char

标签: c linux select stdin


【解决方案1】:

我认为问题在于 - 尽管您使用 cfmakeraw() 初始化了终端属性 - stdout 仍处于行缓冲模式。

尝试将标准输出设置为无缓冲模式。

setbuf(stdout, NULL);

相当于

setvbuf(stdout, NULL, _IONBF, 0);

这避免了在每个putchar(inputbuffer[inputlen]); 之后调用fflush(stdout); 的需要。

可能有一种方法可以使用tcsetattr() 而不是setvbuf() 来完成此操作,但是我不熟悉它。

【讨论】:

    猜你喜欢
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    相关资源
    最近更新 更多