为什么 stringstream ss(s) 与 ss << s 不同?[复制]

Why is stringstream ss(s) different from ss << s? [duplicate]

提问人:Dengzhi Zhang 提问时间:11/1/2023 更新时间:11/1/2023 访问量:111

问:

当我尝试使用字符串流时,例如

#include <iostream>
#include <string>
#include <sstream>

int main() {
    std::string s = "Hello World Test";
    std::stringstream ss(s);

    std::string a, b;
    ss >> a >> b;
    std::cout << a << ' ' << b << std::endl; // Hello World

    ss << " Why Not";
    ss >> a >> b;
    std::cout << a << ' ' << b << std::endl; // Still Hello World

    std::string c, d;
    std::stringstream tt;
    tt << s;

    tt >> c >> d;
    std::cout << c << ' ' << d << std::endl; // Hello World

    tt << " Now Yes";
    tt >> c >> d;  // print Now Yes
    std::cout << c << ' ' << d << std::endl; // Test Now
}

有谁知道为什么字符串蒸汽结构的行为不同?

我希望stringstream可以自由进出。但似乎不是。如果在一个方向上使用,我没有任何问题。

C++ String 构造函数 StringStream Bidirectional

评论

1赞 273K 11/1/2023
Nope godbolt.org/z/en4c1b7b1
0赞 Chris Dodd 11/1/2023
@273K:显示输出的第二行是应该的Test WorldTest Why
0赞 273K 11/1/2023
不是 Hello World
0赞 Ted Lyngmo 11/1/2023
@273K毕竟,这也许值得一提。
0赞 273K 11/1/2023
@TedLyngmo 我找不到手册参考。

答:

5赞 Chris Dodd 11/1/2023 #1

当您从这样的字符串创建字符串流时,默认模式是 -- 表示允许输入或输出,但所有指针都默认指向缓冲区的开头。因此,当你用它写入字符串流时,它会覆盖那里的字符串,而你在末尾的读取将只在末尾运行。in|out<<

如果你这样做

std::stringstream ss(s, std::ios_base::in | std::ios_base::out | std::ios_base::ate);

(添加“at the end”标志)它将更像您预期的那样工作,在初始字符串的末尾开始 pptr。

为什么这不是默认设置有点神秘(可能只是标准中编纂的最早实现中的一个错误,因为没有人愿意破坏与此错误功能的向后兼容性)。

评论

0赞 Dengzhi Zhang 11/2/2023
谢谢克里斯。现在我了解到 istream 指针(tellg, seekg) 和 ostream 指针 (tellp, seekp) 是分开的。实际上,这是我第一次知道 tellg 和 seekg 函数。为什么标准委员会选择 tellg 和 seekg 作为函数名称?我想这是因为字母“g”看起来与字母“p”相反。如果是这样的话,为什么我们没有选择tellq和seekq,至少在我看来更好?
0赞 Chris Dodd 11/2/2023
g代表“get”和“put”——从缓冲区中“获取”数据的位置,以及缓冲区中数据“放置”的位置。p
0赞 Dengzhi Zhang 11/3/2023
哦,谢谢你这么详细的解释。