【问题标题】:Get length of multibyte UTF-8 sequence获取多字节 UTF-8 序列的长度
【发布时间】:2014-04-01 15:55:11
【问题描述】:

我正在解析一些 UTF-8 文本,但只对 ASCII 范围内的字符感兴趣,也就是说,我可以跳过多字节序列。

我可以很容易地检测到序列的开头,因为设置了符号位,所以 char 的值

我不需要执行任何验证,即我可以假设输入是有效的 UTF-8。

【问题讨论】:

  • 请记住,char 可以实现为有符号或无符号,具体取决于您的编译器。如果 char ch 设置了高位,则可能表示 ch < 0 或表示 ch >= 128

标签: c utf-8


【解决方案1】:

只需去掉所有不是有效 ascii 的字节,不要试图变得可爱并解释字节 >127。只要您在 ascii 范围内没有任何带有基本字符的组合序列,它就可以工作。对于那些你需要自己解释代码点的人。

【讨论】:

  • 这不是一个好主意。在这种情况下,您可以包含属于 UTF-8 序列的字符
  • @Yossarian:请举个例子。 UTF-8 明确地使您的方案不可能 AFAIK。
  • @Yossarian 所有包含超过 1 个字节 (2,3,4) 的 UTF-8 序列包含设置了 MSBit 的字节。
  • @Deduplicator 我看到您对Unicode equivalence 的关注。如果“é”由 Unicode 代码点 x00e9 或“e”(x0065)和“◌́”(x0301)组成。因此,如果我们只关心非组合代码点,您的解决方案可以正常工作。我怀疑它也符合 OP 的目标。还是最喜欢你的解决方案。
  • @goldilocks & Yossarian,需要根据 UTF-8 序列 Unicode equivalence 修改我关于 UTF-8 sequences 的断言。包含超过 1 个字节 (2,3,4) 的“未组合”UTF-8 序列仅包含设置了 MSBit 的字节。
【解决方案2】:

虽然 Deduplicator 的回答更适合跳过多字节序列的特定目的,但如果需要获取每个此类字符的长度,请将第一个字节传递给此函数:

int getUTF8SequenceLength (unsigned char firstPoint) {
    firstPoint >>= 4;
    firstPoint &= 7;
    if (firstPoint == 4) return 2;
    return firstPoint - 3;
}

这将返回序列的总长度,包括第一个字节。为了清楚起见,我在这里使用无符号字符值作为firstPoint 参数,但请注意,如果参数是有符号字符,则此函数的工作方式完全相同。

解释一下:

  • UTF-8 在序列的第一个字节中使用位 5、6 和 7 来指示剩余长度。如果所有三个都设置,则序列是 3 个附加字节。如果仅设置了这些 左侧的第一个(第 7 位),则序列是 1 个附加字节。如果设置了左侧的前两个字节,则序列是 2 个附加字节。因此,我们要检查这三个位(这里的值只是一个例子):

     11110111
      ^^^
    
  • 该值被向下移动 4,然后与 7 进行“与”运算。这仅留下第 1、第 2 和第 3 位 从右侧作为唯一可能的设置。这些位的值分别为 1、2 和 4。

    00000111
         ^^^ 
    
  • 如果值现在是 4,我们知道只有左边的第一位(我们正在考虑的三个)被设置并且可以返回 2。

  • 1234563总计。

这涵盖了以 UTF-8 表示的有效 Unicode 字符的范围。

【讨论】:

    猜你喜欢
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 2012-09-22
    • 2011-01-26
    • 2013-08-14
    • 2016-01-01
    相关资源
    最近更新 更多