C-如何在没有缓冲的情况下轮询()输入?
我试图检测任何输入到stdin的字符(没有换行符) 我试过:C-如何在没有缓冲的情况下轮询()输入?,c,io,buffer,stdin,C,Io,Buffer,Stdin,我试图检测任何输入到stdin的字符(没有换行符) 我试过: setvbuf(stdin, NULL, _IONBF); //This returns 0 struct pollfd pfd = {STDIN_FILENO, POLLIN}; while (!poll(pfd, 1, ms)) { /* do some thing, e.g. printf("n\n"); */ } 当我键入q时,它似乎并没有停止打印,但在我按enter键后它确实停止了打印。我正在使用的系统是arch l
setvbuf(stdin, NULL, _IONBF); //This returns 0
struct pollfd pfd = {STDIN_FILENO, POLLIN};
while (!poll(pfd, 1, ms)) {
/* do some thing, e.g. printf("n\n"); */
}
当我键入q时,它似乎并没有停止打印,但在我按enter键后它确实停止了打印。我正在使用的系统是arch linux,编译器是gcc。内核的TTY层驱动程序/缓冲区中的
q
被挂起,因为它处于“熟”模式
在这种模式下,只有当驱动程序看到换行符时,才会向应用程序返回某些内容。然后它返回:q\n
(即q
)
要让它在任何字符上立即返回,必须使用ioctl
调用将TTY层置于“原始”模式
您需要使用[推荐]的termios
调用:tcgetattr
和tcsetattr
更新:
ioctl单独起作用吗?哪个命令对应将终端更改为原始模式 查看
人工术语
。它有关于如何设置原始模式(手册页中称为“非规范”模式)的完整文档
我已经有一段时间没有这样做了,但这里有一个骨架函数
虽然函数在最后恢复原始状态,但您可能希望在程序启动时设置一次非规范模式
但是,对于程序中需要常规行编辑的其他部分,您必须自己处理所有行编辑(例如,支持退格等)
#include <termios.h>
#include <unistd.h>
void
change_tty(int fd)
{
struct termios orig;
struct termios raw;
// get original cooked/canonical mode values
tcgetattr(fd,&orig);
// set options for raw mode
raw = orig;
#if 0
raw.c_lflag &= ~ICANON;
raw.c_cc[VMIN] = ...
raw.c_cc[VTIME] = ...
#else
cfmakeraw(&raw);
#endif
// put unit into raw mode ...
tcsetattr(fd,TCSANOW,&raw);
// do stuff in raw mode ...
// restore original mode
tcsetattr(fd,TCSANOW,&orig);
}
#包括
#包括
无效的
更改时间(int fd)
{
结构术语来源;
结构termios raw;
//获取原始烹调/规范模式值
tcgetattr(fd和orig);
//设置原始模式的选项
原始=原始;
#如果0
原始c_lflag&=~ICANON;
原始.c_cc[VMIN]=。。。
原始.c_cc[VTIME]=。。。
#否则
cfmakeraw(&raw);
#恩迪夫
//将设备置于原始模式。。。
tcsetattr(fd、TCSANOW和raw);
//在原始模式下做一些事情。。。
//恢复原始模式
tcsetattr(fd、TCSANOW和orig);
}
内核的TTY层驱动程序/缓冲区中的q
被挂起,因为它处于“煮熟”模式
在这种模式下,只有当驱动程序看到换行符时,才会向应用程序返回某些内容。然后它返回:q\n
(即q
)
要让它在任何字符上立即返回,必须使用ioctl
调用将TTY层置于“原始”模式
您需要使用[推荐]的termios
调用:tcgetattr
和tcsetattr
更新:
ioctl单独起作用吗?哪个命令对应将终端更改为原始模式
查看人工术语
。它有关于如何设置原始模式(手册页中称为“非规范”模式)的完整文档
我已经有一段时间没有这样做了,但这里有一个骨架函数
虽然函数在最后恢复原始状态,但您可能希望在程序启动时设置一次非规范模式
但是,对于程序中需要常规行编辑的其他部分,您必须自己处理所有行编辑(例如,支持退格等)
#include <termios.h>
#include <unistd.h>
void
change_tty(int fd)
{
struct termios orig;
struct termios raw;
// get original cooked/canonical mode values
tcgetattr(fd,&orig);
// set options for raw mode
raw = orig;
#if 0
raw.c_lflag &= ~ICANON;
raw.c_cc[VMIN] = ...
raw.c_cc[VTIME] = ...
#else
cfmakeraw(&raw);
#endif
// put unit into raw mode ...
tcsetattr(fd,TCSANOW,&raw);
// do stuff in raw mode ...
// restore original mode
tcsetattr(fd,TCSANOW,&orig);
}
#包括
#包括
无效的
更改时间(int fd)
{
结构术语来源;
结构termios raw;
//获取原始烹调/规范模式值
tcgetattr(fd和orig);
//设置原始模式的选项
原始=原始;
#如果0
原始c_lflag&=~ICANON;
原始.c_cc[VMIN]=。。。
原始.c_cc[VTIME]=。。。
#否则
cfmakeraw(&raw);
#恩迪夫
//将设备置于原始模式。。。
tcsetattr(fd、TCSANOW和raw);
//在原始模式下做一些事情。。。
//恢复原始模式
tcsetattr(fd、TCSANOW和orig);
}
这对我有效,但可能取决于您的系统/终端
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int main() {
int i = 0;
struct termios ts;
tcgetattr(0, &ts);
ts.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &ts);
while (!ioctl(0, FIONREAD, &i) && !i) {
printf("x");
fflush(stdout);
sync();
usleep(100);
}
printf("\n");
return 0;
}
#包括
#包括
#包括
#包括
int main(){
int i=0;
结构术语;
tcgetattr(0和ts);
ts.c_lflag&=~ICANON;
tcsetattr(0、TCSANOW和ts);
而(!ioctl(0,FIONREAD,&i)和&!i){
printf(“x”);
fflush(stdout);
sync();
usleep(100);
}
printf(“\n”);
返回0;
}
克雷格真的为你回答了这个问题。我只是好奇地找到了一个实现。ioctl(0,FIONREAD,&i)获取缓冲区中的字符数并将其放入i。termios和ioctl_tty的手册页包含了提出此解决方案所需的所有详细信息
不过,老实说,如果您想让这样的东西具有交互性,ncurses会让它变得更简单。这对我来说很有效,但可能取决于您的系统/终端
#include <stdio.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
int main() {
int i = 0;
struct termios ts;
tcgetattr(0, &ts);
ts.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &ts);
while (!ioctl(0, FIONREAD, &i) && !i) {
printf("x");
fflush(stdout);
sync();
usleep(100);
}
printf("\n");
return 0;
}
#包括
#包括
#包括
#包括
int main(){
int i=0;
结构术语;
tcgetattr(0和ts);
ts.c_lflag&=~ICANON;
tcsetattr(0、TCSANOW和ts);
而(!ioctl(0,FIONREAD,&i)和&!i){
printf(“x”);
fflush(stdout);
sync();
usleep(100);
}
printf(“\n”);
返回0;
}
克雷格真的为你回答了这个问题。我只是好奇地找到了一个实现。ioctl(0,FIONREAD,&i)获取缓冲区中的字符数并将其放入i。termios和ioctl_tty的手册页包含了提出此解决方案所需的所有详细信息
老实说,如果你想让这样的东西具有交互性,ncurses会让它变得更简单。“尝试使用setvbuf(stdin,NULL,_IONBF)然后poll(…)”-->Post这段代码,@chux我认为这很明显,但我现在确实让它更完整了。当代码不能按预期工作时,早期调试是检查函数的返回值,如int setvbuf()
。它是否为您返回了0?由于poll()
不是标准的C语言,所以对像Linux一样使用的扩展进行post/tag?返回什么?@chux是的,setvbuf返回0,应该可以。poll在不“enter”时返回0。“尝试使用setvbuf(stdin,NULL,_IONBF)然后poll(…)”-->发布该代码,a@chux我认为这很明显,b