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 |
有了这个,思路就清晰了:首先,我要判断之后一个字是几个字节的,然后截取相应的字节数。于是有了如下代码:
void Dictionary::splitWord(const string & word, vector<string> & characters)
{
int num = word.size();
int i = ;
while(i < num)
{
int size;
if(word[i] & 0x80)
{
if(word[i] & 0x20)
{
if(word[i] & 0x10)
{
if(word[i] & 0x08)
{
if(word[i] & 0x04)
{
size = ;
}else{
size = ;
}
}else{
size = ;
}
}else{
size = ;
}
}else{
size = ;
}
}else{
size = ;
}
string subWord;
subWord = word.substr(i, size);
characters.push_back(subWord);
i += size;
}
}
if之中嵌套if,虽然过程很清晰,但是代码行数也太多了,于是对其进行修改,得到如下代码:
void Dictionary::splitWord(const string & word, vector<string> & characters)
{
int num = word.size();
int i = ;
while(i < num)
{
int size = ;
if(word[i] & 0x80)
{
char temp = word[i];
temp <<= ;
do{
temp <<= ;
++size;
}while(temp & 0x80);
}
string subWord;
subWord = word.substr(i, size);
characters.push_back(subWord);
i += size;
}
}
少了一半左右。
分解出来的结果是存在vector容器中的,这个可以根据具体需要进行更改。
最后发现,中文在utf-8编码中是三个字节的
其实,只需要手动打印出对应string的size,就可以计算出每个字占多少字节了,当时怎么没发现呢?
C++里将string类字符串(utf-8编码)分解成单个字(可中英混输)的更多相关文章
- 萌新笔记——C++里将string类字符串(utf-8编码)分解成单个字(可中英混输)
最近在建词典,使用Trie字典树,需要把字符串分解成单个字.由于传入的字符串中可能包含中文或者英文,它们的字节数并不相同.一开始天真地认为中文就是两个字节,于是很happy地直接判断当前位置的字符的A ...
- hiho1482出勤记录II(string类字符串中查找字符串,库函数的应用)
string类中有很多好用的函数,这里介绍在string类字符串中查找字符串的函数. string类字符串中查找字符串一般可以用: 1.s.find(s1)函数,从前往后查找与目标字符串匹配的第一个位 ...
- Java里的String类为什么是final的
今天在看<图解设计模式>,里面出了一个问题“String类用final修饰,导致它无法被继承(扩展),这样做违反了开闭原则,这么做有什么正当理由?” 答案是效率和安全性 首先是效率,由于 ...
- 《java入门》第一季之类(String类字符串一旦被赋值就没法改变)
毫无疑问,String类是java里面最重要的类之一.因此它有很多方法需要了解和掌握. 字符串一旦被赋值,值就不能发生改变: package cn.itcast_02; /* * 字符串的特点:一旦被 ...
- 常用类一一字符串相关类一一String类 字符串的使用
Java字符串就是Unicode字符序列,例如“Java”就是4个Unicode字符J,a,v,a组成的. Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义的类String,每个 ...
- 关于C语言打印string类字符串的问题
首先因为printf函数输出字符串是针对char *的,即printf只能输出c语言的内置数据,而string不是c语言的内置数据. 其次string类型的对象不止包含字符串,还包含了许多用于操作的函 ...
- STL --> string类字符串
基本使用方法 一.输入 string s: cin >> s; getline(cin, s) ; //使用默认的'\n'作为终止符 getline(cin, s, '!') ; //以' ...
- 01.String类字符串本质
String类是在java开发过程中,使用最最频繁的一个类,不管是 用户名 密码 还是http报文接收过来的数据,其本质就是字符序列 所以做为一个java开发者,我们要重点掌握好String的方法使用 ...
- 工具类:将其他编码类型转换成UTF-8或者其他类型的工具类
将其他编码类型转换成UTF-8或者其他类型的工具类 public static String changeUTF(String str) { String newStr = null; try { n ...
随机推荐
- docker加速器配置
我使用docker的原因 最近自己一直在强迫自己使用docker,一方面是docker的容器化服务,使得每一个配置相互独立,易于维护.而且如果到后面如果深入了的话,通过自己编写dockerfile,那 ...
- Wormholes 虫洞 BZOJ 1715 spfa判断负环
John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地 ...
- 2.1、Softmax Regression模型
Softmax Regression模型 由于Logistics Regression算法复杂度低,容易实现等特点,在工业中的到广泛的使用,但是Logistics Regression算法主要用于处理 ...
- 在makefile通过宏定义来控制源程序的编译
在Makefile中我们可以通过宏定义来控制源程序的编译.只要在Makefile中的CFLAGS中通过选项-D来指定你于定义的宏即可. 如:CFLAGS += -D _XXX在编译的时候加上此选项就可 ...
- 【转】Caused by: Action class [com.struts.action.xxxAction] not found 解决方法
刚学习Struts,自己写了个简单程序,一启动tomcat就报错,但是我按着ctrl点击struts.xml中com.struts.action.LoginAction也能定位到LoginAction ...
- LeetCode6. Z字形变换
描述 The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows li ...
- 关于 Gojs 你可能用到的方法 / gojs自定义 / gojs
以下归纳如果对你有帮助的话请点下文章下面的推荐,谢谢! 1.阻止键盘事件 myDiagram.commandHandler.doKeyDown = function () { var e = myDi ...
- [转] CSS 选择器参考手册
[From] http://www.w3school.com.cn/cssref/css_selectors.asp CSS3 选择器 在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素. ...
- nodejs的一些学习
要使用npm的时候,其实是可以直接下载node.js的.参考文档http://www.runoob.com/nodejs/nodejs-npm.html 安装成功之后.判断是否安装成功.是不能直接用n ...
- Mac上Node环境配置
公司配备Mac笔记本,以前没用过mac开发项目,一开始依然是从node官网下载安装包,后来领导说最好是用brew安装软件,这样比较方便,安装和卸载,只要在命令行输入相应的 install 和 unin ...