选择(2)和ioctl(2),在stdin有数据时返回0

选择(2)和ioctl(2),在stdin有数据时返回0,c,macos,unix,select,ioctl,C,Macos,Unix,Select,Ioctl,我正在尝试检测stdin上是否有数据供我读取 具体地说,我已经使用TceTattr关闭了规范模式,所以我可以一次读取一个字符。我想检测由箭头键生成的转义序列,但要将它们与单独的转义键区分开来。另外,我想快速知道输入的是哪一个;我假设我的终端相当快,^[之后的转义序列的其余部分相当快 假设我已经知道,例如,使用select2,在stdin上有一些内容需要读取。我使用getchar读取一个字符,它是一个^[,ASCII 27。现在我想知道在某个时间间隔内是否会出现更多字符,或者这个转义字符是表示转义

我正在尝试检测stdin上是否有数据供我读取

具体地说,我已经使用TceTattr关闭了规范模式,所以我可以一次读取一个字符。我想检测由箭头键生成的转义序列,但要将它们与单独的转义键区分开来。另外,我想快速知道输入的是哪一个;我假设我的终端相当快,^[之后的转义序列的其余部分相当快

假设我已经知道,例如,使用select2,在stdin上有一些内容需要读取。我使用getchar读取一个字符,它是一个^[,ASCII 27。现在我想知道在某个时间间隔内是否会出现更多字符,或者这个转义字符是表示转义键被击中的所有字符。使用select2进行此操作似乎不起作用,因为我注意到,并在其他地方读取,其余字符已被缓冲,因此select2不再需要检测。所以我使用FIONREAD转向ioctl2,但这似乎也不起作用

最小非工作示例:

包括 包括 包括 包括 包括 包括 结构termios tios_bak; void initkeyboardvoid{ 结构termios tios; tcgetattr0和tios_-bak; tios=tios_-bak; tios.c_lflag&=~ICANON; tios.c_cc[VMIN]=1;//一次读取一个字符 tios.c_cc[VTIME]=0;//读取时没有超时,将其设为阻塞读取 tcsetattr0、TCSAFLUSH和tios; } void endkeyboardvoid{ tcsetattr0、TCSAFLUSH和tios_-bak; } int mainvoid{ 初始化键盘; ATEXITEND键盘; 打印按箭头键或escape键,或escape键后跟其他键。\n; char c=getchar; ifc!=27{ 打印请输入转义序列或密钥\n; 出口1; } //现在我们使用select2来确定是否还有其他内容需要阅读。 //如果这是一把单独的逃生钥匙,那么在一段时间内就不会有什么新东西了。 fd_集rdset; FD_零&rdset; FD_SET0和&rdset; 结构时间值电视; tv.tv_sec=1;//这里我们等待一秒钟;这只是为了说明。在真实环境中 tv.tv_usec=0;//我会等待大约100ms,因为这对于终端来说是合理的。 int-ret=select1,&rdset,NULL,NULL,&tv; assertret!=-1;//基本上忽略了错误检查 ifret==0{ printfselect2返回0。\n; int n; 断言octl0,FIONREAD,&n>=0; 资产n>=0; ifn==0{ printfioctl2给出了0;无需读取:单独的转义键\n; //在此处插入printf%c\n,getchar;,以证明在转义序列的情况下这是错误的 }否则{ c=getchar; printfioctl2表示读取缓冲区第一个字符中有%d个字节=%c\n,n,c; } }否则{ c=getchar; printfselect2返回%d:第一个字符%c有更多内容需要读取\n,ret,c; } } 抱歉,代码太长。发生的情况如下:

当您只需按escape键,它就会成功地检测到。 当您按下escape键,然后快速按下其他一些键(如“a”)时,代码成功地检测到还有更多内容需要读取,这很好;特定的转义序列检测超出范围。 当您生成转义序列时,例如按箭头键时,select2和ioctl2都返回无需读取的内容,但显然有;可以通过在指定位置插入printf%c\n,getchar;轻松检查。这将打印[在箭头键的情况下,至少是这样]。 问题:如何正确检测案例3中的输入?

来自手册页:

不建议混合调用来自的输入函数 stdio库,对文件描述符的read2进行低级调用 与输入流关联;结果将是未定义的 很可能不是你想要的

不要混合使用缓冲和非缓冲输入功能

选择必须与组合使用

read(fileno(stdin), &c, 1);
而不是

c = getchar();

谢谢,就这样!还没有看到其他地方解释过这个要求。