为什么 while(getline(...)) 不对字符串流执行多次?

0 c++

我正在使用 while(getline(...)) 结构将填充有许多制表符的字符串流分解为单独的块以进行数据处理。实际上执行中断的 while 循环对第一行正确运行,但随后不会进入数据集中任何其他行的执行,即使在使用 str() 更新字符串流时也是如此。

我目前正在解析数据集。因为数据集包含许多逗号,并且因为我知道 std::getline() 有一个使用唯一分隔符的参数,所以我选择将数据集导出为 .tsv 而不是通常的 .csv。我取一条线并将其分成每个单元格的逻辑遵循我几乎总是这样做的:

    for (int i = 0; i < 4; i++) {
        counter = 0;
        getline(inputfile, tsvLine);
        lineStream.str(tsvLine);
        while(getline(lineStream, currentChunk, '\t')){
            cout << "[Part: " << ++counter << "] "; 
            cout << currentChunk << endl;
        }
    }
Run Code Online (Sandbox Code Playgroud)

for 循环内的所有内容都是我用于分解 .tsv 行的代码。获取inputfile(一个 ifstream)并将其 getline 到tsvLine(一个字符串)中,使用该字符串来更新 stringstream lineStream。一旦lineStream更新,将其放入由制表符分隔的 while(getline()) 中,以将每个部分分解为 currentChunk 字符串)并将其打印出来。这适用于 .tsv 中的第一行,并正确计数 65 个块。

顶部的 for 循环只是作为占位符放置到位,以便我可以在文件的前四行上运行代码。但是,接下来的三行不会运行。调试显示 tsvLine 已正确更新,lineStream 也已正确更新(我已经完成cout << lineStream.str();验证了这一点),但 while 循环根本没有进入第二次,我非常不确定为什么。

我已经研究过lineStream.ignore();,只需再次调用 getline() 以确保缓冲区已清除,lineStream.str("");然后使用 手动清除它,我什至在不同的第一行上测试了代码,以确保它始终成功读取一行(确实如此)但无论我做什么,我似乎都无法让 while 循环第二次进入。围绕这个主题的许多其他问题似乎都提到要小心cin >>和换行符\n,我故意尝试使用 getline() 来避免。我很茫然。

pad*_*ddy 5

当您替换底层字符串时,它不会清除流状态。处理第一行数据后,您的流将处于错误状态,必须清除该状态。因为您没有这样做,所以该流的所有后续使用都将失败。

您应该能够通过添加对以下内容的调用来解决此问题.clear()

lineStream.str(tsvLine);
lineStream.clear();
Run Code Online (Sandbox Code Playgroud)

但这并不是一种非常 C++ 的方法。通常,您可以在循环内定义对象并使用 RAII 代替:

std::istringStream lineStream(tsvLine);
Run Code Online (Sandbox Code Playgroud)

这为您提供了一个新鲜的对象,并且您无需担心以前使用的脏状态。

旁注:在 for 循环中,您实际上并没有检查该行是否已成功从inputfile. 如果不这样做可能会导致其他问题。