C++ 为什么在空流上调用std::istream::ignore时不返回?
std::cin是一个全局对象,因此我总是希望在使用它之前将其设置为良好状态。但是,在未使用的cin上调用ignore()时,函数不会返回 请参见下面的示例代码。如果没有用户干预,执行不会到达第8行(cout)。在我的测试中,无论是否使用第二个参数(分隔符,我尝试了“\n”和EOF),此行为都是一致的 我在网上查阅了一些参考资料,但我不明白为什么会发生这种情况C++ 为什么在空流上调用std::istream::ignore时不返回?,c++,c++11,std,iostream,C++,C++11,Std,Iostream,std::cin是一个全局对象,因此我总是希望在使用它之前将其设置为良好状态。但是,在未使用的cin上调用ignore()时,函数不会返回 请参见下面的示例代码。如果没有用户干预,执行不会到达第8行(cout)。在我的测试中,无论是否使用第二个参数(分隔符,我尝试了“\n”和EOF),此行为都是一致的 我在网上查阅了一些参考资料,但我不明白为什么会发生这种情况 #include <limits> #include <iostream> #include <strin
#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();
}
#包括
#包括
#包括
std::string readInput(){
std::string input=“”;
std::cin.clear();
std::cin.ignore(std::numeric_limits::max(),'\n');
std::cout请参见第二个参数'\n'
。您正在请求读取小于等于'\n'
的字符并忽略它们。由于流上没有'\n'
,这意味着在收到一个字符之前将一直阻塞
希望很清楚,您应该只在知道流上存在'\n'
时进行此调用
因此,第二个问题的答案是,在使用之前,不要做任何事情,因为流中没有任何数据
清除流的时间是在从流中读取一些数据之后;然后根据您使用的读取操作,您将知道是否有换行符
请注意,没有“清除流中的任何内容”这样的操作(这是有意设计的)。相反,您的操作将类似于“清除行的其余部分”,其中“行”定义为最多下一个换行符;输入将来自使用换行符的文件或用户按Enter键的交互式终端。请参阅第二个参数'\n'
。您请求读取最多包含'\n'
的字符,并忽略它们。因为该参数上没有'\n'
流,这意味着阻止,直到收到一个
希望很清楚,您应该只在知道流上存在'\n'
时进行此调用
因此,第二个问题的答案是,在使用之前,不要做任何事情,因为流中没有任何数据
清除流的时间是在从流中读取一些数据之后;然后根据您使用的读取操作,您将知道是否有换行符
请注意,没有“清除流中的任何内容”这样的操作(这是有意设计的)。相反,您的操作将类似于“清除行的其余部分”,其中“行”定义为最多下一个换行符;输入将来自使用换行符的文件,或用户按Enter键的交互式终端。如中所述:
ignore的行为类似于未格式化的PutFunction。在构造和检查sentry对象后,它将从流中提取字符并丢弃它们,直到出现以下任一情况:[……]
输入序列中的下一个可用字符c是delim,由Traits::eq_int_type(Traits::to_int_type(c),delim)确定。将提取并丢弃分隔符字符。如果delim是Traits::eof()
因此,如果流为空,它将触发对相应流缓冲区的underflow()的调用,因为在您的示例中,ignore正在等待'\n'
注意:当您想确保流缓冲区完全为空时,可以在_avail()中调用cin.rdbuf()->获取仍在等待从输入缓冲区提取的字符数,如果缓冲区为空,则为0。但是,这高度依赖于实现,因为它将在Visual Studio开箱即用的情况下工作。另一方面,对于GCC,您必须调用cin.sync_with_stdio(false)为了拥有内部缓冲,它不会像这样与LLVM一起工作。如中所述:
ignore的行为类似于未格式化的PutFunction。在构造和检查sentry对象后,它将从流中提取字符并丢弃它们,直到出现以下任一情况:[……]
输入序列中的下一个可用字符c是delim,由Traits::eq_int_type(Traits::to_int_type(c),delim)确定。将提取并丢弃分隔符字符。如果delim是Traits::eof()
因此,如果流为空,它将触发对相应流缓冲区的underflow()的调用,因为在您的示例中,ignore正在等待'\n'
注意:当您想确保流缓冲区完全为空时,可以在_avail()中调用cin.rdbuf()->获取仍在等待从输入缓冲区提取的字符数,如果缓冲区为空,则为0。但是,这高度依赖于实现,因为它将在Visual Studio开箱即用的情况下工作。另一方面,对于GCC,您必须调用cin.sync_with_stdio(false)之前,它将拥有内部缓冲。但它不会像这样与LLVM一起工作