按下键时如何准备好标准输入文件描述符?
How to make stdin file descriptor ready when pressing a key?
我有一个用于非阻塞字符输入的自定义 _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 后它会输出整个字符串。
我认为问题在于 - 尽管您使用 cfmakeraw()
初始化了终端属性 - stdout
仍处于 line-buffered 模式。
尝试将标准输出设置为无缓冲模式。
setbuf(stdout, NULL);
相当于
setvbuf(stdout, NULL, _IONBF, 0);
这避免了在每个 putchar(inputbuffer[inputlen]);
之后调用 fflush(stdout);
的需要。
可能有一种方法可以使用 tcsetattr()
而不是 setvbuf()
来完成此操作,但我不熟悉它。
我有一个用于非阻塞字符输入的自定义 _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 后它会输出整个字符串。
我认为问题在于 - 尽管您使用 cfmakeraw()
初始化了终端属性 - stdout
仍处于 line-buffered 模式。
尝试将标准输出设置为无缓冲模式。
setbuf(stdout, NULL);
相当于
setvbuf(stdout, NULL, _IONBF, 0);
这避免了在每个 putchar(inputbuffer[inputlen]);
之后调用 fflush(stdout);
的需要。
可能有一种方法可以使用 tcsetattr()
而不是 setvbuf()
来完成此操作,但我不熟悉它。