C 获取多字节UTF-8序列的长度

C 获取多字节UTF-8序列的长度,c,utf-8,C,Utf 8,我正在解析一些UTF-8文本,但只对ASCII范围内的字符感兴趣,也就是说,我可以跳过多字节序列 我可以很容易地检测序列的开头,因为设置了符号位,所以char值小于0。但是我如何知道序列中有多少字节,以便跳过它呢 我不需要执行任何验证,也就是说,我可以假设输入是有效的UTF-8。尽管重复数据消除器的答案更适合跳过多字节序列的特定目的,但如果需要获得每个此类字符的长度,请将第一个字节传递给此函数: int getUTF8SequenceLength (unsigned char firstPoin

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

我可以很容易地检测序列的开头,因为设置了符号位,所以
char
值小于0。但是我如何知道序列中有多少字节,以便跳过它呢


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

尽管重复数据消除器的答案更适合跳过多字节序列的特定目的,但如果需要获得每个此类字符的长度,请将第一个字节传递给此函数:

int getUTF8SequenceLength (unsigned char firstPoint) {
    firstPoint >>= 4;
    firstPoint &= 7;
    if (firstPoint == 4) return 2;
    return firstPoint - 3;
}
这将返回序列的总长度,包括第一个字节。为了清楚起见,我在这里使用了一个unsigned char值作为
firstPoint
参数,但是请注意,如果该参数是一个有符号的char,那么这个函数将以完全相同的方式工作

解释:

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

  • 该值下移4,然后加上7。这只剩下从右侧开始的第1、第2和第3位作为唯一可能的设置。这些位的值分别为1、2和4

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

  • 在此之后,值为7,表示所有三个位都已设置,因此序列总共为4个字节;或为6,表示从左侧开始的前两个位已设置,因此序列总共为3个字节


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

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

这不是一个好主意。在这种情况下,可以包含UTF-8中的字符sequence@Yossarian:请举例说明。UTF-8明确地使您的场景不可能实现。@Yossarian所有包含1个以上字节(2,3,4)的UTF-8序列只包含设置了MSBit的字节。@Deduplicator我明白您的问题所在。如果“é”由Unicode代码点x00e9或“e”(x0065)和组成◌́'(x0301)。因此,如果我们只关心非组合的代码点,那么您的解决方案工作得很好。我怀疑这也达到了OP的目标。还是最喜欢你的解决方案。@goldilock&Yossarian,需要根据UTF-8序列修改我关于
UTF-8序列的断言。由1个以上字节(2,3,4)组成的“未组合”UTF-8序列仅由设置了MSBit的字节组成。请记住,
char
可以实现为有符号或无符号,具体取决于编译器。如果字符
ch
设置了高位,则可能表示
ch<0
,也可能表示
ch>=128
00000111
     ^^^