Hatena::ブログ(Diary)

Life like a clown このページをアンテナに追加 RSSフィード Twitter

2007-11-06

拡張 lexical_cast

C++で数字文字列<->数値の変換を行うときには専らlexical_castを使っているのですが, 16進数や8進数などに変換できないことに気づきました. そこで,strtolなどの関数を見てみるとbaseと言う引数で基数を指定できるように なっていたので,これに習ってlexical_castを拡張してみました. 場合によってsetf()するだけなので,拡張と言うほど大げさなものでもないですが.

lexical_castの第二引数には,基数としてstd::ios::dec,std::ios::hex,std::ios::octを指定することができます.基数を指定した場合,lexical_castは基数にしたがって数字文字列をそれぞれ10進数,16進数,8進数として変換を行います.尚,基数を省略した場合は10進数(std::ios::dec)として変換が行われるので, 普段はboost::lexical_castと同じ感覚で使うことができます.

また,第二引数にstd::ios::showbaseを指定した場合には,文字列に応じた変換がなされます.つまり,0xで始まる数字文字列であるならば16進数として,0で始まる数字文字列であるならば8進数として,それ以外の数字文字列は10進数として変換が行われます.

以下がサンプルプログラム.lexical_cast.hはCLX C++ Librariesからダウンロードして下さい.

#include <iostream>
#include <string>
#include "clx/lexical_cast.h"

int main(int argc, char* argv[]) {
    std::string s1 = "326";
    std::string s2 = "0xf2a";
    std::string serr = "nonum";
    
    try {
        int a = clx::lexical_cast<int>(s1, std::ios::oct);
        int b = clx::lexical_cast<int>(s2, std::ios::showbase);
        
        std::cout << "str " << s1 << ", val " << a << std::endl;
        std::cout << "str " << s2 << ", val " << b << std::endl;
        
        int c = clx::lexical_cast<int>(serr);
        std::cout << "str " << serr << ", val " << c << std::endl;
    }
    catch (clx::bad_lexical_cast e) {
        std::cerr << "exeption: " << e.what() << std::endl;
        std::exit(-1);
    }
    
    return 0;
}
Result
str 326, val 214
str 0xf2a, val 3882
exeption: bad lexical cast