10

を使用して utf8 Unicode 文字を一致させるにはどうすればよいboost::spiritですか?

たとえば、次の文字列のすべての文字を認識したい:

$ echo "На берегу пустынных волн" | ./a.out
Н а б е р е гу п у с т ы н н ы х в о л н

この単純なboost::spiritプログラムを試してみると、Unicode 文字が正しく一致しません。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/foreach.hpp>
namespace qi = boost::spirit::qi;

int main() {
  std::cin.unsetf(std::ios::skipws);
  boost::spirit::istream_iterator begin(std::cin);
  boost::spirit::istream_iterator end;

  std::vector<char> letters;
  bool result = qi::phrase_parse(
      begin, end,  // input     
      +qi::char_,  // match every character
      qi::space,   // skip whitespace 
      letters);    // result    

  BOOST_FOREACH(char letter, letters) {
    std::cout << letter << " ";
  }
  std::cout << std::endl;
}

次のように動作します。

$ echo "На берегу пустынных волн" | ./a.out | less
<D0> <9D> <D0> <B0> <D0> <B1> <D0> <B5> <D1> <80> <D0> <B5> <D0> <B3> <D1> <83> <D0> <BF> <D1> <83> <D1> <81> <D1> <82> <D1> <8B> <D0> <BD> <D0> <BD> <D1> <8B> <D1> <85> <D0> 
<B2> <D0> <BE> <D0> <BB> <D0> <BD> 

アップデート:

さて、私はこれにもう少し取り組みましたが、次のコードはある程度機能しています。まず、入力を 32 ビット Unicode 文字の反復子に変換します (ここで推奨されているように)。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/foreach.hpp>
#include <boost/regex/pending/unicode_iterator.hpp>
namespace qi = boost::spirit::qi;

int main() {
  std::string str = "На берегу пустынных волн";
  boost::u8_to_u32_iterator<std::string::const_iterator>
      begin(str.begin()), end(str.end());
  typedef boost::uint32_t uchar; // a unicode code point
  std::vector<uchar> letters;
  bool result = qi::phrase_parse(
      begin, end,             // input
      +qi::standard_wide::char_,  // match every character
      qi::space,              // skip whitespace
      letters);               // result
  BOOST_FOREACH(uchar letter, letters) {
    std::cout << letter << " ";
  }
  std::cout << std::endl;
}

コードは Unicode コード ポイントを出力します。

$ ./a.out 
1053 1072 1073 1077 1088 1077 1075 1091 1087 1091 1089 1090 1099 1085 1085 1099 1093 1074 1086 1083 1085 

公式のUnicode tableによると、これは正しいようです。

さて、この Unicode コード ポイントのベクトルを指定して、代わりに実際の文字を出力する方法を誰か教えてもらえますか?

4

3 に答える 3

7

私はあまり使ったことがありませんが、Spirit (SVN トランク バージョン) は Unicode をサポートしているようです。

#define BOOST_SPIRIT_UNICODE // We'll use unicode (UTF8) all throughout

たとえば、スキームのデモにあるsexpr パーサーのサンプルを参照してください。

BOOST_ROOT/libs/spirit/example/scheme

これは、Bryce Lelbach 1によるプレゼンテーションのデモに基づいていると思います。

  • wchar サポート
  • utree 属性 (まだ実験的)
  • s式

S 式とバリアントに関するオンライン記事があります。


1実際にそうである場合、ここにそのプレゼンテーションのビデオスライド (pdf)があります (odp)。

于 2012-05-07T07:31:46.727 に答える
2

できません。問題はboost::spiritにはありませんが、Unicodeは複雑です。char文字を意味するのではなく、「バイト」を意味します。また、コードポイントレベルで作業している場合でも、ユーザーが認識する文字は複数のコードポイントで表される場合があります。(たとえば、пусты́нныхは9文字ですが、10コードポイントです。ロシア語では発音区別符号をあまり使用しないため、十分に明確ではない可能性があります。他の言語では使用されます。)

ユーザーが認識した文字(またはUnicode用語では書記素クラスター)を実際に反復処理するには、Unicode専用ライブラリ(ICU)を使用する必要があります。

しかし、文字を反復処理する実際の使用法は何ですか?

于 2012-05-06T22:14:23.820 に答える
2

Boost 1.58 では、任意の Unicode シンボルをこれと一致させることができます:

*boost::spirit::qi::unicode::char_

特定の範囲の Unicode シンボルを定義する方法がわかりません。

于 2016-10-06T20:23:16.227 に答える