web-dev-qa-db-ja.com

C ++で指定された長さの文字列に数値を変換します

長さが異なる数値(1、999、76492など)があり、それらをすべて共通の長さの文字列に変換したい(たとえば、長さが6の場合、これらの文字列は '000001'になります) 、「000999」、「076492」)。

つまり、数字に正しい量の先行ゼロを追加する必要があります。

int n = 999;
string str = some_function(n,6);
//str = '000999'

C++にこのような関数はありますか?

42
Degvik

またはstringstreamsを使用して:

#include <sstream>
#include <iomanip>

std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();

arachnoid.com で見つけた情報を編集しました。これは、入出力ストリームのタイプセーフな方法がより好きだからです。また、このコードを他の出力ストリームでも同様に使用できます。

58
xtofl
char str[7];
snprintf (str, 7, "%06d", n);

snprintf を参照してください

13
Isak Savo

mayに注意したいことの1つは、stringstreamアプローチを使用するときにロックが発生する可能性があることです。 Visual Studio 2008に同梱されているSTLでは、少なくとも、フォーマット中にさまざまなロケール情報が使用されるため、多くのロックが解除および解放されます。これは、数を文字列に同時に変換する可能性のあるスレッドの数によっては、問題になる場合もあれば、そうでない場合もあります...

sprintfバージョンは(少なくとも現時点で開発中のロック監視ツールによれば)ロックを取得しないため、同時状況での使用には「より良い」かもしれません。

このことに気づいたのは、私のツールが最近、「ロケール」ロックをサーバーシステムのロックで最も競合しているものとして吐き出しているためです。それは少し驚きであり、私が取っているアプローチを修正する可能性があります(つまり、sprintfからstringstreamに向かって戻る)...

8
Len Holgate

このメソッドはストリームもsprintfも使用しません。ロックの問題以外に、ストリームにはパフォーマンスのオーバーヘッドが発生し、実際には過剰です。ストリームの場合、オーバーヘッドはSteamとストリームバッファーを構築する必要から生じます。 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;
}
3
sep

これを行うには多くの方法があります。最も簡単なものは次のとおりです。

int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
3
Pramod

stringstreamは( xtoflが指摘したように )します。 Boost format はsnprintfのより便利な代替です。

3
PW.

sprintfはこれを行うCのような方法で、C++でも機能します。

C++では、stringstreamとストリーム出力フォーマットの組み合わせ( http://www.arachnoid.com/cpptutor/student3.html を参照)が仕事をします。

1
Chris Johnson

これは古いスレッドですが、 fmt が標準になる可能性があるため、追加のソリューションを次に示します。

_#include <fmt/format.h>

int n = 999;

const auto str = fmt::format("{:0>{}}", n, 6);
_

fmt::format("{:0>6}", n)は、コンパイル時に目的の幅がわかっている場合にも同様に機能することに注意してください。別のオプションは abseil

_#include <absl/strings/str_format.h>

int n = 999;

const auto str = absl::StrFormat("%0*d", 6, n);
_

繰り返しますが、abs::StrFormat("%06d", n)は可能です。 ブースト形式 は、この問題の別のツールです。

_#include <boost/format.hpp>

int n = 999;

const auto str = boost::str(boost::format("%06d") % n);
_

残念ながら、_%_演算子でチェーンされた引数としての可変幅指定子はサポートされていません。これにはフォーマット文字列のセットアップが必要です(例:const std::string fmt = "%0" + std::to_string(6) + "d";)。

パフォーマンスに関しては、abseilとfmtは非常に魅力的で、ブーストよりも高速であると主張しています。いずれにせよ、3つのソリューションはすべて_std::stringstream_アプローチよりも効率的である必要があり、_std::*printf_ファミリ以外では、タイプセーフを犠牲にしません。

0
lubgr