Lexical Cast
Home >> Note >> Lexical Cast

数値文字列の相互変換

ログファイル等からデータを読み込むと,それらは最初は文字列として認識されています (文字列の"1000"など).したがって,実際にそれらをデータ(数値)として扱うためには, 一旦データに変換しなければなりません.Cでは(C++でもそれなりに使っていますが), atoi(),atol(),atof()などの関数を使用してその変換を行っていましたが, これらの関数を利用する場合には,あらかじめ変換後の型が分かっていなければなりません. そのため,テンプレートを使用したクラスを作成する場合には,この問題がネックになってきます.

この悩みを解消するために,boostライブラリにはlexical_castと呼ばれるテンプレート関数が 用意されています.これを用いると,例えば文字列の"1000"を整数に変換する場合には,

int a = boost::lexical_cast<int>("1000");

と言った形式で記述するで事がき,非常に便利です.

このlexical_castというテンプレート関数ですが,かなり用意に実装することができるようです.

中では std::stringstream に << で流し込んで >> で取り出す、 という形で実装されていますので、 標準のストリームI/Oに対応していてデフォルトコンストラクタ / コピーコンストラクタ / 代入演算子が正しく実装されているクラスなら、 何でも行けちゃいます。

つまり,lexical_castは以下のような実装になっています.

#include <iostream>
#include <sstream>

template <class Type, class Source>
Type str_cast(Source& s) {
    std::stringstream ss;
    Type dest;
    
    ss << s;
    ss >> dest;
    
    return dest;
}

// テスト用
int main(int argc, char* argv[])
{
    std::string s = "1000";
    int n = str_cast<int>(s);
    
    std::cout << n << std::endl;
    
    return 0;
}

実際には,ホワイトスペースやワイド文字,例外のことを考慮しているようなので, もう少し複雑になりますが,基本的にはこんな感じです.蓋を開けてみるとちょっとしたものが, すごく便利なものになるという良い例だと思います.