Умножение строк в переполнении стека

Здесь уже есть вопрос: Как повторить строку переменное количество раз в C ++? Однако поскольку вопрос был сформулирован плохо, в первую очередь персонаж умножение было дано. Есть два правильных, но дорогих ответа, поэтому я буду уточнять требования здесь.


Perl предоставляет x оператор: http://perldoc.perl.org/perlop.html#Multiplicative-Operators который позволил бы мне сделать это:

$foo = "0, " x $bar;

Я понимаю, что могу сделать это с помощью вспомогательных функций, таких как в другом ответе. Я хочу знать, могу ли я сделать это без моей собственной вспомогательной функции? Моим предпочтением было бы то, что я мог бы инициализировать const string с, но если я не могу этого сделать, я почти уверен, что на это можно было бы ответить стандартным алгоритмом и лямбда-выражением.

2

Решение

Вы можете переопределить оператор умножения

#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;
}

… или используйте лямбду …

#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;
}

… или используйте лямбду с захватом ссылок …

#include <string>
#include <sstream>
#include <iostream>

int main() {
std::string s = "Hello World!";
size_t times = 5;

std::string repeated = [&s, &times]() {std::stringstream stream; for (size_t i = 0; i < times; i++) stream << str; return stream.str(); }();
std::cout << repeated << std::endl;

return 0;
}

Вместо того, чтобы использовать std::stringstream Вы также можете использовать std::string в комбинации с std::string::reserve(size_t) как вы уже знаете (или можете рассчитать) размер строки результата.

std::string repeated; repeated.reserve(str.size() * times);
for (size_t i = 0; i < times; i++) repeated.append(str);
return repeated;

Это может быть быстрее: Сравнить http://goo.gl/92hH9M с http://goo.gl/zkgK4T

3

Другие решения

Это можно сделать, используя только стандартный алгоритм и лямбду с generate_n, но он все еще не может инициализировать const string это нужно сделать отдельной строкой:

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];});

Я создал живой пример здесь: http://ideone.com/uIt2Ee Но, как, вероятно, стало ясно из всех комментариев к вопросу, требование сделать это в одной строке приводит к ухудшению кода. Сразу же, мы видим, что постоянная, 3, представляет размер multiplicand и излишне требует изменений в инициализации multiplicand также обновить этот литерал.

Очевидное улучшение, которое должно быть сделано:

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];
});

Следующим улучшением будет устранение перераспределения как foo растет, что может быть дорого, если bar или же length большой. Это может быть достигнуто путем построения foo с достаточным пространством для размещения всей сгенерированной строки:

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];
});
[Живой пример]
0

По вопросам рекламы [email protected]