为什么std :: istream :: ignore在空流上调用时不返回?

时间:2017-10-05 10:06:46

标签: c++ c++11 std iostream

std :: cin 是一个全局对象,因此我总是希望在使用之前将其设置为良好状态。但是,在未使用的 cin 上调用ignore()时,函数不会返回。

请参阅下面的示例代码。没有用户干预,执行不会到达第8行( cout )。在我的测试中,这种行为与第二个参数(分隔符,我已经尝试过'\ n'和EOF)是否一致。

我经历了几个在线参考,但我不明白为什么会这样。

#include <limits>
#include <iostream>
#include <string>
std::string readInput() {
    std::string input = "";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cout << "We never get here..." << std::endl;
    std::getline(std::cin, input);
    return input;
}
int main() {    
    std::string foo = readInput();  
}
  1. 为什么在这种情况下ignore()不返回?
  2. 如何在使用之前安全地重置和清空std :: cin

2 个答案:

答案 0 :(得分:2)

请参阅第二个参数'\n'。您要求读取包括'\n' 在内的字符并忽略它们。由于流上没有'\n',这意味着要阻止直到收到一个。

希望很明显,只有在知道流上有'\n'时才应拨打此电话。

所以,你的第二个问题的答案是,在使用之前,什么都不做,因为流上没有数据。

从中读取一些数据后,清除流的时间是;然后根据您使用的读取操作,您将知道是否有换行符。

请注意,没有这样的操作“清除流上的任何内容”(这是故意设计)。相反,您的操作将是“清除行的其余部分”,其中“行”定义为下一个换行符;并且输入将来自使用行的文件,或者用户按Enter键的交互式终端。

答案 1 :(得分:2)

documentation中所述:

  

ignore表现为UnformattedInputFunction。在构造和检查岗哨对象之后,它从流中提取字符并丢弃它们,直到出现以下任何一种情况:[...]   输入序列中的下一个可用字符c是delim,由Traits :: eq_int_type(Traits :: to_int_type(c),delim)确定。提取并丢弃分隔符字符。如果delim是Traits :: eof()

,则禁用此测试

因此,如果流为空,它将触发对相应流缓冲区的下溢()的调用,因为在你的情况下忽略'\ n'。

注意:如果要确保流缓冲区完全为空,可以调用cin.rdbuf() - &gt; in_avail()来获取仍在等待从输入缓冲区中提取的字符数量,因此如果缓冲区为空,则为0。然而,这是高度依赖于实现的,因为它将起作用,例如,使用Visual Studio开箱即用。另一方面,对于GCC,您必须先调用cin.sync_with_stdio(false)才能使自己的内部缓冲。但是,它不适用于这样的LLVM。