C++ Stringstream 只拾取第一个字符串

moc*_*de9 4 c++ string stream

我有一个文本文件,其中包含一系列两个字符串,每行以冒号分隔。

我使用 getline 来抓取整行,然后使用字符串流来拆分两个字符串并将它们放到一个向量上。该代码在第一遍时运行良好,它完美地抓取了字符串。然后在 while 循环的第二遍之后,依此类推,它不会获取新的输入。由于某种原因,字符串流似乎保留了原始的第一个值。

 if (infile.is_open()) {
    std::stringstream ss;
    std::string current_line;
    std::string tempProxy;
    std::string tempPort;

    while (std::getline(infile, current_line)) {
        ss << current_line;
        std::getline(ss, tempProxy, ':');
        std::getline(ss, tempPort);
        std::cout << tempProxy << " and " << tempPort << std::endl;
    }
Run Code Online (Sandbox Code Playgroud)

知道为什么它不想在第一次迭代之外的任何传递中从 current_line 中获取字符串吗?

bam*_*s53 5

您正在重用ss但未正确重置它。当您从第一行中提取第二个单词时,流将耗尽并处于“EOF”状态。当流处于此或任何其他“错误”状态时,它们不会执行任何操作。您必须先清除错误,然后才能继续使用它们。

如果你要检查通过返回的错误operator<<getline(或如果你要引起循环ss扔在错误异常*),你会发现他们表示他们都没有成功过一次迭代。始终检查错误是一个很好的一般做法,尤其是在调试时。

您可以通过更改循环来清除错误:

while (std::getline(infile, current_line)) {
    ss.clear(); // clears the error, not the contents
    ss << current_line;
Run Code Online (Sandbox Code Playgroud)

然而,这样做意味着ss将在其内部缓冲区中累积所有行。除非文件很大并且内存不足或类似的东西,否则代码将产生您预期的输出。

您可以使用以下内容查看累积的内部缓冲区:

while (std::getline(infile, current_line)) {
    ss.clear();
    ss << current_line;
    std::cout << "ss internal buffer: " << ss.str();
Run Code Online (Sandbox Code Playgroud)

而不是使用格式化输入来添加ss您可能最好使用.str()成员来设置它,这将替换以前的数据而不是添加到它。

while (std::getline(infile, current_line)) {
    ss.clear();
    ss.str(current_line);
Run Code Online (Sandbox Code Playgroud)

或者,您可以stringstream在循环的每次迭代中构造一个新的。这确实确保没有错误状态或数据从先前的迭代中被遗留下来。它也可能更慢,但你必须自己分析。

while (std::getline(infile, current_line)) {
    std::stringstream ss(current_line);
Run Code Online (Sandbox Code Playgroud)

* 异常很好,因为你不需要记住检查它们......除非在默认情况下它们没有启用的情况。此外,我还注意到一些 C++ 实现在其 iostreams 异常代码中存在错误,因为人们很少使用它。