c++ - 如何在不阻塞输入的情况下使用 getline?

标签 c++ nonblocking getline

有没有什么方法可以调用 getline() 并且在没有输入的情况下不阻塞等待?

我有以下代码:

 while(true){
    if(recv(sd, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) > 0) break;
    getline(cin,send);
 }

我想等待输入,但如果我在 sd 套接字上收到一些数据,我想停止等待数据并退出 while。我现在的代码只是停留在 getline() 的第一次迭代中。我想评估 getline(),如果没有可用的输入,返回 if

这可能吗?

PS:我尝试使用 cin.peek(),但它也会阻止输入。

最佳答案

你应该能够通过在标准输入、文件描述符 0 上设置非阻塞模式来做到这一点:

int flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NONBLOCK);

现在,如果没有可用的输入,底层的 read() 系统调用将返回 0,并且 std::cin 会认为这是文件结尾,并在 std::cin 上设置 eof()

当您希望再次从标准输入读取时,只需clear() 流的状态即可。

这里唯一复杂的因素是,这使得很难在 std::cin 上检测到真正的文件结束条件。当标准输入是交互式终端时问题不大;但如果标准输入可以是一个文件,这将是一个问题。

在这种情况下,您唯一现实的选择是完全放弃 std::cin,将非阻塞模式置于文件描述符 0、poll()select() 它,确定什么时候有东西要读,然后 read() 它。

尽管您也可以将 poll()select()std::cin 一起使用,但这会变得复杂,因为您需要明确检查 std::cinstreambuf 中是否已经缓冲了任何内容,因为这显然会抢占任何类型的 poll() select() 检查;但是通过尝试从 std::cin 中读取某些内容,您仍然冒着读取缓冲数据的风险,然后尝试从现在的底层文件描述符中 read()在非阻塞模式下,这会导致伪造的文件结束条件。

总而言之:您需要投入一些额外的时间来阅读和理解文件流和流缓冲区的工作原理;以及文件描述符实际如何工作,以及非阻塞模式如何工作;为了找出您需要使用的正确逻辑。

哦,如果你坚持使用 std::cingetline() 的非阻塞路线,你将没有简单的方法来确定是否getline() 返回的字符串结束,因为 getline() 实际上从标准输入读取了一个换行符,或者它达到了过早的假文件结束条件而不是整行实际上已经读取了输入。

因此,使用非阻塞模式和 std::cin,您将不得不使用 read(),而不是 getline ()

关于c++ - 如何在不阻塞输入的情况下使用 getline?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41558908/

相关文章:

c++ - 用连字符替换字符串中的文本

c++ - 默认构造函数和析构函数的 "=default"与 "{}"有何不同?

c++ - 在另一个模板类构造函数中使用 typedef 模板时出错

c++ - 如何找到我的 C++ 应用程序正在使用的 header ?

dialog - Applescript 中的非阻塞对话框

c - getline 检查行是否为空格

PE (.exe) 周围的 Java 包装器

javascript - 将 REST 请求中的大数据 JSON 反序列化为对象而不锁定浏览器?

perl - IO::Select线程中的select()包装器安全吗?如何解决?

c++ - C++ 中没有 `while (!my_ifstream.eof()) { getline(my_ifstream, line) }`?