stringstream 两次输入输出,无法正常工作

Stringstream两次输入输出,无法正常工作

连续使用stringstream写和读,会出现错误

int main() {
    stringstream ss;
    string s = "123";
    int a;
    ss << s;
    ss >> a;										//123
    cout << ss.str() << endl;   //123
    ss << s;                    //error
    cout << ss.str() << endl;   //实际123 预期123123
}

但是,如果在第二次写之前,把stringstream的状态复位,就可以正常执行了,代码如下:

int main() {
    stringstream ss;
    string s = "123";
    int a;
    ss << s;
    ss >> a;										//123
    cout << ss.str() << endl;   //123
    ss.clear();
    ss << s;                    
    cout << ss.str() << endl;   //123123
}

所以,这跟stringstream在进行读写的时候的状态置位有关了,所以要看看stringstream的读写逻辑。

先上一张stringstream的继承关系图

image-20220225105555325

根据cppreferance,stringstream中>>的功能是继承自istream

我们来看看istream>>是怎么执行的,对于流输入到数值类型的时候,>>执行的工作如下

Extracts and parses characters sequentially from the stream to interpret them as the representation of a value of the proper type, which is stored as the value of val.
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to false). Then (if good), it calls num_get::get (using the stream’s selected locale) to perform both the extraction and the parsing operations, adjusting the stream’s internal state flags accordingly. Finally, it destroys the sentry object before returning.

----cppreference

简单来说,流输入进行的条件是good为1,因此,stringstream无法工作的原因是在进行第二次写操作的时候,good不为1。

那么,我们首先得看看,good是什么

image-20220225100604542

最左边的一列表示iostate(io状态)的各位(因为状态iostate是由四个状态位逻辑或组成),每一位被置位之后,不同的状态确认函数(第三列)就会有不同的返回值,这之中包括了good()函数。

所以,stringstream无法工作的原因就是因为其他状态位(eofbit、failbit或者badbit)被置位了,那什么时候这些状态位会被改变呢?

我们可以看看上表的第二列,它描述了什么时候某一位会被置位。而且,对应的状态确认函数会有不一样的结果。所以,我们可以根据状态确认函数的结果来判断出现了什么情况。

int main() {
    stringstream ss;
    string s = "123";
    int a;
    ss << s;
    ss >> a;
    std::cout << std::boolalpha
              << "\nss.eof()  = " << ss.eof()
              << "\nss.good() = " << ss.good()
              << "\nss.bad()  = " << ss.bad()
              << "\nss.fail() = " << ss.fail();
}

结果

ss.eof()  = true
ss.good() = false
ss.bad()  = false
ss.fail() = false

所以,我们可以通过查表得知当前状态位被置位的原因是读到了EOF(文件结束符)。

那么到这里我们程序的问题就已经解决了,即第二次写无法写的原因是由于第一次读的时候读到了eof,导致eofbit位被置位,因而good函数返回值为false,导致接下来的流输入无法进行。

但是,为什么平时cin(实际上是istream的一个实例),但是平时普通使用的时候不会遇到eof的问题?这是因为,每次cin的时候都会有一个回车,而cin到回车就不会继续读下去了,因此读不到EOF

所以也许我们在使用stringstream的时候应该都带上回车以避免上述问题?

例如:

int main() {
    stringstream ss;
    string s = "123";
    int a;
    ss << s << endl;
    ss >> a;							//123
    s += "321";
    ss << s;
    ss >> a;
    cout << a << endl;		//123321
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值