stringstream重复最后一个单词

Kar*_*and 7 c++

我正在尝试使用stringstream分割字符串:

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

using namespace std;

int main(){
    ifstream fp;
    string name;

    fp.open("in.txt");
    while (fp){
        string line;
        getline(fp, line);
        cout << line << endl;
        istringstream line_stream(line);

        while (line_stream){
            line_stream >> name;
            cout << name << " ";
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是in.txt:

cat bat rat sat
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

cat bat rat sat
cat bat rat sat sat
Run Code Online (Sandbox Code Playgroud)

getline()函数中检索到的行是正确的,但在分割的过程中我得到了最后一个单词两次.我不确定为什么会这样.

Jam*_*nze 7

您正在使用结果getline而不检查它是否成功.这是第一个错误(可能会导致您显示的代码出现额外的空行).同样,你使用结果line_stream >> name而不检查它是否成功; 在这种情况下(因为name每次都不是新构造的),您可能最终得到先前读取的值(但在这两种情况下,字符串的内容都未指定).

如果没有先测试是否成功,就必须永远不要使用输入结果.这样做的最常见方式(但肯定不是唯一的方法)是在循环条件下进行输入:

while ( std::getline( fp, line ) ) ...
Run Code Online (Sandbox Code Playgroud)

while ( line_stream >> name ) ...
Run Code Online (Sandbox Code Playgroud)

如果您仍想将变量的范围限制为循环,则必须编写:

while ( fp ) {
    std::string line;
    if ( std::getline( fp, line ) ) {
        //  rest of loop
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您(在某种情况下)修改全局状态(可以理解),您必须写:

std::getline( fp, line );
while ( fp ) {
    //  ...
    std::getline( fp, line );
}
Run Code Online (Sandbox Code Playgroud)

虽然我认为有充分的理由支持这一点,但这个while ( std::getline( fp, line ) )成语无处不在,其他任何东西都会让读者想知道为什么.