如何计算C++中UTF-8文件中的unicode字符?也许有人会如此友善地向我展示一个"独立"的方法,或者使用http://icu-project.org/index.html这个简短的例子.
编辑:一个重要的警告是我需要构建每个字符的计数,所以它不像我计算字符总数,而是计算一组字符的出现次数.
在UTF-8中,非前导字节始终将前两位设置为10,因此只需忽略所有这些字节.如果你不介意额外的复杂性,你可以做更多的事情(根据前导字节的位模式跳过非前导字节)但实际上,除了短字符串之外它不太可能有很大差异(因为你通常会接近内存带宽).
编辑:我最初错误地读了你的问题,只是询问如何计算以UTF-8编码的字符串的长度.如果你想计算字符频率,你可能想要将它们转换为UTF-32/UCS-4,那么你需要某种稀疏数组来计算频率.
其中最难的部分是计算代码点数与字符数.例如,考虑字符"À" - "带有坟墓的拉丁大写字母A".至少有两种不同的方法可以产生这个角色.您可以使用代码点U + 00C0,它在单个代码点中对整个事物进行编码,或者您可以使用代码点U + 0041(拉丁大写字母A),然后使用代码点U + 0300(结合严重重音).
规范化(相对于Unicode)意味着将所有这些字符转换为相同的形式.您可以将它们全部组合到一个代码点中,也可以将它们全部分成单独的代码点.出于您的目的,尽可能将它们组合成单个代码点可能更容易.自己写这个可能不太实际 - 我会使用ICU项目中的normalizer API.
如果您知道 UTF-8 序列的格式良好,那就很容易了。对以零位或两个 1 位开头的每个字节进行计数。第一个条件将捕获由单个字节表示的每个代码点,第二个条件将捕获每个多字节序列的第一个字节。
while (*p != 0)
{
if ((*p & 0x80) == 0 || (*p & 0xc0) == 0xc0)
++count;
++p;
}
Run Code Online (Sandbox Code Playgroud)
或者,如评论中所述,您可以简单地跳过作为延续的每个字节:
while (*p != 0)
{
if ((*p & 0xc0) != 0x80)
++count;
++p;
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您想变得非常聪明并使其成为 2-liner:
for (p; *p != 0; ++p)
count += ((*p & 0xc0) != 0x80);
Run Code Online (Sandbox Code Playgroud)