简体   繁体   English

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

[英]Why does std::istream::ignore not return when called on an empty stream?

std::cin is a global object, and as such I always want to set it to a good state before using it. std :: cin是一个全局对象,因此,我始终希望在使用它之前将其设置为良好状态。 However, when invoking ignore() on an unused cin the function doesn't return. 但是,在未使用的cin上调用ignore()时,该函数不会返回。

See sample code below. 请参见下面的示例代码。 Execution doesn't reach line 8 ( cout ) without user intervention. 没有用户干预,执行不会到达第8行( cout )。 In my testing this behavior is consistent with or without the second argument (the delimiter, I've tried '\\n' and EOF). 在我的测试中,此行为与是否有第二个参数(分隔符,我已经尝试过'\\ n'和EOF)一致。

I've been through a couple of online references, but I don't see why this happens. 我已经看过一些在线参考资料,但是我不明白为什么会这样。

#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. Why does ignore() not return in this case? 为什么在这种情况下ignore()不返回?
  2. How can I safely reset and empty std::cin before use? 如何使用安全地重置并清空std :: cin?

See the second argument '\\n' . 参见第二个参数'\\n' You are requesting to read characters up to and including a '\\n' and ignore them. 您正在要求读取不超过'\\n'字符并忽略它们。 Since there is no '\\n' on the stream, this means to block until one is received. 由于流上没有'\\n' ,因此这意味着阻塞直到接收到一个。

Hopefully it is clear that you should only make this call when it is known that there is a '\\n' on the stream. 希望很明显,仅应在知道流中存在'\\n'时才进行此调用。

So , the answer to your second question is that before use, do nothing , since there is no data on the stream anyway. 因此,您的第二个问题的答案是,在使用之前, 请勿执行任何操作 ,因为流上始终没有数据。

The time to clear the stream is after reading some data from it; 清除流的时间是从读它的一些数据之后 ; and then depending on which read operation you used, you will know whether or not there is a newline. 然后根据您使用的读取操作,您将知道是否有换行符。

Note that there is no such operation "clear whatever is on the stream" (this is intentional design). 请注意,没有这样的操作“清除流中的内容”(这是有意设计)。 Instead your operations would be things like "clear the remainder of the line", where "the line" is defined as up to the next newline character; 相反,您的操作将是“清除行的其余部分”之类的操作,其中“行”被定义为下一个换行符。 and input would have come from a file that uses lines, or an interactive terminal where the user presses Enter. 而输入将来自使用行的文件或用户按Enter的交互式终端。

As stated in the documentation : 文档中所述:

ignore behaves as an UnformattedInputFunction. ignore表现为UnformattedInputFunction。 After constructing and checking the sentry object, it extracts characters from the stream and discards them until any one of the following conditions occurs: [...] the next available character c in the input sequence is delim, as determined by Traits::eq_int_type(Traits::to_int_type(c), delim). 在构造并检查了哨兵对象之后,它将从流中提取字符并丢弃它们,直到出现以下任何一种情况:[...]输入序列中的下一个可用字符c是delim,由Traits :: eq_int_type确定(特性:: to_int_type(c),delim)。 The delimiter character is extracted and discarded. 分隔符字符被提取并丢弃。 This test is disabled if delim is Traits::eof() 如果delim为Traits :: eof(),则此测试被禁用

Therefore, it will trigger a call to underflow() of the corresponding stream buffer if the stream is empty, as ignore in your case is waiting for '\\n'. 因此,如果流为空,它将触发对相应流缓冲区的underflow()的调用,因为在您的情况下,忽略正在等待'\\ n'。

Note: When you want to make sure your stream buffer is entirely empty, you may call cin.rdbuf()->in_avail() to get the amount of characters still waiting to be extracted from the input buffer, thus being 0 if the buffer is empty. 注意:当要确保流缓冲区完全为空时,可以调用cin.rdbuf()-> in_avail()以获取仍在等待从输入缓冲区中提取的字符数,如果缓冲区为0,则为0是空的。 This however is highly implementation-dependent, as it will work eg with Visual Studio out of the box. 但是,这是高度依赖于实现的,因为它可以与现成的Visual Studio一起使用。 For GCC on the other hand, you have to call cin.sync_with_stdio(false) before in order to turn own the internal buffering. 另一方面,对于GCC,必须先调用cin.sync_with_stdio(false)才能拥有内部缓冲。 It will not work with LLVM like this, though. 但是,它不适用于这样的LLVM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 std::istream::ignore 丢弃字符? - Why does std::istream::ignore discard characters? 替代std :: istream :: ignore - Alternative to std::istream::ignore 为什么 std::basic_istream::ignore() 提取的字符多于指定的字符? - Why does std::basic_istream::ignore() extract more characters than specified? 为什么在std :: istream_iterators上使用的std :: find_if似乎返回最后一个元素? - Why does std::find_if used on std::istream_iterators seem to return the last element? 为什么std :: istream :: gcount返回的字符数比预期的多 - Why does std::istream::gcount return one char more than expected 为什么std :: istream :: getline不能在std :: string上运行? - Why does std::istream::getline not operate on std::string? 返回一个带有“return std :: set”的空集 <int> ()“ - 它为什么运行? - Return an empty set with “return std::set<int>()” - why does it run? 为什么std :: operator &gt;&gt;(istream&,char&)提取空格? - Why does std::operator>>(istream&, char&) extract whitespace? 为什么在使用clang时std :: boolalpha会忽略字段宽度? - Why does std::boolalpha ignore field width when using clang? 为什么&(std :: to_wstring())返回一个空字符串? - why does &(std::to_wstring()) return an empty string?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM