中文分詞的時候,發現string對中文的處理很不好,自己寫了一個zhstring類,從string繼承,重寫了
length:返回字符數,一個漢子作為一個字符。
substr:可以正確的截取字符串
find:查找子串的位置。
上述實現的參數都是字符位置,非字節位置
順表簡單說一下中文字符在計算機中的編碼。中文和英文不同,英文26個字母就能組合各種詞匯,但是中文有很多漢字,因此,計算機中對中文需要編碼,也就是用多個字節表示一個漢字。
計算機中中文有多種編碼方式,比如ANSI編碼,unicode編碼。根據資料,unicode貌似只是編碼方式,而不是實現方式。它有多種實現方式,比如UTF-8,UTF-16等。其中常用的UTF-8是不定長編碼,也就是說字符可能只有一個字節,比如英文字符,也可能有2-4個字節,比如漢字。其中英文字符的碼值和ASCII一致,都小於128.
既然漢字等字符是多字節組成的,那么諸如
string str="hello你好寶貝";
這樣的字符串,想要截取“你好”兩個漢字就稍微復雜一些,肯定不能用substr(5,2)這樣子,因此長度2只是字節數,不是一個漢字真是的字節數,一個漢字可能2個字節,也可能4個字節。那么怎么知道漢字的實際字節數目呢?
漢字編碼的第一個字節,結構必然是如:
11100xxx或者11000xxx這樣子的:前面幾個1,然后是0,再然后是其他碼值(0或者1),最前面有幾個1,表明這個漢字由幾個字節組成,后面的字節都是10開頭。
比如以下代碼:
int main()
{
char a[]="你好";
string s(a);
cout<<a<<endl;
return 0;
}
我們在程序中用char[]存儲漢字,發現某個漢字在char數組中的值是8進制的"\347",對應的二進制是"11100111",表明漢字“你”有3個字節組成,那么要截取一個漢字,就應該是(假如是字符串類型):
s.substr(0,3),少於或者多余這個字節數都會出現亂碼。
怎么計算前面1的個數?方法很多,我才用的是移位運算,代碼如下:
......
typedef unsigned char UBIT8;
......
int zhstring::getBytes(UBIT8 c)
{
if (c < 128)
return 1;
int count;
for (count = 1; count < 8; count++)
{
unsigned char b = c << count;
if (b < 128)
break;
}
return count;
}
較為完整的zhstring類代碼看gitee:https://gitee.com/svod5306/cpp/blob/master/中文string類/zhstring.h
