C++⾥将string类字符串(utf-8编码)分解成单个字(可中英混
输)
最近在建词典,使⽤Trie字典树,需要把字符串分解成单个字。由于传⼊的字符串中可能包含中⽂或者英⽂,它们的字节数并不相同。⼀开始天真地认为中⽂就是两个字节,于是很happy地直接判断当前位置的字符的ASCII码是否处于0~127之间,如果是就提取⼀个字符,否则提取两个。在测试分字效果的时候,这种⽅法出了问题。⽐如我传⼀个“abcde⼀⼆三四五”进去,abcde可以正常分解成 a b c d e,⽽后⾯的“⼀⼆三四五”则成了乱码。
于是我开启了⾕歌之旅,搜索“如何在C++中将string中的中⽂分解成单个字”云云,搜索到的⽅法⼤多与我之前的⽅法雷同,把代码copy 下来直接运⾏也是会出现乱码。我突然想到,linux下可能会出现中⽂乱码的原因之⼀就是编码问题,于是我打开了vim的配置⽂件,发现我确实是把中⽂设置成了utf-8。
发现了这点之后,我专门搜索了utf-8,得知它是⼀种变长编码,具体规则如下:
1)对于单字节的符号,字节的第⼀位设为0,后⾯7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第⼀个字节的前n位都设为1,第n+1位设为0,后⾯字节的前两位⼀律设
为10。剩下的没有提及的⼆进制位,全部为这个符号的unicode码。
如表:
1字节0xxxxxxx
2字节110xxxxx 10xxxxxx
3字节1110xxxx 10xxxxxx 10xxxxxx
4字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
有了这个,思路就清晰了:⾸先,我要判断之后⼀个字是⼏个字节的,然后截取相应的字节数。于是有了如下代码:
1 void Dictionary::splitWord(const string & word, vector<string> & characters)
2 {
3 int num = word.size();
4 int i = 0;
5 while(i < num)
6 {
7 int size;
8 if(word[i] & 0x80)
9 {
10 if(word[i] & 0x20)
11 {
12 if(word[i] & 0x10)
13 {
14 if(word[i] & 0x08)
15 {
16 if(word[i] & 0x04)
17 {
18 size = 6;
19 }else{
20 size = 5;
21 }
22 }else{
23 size = 4;
24 }
25 }else{
26 size = 3;
27 }
28 }else{
29 size = 2;
30 }
31 }else{
32 size = 1;
33 }
34 string subWord;
35 subWord = word.substr(i, size);
36 characters.push_back(subWord);
37 i += size;
38 }
39 }
if之中嵌套if,虽然过程很清晰,但是代码⾏数也太多了,于是对其进⾏修改,得到如下代码:
1 void Dictionary::splitWord(const string & word, vector<string> & characters)
2 {
乱码符号怎么打出来3 int num = word.size();
4 int i = 0;
5 while(i < num)
6 {
7 int size = 1;
8 if(word[i] & 0x80)
9 {
10 char temp = word[i];
11 temp <<= 1;
12 do{
13 temp <<= 1;
14 ++size;
15 }while(temp & 0x80);
16 }
17 string subWord;
18 subWord = word.substr(i, size);
19 characters.push_back(subWord);
20 i += size;
21 }
22 }
少了⼀半左右。
分解出来的结果是存在vector容器中的,这个可以根据具体需要进⾏更改。
最后发现,中⽂在utf-8编码中是三个字节的
其实,只需要⼿动打印出对应string的size,就可以计算出每个字占多少字节了,当时怎么没发现呢?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论