Extended Lexical Cast
Home >> Note >> Extended Lexical Cast

拡張 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

  #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