C++里将string类字符串(utf-8编码)分解成单个…
2018-06-17 23:32:50来源:未知 阅读 ()
最近在建词典,使用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,就可以计算出每个字占多少字节了,当时怎么没发现呢?
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:C++之菜鸟入门概念A
下一篇:【C++】pair
- C++ 转换函数搭配友元函数 2020-06-10
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++ rand函数 2020-06-10
- C++ 友元函数 2020-06-10
- C++ 运算符重载 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash