There is already a question for this here: How to repeat a string a variable number of times in C++? However because the question was poorly formulated primarily answers about character multiplication were given. There are two correct, but expensive answers, so I'll be sharpening the requirement here.
Perl provides the x
operator: http://perldoc.perl.org/perlop.html#Multiplicative-Operators which would let me do this:
$foo = "0, " x $bar;
I understand that I can do this with the helper functions such as those in the other answer. I want to know can I do this without my own helper function? My preference would be something that I could initialize a const string
with, but if I can't do that I'm pretty sure that this could be answered with a standard algorithm and a lambda.
You can either override the multiplication operator
#include <string>
#include <sstream>
#include <iostream>
std::string operator*(const std::string& str, size_t times)
{
std::stringstream stream;
for (size_t i = 0; i < times; i++) stream << str;
return stream.str();
}
int main() {
std::string s = "Hello World!";
size_t times = 5;
std::string repeated = s * times;
std::cout << repeated << std::endl;
return 0;
}
... or use a lambda ...
#include <string>
#include <sstream>
#include <iostream>
int main() {
std::string s = "Hello World!";
size_t times = 5;
std::string repeated = [](const std::string& str, size_t times) {std::stringstream stream; for (size_t i = 0; i < times; i++) stream << str; return stream.str(); } (s, times);
std::cout << repeated << std::endl;
return 0;
}
... or use a lambda with reference capturing ...
#include <string>
#include <sstream>
#include <iostream>
int main() {
std::string s = "Hello World!";
size_t times = 5;
std::string repeated = [&s, ×]() {std::stringstream stream; for (size_t i = 0; i < times; i++) stream << str; return stream.str(); }();
std::cout << repeated << std::endl;
return 0;
}
Instead of using std::stringstream
you could also use std::string
in combination with std::string::reserve(size_t)
as you already know (or can calculate) the size of the result string.
std::string repeated; repeated.reserve(str.size() * times);
for (size_t i = 0; i < times; i++) repeated.append(str);
return repeated;
This might be faster: Compare http://goo.gl/92hH9M with http://goo.gl/zkgK4T
It is possible to do this using just a standard algorithm and a lambda with generate_n
, but it still cannot initialize a const string
it needs to be done in a separate line:
string foo;
const auto bar = 13U;
generate_n(back_inserter(foo), bar * 3U, [](){
static const char multiplicand[] = "0, ";
static const auto length = strlen(multiplicand);
static auto i = 0U;
return multiplicand[i++ % length];});
I've created a live example here: http://ideone.com/uIt2Ee But as is probably been made plain by all the question comments, the requirement of doing this in a single line results in inferior code. Right off the bat, we can see that the bare constant, 3
, represents the size of multiplicand
and unnecessarily requires changes to the initialization of multiplicand
to also update this literal.
The obvious improvement that should be made is:
string foo;
const auto bar = 13U;
const char multiplicand[] = "0, ";
const auto length = strlen(multiplicand);
generate_n(back_inserter(foo), bar * length, [&](){
static auto i = 0U;
return multiplicand[i++ % length];
});
The next improvement would be eliminating the reallocation as foo
grows, which could be expensive if bar
or length
is large. That can be accomplished by constructing foo
with sufficient space to contain the entire generated string:
const auto bar = 13U;
const char multiplicand[] = "0, ";
const auto length = strlen(multiplicand);
string foo(bar * length, '\0');
generate_n(foo.begin(), bar * length, [&](){
static auto i = 0U;
return multiplicand[i++ % length];
});
[Live Example]