【问题标题】:counting unicode characters in c++在 C++ 中计算 unicode 字符
【发布时间】:2010-08-27 18:02:11
【问题描述】:

如何在 C++ 中计算 UTF-8 文件中的 unicode 个字符?也许如果有人愿意向我展示一个“独立”方法,或者使用http://icu-project.org/index.html 的简短示例。

编辑:一个重要的警告是我需要建立每个字符的计数,所以我不是在计算字符的总数,而是在计算一组字符的出现次数.

【问题讨论】:

标签: c++ unicode


【解决方案1】:

在 UTF-8 中,非前导字节的前两位总是设置为 10,因此请忽略所有此类字节。如果您不介意额外的复杂性,您可以做更多的事情(根据前导字节的位模式跳过非前导字节),但实际上,除了短字符串之外,它不太可能产生太大影响(因为无论如何,您通常会接近内存带宽)。

编辑:我最初将您的问题误读为只是询问如何计算以 UTF-8 编码的字符串的长度。如果你想计算字符频率,你可能想convert those to UTF-32/UCS-4,那么你需要某种稀疏数组来计算频率。

这其中的难点在于计算代码点与字符。例如,考虑字符“À”——“带有坟墓的拉丁大写字母 A”。至少有两种不同的方式来产生这个角色。您可以使用代码点 U+00C0,它将整个事物编码为单个代码点,您可以使用代码点 U+0041(拉丁文大写字母 A)后跟代码点 U+0300(结合重音符号) )。

规范化(相对于 Unicode)意味着将所有此类字符转换为相同的形式。您可以将它们全部组合成一个代码点,也可以将它们全部分成单独的代码点。出于您的目的,尽可能将它们组合成一个代码点可能更容易。自己编写可能不太实用——我会使用 ICU 项目中的 normalizer API

【讨论】:

  • +1 用于 unicode 规范化。为此还有一个 win32 api。
【解决方案2】:

如果您知道 UTF-8 序列格式正确,那就很容易了。对以 0 位或两个 1 位开头的每个字节进行计数。第一个条件将聊天每个由单个字节表示的代码点,第二个条件将捕获每个多字节序列的第一个字节。

while (*p != 0)
{
    if ((*p & 0x80) == 0 || (*p & 0xc0) == 0xc0)
        ++count;
    ++p;
}

或者,如 cmets 中所述,您可以简单地跳过作为延续的每个字节:

while (*p != 0)
{
    if ((*p & 0xc0) != 0x80)
        ++count;
    ++p;
}

或者,如果您想变得超级聪明并使其成为 2-liner:

for (p; *p != 0; ++p)
    count += ((*p & 0xc0) != 0x80);

Wikipedia page for UTF-8 清楚地显示了模式。

【讨论】:

  • 应该是 (*p & 0xc0) != 0x80
  • == 的优先级高于 &
  • @jean 你是对的,谢谢!我通常在我的代码中添加额外的括号,以确保我不会像那样被赶上,不知道为什么我这次没有。
【解决方案3】:

关于用 C++ 编写的完整例程的讨论在 http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html

【讨论】:

    【解决方案4】:

    我知道,这个帖子已经晚了,但它可以提供帮助

    对于 ICU 的东西,我是这样做的:

    string TheString = "blabla" ;
    UnicodeString uStr = UnicodeString::fromUTF8( theString.c_str() ) ;
    cout << "length = " << uStr.length( ) << endl ;
    

    【讨论】:

      【解决方案5】:

      我不会认为这是一个以语言为中心的问题。 UTF-8 格式相当简单;从文件中解码应该只需要几行任何语言的代码。

      open file
      until eof
          if file.readchar & 0xC0 != 0x80
              increment count
      close file
      

      【讨论】:

      • (file.readchar & 0xC0) != 0x80。至少在 C 中,!= 的优先级高于 &
      猜你喜欢
      • 1970-01-01
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2015-01-21
      相关资源
      最近更新 更多