如何解决如何获取`cin`以读取原始模式终端
为什么标准流可以在规范模式下接收来自终端的输入,但是您将其置于原始模式下却突然不再有效?我很了解POSIX串行编程,通常您使用read
。我试图更好地理解标准流。
#include <termios.h>
#include <unistd.h>
#include <iostream>
termios original;
void enableRawMode() {
tcgetattr(STDIN_FILENO,&original);
termios raw = original;
cfmakeraw(&raw);
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
tcsetattr(STDIN_FILENO,TCSAFLUSH,&raw);
}
int main() {
enableRawMode();
char c;
// This works as expected.
//int nread;
//while ((nread = read(STDIN_FILENO,&c,1)) != 1) {
// if (nread == -1 && errno != EAGAIN) {
// break;
// }
//}
// This loops forever,the failbit is always true,gcount is always 0.
while (!(std::cin.get(c))) {
if (std::cin.bad() || std::cin.eof()) {
break;
}
std::cin.clear();
}
tcsetattr(STDIN_FILENO,&original);
}
解决方法
经过大量讨论和一些调查,我发现这对给定标准流的实现是一个限制。基本上,我推断出标准流在您的终端处于煮熟模式时可以正常工作,但在原始模式下则不可靠。
可以将代码简化为使用std::cin.rdbuf()->sbumpc()
,在这种情况下将调用uflow
,后者很可能会调用underflow
,这将从底层设备中获取数据。与标准流关联的流缓冲区是实现定义的。
对sbumpc
的第一次调用,更具体地说是对underflow
的最终调用,将在从标准输入中读取时启动与VTIME
关联的计时器。如果在超时时间内收到输入,cin
将按预期工作。但是,如果发生超时,则流缓冲区将进入未定义状态,并且sbumpc
将永远返回EOF
。
状态与流而不是流缓冲区相关联,因此调用std::cin.clear()
会清除状态标志,但不能纠正流缓冲区中仍然存在的潜在问题。
在重置搜索位置时可能有一种解决方案,但是同样,给定的标准流是实现定义的,并且不知道它们可能拥有什么内部状态,或者在一个平台上是否成功,是否会在另一个平台上成功。据我所知,该文档只是不存在的。
两种可能的解决方案是直接使用POSIX API并喜欢它,或者编写使用POSIX API的自己的流实现。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。