C ++で指定された長さの文字列に数値を変換します
質問
異なる長さの数字(1、999、76492など)があり、それらをすべて共通の長さの文字列に変換したい(たとえば、長さが6の場合、これらの文字列は次のようになります) 「000001」、「000999」、「076492」)。
言い換えると、数字に正しい量の先行ゼロを追加する必要があります。
int n = 999;
string str = some_function(n,6);
//str = '000999'
C ++にこのような関数はありますか?
解決
またはstringstreamsを使用:
#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();
arachnoid.com で見つけた情報を編集しました。入出力ストリームの安全な方法。また、このコードを他の出力ストリームでも同様に使用できます。
他のヒント
char str[7];
snprintf (str, 7, "%06d", n);
を参照してください。 に注意したいことの1つは、 stringstream
アプローチを使用するときにロックが発生する可能性があることです。 Visual Studio 2008に同梱されているSTLでは、少なくとも、フォーマット中にさまざまなロケール情報が使用されるため、多くのロックが解除および解放されます。数値を文字列に同時に変換する可能性のあるスレッドの数に応じて、これが問題になる場合とそうでない場合があります...
sprintf
バージョンはロックを取得しません(少なくとも、現在開発中のロック監視ツールによると...)。同時状況。
このことに気づいたのは、最近、私のツールが「ロケール」ロックをサーバーシステムのロックで最も競合しているものとして吐き出しているためです。それは少し驚きで、私が取っているアプローチを修正するかもしれません(つまり、 stringstream
から sprintf
に戻る)...
stringstreamが行う( as xtoflが指摘した)。 ブースト形式の方が便利ですsnprintfの代替。
このメソッドはストリームもsprintfも使用しません。ロックの問題があるほかに、ストリームにはパフォーマンスのオーバーヘッドが発生し、実際には過剰です。ストリームのオーバーヘッドは、スチームバッファーとストリームバッファーを構築する必要から生じます。 sprintfの場合、オーバーヘッドはフォーマット文字列を解釈する必要があることから生じます。これは、 n が負の場合、または n の文字列表現が len より長い場合でも機能します。これが最速のソリューションです。
inline string some_function(int n, int len)
{
string result(len--, '0');
for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
result[len]='0'+val%10;
if (len>=0&&n<0) result[0]='-';
return result;
}
これを行うには多くの方法があります。最も簡単なものは次のとおりです。
int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
sprintfはこれを行うCのような方法で、C ++でも機能します。
C ++では、stringstreamとストリーム出力フォーマットの組み合わせ( http:// www .arachnoid.com / cpptutor / student3.html )が仕事をします。
これは古いスレッドですが、 fmt が標準になる可能性があるため、ここで追加のソリューションです:
#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);
fmt :: format(&quot; {:0&gt; 6}&quot ;, n)
は、コンパイル時に目的の幅がわかっている場合も同様に機能することに注意してください。別のオプションは abseil :
#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);
もう一度、 abs :: StrFormat(&quot;%06d&quot ;, n)
が可能です。 ブースト形式は、この問題の別のツールです。
#include <boost/format.hpp>
int n = 999;
const auto str = boost::str(boost::format("%06d") % n);
残念ながら、%
演算子でチェーンされた引数としての可変幅指定子はサポートされていません。これにはフォーマット文字列の設定が必要です(例: const std :: string fmt =&quot;%0&quot; + std :: to_string(6)+&quot; d&quot ;;
)。
パフォーマンスに関しては、abseilとfmtは非常に魅力的で、ブーストよりも高速であると主張しています。いずれにせよ、3つのソリューションはすべて、 std :: stringstream
アプローチよりも効率的である必要があり、 std :: * printf
ファミリ以外では、タイプセーフを犠牲にしません。