C++ 如何从std::vector构造std::string<;字符串>;?
我想从C++ 如何从std::vector构造std::string<;字符串>;?,c++,stl,string-concatenation,stringstream,stdstring,C++,Stl,String Concatenation,Stringstream,Stdstring,我想从std::vector构建一个std::string 我可以使用std::stringsteam,但想象一下有一种更短的方法: std::string string_from_vector(const std::vector<std::string> &pieces) { std::stringstream ss; for(std::vector<std::string>::const_iterator itr = pieces.begin();
std::vector
构建一个std::string
我可以使用std::stringsteam
,但想象一下有一种更短的方法:
std::string string_from_vector(const std::vector<std::string> &pieces) {
std::stringstream ss;
for(std::vector<std::string>::const_iterator itr = pieces.begin();
itr != pieces.end();
++itr) {
ss << *itr;
}
return ss.str();
}
std::string string_from_vector(const std::vector&pieces){
std::stringstream-ss;
对于(std::vector::const_迭代器itr=pieces.begin();
itr!=碎片。结束();
++itr){
ss您可以使用
标题中的标准函数(其工作原理是为字符串
定义了运算符+
重载,返回其两个参数的串联):
为什么不直接使用operator+将它们添加到一起
std::string string_from_vector(const std::vector<std::string> &pieces) {
return std::accumulate(pieces.begin(), pieces.end(), std::string(""));
}
std::string string_from_vector(const std::vector&pieces){
返回std::accumulate(pieces.begin()、pieces.end()、std::string(“”);
}
STD::Stand使用默认的STD::加上两个字符串,在C++中加上,因为操作符+重载STD::/P>< P>用C++ 11,<强> String Strue方法不太吓人:
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <iostream>
int main()
{
std::vector<std::string> v{"Hello, ", " Cruel ", "World!"};
std::stringstream s;
std::for_each(begin(v), end(v), [&s](const std::string &elem) { s << elem; } );
std::cout << s.str();
}
#包括
#包括
#包括
#包括
#包括
int main()
{
向量v{“你好”,“残忍”,“世界!”;
std::strings;
std::for_each(begin(v)、end(v),[&s](const std::string&elem){s C++03
std::字符串s;
对于(std::vector::const_迭代器i=v.begin();i!=v.end();++i)
s+=*i;
返回s;
C++11(MSVC 2010子集)
std::字符串s;
std::for_each(v.begin()、v.end()、[&](const std::string&piece){s+=piece;});
返回s;
C++11
std::字符串s;
对于(常数自动和工件:v)s+=工件;
返回s;
不要使用std::acculate
进行字符串连接,这是一个经典,甚至比C中使用strcat
的常见示例更糟糕。如果没有C++11移动语义,向量的每个元素都会产生两个不必要的累加器副本。即使使用移动语义,也会产生一个不必要的累加器副本每个元件的蓄能器
上面的三个例子是O(n)
std::accumulate
对于字符串是O(n²)
通过提供一个
自定义函子:
std::string s = std::accumulate(v.begin(), v.end(), std::string{},
[](std::string &s, const std::string &piece) -> decltype(auto) { return s += piece; });
请注意,s
必须是对非常量(lambda返回类型)的引用
必须是引用(因此decltype(auto)
),正文必须使用
+=
不是+
C++20
在C++20的当前草案中,std::acculate
的定义是在附加到累加器时使用std::move
,因此从C++20开始,acculate
将O(n)用于字符串,并且可以用作一行程序:
std::string s = std::accumulate(v.begin(), v.end(), std::string{});
我个人的选择是基于范围的for循环,如中所示
Boost还提供了一个很好的解决方案:
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> v{"first", "second"};
std::string joined = boost::algorithm::join(v, ", ");
std::cout << joined << std::endl;
}
#包括
#包括
#包括
int main(){
向量v{“第一”、“第二”};
std::string join=boost::algorithm::join(v,“,”);
std::cout晚会有点晚,但我喜欢我们可以使用初始值设定项列表的事实:
std::string join(std::initializer_list<std::string> i)
{
std::vector<std::string> v(i);
std::string res;
for (const auto &s: v) res += s;
return res;
}
Google Abseil有函数absl::StrJoin,可以满足您的需要
他们文件中的示例。
请注意,分隔符也可以是“”
//std::vector v={“foo”、“bar”、“baz”};
//std::string s=absl::StrJoin(v,“-”);
//预期均衡器(“foo-bar-baz”,s);
如果不需要尾随空格,请将
中定义的累积
与自定义联接lambda一起使用
#包括
#包括
#包括
使用名称空间std;
int main(){
向量v;
字符串s;
v、 推回(字符串(“费用”);
v、 向后推(字符串(“fi”);
v、 向后推(字符串(“foe”);
v、 向后推(字符串(“fum”);
s=累加(开始(v)、结束(v)、字符串(),
[](字符串lhs,常量string&rhs){返回lhs.empty()?rhs:lhs+''+rhs;}
);
对于(…){res+=*it;}
?可爱但粗心。它将为每个操作分配一个新字符串,因为它使用运算符+
并生成一个新字符串,而不是运算符+=
来修改现有的字符串。我编写了一个库,它将使用s=v | sum();
内部使用+=
而不是+
;-)@BenjaminLindley实际上并不适用于每个,因为大多数实现仅两倍于每个realloc+1使用free begin()end()的能力而不是.begin.end成员函数。@PSIAlt:再次读取它,它会为每个操作分配一个新字符串,因为每个操作都会生成一个新字符串。倍增大小优化不会影响这一点。BenjaminLindley:他说的是字符串如何“倍增”当你在里面放太多的时候,它就是容量。我会把函数命名为to_string
,而不是string\u from_vector
。我可能也会,但这是原始问题中使用的名称。为什么不使用for(auto&I:v){s为什么还要使用stringstream呢?将s
设为字符串,并将lambda{s+=elem}
@Oktalist no!这是Schlemiel the painter悲观化的教科书示例。@v.oddou它不是Schlemiel the painter,因为std::string
知道它自己的长度。它不必迭代s
来找到空终止符。不过,可以通过使用std::string::reserve
来改进它,以避免重复s
的分配。另请参见上面我的得票最多(但未被接受)的答案。@Oktalist ok显然在考虑end()-begin()时是有保证的所以不要介意我的废话。为什么你要用std::initializer\u list
而不是std::vector
?另外,我认为你不需要复制向量,这样就可以通过常量引用传递。@jb initlist或vectors都是错误的。处理集合的函数应该包含范围。通过应用
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> v{"first", "second"};
std::string joined = boost::algorithm::join(v, ", ");
std::cout << joined << std::endl;
}
std::string join(std::initializer_list<std::string> i)
{
std::vector<std::string> v(i);
std::string res;
for (const auto &s: v) res += s;
return res;
}
join({"Hello", "World", "1"})
// std::vector<std::string> v = {"foo", "bar", "baz"};
// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s);
fee fi foe fum