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

Posted

技术标签:

【中文标题】C++ Stringstream 只拾取第一个字符串【英文标题】:C++ Stringstream only picking up first string 【发布时间】:2017-05-23 00:26:26 【问题描述】:

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

我使用 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;
    

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

【问题讨论】:

为什么ss,tempProxytempPort 在外部范围内?为什么ss 不是std::istringstream 简单地从current_line 构造? 这很奇怪,我认为在循环外构造一次字符串流并使用 >> 运算符为其提供一个新流将比每次通过循环构造它更有效。 【参考方案1】:

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

如果您要检查循环中operator&lt;&lt;getline 返回的错误(或者如果您要导致ss 在错误时抛出异常*),您会发现它们表明它们不成功经过第一次迭代。始终检查错误是一个很好的常规做法,尤其是在调试时。

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

while (std::getline(infile, current_line)) 
    ss.clear(); // clears the error, not the contents
    ss << current_line;

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

您可以通过以下方式查看累积的内部缓冲区:

while (std::getline(infile, current_line)) 
    ss.clear();
    ss << current_line;
    std::cout << "ss internal buffer: " << ss.str();

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

while (std::getline(infile, current_line)) 
    ss.clear();
    ss.str(current_line);

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

while (std::getline(infile, current_line)) 
    std::stringstream ss(current_line);

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

【讨论】:

【参考方案2】:

我认为您正在寻找类似的东西:

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

    while (std::getline(infile, current_line)) 
        std::stringstream to_split;
        to_split.str(current_line);
        std::getline(to_split, tempProxy, ':');
        std::getline(to_split, tempPort);
        std::cout << tempProxy << " and " << tempPort << std::endl;
    

【讨论】:

这很奇怪,我认为在循环外构造一次字符串流并使用 >> 运算符为其提供一个新流将比每次通过循环构造它更有效。但它似乎只对你有用,而不是我的。

以上是关于C++ Stringstream 只拾取第一个字符串的主要内容,如果未能解决你的问题,请参考以下文章

❥关于C++之stringstream典型用法

❥关于C++之stringstream典型用法

C++使用stringstream分割字符串

在 C++ 中使用 stringstream 获取字符串中的所有 N 个连续字符

使用 ostringstream 或 stringstream 将 C++ Int 转换为字符串

c++字符串转化为数字