代码之家  ›  专栏  ›  技术社区  ›  Paul J. Lucas

使用ICU去除发音符号的代码

  •  4
  • Paul J. Lucas  · 技术社区  · 14 年前

    有人能提供一些示例代码来去掉发音符号吗(例如,用不带重音符号、斜线符号等的字符替换不带重音符号、不带重音符号等的字符,例如,每个重音符号 é 会变成一个普通的ASCII码 e 从A UnicodeString 在C++中使用ICU库?例如。:

    UnicodeString strip_diacritics( UnicodeString const &s ) {
        UnicodeString result;
        // ...
        return result;
    }
    

    假定 s 已被规范化。谢谢。

    2 回复  |  直到 11 年前
        1
  •  14
  •   Quentin Pradet    11 年前

    ICU允许您使用特定规则对字符串进行音译。我的规则是 NFD; [:M:] Remove; NFC :分解,移除音调符号,重新组合。以下代码采用UTF-8 std::string 作为输入并返回另一个utf-8 STD::字符串 :

    #include <unicode/utypes.h>
    #include <unicode/unistr.h>
    #include <unicode/translit.h>
    
    std::string desaxUTF8(const std::string& str) {
        // UTF-8 std::string -> UTF-16 UnicodeString
        UnicodeString source = UnicodeString::fromUTF8(StringPiece(str));
    
        // Transliterate UTF-16 UnicodeString
        UErrorCode status = U_ZERO_ERROR;
        Transliterator *accentsConverter = Transliterator::createInstance(
            "NFD; [:M:] Remove; NFC", UTRANS_FORWARD, status);
        accentsConverter->transliterate(source);
        // TODO: handle errors with status
    
        // UTF-16 UnicodeString -> UTF-8 std::string
        std::string result;
        source.toUTF8String(result);
    
        return result;
    }
    
        2
  •  -1
  •   Paul J. Lucas    14 年前

    在其他地方进行更多搜索后:

    UErrorCode status = U_ZERO_ERROR;
    UnicodeString result;
    
    // 's16' is the UTF-16 string to have diacritics removed
    Normalizer::normalize( s16, UNORM_NFKD, 0, result, status );
    if ( U_FAILURE( status ) )
      // complain
    
    // code to convert UTF-16 's16' to UTF-8 std::string 's8' elided
    
    string buf8;
    buf8.reserve( s8.length() );
    for ( string::const_iterator i = s8.begin(); i != s8.end(); ++i ) {
      char const c = *i;
      if ( isascii( c ) )
        buf8.push_back( c );
    }
    // result is in buf8
    

    这是O(n)。