gpt4 book ai didi

c++ - 从 std::string 中提取(第一个)UTF-8 字符

转载 作者:太空狗 更新时间:2023-10-29 21:00:11 26 4
gpt4 key购买 nike

我需要使用 C++ implementation of PHP's mb_strtoupper function模仿维基百科的行为。

我的问题是,我只想向函数提供一个单个 UTF-8 字符,即 std::string 的第一个字符。

std::string s("äbcdefg");
mb_strtoupper(s[0]); // this obviously can't work with multi-byte characters
mb_strtoupper('ä'); // works

是否有一种有效的方法来检测/返回字符串的第一个 UTF-8 字符?

最佳答案

在 UTF-8 中,第一个字节的高位告诉您有多少后续字节属于同一代码点

0b0xxxxxxx: this byte is the entire code point
0b10xxxxxx: this byte is a continuation byte - this shouldn't occur at the start of a string
0b110xxxxx: this byte plus the next (which must be a continuation byte) form the code point
0b1110xxxx: this byte plus the next two form the code point
0b11110xxx: this byte plus the next three form the code point

可以假设该模式继续存在,但我认为有效的 UTF-8 从未使用超过四个字节来表示单个代码点。

如果您编写一个函数来计算设置为 1 的前导位的数量,那么您可以使用它来确定在何处拆分字节序列,以便隔离第一个逻辑代码点,假设输入是有效的 UTF- 8.如果您想针对无效的 UTF-8 进行强化,则必须编写更多代码。

另一种方法是利用连续字节始终与模式 0b10xxxxxx 匹配这一事实,因此您获取第一个字节,然后只要下一个字节匹配就继续获取字节那种模式。

std::size_t GetFirst(const std::string &text) {
if (text.empty()) return 0;
std::size_t length = 1;
while ((text[length] & 0b11000000) == 0b10000000) {
++length;
}
return length;
}

对于许多语言,单个代码点通常映射到单个字符。但是人们认为的单个字符可能更接近 Unicode 所说的字素簇,它是一个或多个代码点组合起来产生一个字形。

在您的示例中,ä 可以用不同的方式表示:它可以是单个代码点 U+00E4 LATIN SMALL LETTER A WITH DIAERESIS 它可能是 U+0061 LATIN SMALL LETTER AU+0308 COMBINING DIAERESIS 的组合。幸运的是,只需选择第一个代码点就可以实现将第一个字母大写的目标。

如果您确实需要第一个字素簇,则必须查看第一个代码点以外的内容,看看下一个是否与它结合。对于许多语言,知道哪些代码点是“非间距”或“组合”或变体选择器就足够了。对于一些复杂的脚本(例如韩文?),您可能需要求助于此 Unicode Consortium technical report .

关于c++ - 从 std::string 中提取(第一个)UTF-8 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22774630/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com