在调用std :: getline之前检查数据可用性

Abr*_*ile 27 c++ iostream

我想从我使用的流中读取一些数据std::getline.下面是一个使用的样本std::cin.

std::string line;
std::getline( std::cin, line );
Run Code Online (Sandbox Code Playgroud)

这是一个阻塞函数,即如果没有数据或行读取它阻止执行.

你知道在调用之前是否存在检查数据可用性的函数std::getline吗?我不想阻止.

如何检查流缓冲区是否满足成功调用的数据std::getline

无论如何看起来像下面的代码

if( dataAvailableInStream() )
{
     std::string line;
     std::getline( std::cin, line );
}
Run Code Online (Sandbox Code Playgroud)

CB *_*ley 18

没有标准的方法来验证是否getline会阻止.您可以使用:

std::cin.rdbuf()->in_avail()
Run Code Online (Sandbox Code Playgroud)

在读取操作可能阻塞之前看看有多少字符是绝对可用的,但是你必须在重新检查之前逐个读取字符,in_avail因为没有办法提前知道任何待处理字符是换行符还是流的实际结束.一个getline电话可能会阻止,如果这是情况并非如此.

请注意,虽然if in_avail()返回一个正数,但保证在流结束之前至少有多个字符可用,反之则不然.如果in_avail()返回零,则可能仍有可用字符,并且流可能不会立即阻止.

  • "我绝对认为它已经烂了." - 什么,MSVC?;-) (5认同)
  • 这对于MSVC 2013来说效果不佳.即使流未关闭且没有可用输入,它似乎也会返回正值.我不会浪费一天测试它,但我绝对认为它是腐烂的. (3认同)

Mic*_*fik 8

iostream库不支持非阻塞I/O的概念.我认为C++标准中没有任何东西可以做到.任何好的解决方案都可能是特定于平台的.如果您可以使用POSIX库,您可以查看select.它通常用于网络连接,但是如果你传递stdin的文件描述符它会工作得很好.


mr *_*NAE 5

此代码可以帮助您检查数据是否存在,stdin而不会阻塞:

std::cin.seekg(0, std::cin.end);
int length = std::cin.tellg();
if (length < 0) return; //- no chars available
Run Code Online (Sandbox Code Playgroud)

如果stdin有一些数据-不要忘记将位置重新设置为开始。

std::cin.seekg(0, std::cin.beg);
Run Code Online (Sandbox Code Playgroud)

然后,您可以读取\0缓冲区末尾的所有数据,包括(可以是多个):

std::vector<char> s(length);
std::cin.read(s.data(), length);
Run Code Online (Sandbox Code Playgroud)

或逐行:

std::string line;
while (std::cin) {
    std::getline(std::cin, line);
    //.....
}
Run Code Online (Sandbox Code Playgroud)

此代码可在MSVC和gcc(Ubuntu)中使用