我需要将 UTF-8 字符串中的字节位置转换为 Objective-C 中相应的字符位置。我确信必须有一个库来执行此操作,但我找不到一个 - 任何人都可以(尽管显然任何 C 或 C++ 库都可以在这里完成这项工作)。
我意识到我可以在所需字符处截断 UTF-8 字符串,将其转换为 NSString,然后读取 NSString 的长度以获得我的答案,但这似乎是一个可以解决的问题的有点棘手的解决方案只需在 C 中使用一个小的 FSM。
谢谢你的帮助。
我需要将 UTF-8 字符串中的字节位置转换为 Objective-C 中相应的字符位置。我确信必须有一个库来执行此操作,但我找不到一个 - 任何人都可以(尽管显然任何 C 或 C++ 库都可以在这里完成这项工作)。
我意识到我可以在所需字符处截断 UTF-8 字符串,将其转换为 NSString,然后读取 NSString 的长度以获得我的答案,但这似乎是一个可以解决的问题的有点棘手的解决方案只需在 C 中使用一个小的 FSM。
谢谢你的帮助。
“字符”是一个有点模棱两可的术语,它在不同的上下文中意味着不同的东西。我猜你想要和你的例子一样的结果,[NSString length]
.
NSString
文档并没有完全提前说明这一点,而是计算[NSString length]
了字符串中UTF-16 代码单元的数量。所以 U+0000..U+FFFF 每个算一个,但 U+10000..U+10FFFF 每个算两个。并且不要拆分代理对!
您可以根据每个 UTF-8 字符的前导字节来计算 UTF-16 代码点的数量。尾随字节使用一组不相交的值,因此您根本不需要跟踪任何状态,除了您在字符串中的位置(好消息:有限状态机是多余的)。
static const unsigned char BYTE_WIDTHS[256] = {
// 1-byte: 0xxxxxxx
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
// Trailing: 10xxxxxx
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
// 2-byte leading: 110xxxxx
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
// 3-byte leading: 1110xxxx
// 4-byte leading: 11110xxx
// invalid: 11111xxx
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0
};
size_t utf8_utf16width(const unsigned char *string, size_t len)
{
size_t i, utf16len = 0;
for (i = 0; i < len; i++)
utf16len += BYTE_WIDTHS[string[i]];
return utf16len;
}
该表是 1 表示 1 字节、2 字节和 3 字节 UTF-8 前导字符,2 表示 4 字节 UTF-8 前导字符,因为这些字符在转换为NSString
.
我在 Haskell 中生成了表格:
elems $ listArray (0,256) (repeat 0) //
[(n,1) | n <- ([0x00..0x7f] ++ [0xc0..0xdf] ++ [0xe0..0xef])] //
[(n,2) | n <- [0xf0..0xf7]]
查看UTF-8 编码并注意代码点以以下 8 位模式开头:
76543210 <- bit
0xxxxxxx <- ASCII chars
110xxxxx \
1110xxxx } <- more byte(s) (of form 10xxxxxx) follow
11110xxx /
这就是您在搜索代码点的开头时应该寻找的内容。
但这只是解决方案的一部分。您需要考虑Combining characters。您需要将变音符号与它们之前的主要字符组合在一起,您不能将它们分开并视为独立字符。
可能还有更多。