C++で数値を文字列にするなんか造作ない:
1 #include <sstream>
2 #include <iostream>
3
4 int main(void)
5 {
6 std::stringstream ss;
7 ss << 10;
8 std::string res(ss.str());
9 std::cout << res << std::endl;
10
11 /*文字列にする必要がないなら無論以下
12 std::cout << 10 << std::endl;
13 */
14 return 0;
15 }
が、このようなぬるま湯に浸かったまま数百万レコードを一気に処理するような「猛烈バッチ」を書くと、まぁまぁ困った事態になる。なんだかんだオーバヘッドが高く、遅い。
となると「itoa」が欲しくなるわけだが、「標準の」itoa なんかない、わけで。で、ワタシの場合なんだかんだ UNIX と Windows を頻繁に行き来する都合、「ifdef だらけのプログラムはやだなぁ」状態にすぐに陥る。VC のバージョンによるが、特に昔(VS 6.0)ほど「VCだけ異質で、しかるべきものがない」ことには随分苦しめられた。となれば「itoaごとき、作っちまえ」と思ってしまうのが人情と言うもの。
これ:
1 //
2 // int_to_ascii
3 //
4 #ifndef __INT_TO_ASCII_H_B60523C31AAC4482A753425514AE85D7__
5 #define __INT_TO_ASCII_H_B60523C31AAC4482A753425514AE85D7__ /*DEFINED, BUT EMPTY*/
6
7 //#include <type_traits> // for make_signed
8 //make_signed short-cut version... (for VS8)
9 template<typename UType_> struct _make_signed {
10 };
11 template<> struct _make_signed<char> {
12 typedef signed char type;
13 };
14 template<> struct _make_signed<unsigned char> {
15 typedef signed char type;
16 };
17 template<> struct _make_signed<unsigned short> {
18 typedef signed short type;
19 };
20 template<> struct _make_signed<unsigned int> {
21 typedef signed int type;
22 };
23 template<> struct _make_signed<unsigned long> {
24 typedef signed long type;
25 };
26 template<> struct _make_signed<unsigned long long> {
27 typedef signed long long type;
28 };
29
30 #include <algorithm>
31
32 namespace utils {
33
34 template<typename ULongType_,
35 typename CharT_,
36 unsigned radix,
37 size_t bufsiz> inline
38 CharT_* int_to_ascii(ULongType_ val, CharT_ *buf, bool is_negative)
39 {
40 typedef typename _make_signed<ULongType_>::type LongType_;
41 CharT_ *p = buf;
42 size_t length = 0;
43 if (is_negative) {
44 *p++ = CharT_('-');
45 length++;
46 val = (ULongType_)(-(LongType_)val);
47 }
48 CharT_ *firstdig = p;
49 unsigned digval;
50 do {
51 digval = (unsigned) (val % radix);
52 val /= radix;
53 if (digval > 9) {
54 *p++ = (CharT_) (digval - 10 + CharT_('a'));
55 } else {
56 *p++ = (CharT_) (digval + CharT_('0'));
57 }
58 length++;
59 } while (val > 0 && length < bufsiz);
60 do {
61 std::swap(*--p, *firstdig++);
62 } while (firstdig < p);
63 return buf + length;
64 }
65
66 }
67
68 #endif // ifndef __INT_TO_ASCII_H_B60523C31AAC4482A753425514AE85D7__
itoaではなく「int_to_ascii」なんて名前にしとるし、「\0端」前提にしないし、とちょいと独特かもしれないけれど、実装の内容はごくごく普通。「C++流儀にしただけ」、と言っていい。だので説明しません。使いたい人はお好きにどーぞ。(C++ STL のストリームよりは十分に速く、C++ STL のストリームより遥かに低機能です。当たり前だよな。)