如何计算C ++中UTF-8文件中的 unicode 字符?也许有人会如此友善地向我展示一个“独立”的方法,或者使用http://icu-project.org/index.html作为简短的例子。
编辑:一个重要的警告是我需要构建每个字符的计数,所以它不像我在计算字符总数,而是计算一组字符的出现次数
答案 0 :(得分:9)
在UTF-8中,非前导字节始终将前两位设置为10
,因此只需忽略所有这些字节。如果你不介意额外的复杂性,你可以做更多的事情(根据前导字节的位模式跳过非前导字节)但实际上,除了短字符串之外它不太可能有很大差异(因为你通常会接近内存带宽。)
编辑:我最初误解了你的问题只是询问如何计算以UTF-8编码的字符串的长度。如果你想计算字符频率,你可能想要convert those to UTF-32/UCS-4,那么你需要某种稀疏数组来计算频率。
这很难解决计算代码点与字符的问题。例如,考虑字符“À” - “带有坟墓的拉丁大写字母A”。至少有两种不同的方法可以产生这个角色。您可以使用代码点U + 00C0,它在单个代码点中编码整个事物,或您可以使用代码点U + 0041(拉丁大写字母A),然后是代码点U + 0300(结合重音符号) )。
规范化(相对于Unicode)意味着将所有这些字符转换为相同的形式。您可以将它们全部组合到一个代码点中,也可以将它们全部分成单独的代码点。出于您的目的,尽可能将它们组合成单个代码点可能更容易。自己写这个可能不太实际 - 我会使用ICU项目中的normalizer API。
答案 1 :(得分:4)
如果你知道UTF-8序列形成良好,那就很容易了。计算以零比特或两比特开始的每个字节。第一个条件将与每个字节表示的每个代码点进行聊天,第二个条件将捕获每个多字节序列的第一个字节。
while (*p != 0)
{
if ((*p & 0x80) == 0 || (*p & 0xc0) == 0xc0)
++count;
++p;
}
或者,正如评论中所述,您可以跳过每个延续的字节:
while (*p != 0)
{
if ((*p & 0xc0) != 0x80)
++count;
++p;
}
或者如果你想变得非常聪明并且让它成为一个双线:
for (p; *p != 0; ++p)
count += ((*p & 0xc0) != 0x80);
Wikipedia page for UTF-8清楚地显示了模式。
答案 2 :(得分:3)
使用C ++编写的完整例程的讨论在http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html
答案 3 :(得分:3)
我知道,这个帖子已经晚了但是,它可以提供帮助
有ICU的东西,我这样做了:
string TheString = "blabla" ;
UnicodeString uStr = UnicodeString::fromUTF8( theString.c_str() ) ;
cout << "length = " << uStr.length( ) << endl ;
答案 4 :(得分:0)
我不认为这是一个以语言为中心的问题。 UTF-8格式相当简单;从文件中解码它应该只有几行代码。
open file
until eof
if file.readchar & 0xC0 != 0x80
increment count
close file