如何在 C + + 中可变次数地重复一个字符串?

我想在 C + + 中的一个字符串的开头插入’n’空格(或任何字符串)。有没有一种直接的方法可以使用 std: : 字符串或 char * 字符串来实现这一点?

例如,在 Python 中,你可以简单地

>>> "." * 5 + "lolcat"
'.....lolcat'
179817 次浏览

在重复单个字符的特殊情况下,可以使用 std::string(size_type count, CharT ch):

std::string(5, '.') + "lolcat"

这不能用于重复多字符字符串。

您应该编写自己的流操作器

cout << multi(5) << "whatever" << "lolcat";

使用字符串的其中一种形式: : insert:

std::string str("lolcat");
str.insert(0, 5, '.');

这将在字符串的开头(位置0)插入“ ... ...”(5个点)。

在 c + + 中没有直接的惯用方法来重复字符串,这种方法与 Python 中的 *操作符或佩尔中的 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

正如 Commodore Jaeger 提到的,我不认为其他任何答案实际上回答了这个问题; 问题是如何重复一个字符串,而不是一个字符。

虽然 Commodore 给出的答案是正确的,但效率很低。这里有一个更快的实现,其想法是通过首先使字符串呈指数级增长来最大限度地减少复制操作和内存分配:

#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倍左右。

你可以使用 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();
}

对于 OP std: : string 的 ctor 提供的示例来说,std::string(5, '.')就足够了。 但是,如果有人正在寻找一个函数来多次重复 std: : string:

std::string repeat(const std::string& input, unsigned num)
{
std::string ret;
ret.reserve(input.size() * num);
while (num--)
ret += input;
return ret;
}

下面是字符串“ abc”repeated的3次示例:

#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <iterator>


using namespace std;


int main() {
ostringstream repeated;
fill_n(ostream_iterator<string>(repeated), 3, string("abc"));
cout << "repeated: " << repeated.str() << endl;  // repeated: abcabcabc
return 0;
}

@ Daniel 提供的实现比它的主执行分支(其中 n > 1且 str 不为空)中的其他应答要快得多。然而,边缘案例的处理效率远远低于它们本来可以达到的效率。

这一实施纠正了这些问题:

#include <string>
#include <cstddef>


std::string repeat(size_t n, const std::string& str) {
if (n == 0 || str.empty()) return {};
if (n == 1) return str;
const auto period = str.size();
if (period == 1) return std::string(n, str.front());


std::string ret(str);
ret.reserve(period * n);
std::size_t m {2};
for (; m < n; m *= 2) ret += ret;
ret.append(ret.c_str(), (n - (m / 2)) * period);
return ret;
}

快速基准测试网站上两种实现的基准比较显示了这些角落情况下的以下差异。第一个数字是 Clang 13.0,第二个数字是 GCC 10.3。- 在所有情况下 O3优化。

  • 对于 n = 0,这个实现更快(9x/11x)。
  • 对于 str.void () = = true,它的速度更快(2.4 x/3.4 x)。
  • 对于 n = 1和 str.size () > 1,它的速度更快(2.1 x/1.4 x)。
  • 对于 str.size () = = 1,它的速度是(1.3 x/1.2 x)。

原始实现的问题归结为通过值将 str传递给函数。这将在每次调用 repeat时调用 str的副本,在某些情况下这是不必要的; 特别是当 n = = 0时。