萌新笔记——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 ...
- 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)
萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
- 萌新笔记——C++里创建 Trie字典树(中文词典)(二)(插入、查找、导入、导出)
萌新做词典第二篇,做得不好,还请指正,谢谢大佬! 做好了插入与遍历功能之后,我发现最基本的查找功能没有实现,同时还希望能够把内存的数据存入文件保存下来,并可以从文件中导入词典.此外,数据的路径是存在配 ...
- 萌新笔记——C++里创建 Trie字典树(中文词典)(三)(联想)
萌新做词典第三篇,做得不好,还请指正,谢谢大佬! 今天把词典的联想做好了,也是比较low的,还改了之前的查询.遍历等代码. Orz 一样地先放上运行结果: test1 ID : char : 件 w ...
- hiho1482出勤记录II(string类字符串中查找字符串,库函数的应用)
string类中有很多好用的函数,这里介绍在string类字符串中查找字符串的函数. string类字符串中查找字符串一般可以用: 1.s.find(s1)函数,从前往后查找与目标字符串匹配的第一个位 ...
- python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字
python3.4学习笔记(二十二) python 在字符串里面插入指定分割符,将list中的字符转为数字在字符串里面插入指定分割符的方法,先把字符串变成list然后用join方法变成字符串str=' ...
- Java学习笔记之:Java String类
一.引言 字符串广泛应用在Java编程中,在Java中字符串属于对象,Java提供了String类来创建和操作字符串. 创建字符串最简单的方式如下: String str= "Hello w ...
- Java里的String类为什么是final的
今天在看<图解设计模式>,里面出了一个问题“String类用final修饰,导致它无法被继承(扩展),这样做违反了开闭原则,这么做有什么正当理由?” 答案是效率和安全性 首先是效率,由于 ...
- C++ primer plus读书笔记——第16章 string类和标准模板库
第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string ...
随机推荐
- Solr学习总结(五)SolrNet的基本用法及CURD
上一篇已经讲到了Solr 查询的相关的参数.这里在讲讲C#是如何通过客户端请求和接受solr服务器的数据, 这里推荐使用SolrNet,主要是:SolrNet使用非常方便,而且用户众多,一直都在更新, ...
- 11.struts2文件上传
文件上传 1.上传单个文件 2.上传多个文件 1.上传单个文件 实现步骤: (1)导入一个Jar包:commons-io-1.3.2.jar.只所以要导入这个Jar包,是因为要用到一个工具类Fil ...
- vue-lazy-render: 延迟渲染大组件,增强页面切换流畅度
最近用element来做项目,在开发的过程中,突然发现页面的操作和切换在数据量大的时候相当卡,后来提了个issue,在furybean解答后才知道,我每个单元格都加了tooltip,会生成大量的节点, ...
- mysql null值处理详细说明
在讲null之前,我们先看一个例子 表数据如下: 3306>select * from t1; +------+-------+ | id | name | +------+-------+ | ...
- sed命令使用详解归纳
用法 sed [option] 'Address Command' yourfile e.g. sed -n '2,13p' lineuser #打印文件lineuser中第2~13行的内容,-n为o ...
- jquery如何判断checkbox(复选框)是否被选中 ...
<script type="text/javascript" src="../lib/jQuery1.11.1.js"></script> ...
- 关系数据库SQL之可编程性事务
前言 前面关系数据库SQL之可编程性函数(用户自定义函数)一文提到关系型数据库提供了可编程性的函数.存储过程.事务.触发器及游标,前文已介绍了函数.存储过程,本文来介绍一下事务的使用.(还是以前面的银 ...
- SqlServer切换MySql总结
最近项目任务不多就琢磨着把SqlServer换成MySql(数据访问使用的ado.net),初步想了下方案有2种: 方案一:继续使用ado.net,重写所有的sql语句 优势:数据访问效率高,改写Sq ...
- 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait
[源码下载] 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait 作者:webabcd 介绍速战速决 之 PHP 类基础 抽象类 接口 trait 示例1.类的相关知识点 1(基础 ...
- 从零开始学 Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...