我想在C ++中的字符串开头插入“ n”个空格(或任何字符串)。是否可以使用std :: strings或char *字符串直接进行此操作?
例如,在Python中,您可以轻松完成
>>> "." * 5 + "lolcat"
'.....lolcat'
我想在C ++中的字符串开头插入“ n”个空格(或任何字符串)。是否可以使用std :: strings或char *字符串直接进行此操作?
例如,在Python中,您可以轻松完成
>>> "." * 5 + "lolcat"
'.....lolcat'
Answers:
在重复单个字符的特定情况下,可以使用std::string(size_type count, CharT ch)
:
std::string(5, '.') + "lolcat"
注意 不能用于重复多字符字符串。
在C ++中,没有直接惯用的方式来重复字符串,等效于Python中的*运算符或Perl中的x运算符。如果您要重复一个字符,则由两个参数组成的构造函数(如先前答案所建议)可以很好地工作:
std::string(5, '.')
这是一个人为设计的示例,说明如何使用ostringstream重复一个字符串n次:
#include <sstream>
std::string repeat(int n) {
std::ostringstream os;
for(int i = 0; i < n; i++)
os << "repeat";
return os.str();
}
取决于实现方式,这可能比简单地串联字符串n次更为有效。
我知道这是一个古老的问题,但是我一直想做同样的事情,并且发现了我认为更简单的解决方案。看来cout具有使用cout.fill()内置的此功能,请参阅链接以获取“完整”说明
http://www.java-samples.com/showtutorial.php?tutorialid=458
cout.width(11);
cout.fill('.');
cout << "lolcat" << endl;
输出
.....lolcat
cout << "" << endl;
正如Jaeger准将所说,我认为没有其他答案能真正回答这个问题。这个问题问如何重复一个字符串,而不是一个字符。
尽管准将给出的答案是正确的,但效率很低。这是一个更快的实现,其思想是通过首先指数增长字符串来最大程度地减少复制操作和内存分配:
#include <string>
#include <cstddef>
std::string repeat(std::string str, const std::size_t n)
{
if (n == 0) {
str.clear();
str.shrink_to_fit();
return str;
} else if (n == 1 || str.empty()) {
return str;
}
const auto period = str.size();
if (period == 1) {
str.append(n - 1, str.front());
return str;
}
str.reserve(period * n);
std::size_t m {2};
for (; m < n; m *= 2) str += str;
str.append(str.c_str(), (n - (m / 2)) * period);
return str;
}
我们还可以定义一个operator*
以获得更接近Python版本的信息:
#include <utility>
std::string operator*(std::string str, std::size_t n)
{
return repeat(std::move(str), n);
}
在我的机器上,这比Commodore提供的实现快大约10倍,比简单的“追加n-1次”解决方案快大约2 倍。
+=
for循环内部的for循环中也有某种循环会进行str.size()
迭代。str.size()
在每个外循环迭代中增长,因此在每个外循环之后,内循环必须执行更多的迭代。您和天真的“复制n次”实现总共复制了两个n * period
字符。由于initial,您的实现只执行一次内存分配reserve
。我猜你有一个相当小的异形你的实现str
和一个大的n
,但还没有大str
和小n
。
str
,小n
两种方法之间。我相信,这与整体流水线的关系远多于分支预测本身,还有数据对齐问题需要考虑。您应该问一个新的问题,为什么它对处理器/内存更友好,我敢肯定它会引起很多兴趣,并且得到比我在此给出的更好的答案。
rep movsb
是最有效的复制方法之一,至少对于中型到大型复制而言。它的微编码实现具有一些恒定的启动开销(在AMD和Intel上),例如在Sandybridge上,大约15至40个周期,加上每条64B高速缓存行4个周期(最佳情况)。对于小副本,最好使用SSE循环,因为它没有启动开销。但这会受到分支错误预测的影响。
您应该编写自己的流操纵器
cout << multi(5)<<“随便什么” <<“ lolcat”;
ITNOA
您可以使用C ++函数执行此操作。
std::string repeat(const std::string& input, size_t num)
{
std::ostringstream os;
std::fill_n(std::ostream_iterator<std::string>(os), num, input);
return os.str();
}