現在携わっている仕事(環境:WinXP,VC++6.0)で、
あるプログラムを作成しているのですが、
移植性を高めるためにMFCを使用しないという
ルールになっています。
普段、文字列操作には
MFC の CString を使用しているのですが、
今回は STL の string を使っています。
大半は不自由ないのですが、
数値を文字列にする場合、以下のような手法しか
分からず多少面倒です。
char caWork[100];
sprintf(caWork, %d %s … , 11111, aaaa, …);
string strWork = caWork;
CString の場合は、CString::Format() で
バッファサイズを意識することもなく簡潔に記述できるのですが、
string でも似たようなことができないものでしょうか?
もう少しすっきりコーディングしたいな思っています。
何かいい手法があったらお教え願いたいです。
#include <sstream>
#include <string>
.....
std::ostringstream oss;
oss << 11111 << << aaaa;
std::string strWork = oss.str();
こんな感じ?
> 数値を文字列にする場合、
環境がゆるすなら boost を導入するとか、
std::string strWork = boost::lexical_cast<std::string>(11111);
このイメージで stringstream のラッパを自作するのもアリでしょうか。
lexical_cast の実装それ自体、 stringstream のラッパです ^^;
>επιστημηさん
> lexical_cast の実装それ自体、 stringstream のラッパです ^^;
御意。ヘッダ内も読んでますからこの事自体は知ってますが、
ただ「実績のない外のライブラリは使っちゃいかんっ」って
現場もあったりするので、わざわざ車輪の再発明が必要かもと
思いまして>自作
# 実は経験者(^ ^;
あるいはsprintfをラップして:
std::string form(const char* format, ...)
をこしらえますか。
みなさん、
ご返事ありがとうございます。
> std::ostringstream oss;
> oss << 11111 << << aaaa;
> std::string strWork = oss.str();
勉強になります。
これなら簡潔になりますね。
欲をいえば、
sprintfとかの書式指定(%05dとか%3.2f)が
使えればいいのですが...
> 環境がゆるすなら boost を導入するとか、
自分自身、boostの概要くらいしか知らず、
仕事での納期もあるため次の機会にしたいです。
個人的には大いに興味があります。
> あるいはsprintfをラップして:
そういう方法もありますね。
バッファサイズを意識しないで使えるように
実装できれば完璧だと思います。
(難しそうではありますが...)
日ごろはCStringを何気なく使っていますが、
使えないと便利さが再認識させられます。
状況に応じて色々やってみようと思います。
> 欲をいえば、
> sprintfとかの書式指定(%05dとか%3.2f)が
> 使えればいいのですが...
書式指定にはマニピュレータと言われるものを使います。
// sample
#include <sstream>
#include <iomanip>
#include <string>
#include <iostream>
int main()
{
using namespace std;
int n = 123;
double r = 1.2;
ostringstream oss;
oss << setw( 5 ) << setfill( '0' ) << n <<
<< setw( 3 ) << fixed << setprecision( 2 ) << r;
string s = oss.str();
cout << s << endl;
}
> バッファサイズを意識しないで使えるように
> 実装できれば完璧だと思います。
とりあえずVC.NET2003だとこんな感じでしょうか。
std::string
form(const char* const format, ...)
{
va_list arguments;
std::vector<char> buffer;
assert(format);
va_start(arguments, format);
try{
int length = _vscprintf(format, arguments) + 1;
if(length < 1) throw std::runtime_error(format);
buffer.resize(length);
int result = vsprintf(&buffer.front(), format, arguments);
if(result < 0) throw std::runtime_error(format);
buffer[length-1] = '\0'; // 保険
}
catch(...)
{
va_end(arguments);
throw;
}
va_end(arguments);
return &buffer.front();
}
残念ながら VC6 だとバッファ長を取得する _vscprintf が
使えないのでちょっと面倒かも。vector::front も使えなかった....。
# なお、上の例だと vector が連続領域に確保されるSTLの実装系に
# 依存しますので、boost::scoped_array あたりにした方がいいかも。
boost は読んでていためになりますし、けっこう面白いです。
# いや、便利なものも多数ありますよ、ちゃんと(^ ^;
> sprintfとかの書式指定(%05dとか%3.2f)が
boost::basic_format なら、
C++ のマニピュレータ指定を C の printf 風に記述できたりします。
# %演算子のオーヴァロードで実装されてます。
実際に使うのかと言われたらまずいらないと思いますが....
オーヴァロードのハックの例でしょうか。(^ ^;
Ban さん、
色々お教えいただきありがとうございます。
大変勉強になります。
> 書式指定にはマニピュレータと言われるものを使います。
これを使用すれば書式指定ができるのですね。
ぜひ使用したいと思います。