C ++で文字列の先頭に「n」個のスペース(または任意の文字列)を挿入したい。std :: stringsまたはchar *文字列を使用してこれを行う直接的な方法はありますか?
たとえば、Pythonでは簡単にできます
>>> "." * 5 + "lolcat"
'.....lolcat'
C ++で文字列の先頭に「n」個のスペース(または任意の文字列)を挿入したい。std :: stringsまたはchar *文字列を使用してこれを行う直接的な方法はありますか?
たとえば、Pythonでは簡単にできます
>>> "." * 5 + "lolcat"
'.....lolcat'
回答:
単一の文字を繰り返す特定のケースでは、以下を使用できますstd::string(size_type count, CharT ch)。
std::string(5, '.') + "lolcat"
NB。これは、複数文字の文字列を繰り返すために使用することはできません。
Python の*演算子またはPerlのx演算子に相当するC ++で文字列を繰り返す直接の慣用的な方法はありません。単一の文字を繰り返す場合、2つの引数を持つコンストラクター(前の回答で提案されているとおり)が適切に機能します。
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回連結するよりも少し効率的かもしれません。
string :: insert:のいずれかの形式を使用します。
std::string str("lolcat");
str.insert(0, 5, '.');
これにより、文字列の先頭(位置0)に "....."(5つのドット)が挿入されます。
これは古い質問であることはわかっていますが、同じことをしたいと思っていましたが、私がより簡単な解決策だと思うものを見つけました。coutにはcout.fill()でこの関数が組み込まれているようです。「完全な」説明についてはリンクを参照してください
http://www.java-samples.com/showtutorial.php?tutorialid=458
cout.width(11);
cout.fill('.');
cout << "lolcat" << endl;
出力
.....lolcat
cout << "" << endl;
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倍速く、単純な「append n-1 times」ソリューションよりも約2倍速くなっています。
+=、あなたのためのループ内で内部的にもない、ある種のループがあるstr.size()反復を。str.size()外側のループが繰り返されるたびに大きくなるため、外側の各繰り返しの後に、内側のループはさらに多くの繰り返しを行う必要があります。あなたと素朴な「コピーn回」の実装では、合計で両方のコピーn * period文字が使用されます。あなたの実装は、初期のため、1回だけメモリ割り当てを行いreserveます。実装のプロファイリングはかなり小さくstrて大きなものnだったと思いますが、大きくもstr小さくもありませんn。
rep movsb少なくとも中規模から大規模のコピーの場合、最も効率的なコピー方法の1つです。そのマイクロコード化された実装には、ほぼ一定の起動オーバーヘッド(AMDとIntelの両方)があります。たとえば、Sandybridgeでは、15から40サイクル、さらに64Bキャッシュラインあたり4サイクル(ベストケース)です。小さなコピーの場合は、起動のオーバーヘッドがないため、SSEループが最適です。しかし、それはブランチの誤予測の影響を受けます。
独自のストリームマニピュレータを作成する必要があります
cout << multi(5)<< "whatever" << "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();
}