読者です 読者をやめる 読者になる 読者になる

C++で日本語を扱う場合

  • Unicodeは文字セット(文字集合)を規定している

  • Unicodeの中で文字を表現する場合、コードポイントを用いる(単に文字集合の中の各文字に対して数字を割り振ったもの)

  • UTF-8Unicodeの文字セットを1〜4byteの文字コードで扱う(コードポイントは21bitの数値であり、文字コードは1byte単位の1〜4つの組で使う符号バイト列)

  • UnicodeUTF-8の区別 Character Code UTF-8 文字コード考え方から理解するUnicodeとUTF-8の違い | ギークを目指して

  • 基本的に日本語(ひらがな・カタカナ・漢字)は3byteで表現される(アルファベットはASCIIと同じ文字コードなので1byte)

  • UTF-8の変換表 UTF-8の文字コード表 - オレンジ工房

  • 1byteの文字列と2byte以上の文字列が、混在している文字列を、マルチバイト文字列という

  • wchar_tはワイド文字列=2byteの文字列

  • mbstowcs()は、マルチバイト文字列をワイド文字列に置き換える

    • 3byte以上の文字列を2byteに切り詰めるので、置き換えることができない文字列が存在する可能性がある
  • Boost:wregex はregex_searchにおいてワイド文字列を使用可能

    • ただし上述のように、3byte以上のマルチバイト文字列は、2byteのワイド文字列に置き換えられることが保障できない(少なくとも、区別がつく形では)
  • 実際、regex_searchがセグる事象に遭遇(以下、部分抜粋)

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff4750700 (LWP 26062)]
0x00007ffff7983cb5 in boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::find_restart_any() () from /usr/local/lib/libboost_regex.so.1.56.0
(gdb) backtrace
#0  0x00007ffff7983cb5 in boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::find_restart_any() () from /usr/local/lib/libboost_regex.so.1.56.0
#1  0x00007ffff797e976 in boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::find_imp() () from /usr/local/lib/libboost_regex.so.1.56.0
#2  0x0000000000415c40 in boost::regex_search<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >, wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > (first=0 L'\000', last=0 L'\000', m=..., e=..., 
    flags=boost::regex_constants::match_default, base=0 L'\000') at /usr/local/include/boost/regex/v4/regex_search.hpp:56
#3  0x00000000004134e1 in boost::regex_search<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<wchar_t const*, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > >, wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > > (first=0 L'\000', last=0 L'\000', m=..., e=..., 
    flags=boost::regex_constants::match_default) at /usr/local/include/boost/regex/v4/regex_search.hpp:42
...
  • シンボルだけの文字列を検出して排除する方法を模索していたが、そういう文字列がこのプログラムに入ってこないような条件を付けることで対処した