如何从 std::vector 构造一个 std::string<string>?
How to construct a std::string from a std::vector<string>?
我想从std::vector<std::string>
构建一个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();
}
我还能怎么做呢?
c++ 03
std::string s;
for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
s += *i;
return s;
c++ 11 (MSVC 2010子集)
std::string s;
std::for_each(v.begin(), v.end(), [&](const std::string &piece){ s += piece; });
return s;
<标题> c++ 11 h1> strong>不要使用std::accumulate
进行字符串连接,这是一个经典的Schlemiel the Painter算法,甚至比在C中使用strcat
的通常示例更糟糕。没有c++ 11的移动语义,它会为向量的每个元素产生两个不必要的累加器副本。即使使用move语义,它仍然会为每个元素产生一次不必要的累加器拷贝。
上面三个例子是O(n)。
std::accumulate
is O(n²) for string .
<标题> C + + 20您可以通过提供a来使
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
必须是对非const (lambda返回类型)的引用必须是引用(因此decltype(auto)
),并且主体必须使用+=
not+
.
在预计成为c++ 20的当前草案中,std::accumulate
的定义被修改为在追加到累加器时使用std::move
,因此从c++ 20开始,accumulate
对于字符串将为O(n),并且可以作为一行代码使用:
std::string s = std::accumulate(v.begin(), v.end(), std::string{});
标题>标题>您可以使用<numeric>
头文件中的std::accumulate()
标准函数(它可以工作,因为为string
定义了operator +
的重载,它返回其两个参数的连接):
#include <vector>
#include <string>
#include <numeric>
#include <iostream>
int main()
{
std::vector<std::string> v{"Hello, ", " Cruel ", "World!"};
std::string s;
s = accumulate(begin(v), end(v), s);
std::cout << s; // Will print "Hello, Cruel World!"
}
或者,您可以使用更有效的小for
循环:
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::vector<std::string> v{"Hello, ", "Cruel ", "World!"};
std::string result;
for (auto const& s : v) { result += s; }
std::cout << result; // Will print "Hello, Cruel World!"
}
我个人的选择是基于范围的for循环,如Oktalist的答案。
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;
}
这个打印:
第一,第二
为什么不直接使用运算符+将它们相加呢?
std::string string_from_vector(const std::vector<std::string> &pieces) {
return std::accumulate(pieces.begin(), pieces.end(), std::string(""));
}
std::accumulate默认在底层使用std::plus,在c++中,添加两个字符串是串联的,因为std::string重载了+操作符。
Google Abseil有函数absl::StrJoin,做你需要的。
头文件中的例子。注意分隔符也可以是""
// std::vector<std::string> v = {"foo", "bar", "baz"};
// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s);
有点晚了,但我喜欢我们可以使用初始化器列表的事实:
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;
}
然后你可以调用(Python风格):
join({"Hello", "World", "1"})
如果不需要尾随空格,则使用<numeric>
中定义的accumulate
和自定义连接lambda。
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
int main() {
vector<string> v;
string s;
v.push_back(string("fee"));
v.push_back(string("fi"));
v.push_back(string("foe"));
v.push_back(string("fum"));
s = accumulate(begin(v), end(v), string(),
[](string lhs, const string &rhs) { return lhs.empty() ? rhs : lhs + ' ' + rhs; }
);
cout << s << endl;
return 0;
}
输出:fee fi foe fum
在c++11中,stringstream的方式并不太可怕:
#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();
}
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- std中有类似find_last_of的函数,而string中没有
- 使用 std::string () const 函数启动线程或未来
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 如何更改大小(std::string)
- std::string 的对象真的可以移动吗?
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- 确切地说,如何解释 std::getline(stream, string) 函数在C++中填充的字符串
- C++:考虑C++ std::string 中双引号 (") 的字面含义,而不使用反斜杠 (\)
- 'int main(int, int, std::__cxx11::string, std::__cxx11::string)'只需要零或两个参数 [-Wmain]
- C++ 在列表和列表之间选择返回类型<<string>std::p air<string,string>>
- std::string, std::wstring and UTF8
- uan inplace replacement of std::string/std::wstring?
- #define Glib::string std:wstring
- 从 std::string & std::wstring 中获取 char 整数值
- BSTR转换为std::string(std::wstring),反之亦然