我可以在C ++中执行类似下面的Perl代码吗?
即重复$string
n
次?
printf ("%s\n",$string x 4);
答案 0 :(得分:3)
虽然C ++没有operator x
,但C ++是一种足够灵活的语言,您可以编写一个命名运算符x
,它的作用是乘以字符串:
#include <string>
namespace strop {
struct x_op {} x;
struct x_lhs { std::string s; };
x_lhs operator*( std::string s, x_op ) {
return {std::move(s)};
}
std::string operator*( x_lhs&& lhs, std::size_t rhs ) {
std::string retval;
for( std::size_t i = 0; i < rhs; ++i ) {
retval += lhs.s;
}
return retval;
}
}
使用:
#include <iostream>
using strop::x;
int main () {
std::string foo = "foo";
std::cout << (foo *x* 5) << "\n"; // if you prefer std::cout
printf("%s", (foo *x* 5).c_str()); // if you prefer printf
}
以上使用了一些简单的C ++ 11特性,但并非本质上。
C ++ 03版本(效率较低):
#include <string>
namespace strop {
struct x_op {} x;
struct x_lhs { std::string s; x_lhs(std::string s_):s(s_) {} };
x_lhs operator*( std::string s, x_op ) {
return x_lhs(s);
}
std::string operator*( x_lhs lhs, std::size_t rhs ) {
std::string retval;
for( std::size_t i = 0; i < rhs; ++i ) {
retval += lhs.s;
}
return retval;
}
}
有趣的是,这适用于字符串文字:
std::cout << "bar" *x* 3 << "\n";
因为它们会隐式变成std::string
。如果您使用printf
,则仍需将其包装在().c_str()
中,否则您将面临未定义的行为(即使您从未提及std::string
)。
你可以改为重载一些其他非命名运算符,但是当你在重载中拥有 类型时重载运算符是非常粗鲁的,并且可能导致复杂化。
上述技术使用占位符类型x_op
和x_lhs
来确保重载运算符仅在我们与命名运算符交互时生效。
选择*
来包装我们的命名运算符x
是因为操作是乘法的。
Bonus:operator*
的疯狂版本,它使用rhs的位值来减少字符串争用的数量:
std::string operator*( x_lhs lhs, std::size_t rhs ) {
std::string retval;
auto done = [rhs]( std::size_t n ) {
return !(i < (sizeof(rhs)*8) && !(rhs &~std::size_t((1<<i)-1)));
};
for( int i = 0; true; ++i) {
if (!done(i+1)) {
if (rhs & (1 << i))
retval += lhs;
lhs += lhs;
continue;
} else {
// high bit must be set, or we'd be done before, unless rhs was 0:
if (rhs != 0)
retval += std::move(lhs);
break;
}
}
return retval;
}
尚未经过测试,但让我很开心。
答案 1 :(得分:1)
不,不是直接的。你需要自己做:
for (size_t i = 0; i < 4; ++i)
printf ("%s", astring);
printf ("\n");
答案 2 :(得分:1)
前言:重载运算符是一种细微差别的做法。如果您不小心,可能会导致难以阅读和维护的代码。那说......
您可以尝试重载operator*()
,但为了完成这项工作,您需要使用字符串对象而不是裸c字符串。原因是C ++不允许重载仅引用内置类型的运算符。 std::string
类不是内置于该语言中。
例如,以下函数将执行您对std :: string对象的操作。请注意,返回类型是一个const char *,与printf()
兼容。
const char* operator*(const std::string& input, size_t repeat)
{
std::string output;
for (size_t ii=0; ii<repeat; ++ii)
output += input;
return output.c_str();
}
使用该函数,如果字符串存储在std :: string对象中,您可以使用您喜欢的语法:
int main(int argc, char** argv)
{
std::string input = argv[1];
printf("%s\n", input*3); // works
printf("%s\n", std::string(argv[1])*3); // works
//printf("%s\n", argv[1]*3); // compile error
}
更自然的C ++方法是使用<iostream>
,这不需要您在重载运算符中混合使用char*
和std::string
类型。
std::string operator*(const std::string& input, size_t repeat)
{
std::string output;
for (size_t ii=0; ii<repeat; ++ii)
output += input;
return output;
}
int main(int argc, char** argv)
{
std::cout << std::string(argv[1])*3 << std::endl;
}
答案 3 :(得分:1)
令人印象深刻的是@ Yakk的重载,为什么不定义一个简单的函数?
std::string repeat(const std::string& s, int times) {
std::string res;
res.reserve(s.size() * times);
for (int i = 0; i < times; ++i)
res += s;
return s;
}
然后你可以做
std::cout << repeat("foo", 4) << std::endl;
打印foofoofoofoo
。
答案 4 :(得分:0)
你可以使用for循环:
for(int i=0;i<n;i++)
cout<<string;