std::stringstream clear()与str()踩坑

最近使用std::stringstream 格式化字符串,然后输出打印。使用同一个std::stringsteram挨个序列化输出,并调用str()输出。每次输出后都用clear()清除一下,但是结果没想到的是居然会保存原来的内容。经过自己测试原来真的是这样,测试代码如下。

    std::stringstream ss;
    int temp = -1;
    ss << "1 2 3";
    std::cout << __LINE__ << " " << ss.str() << std::endl;
    ss.clear();
    ss << "4 5 6";
    std::cout << __LINE__ << " " << ss.str() << std::endl;

以上代码输出为

124 1 2 3
127 1 2 34 5 6

因此,经过百度,确实不能用这个clear()来清除内容;而应该使用str(""),该函数定义可以看到是将std::stringstream中的他部内容用传入的字符串进行assgin,这样便能清除内容。更正后如下

    std::stringstream ss;
    int temp = -1;
    ss << "1 2 3";
    std::cout << __LINE__ << " " << ss.str() << std::endl;
    ss.str("");
    ss << "4 5 6";
    std::cout << __LINE__ << " " << ss.str() << std::endl;


    结果为:
    124 1 2 3
    127 4 5 6

这时我做了另外两个测试,如果str("")中的参数不是空字符串呢;经过测试发现std::stringstream会将内容的内存和内容全部替换为传入的字符串,当你后面再使用<<时,依然从std::stringstream的起始位置开始覆盖写入,当内存不够时再按<<所需补充;测试如下

    std::stringstream ss;
    int temp = -1;
    ss << "1 2 3";
    std::cout << __LINE__ << " " << ss.str() << std::endl;
    ss.str("gggggwer");
    ss <<  "4 5 6";
    std::cout << __LINE__ << " " << ss.str() << std::endl;


    结果为:
    124 1 2 3
    127 4 5 6wer

我初始化多了wer时再使用<<,就会发现内容多出了wer;经过多次测试上面结论成立;

再使用少于于后面使用的字符串时就会被覆盖

    std::stringstream ss;
    int temp = -1;
    ss << "1 2 3";
    std::cout << __LINE__ << " " << ss.str() << std::endl;
    ss.str("ggg");
    ss <<  "4 5 6";
    std::cout << __LINE__ << " " << ss.str() << std::endl;


    结果为:
    124 1 2 3
    127 4 5 6

所以std::stringstream应该合理使用str(arg:str)来初始化内部内存与内容,当需要提前开辟空间时可以传入一个固定长度的空字符串(传入\0的字符串 未测试),如果想清空文本与内容那就str("")吧

 

那么clear()怎么用呢,这个求助百度后发现;是在使用>>将字符串转成其它类型的时候用,用于清除内部的eof之类的文件标志位

    std::stringstream ss;
    int temp = -1;
    ss << "1";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;
    ss << "2";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;

    输出结果:
    125 1 1
    128 1 1

如果是这样呢

    std::stringstream ss;
    int temp = -1;
    ss << "1 ";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;
    ss << "2";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;

    结果为:
    125 1 1 
    128 2 1 2

这次达标了,只是在1后面加了个空字符串;

为它加上clear()之后

    std::stringstream ss;
    int temp = -1;
    ss << "1";
    ss >> temp;
    ss.clear();
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;
    ss << "2";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;

    输出为:
    126 1 1
    129 2 12

可以看到当加入clear()后转出的数据正常了,但是ss中的字符串内容已经变成12了,这个可以由上面的str("")来解释;如果变成下面这样

    std::stringstream ss;
    int temp = -1;
    ss << "1";
    ss >> temp;
    ss.clear();
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;
    ss << "2";
    ss << "34";
    ss >> temp;
    ss.clear();
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;
    ss << "56";
    ss >> temp;
    std::cout << __LINE__ << " " << temp << " " << ss.str() << std::endl;

    输出为:
    126 1 1
    131 234 1234
    134 56 123456

由此可见,每次使用>>转出后,ss内部都会记录一个已经转到哪儿了的位置,然后下一次转换就从这个位置开始到转出类型结束位置或者换行或者空格的位置之间的内容转出(可以百度std::stringstream >>结束分隔符)。

到此大概分晰完了,std::stringstream使用>>转出时都会记录转出后的位置,如果是文件末尾了,你后面没使用clear(),你使用<<已经不能再将内容追加到其后了,所以这是你为啥后面的内容都是原来的值的原因。当使用clear()后,如果当前转出记录位置在文件末尾便会清除std::stringstream的eof标记(就是说已经转到末尾了),使得后面你还可以追加内容,下一次又可以从该位置到下一个转出类型的结束位置转数据了。

一句话:当转出数据已经转到std::stringstream末尾了,使用clear(),继续追加内容,继续转;就和一个刚开始的std::stringstream一样;清除内容用str("");

需要注意的有这种情况

    std::stringstream osstr("1 2 3");
    std::vector<std::string> result;
    std::copy(std::istream_iterator<std::string>(osstr),     std::istream_iterator<std::string>(), std::back_inserter(result));
    osstr.str("");
    osstr.clear();
    std::copy(result.begin(), result.end(), std::ostream_iterator<std::string>(osstr, ","));

这种情况osstr中的>>被隐藏到std::copy中去了,当这行代码执行完时,转出后位置已经在末尾了,要使用clear(),另外上面的想法是输出转化后的字符串,所以还有str("");

 

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值