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

C++ 如何在不阻塞输入的情况下使用getline?,c++,nonblocking,getline,C++,Nonblocking,Getline,是否有任何方法可以调用getline(),如果没有输入,则不进行阻塞和等待 我有以下代码: while(true){ if(recv(sd, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) > 0) break; getline(cin,send); } 我想等待输入,但如果我在sd套接字上收到一些数据,我想停止等待数据,并在时退出。我现在的代码,只是在getline()上进行第一次迭代。我想计算getline()

是否有任何方法可以调用
getline()
,如果没有输入,则不进行阻塞和等待

我有以下代码:

 while(true){
    if(recv(sd, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) > 0) break;
    getline(cin,send);
 }
我想等待输入,但如果我在
sd
套接字上收到一些数据,我想停止等待数据,并在
时退出
。我现在的代码,只是在
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
将认为这是文件的结尾,并将
eof()
设置为on
std::cin

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

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

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

虽然您也可以将
poll()
select()
std::cin
一起使用,但这将变得复杂,因为您需要显式检查
std::cin
streambuf
中是否已经缓冲了任何内容,因为这显然会抢占任何类型的
poll()
选择()
检查;但是,通过尝试从
std::cin
中读取某些内容,您仍然有读取缓冲数据的风险,然后尝试从现在处于非阻塞模式的底层文件描述符中读取()
,这会导致出现虚假的文件结束条件

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

哦,如果您坚持使用
std::cin
getline()
执行非阻塞路由,您将无法轻松确定
getline()
返回的字符串是否结束,因为
getline()
实际上从标准输入读取新行,或者它达到了一个过早的假文件结束条件,并且没有实际读取整行输入

因此,使用非阻塞模式和
std::cin
,您将被迫使用
read()
,而不是
getline()
,该方法可用于执行非阻塞读取。您可以使用它来构建的非阻塞等价物

此函数的工作原理与原始的
std::getline()
函数相同,只是它总是立即返回。我使用它是因为它偶尔会派上用场。

我使用select()来检索stdin文件描述符的状态。这在Ubuntu和嵌入式Linux板上都有效。如果stdin仍然没有收到用户的输入键,select将等待一段时间并报告stdin尚未就绪。stopReading可以停止监视stdin并继续处理其他内容。您可以根据需要对其进行编辑。它可能无法在特殊输入tty上工作

#include <sys/select.h>

static constexpr int STD_INPUT = 0;
static constexpr __suseconds_t WAIT_BETWEEN_SELECT_US = 250000L;

// Private variable in my class, but define as needed in your project
std::atomic<bool> stopReading;

...

std::string userInput = "";
while (false == stopReading)
{
    struct timeval tv = { 0L, WAIT_BETWEEN_SELECT_US };
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(STD_INPUT, &fds);
    int ready = select(STD_INPUT + 1, &fds, NULL, NULL, &tv);

    if (ready > 0)
    {
        std::getline(std::cin, userInput);
        break;
    }
}
#包括
静态constexpr int STD_输入=0;
静态constexpr uu suseconds u t WAIT u SELECT u US=250000L;
//我的类中的私有变量,但在项目中根据需要定义
原子停读;
...
std::string userInput=“”;
while(false==停止读取)
{
struct timeval tv={0L,WAIT_BETWEEN_SELECT_US};
fd_集fds;
FD_零(&fds);
FD_设置(标准_输入和fds);
int ready=select(标准输入+1,&fds,NULL,NULL,&tv);
如果(就绪>0)
{
std::getline(std::cin,userInput);
打破
}
}

回答问题:是的,这是可能的。至少在Linux上.我用的是Ubuntu。。这怎么可能?你能给我一些链接或者给我解释一下吗?简单的回答是:1)使用低级I/O,而不是
getline
。2) 使用
select
。这只在以下情况下起作用:
std::ios\u base::sync\u with_stdio(false)
#include <sys/select.h>

static constexpr int STD_INPUT = 0;
static constexpr __suseconds_t WAIT_BETWEEN_SELECT_US = 250000L;

// Private variable in my class, but define as needed in your project
std::atomic<bool> stopReading;

...

std::string userInput = "";
while (false == stopReading)
{
    struct timeval tv = { 0L, WAIT_BETWEEN_SELECT_US };
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(STD_INPUT, &fds);
    int ready = select(STD_INPUT + 1, &fds, NULL, NULL, &tv);

    if (ready > 0)
    {
        std::getline(std::cin, userInput);
        break;
    }
}