As I know that C++ only allows to add 2 strings together, i.e:
s = s1 + s2
But how can I add many strings together? Like:
s = s1 + s2 + s3 + s4 + ... + sn
If you're trying to append string objects of std::string class, this should work.
string s1 = "string1";
string s2 = "string2";
string s3 = "string3";
string s = s1 + s2 + s3;
OR
string s = string("s1") + string("s2") + string("s3") ...
operator+(std::basic_string<t>, std::basic_string<t>) you will incur exponential time in C++03. Using the std::basic_string<t>::append member function takes only linear time in comparison.string, so string("s1") + "s2" + "s3" will also work. The reason is that normal string constants like "s1" are of type const char*, and you can't just add such pointers together. string objects on the other hand know how to add a const char* to form a new string. (Also: Nothing will use exponential time here, so don't worry too much about that)First of all, you can do the +sn thing just fine. Though it's going to take exponential quadradic(see comments) time assuming you're using std::basic_string<t> strings on C++03.
You can use the std::basic_string<t>::append in concert with std::basic_string<t>::reserve to concatenate your string in O(n) time.
EDIT: For example
string a;
//either
a.append(s1).append(s2).append(s3);
//or
a.append("I'm a string!").append("I am another string!");
append will be faster, but in general quadratic anyway because it needs to reallocate form time to time. In the very most cases both methods won't be slow enough to be noticeable, though.(0*N + N) + (1*N + N) + (2*N + N) + ... + ((K-1)*N + N) which equals (1+2+...+(K-1)) * N + K*N = (K*(K-1)/2) * N + K*N = ((K^2 + K) / 2) * N = O(K^2 * N). So it is quadratic in the number of parts K. In the number of characters in each part, N, it is linear.append(): I seem to have missed that you mentioned reserve(). Used with reserve() it is indeed linear.append takes linear amortized time which is way faster than quadratics = s1 + s2 + s3 + .. + sn;
will work although it could create a lot of temporaries (a good optimizing compiler should help) because it will effectively be interpreted as:
string tmp1 = s1 + s2;
string tmp2 = tmp1 + s3;
string tmp3 = tmp2 + s4;
...
s = tmpn + sn;
An alternate way that is guaranteed not to create temporaries is:
s = s1;
s += s2;
s += s3;
...
s += sn;
std::ostringstream is build for that, see example here. It's easy:
std::ostringstream out;
out << "a" << "b" << "c" << .... << "z";
std::string str( out.str());
Use a template to add strings, char* and char's to form a string
strlen:-
#include <iostream>
#include <cstring>
// it_pair to wrap a pair of iterators for a for(:) loop
template<typename IT>
class it_pair
{
IT b;
IT e;
public:
auto begin() const
{
return b;
}
auto end() const
{
return e;
}
};
// string length
template<typename S> auto strlen(const S& s) -> decltype(s.size())
{
return s.size();
}
auto strlen(char c) -> size_t
{
return 1u;
}
auto strlen(const std::initializer_list<char>& il) -> size_t
{
return il.size();
}
template<typename IT>
auto strlen(const it_pair<IT>& p)
{
auto len = size_t{};
for(const auto& s:p)
len += strlen(s);
return len;
}
template<typename S, typename ...SS> auto strlen(S s, SS&... ss) -> size_t
{
return strlen(s) + strlen(ss...);
}
appending strings
// terminate recursion
template<typename TA, typename TB>
void append(TA& a, TB& b)
{
a.append(b);
}
// special case for a character
template<>
void append<std::string, const char>(std::string& a, const char& b)
{
a.append(1, b);
}
// special case for a collection of strings
template<typename TA, typename TB>
void append(TA& a, const it_pair<TB>& p)
{
for(const auto& x: p)
a.append(x);
}
// recursion append
template<typename TA, typename TB, typename ...TT>
void append(TA& a, TB& b, TT&... tt)
{
append(a, b);
append(a, tt...);
}
template<typename ...TT>
std::string string_add(const TT& ... tt)
{
std::string s;
s.reserve(strlen(tt...));
append(s, tt...);
return s;
}
template<typename IT>
auto make_it_pair(IT b, IT e)
{
return it_pair<IT>{b, e};
}
template<typename T>
auto make_it_pair(const T& t)
{
using namespace std;
return make_it_pair(cbegin(t), cend(t));
}
main example
int main()
{
const char * s[] = {"vw", "xyz"};
std::vector<std::string> v{"l", "mn", "opqr"};
std::string a("a");
std::string b("bc");
std::string c("def");
std::cout << string_add(a, b+c, "ghij", make_it_pair(v), 'k', make_it_pair(s));
}
If you want to be able to do this
Then this will do the job
auto s = std::string(s1).append(s2).append(s3).append(sn);
And if you like things nicely formatted
auto s = std::string(s1).append(s2)
.append(s3)
.append(sn)
"asd" "123"becomes"asd123". But run-time addition of strings requires you use the string class.