2016-02-19 63 views
2

这里已经有一个问题:How to repeat a string a variable number of times in C++?但是因为这个问题很少公式化,主要是关于字符乘法的回答。有两个正确的,但昂贵的答案,所以我会在这里锐化需求。在C++中的字符串乘法


Perl提供了x操作:http://perldoc.perl.org/perlop.html#Multiplicative-Operators这将让我做到这一点:

$foo = "0, " x $bar; 

我知道我可以,如在对方的回答与辅助功能做到这一点。我想知道我是否可以在没有我自己的帮助功能的情况下执行此操作?我的偏好是我可以初始化一个const string,但如果我不能这样做,我很确定这可以用标准算法和lambda来回答。

+0

简短的回答是:不。 –

+4

“标准算法和lambda” - 这不是一个辅助函数吗?请澄清。你想在这里做什么? –

+1

@KarolyHorvath我认为这些部分一起“做这个没有我自己的帮助功能” - “如果我不能做到这一点,我敢肯定,这可以用标准算法和lambda回答” –

回答

3

您可以覆盖乘法运算

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

...或使用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; 
} 

...或使用lambda参考捕捉...

#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::stringstd::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/92hH9Mhttp://goo.gl/zkgK4T

0

这是可能做到这一点只使用一个标准的算法,并与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增长,这可能是昂贵的,如果barlength大。这可通过构建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]; 
}); 

[Live Example]

+0

'string :: reserve'而不是调整大小在建设将避免初始化'foo'两次。 – Jarod42

+0

@ Jarod42嗯......我不会调用'保留'或'调整大小'。你在说我的构造参数是'calloc's'foo':'string foo(bar * length,'\ 0');'? –

+0

是的,我谈到'string foo(bar * length,'\ 0')'。被'string foo替换; foo.reserve(bar * length);'。 – Jarod42