2010-08-27 30 views
2

如何計算unicode字符在C++中的UTF-8文件中?也許如果有人會如此友善地向我展示「獨立」方法,或者使用http://icu-project.org/index.html作爲簡單示例。在C++中統計unicode字符

編輯:一個重要的條件是,我需要建立每個字符的計數,所以它不喜歡我數字符的總數,而是一組字符的出現次數。

+3

你想算的字符或代碼點?根據你的編輯,這聽起來像你會關心正常化。所有答案(截至撰寫本文時)都是關於計數碼點的。 – 2010-08-27 18:16:25

+0

@Logan:「正常化」是什麼意思? – 2010-08-27 18:18:25

+2

Logan是對的。鏈接:http://unicode.org/reports/tr15/ – 2010-08-27 18:35:17

回答

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

+0

對於Unicode統一化。這也是一個win32 api。 – 2010-08-28 19:29:17

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清楚地顯示了模式。

+0

它應該是(* p&0xc0)!= 0x80 – jean 2016-02-26 03:21:25

+0

@jean或者其中一個工作原理相同。 – 2016-02-26 05:10:35

+0

==優先級高於& – jean 2016-02-26 05:53:35

0

我不認爲這是一個以語言爲中心的問題。 UTF-8格式非常簡單;從文件解碼應該只有幾行任何語言的代碼。

open file 
until eof 
    if file.readchar & 0xC0 != 0x80 
     increment count 
close file 
+0

(file.readchar&0xC0)!= 0x80。至少在C中,!=具有比& – jean 2016-02-26 03:24:53

3

我知道,這是遲到了這個線程,但它可以幫助

與ICU的東西,我沒有這樣說:

string TheString = "blabla" ; 
UnicodeString uStr = UnicodeString::fromUTF8(theString.c_str()) ; 
cout << "length = " << uStr.length() << endl ;