为什么stringstream有这种行为?

时间:2015-07-19 21:31:15

标签: c++ string stringstream

我有一个类似的代码,关于stringstream。我发现了一个奇怪的行为:

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
  int     p, q;
  fstream file;
  string  str;
  stringstream sstr;

  file.open("file.txt", ios::in);
  if(file.is_open()) {
    while(getline(file, str)) {
      sstr << str;
      sstr >> p >> q;
      cout << p << ' ' << q << endl;
      sstr.str("");
    }
  }
  file.close();

  return 0;
}

假设我将file.txt设为

4 5

0 2

在第一行中5之后返回,第二行中返回2。该计划给了我:

4 5

4 5

表示未正确分配pq。但我每次sstr.str()检查时都会检查该行的正确字符串。

为什么stringstream有这样的行为?

3 个答案:

答案 0 :(得分:3)

在读取第二个整数后,流处于非良好状态,因此您必须在恢复之前重置其错误状态。

你真正的错误是没有检查输入操作的返回值,或者你会立即发现它!

更简单的解决方案可能是不尝试重用相同的流,而是每轮重新创建它:

for (std::string line; std::getline(file, line); )
{
    std::istringstream iss(line);
    if (!(iss >> p >> q >> std::ws) || !iss.eof())
    {
        // parse error!
        continue;
    }
    std::cout << "Input: [" << p << ", " << q << "]\n";
}

答案 1 :(得分:1)

当您阅读p,然后q时,您会到达流的末尾并设置标记eofbit,您无法再执行任何操作了。 只需clear()它,您的代码就会按预期运行。

但您可能希望直接使用file,而file.close();会在if中有更好的位置:

fstream file;
file.open("file.txt", ios::in);
if(file.is_open()) {
  int p, q;
  while(file >> p >> q) {
    cout << p << ' ' << q << endl;
  }
  file.close();
}

答案 2 :(得分:0)

您的代码有一些冗余行:fstream可以在定义期间打开,并且不需要显式文件close(),因为它会在main()结束时自动销毁。

此外,在您的文件阅读循环中,如果您要为每一行初始化新的sstr << str,则应将stringstream sstr(line);行替换为stringstream,这将构成以下行: sstr.str("");也是多余的。

应用上述更正,以下是您的代码:

int main() {

   int p, q;
   fstream file("file.txt", ios::in);

   // check status
   if (!file) cerr << "Can't open input file!\n"; 

   string line;

   // read all the lines in the file
   while(getline(file, line)) {

       // initialize the stringstream with line
       stringstream sstr(line);

       // extract line contents (see Note)
       while (sstr >> p >> q) { 

           // print extracted integers to standard output
           cout <<"p: " << p <<" q: "<< q << endl;
       }
   }

   return 0;
}

注意:行while (sstr >> p >> q)假定一行只包含整数,用空格分隔。