如何删除 utf8 字符串的尾随空格而不读取整个字符串以提高性能?

cha*_*m15 1 c performance

我有一个函数如下:

void utf8_trim_end(char *data, int length){
  int bytecount = 1;
  int idx = length;
  char *current = data;
  for (int i = 0; i < length; i += bytecount){
     if (!iswhitespace(&data[i])){
        idx = i;
     }
     bytecount = utf8_bytecount(&data[i], length-i);
  }
  data[idx] = 0;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,为了确保我们查看多字节字符的开头,我们从头开始并迭代。这可行,但对于长字符串来说速度很慢。我想知道是否有一种可接受的方法从最后开始并从那里向后工作?(另外,不想找图书馆,想自己做)

Nor*_*ray 6

可以走到最后并倒退。

\n

所有 UTF-8 多字节字符都表示为起始字节,后跟许多 \xe2\x80\x98continuation\xe2\x80\x99 字节,可以通过检查起始字节来确定其数量。所有连续字节的形式都是0b10xx xxxx. 因此,无论位于 UTF-8 字符串中的哪个位置,如果位于连续字节上,都可以向前或向后扫描以跳过连续字节并找到起始字节。

\n

从 UTF-8 流中查找并识别 Unicode 空白字符(向后阅读)会有点麻烦,但留给读者作为练习!

\n

(维基百科的一篇优秀文章中描述了编码)。

\n
\n

(编辑添加:)

\n

如果您(或任何其他人)需要的是一个快速而肮脏的解决方案,那么,由于 ASCII 范围内的代码点以 UTF-8 编码为相应的字节(即,空格字符被编码为0x20),所以您只需使用 ctype 去除 ASCII 空格即可从 UTF-8 编码字符串中去除大部分isspace()尾随空格。

\n

但是,如果删除空格很重要,从某种意义上说,有人可能想破解该进程,那么您仍然必须正确执行 \xe2\x80\x98\'。这是因为,虽然不推荐,但字符可能会被编码为 \xe2\x80\x98overlong\xe2\x80\x99:空格字符可能会显示为多字节序列 、0xC0 0xA00xE0 0x80 0xA0、 或0xF0 0x80 0x80 0xA0,所有这些会解码为空格字符,从而欺骗快速而肮脏/天真的空白剥离器。

\n

(我现在要闭嘴了,但我最近不得不与这些东西进行有趣的争论,所以它在我的脑海中仍然新鲜)

\n

  • @chacham15 第一个字节将以“11”位“开始”。 (2认同)