我可以在 C++ 中执行类似以下 Perl 代码的操作吗?
即复制 $string
n
次 ?
printf ("%s\n",$string x 4);
最佳答案
虽然 C++ 没有运算符 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::字符串
).
您可以改为重载一些其他未命名的运算符,但是当您在重载中拥有两种类型时重载运算符是非常粗鲁的,并且可能导致并发症。
上述技术使用占位符类型 x_op
和 x_lhs
来确保重载运算符仅在我们与命名运算符交互时才会生效。
选择 *
来包装我们命名的运算符 x
是因为该运算类似于乘法。
奖励: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;
}
尚未测试,但让我觉得很有趣。
关于c++ - 在 C++ 中像 Perl 一样打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17071427/