字符串流有啥意义? [复制]
Posted
技术标签:
【中文标题】字符串流有啥意义? [复制]【英文标题】:What's the point of stringstream? [duplicate]字符串流有什么意义? [复制] 【发布时间】:2016-05-31 18:24:02 【问题描述】:我将保持这个问题非常简单。我正在学习 C++,并且遇到过字符串流。我知道它们的主要用途是将变量输入到它们中,以便它们以后可以使用 str() 作为字符串输出它们保存的值。我的问题是——这有什么意义?这听起来像是一种非常奇特的方式,只需使用 + 运算符连接字符串对象中的一堆变量。它是否有更多的意义,或者它只是让新手感到困惑并导致他们考试不及格?
【问题讨论】:
实用性的完美示例:***.com/questions/236129/split-a-string-in-c 所以它就像连接,除了它还跟踪输入的变量? 它也可以用于取消连接字符串。 太棒了,谢谢!我可以给你点赞吗? 不,但您确实有几个答案可以考虑支持或接受。 【参考方案1】:嗯,一个问题是您不能“使用 + 运算符连接字符串中的一堆变量”(仅适用于其他字符串或 char*s)。
那么,您将如何将所有对象转换为字符串?与 Java 不同,C++ 没有任何 to_string() 成员约定。另一方面,每个对使用 iostream 感兴趣的类都会定义流插入器(std::ostream& operator<<(std::ostream& os, const MyClass& foo)
可能还有std::istream& operator>>(std::istream& os, MyClass& foo)
。)
因此,您使用流插入器将对象转换为文本。有时您不想写入控制台或文件,而是想将其存储为字符串。
此外,使用 iostream 框架可以让您使用操纵器来控制精度、宽度、数字基数等,而不是在构建字符串时尝试手动完成所有这些操作。
现在,这并不是说 stringstream 解决方案是理想的:事实上,存在许多库可以更好地完成相同类型的任务(至少包括 Boost.Format、Boost.Convert、Boost.Lexical_Cast 和 Boost .Spirit 就在 Boost 中。)
【讨论】:
“C++ 没有任何 to_string() 成员约定。” 好吧,那不是entirely true。 @πάνταῥεῖ:“成员”是指在您定义的所有类中创建to_string()
成员函数不是标准的,标准库不会尝试使用此类函数。标准库中存在名为to_string
的函数这一事实并不是真正相关的。您可以为您的类声明免费的 to_string
函数,以便通过 ADL 通用地使用,但 AFAIK 这也不是一个约定——最好使用 boost::lexical_cast 来处理这类事情。
嗯,boost就是boost,c++标准就是c++标准。【参考方案2】:
如果你有:
int a = 3;
std::string str = "hello";
MyObject obj;
然后:
std::string concat = a + str + obj;
std::string objstr = obj;
不起作用,而:
std::stringstream stream;
stream << a << str << obj;
std::string concat = stream.str();
std::stringstream stream2;
stream2 << obj;
std::string objstr = stream2.str();
会起作用(至少如果MyObject
定义了operator<<
)。这就是std::stringstream
的全部意义所在:使将“任何东西”重定向到字符串变得容易。
任何可以重定向到std::ostream
(std::fstream
、std::cout
...)的对象也可以重定向到std:::stringstream
(因为它也派生自̀std::ostream
)。然后你只需要声明一个std::ostream
重定向操作符(operator<<
),它就可以用来在任何地方重定向对象(文件,控制台,还有字符串......)。
重点是您可以声明operator+
和operator+=
,以便将您的对象连接到std::string
。但是,如果您还希望将其重定向到流(文件、cout),则必须声明 3 个运算符(operator+
、operator+=
,最后是 operator<<
用于流),它们几乎都在做同样的事情.最后,感谢std::stringstream
,只有一个运算符(operator<<
)就足以重定向到文件、cout 和字符串。
【讨论】:
通过可变参数模板,我们可以拥有一个函数,该函数使用该代码与任意数量的元素,并轻松调用它以将任意数量的任何类型的参数连接成一个字符串。 所以它在某些方面类似于Java中的toString()?operator<<
类似于 toString()
。 ̀std::stringstream` 可以将 ̀std::string` 用作目标。【参考方案3】:
stringstream 的意义何在?
它是一种灵活且快速的流,可作为其他(相对)慢速流的模拟器。我将 stringstream 用于许多不同的事情。
我最喜欢的用途是测试。我创建了一个 std::istream 并用测试数据填充它。这使我可以使用与我编码相同的编辑器创建测试数据“文件”(并且没有实际文件污染我的工作目录)。添加更多测试用例的耗时明显减少。
// 012345678901234567890123456789012345678901234567890
std::istringstream iss("7 ((23, 342), (17, 234), (335, 159), (10, 10))");
// ---|^^^^^^^|^v|vvvvvvv|v^|^^^^^^^^|^v|vvvvvv|^
// 1 2 3 4
// echo to user of test
std::cout << "Test Data Input: " << iss.str() << std::endl ;
// code under test starts here ...
int nTowns = 1;
char lparen0 = 2;
iss >> nTowns // NOTE : formatted input drops whitespace
>> lparen0;
// and continues with echo of post conversion
std::cout << " 0: " << nTowns << ' ' << lparen0 << std::endl;
// then more of the same - until record is completely read.
我已经使用 stringstream 来构建屏幕更新,并使用该动态变化的字符串来“测量”横幅宽度,并计算在屏幕上开始放置的位置,以便横幅居中(或左侧或右侧) :
static void centerUpdateScreenBanner( uint64_t gen,
int pdMS,
int changes,
TC_t& tc)
// build contents of screen banner update
std::stringstream ss;
ss << std::setw(3) << pdMS << " "
<< std::setw(4) << gen << " "
<< std::setw(4) << changes;
// compute start column placement for centering
int rCol = tc.maxCol -
static_cast<int>(ss.str().size()) +
tc.DfltIndnt-1;
// send banner to terminal device for user info
tc.termRef << Ansi_t::gotoRC(0, rCol) // top right
<< ss.str() << std::flush;
在这个链接列表中,我使用一个字符串流来吸收和递归连接列表节点信息。虽然这是递归构建的,但其他 cout 或 cerr 可以不受阻碍地继续进行 - 就像第三个通道一样。
std::string showR(void)
std::stringstream ss;
ss << m_payload->show(); // this node
if(m_next) ss << m_next->showR(); // subsequent nodes
return (ss.str());
总结:我发现 std::stringstream 非常有用。
【讨论】:
以上是关于字符串流有啥意义? [复制]的主要内容,如果未能解决你的问题,请参考以下文章