boost

boost::xpressive 静的正規表現で書いてみた

VS2008以後は削除されてしまったCAtlRegExpのかわりにwindowsアプリの時はboost::xpressiveを使ってきましたが、はじめて静的正規表現を使ってみました。また、xpressiveはマルチバイト文字列非対応なんで_Unicodeプリプロセッサ付きです。(普段は国際化なんて意識していないのでTCHAR.h系の関数に慣れてなくて結構イライラしました...)

boost::xpressiveのイテレータ型の対応は、boost.Xpressive(日本語訳)(すばらしい!感謝)にあります。

string::const_iterator char* const wstring::const_iterator wchar_t* const
basic_regex<> sregex cregex wsregex wcregex
match_results<> smatch cmatch wsmatch wcmatch
regex_compiler<> sregex_compiler cregex_compiler wsregex_compiler wcregex_compiler
regex_iterator<> sregex_iterator cregex_iterator wsregex_iterator wcregex_iterator
regex_token_iterator<> sregex_token_iterator cregex_token_iterator wsregex_token_iterator wcregex_token_iterato

今回はワイド文字列対応なんで、wsregexとwsmatchを使います。先にも書きましたがこれまでは(仕様さえ決まってしまえば)特に動的である必要はないのに動的正規表現を使っていた怠慢を反省し静的正規表現で書いてみました。とりあえず、現状決まっているのは、文字列を「最後の空白」空白がなければ、「最初の数字」で区切るです。

pair<wstring,wstring> split_wstr(const wstring& wstr)
{
  boost::xpressive::wsmatch matched;

  //最後の空白で分割
#ifdef _DYNAMIC_REGEX_
  boost::xpressive::wsregex regex_lastw = 
    boost::xpressive::wsregex::compile(_T("^(\\S.+)\\s(.+)$"));
#else
  boost::xpressive::wsregex regex_lastw = 
    bos >> (s1=~_s >> +_) >> _s >> (s2=+_) >> eos;
#endif
  if (boost::xpressive::regex_match(zname,matched,regex_lastw))
  {
    return pair<wstring,wstring>(matched.str(1),matched.str(2));
  }

  //最初の数字で分割
#ifdef _DYNAMIC_REGEX_
  boost::xpressive::wsregex regex_firstn = 
    boost::xpressive::wsregex::compile(_T("^(\\D+)(\\d.+)$"));
#else
  boost::xpressive::wsregex regex_firstn = 
    bos >> (s1=+~_d) >> (s2=_d >> +_) >> eos;
#endif
  if (boost::xpressive::regex_match(zname,matched,regex_firstn))
  {
    return pair<wstring,wstring>(matched.str(1),matched.str(2));
  }

  // 以下仕様に応じていろんな分割が続く
  :
}

ご覧の通り、普段perlやrubyなんかで正規表現書いている人にとっては一見わかりにくいのが弱点でしょうか?特にドットをアンダースコアにするとか*や+が前に来るなどなかなか習慣からは抜け出せないと思うので、コメントとデバグの意味を込めて動的正規表現も併記したほうが後々のためかもしれません。

boost::gregorian::dateの月(数値)の取得

boost::gregorian::dateでdateObj.month()すると、NovとかDecとかが返ってくる。dateObj.month().as_number()がデフォルトのほうが僕はいいと思う。月を取得して文字列が返るのは直感的では内容に思うのですが。いや、ハマったから言うのじゃありません... 

それにしても、boost::gregorianは重いですね。Regexなんかと併用するとプリコンパイルのメモリが足りないとか言って(VS2008)きて/zmするハメになります。こうなると大抵Intellisenseが壊れるのでまあ、今回のようにヘッダを読む羽目になるわけです。windowsアプリの場合、無理して使わないようにしようかと思います。

コンテンツの配信