【问题标题】:Difference between initializations stringstream.str( a_value ) and stringstream << a_value初始化 stringstream.str( a_value ) 和 stringstream << a_value 之间的区别
【发布时间】:2012-11-13 13:02:48
【问题描述】:

考虑:

std::string        s_a, s_b;

std::stringstream  ss_1, ss_2;

// at this stage:
//     ss_1 and ss_2 have been used and are now in some strange state
//     s_a and s_b contain non-white space words

ss_1.str( std::string() );
ss_1.clear();

ss_1 << s_a;
ss_1 << s_b;

// ss_1.str().c_str() is now the concatenation of s_a and s_b, 
//                    <strike>with</strike> without space between them

ss_2.str( s_a );
ss_2.clear();

// ss_2.str().c_str() is now s_a

ss_2 << s_b;  // line ***

// ss_2.str().c_str() the value of s_a is over-written by s_b 
// 
// Replacing line *** above with "ss_2 << ss_2.str() << " " << s_b;"
//                    results in ss_2 having the same content as ss_1.

问题:

  1. stringstream.str(a_value); 有什么区别和 字符串流

  2. 为什么 ss_1 会自动获得 s_a 和 s_b 之间的空白,但是 我们是否需要在可能的行中显式添加空格 替换行***:ss_2 &lt;&lt; ss_2.str() &lt;&lt; " " &lt;&lt; s_b;?

【问题讨论】:

  • 在您的示例中,您的字符串为空。 automatically get white-space between s_a and s_b 是什么意思?
  • @JesseGood // s_a and s_b contain non-white space words

标签: c++ initialization concatenation stringstream


【解决方案1】:

您遇到的问题是因为std::stringstream 默认使用ios_base::openmode mode = ios_base::in|ios_base::out 构造,这是一个非附加 模式。

你对这里的输出模式感兴趣(即:ios_base::openmode mode = ios_base::out

std::basic_stringbuf::str(const std::basic_string&lt;CharT, Traits, Allocator&gt;&amp; s) 以两种不同的方式运行,具体取决于openmode

  1. mode &amp; ios_base::ate == false:(即:非附加输出流):

    str 将设置pptr() == pbase(),以便后续输出将覆盖从 s 复制的字符

  2. mode &amp; ios_base::ate == true:(即:追加输出流):

    str 将设置pptr() == pbase() + s.size(),以便后续输出将追加到从 s 复制的最后一个字符

(注意这个追加模式是c++11以后的新模式)

更多详情请见here

如果您想要 附加 行为,请使用 ios_base::ate 创建您的 stringstream

std::stringstream ss(std::ios_base::out | std::ios_base::ate)

这里是简单的示例应用程序:

#include <iostream>
#include <sstream>

void non_appending()
{
    std::stringstream ss;
    std::string s = "hello world";

    ss.str(s);
    std::cout << ss.str() << std::endl;

    ss << "how are you?";
    std::cout << ss.str() << std::endl;
}

void appending()
{
    std::stringstream ss(std::ios_base::out | std::ios_base::ate);
    std::string s = "hello world";

    ss.str(s);
    std::cout << ss.str() << std::endl;

    ss << "how are you?";
    std::cout << ss.str() << std::endl;
}

int main()
{
    non_appending();
    appending();

    exit(0);
}

这将以上述两种不同的方式输出:

hello world
how are you?
hello world
hello worldhow are you?

【讨论】:

  • 另一种不修改openmode的方法是在插入之前寻找到流的末尾。 ss.str(s); ss.seekp(0, std::ios_base::end); ss &lt;&lt; "how are you?";
  • 谢谢;小调整:在 non_appending() 中,如果第一次初始化更长,例如 std::string s = "A very long hello world!"; 那么第二行输出将是:"你好吗?世界你好!”
  • @user1823664 - 要了解这里发生了什么,您需要了解stringstream's streambuffer 使用内部指针来存储缓冲区中的位置。 str() 使用这些指针创建一个新的 std::string - 并且取决于 egptrpptr 的位置,您将从这些指针中获得一个字符串。
【解决方案2】:

建议您阅读字符串流参考:http://en.cppreference.com/w/cpp/io/basic_stringstream

std::stringstream::str() 替换底层字符串的内容

operator&lt;&lt; 将数据插入流中。

【讨论】:

  • 仍然没有解释为什么str() 后跟&lt;&lt; 有这样的行为,除非我误读了一些东西
  • 另外一件事是使用str()后,事情变得不同步了。例如,在一个新实例上使用str(),后跟operator&lt;&lt; 将在开头插入第二部分,覆盖第一部分。 ideone.com/OPR9Ps
  • 他在问为什么调用operator&lt;&lt; 之后 使用str 替换内容没有追加到最后 - 答案是因为openmode 没有设置ate
猜你喜欢
  • 1970-01-01
  • 2010-12-11
  • 2018-10-29
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
相关资源
最近更新 更多