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アプリの場合、無理して使わないようにしようかと思います。






最近のコメント
34 weeks 2 days ago
51 weeks 2 days ago
51 weeks 2 days ago
1年 16 weeks ago
1年 16 weeks ago
1年 16 weeks ago
1年 28 weeks ago
1年 28 weeks ago
2 years 8 weeks ago
2 years 17 weeks ago