我要保持这个问题非常简单。我正在学习C ++,而且我遇到过串流。我知道它们的主要用途是将变量输入到它们中,以便稍后可以使用str()作为字符串输出它们保存的值。我的问题是 - 这有什么意义?这听起来像是一种非常奇特的方式,只需使用+运算符连接字符串对象中的一堆变量。它是否比它更多还是它只是因为它混淆了新手而导致他们考试不及格?
答案 0 :(得分:6)
好吧,一个问题是你不能“使用+运算符”连接字符串中的一堆变量“(只有其他字符串或char *)。
那么,您如何将所有对象转换为字符串?与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中。)
答案 1 :(得分:5)
如果你有:
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
(因为它派生自{ {1}}也是。然后你只需要声明一个std::ostream
重定向操作符(std::ostream
),它可以用来将对象重定向到任何地方(文件,控制台,还有字符串......)。
重点是您可以声明operator<<
和operator+
,以便将对象连接到operator+=
。但是,如果您还希望将其重定向到流(文件,cout),则必须为流声明3个运算符(std::string
,operator+
和最后operator+=
),所有人都在做同样的事情。最后,感谢operator<<
,只有一个运算符(std::stringstream
)足以重定向到file,cout和string。
答案 2 :(得分:0)
串流的重点是什么?
它是一个灵活而快速的流,可以作为其他(相对)慢流的模拟器。我将stringstream用于许多不同的事情。
我最喜欢的用途是测试。我创建了一个std :: istream并用测试数据填充它。这允许我创建测试数据文件&#39;使用我编码的相同编辑器(并没有实际文件污染我的工作目录)。添加更多测试用例的时间非常短。
// 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来构建屏幕更新,并使用该动态更改字符串来衡量&#39;横幅宽度,并计算在屏幕上开始放置的位置,以便横幅居中(或左或右):
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非常有用。