C++ - 重置 stringstream 是否不会重置获取位置或清除标志?
C++ - Does resetting stringstream not reset the get position or clear flags?
我在循环中从字符串流中提取值,每次循环执行时都在循环顶部重置字符串流。但是,stringstream 的 >>
运算符每次都会在第二次迭代时失败。这个代码的精简版本重现了我遇到的问题:
istringstream word;
string in;
int number;
while(cin >> in) {
word.str(in);
//Uncommenting either one of the following lines seems to solve the issue:
//word.clear();
//word.seekg(0);
word >> number;
if(word.fail()) {
cerr << "Failed to read int" << endl;
return 1;
}
cout << in << ' ' << number << endl;
}
就目前而言,它总是在第二次循环迭代时失败。但是,取消注释两行注释代码中的任何一行都可以解决问题。我不明白的是,既然我已经用 word.str(in)
重置了字符串流,为什么它仍然失败?为什么重置获取位置可以解决问题?
我是否遗漏了有关字符串流工作原理的信息?它是否在最后一次有效读取而不是由于 EOF 而失败的读取上设置 eofbit
标志?如果是这样,为什么 seekg(0)
似乎清除了该标志,而重置 stringstream 却没有?
正如@Someprogrammerdude 建议的那样:只需将 istringstream
移动到 while
循环中(您可以将其更改为 for
循环以将 in
保留在循环中嗯):
for (string in; cin >> in;)
{
istringstream word(in);
int number;
if (!(word >> number))
{
cerr << "Failed to read int" << endl;
return 1;
}
cout << in << ' ' << number << endl;
}
这样每个循环都会重新创建。
当你这样做的时候,把 number
也移进去(当然,除非你在循环外使用它)。
如果你看一下流的状态,这应该会更清楚一些。
int main()
{
std::vector<std::string> words = { "10", "55", "65" };
std::istringstream word;
for (const auto &in : words)
{
word.str(in);
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
int number;
word >> number;
if (word.fail()) {
std::cerr << "Failed to read int" << std::endl;
return 1;
}
std::cout << in << ' ' << number << std::endl;
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
}
}
这将导致:
stream state:
10 10
stream state: eof
stream state: eof
Failed to read int
所以最初设置了 none 个标志,但是读取数字到达流的末尾,设置 eofbit
。 std::istringstream::str
is defined as if to call rdbuf()->str(new_str)
。这与清除标志无关。
调用 clear()
当然会清除 eofbit
,但在 C++11 或更新的 中调用 seekg
也会清除。 “
在做任何事情之前,seekg 清除 eofbit。 (C++11 起)".
请注意,如果您说“10 20”,它只会丢弃“20”,而不会检测到错误。
stream state:
10 20 10
stream state:
stream state:
55 55
stream state: eof
stream state: eof
Failed to read int
所以您可能真的想检查那个 eof 标志,看看您是否阅读了整个流。
正如其他人所指出的,当然每个循环构造一个新的流对象也意味着不用担心以前的 flags/states。
我在循环中从字符串流中提取值,每次循环执行时都在循环顶部重置字符串流。但是,stringstream 的 >>
运算符每次都会在第二次迭代时失败。这个代码的精简版本重现了我遇到的问题:
istringstream word;
string in;
int number;
while(cin >> in) {
word.str(in);
//Uncommenting either one of the following lines seems to solve the issue:
//word.clear();
//word.seekg(0);
word >> number;
if(word.fail()) {
cerr << "Failed to read int" << endl;
return 1;
}
cout << in << ' ' << number << endl;
}
就目前而言,它总是在第二次循环迭代时失败。但是,取消注释两行注释代码中的任何一行都可以解决问题。我不明白的是,既然我已经用 word.str(in)
重置了字符串流,为什么它仍然失败?为什么重置获取位置可以解决问题?
我是否遗漏了有关字符串流工作原理的信息?它是否在最后一次有效读取而不是由于 EOF 而失败的读取上设置 eofbit
标志?如果是这样,为什么 seekg(0)
似乎清除了该标志,而重置 stringstream 却没有?
正如@Someprogrammerdude 建议的那样:只需将 istringstream
移动到 while
循环中(您可以将其更改为 for
循环以将 in
保留在循环中嗯):
for (string in; cin >> in;)
{
istringstream word(in);
int number;
if (!(word >> number))
{
cerr << "Failed to read int" << endl;
return 1;
}
cout << in << ' ' << number << endl;
}
这样每个循环都会重新创建。
当你这样做的时候,把 number
也移进去(当然,除非你在循环外使用它)。
如果你看一下流的状态,这应该会更清楚一些。
int main()
{
std::vector<std::string> words = { "10", "55", "65" };
std::istringstream word;
for (const auto &in : words)
{
word.str(in);
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
int number;
word >> number;
if (word.fail()) {
std::cerr << "Failed to read int" << std::endl;
return 1;
}
std::cout << in << ' ' << number << std::endl;
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
}
}
这将导致:
stream state: 10 10 stream state: eof stream state: eof Failed to read int
所以最初设置了 none 个标志,但是读取数字到达流的末尾,设置 eofbit
。 std::istringstream::str
is defined as if to call rdbuf()->str(new_str)
。这与清除标志无关。
调用 clear()
当然会清除 eofbit
,但在 C++11 或更新的 中调用 seekg
也会清除。 “
在做任何事情之前,seekg 清除 eofbit。 (C++11 起)".
请注意,如果您说“10 20”,它只会丢弃“20”,而不会检测到错误。
stream state: 10 20 10 stream state: stream state: 55 55 stream state: eof stream state: eof Failed to read int
所以您可能真的想检查那个 eof 标志,看看您是否阅读了整个流。
正如其他人所指出的,当然每个循环构造一个新的流对象也意味着不用担心以前的 flags/states。