日常随笔——如何判断字符是汉字、字母、还是拼音? 在C++中又该如何判断?
最近遇到一个问题,需要判断一个字符串中是否包含汉字、拼音、普通字符,于是就简单记录下来。
首先,如何判断这些,绕不开操作系统中的编码,常见的有三种:ASCII、Unicode、UTF-8
ASCII
这是最早的一种编码方式,因此只将英文字符编码进去了,也就是一些大小写字母和一些符号。但是,由于后续计算机扩展到各个国家,各国的语音也需要编码,因此ASCII编码(00000000 - 01111111)127位就不够用了,于是就制定了其他编码方式。
各国都有各自的一套编码方式,比如中国制定了GB2312编码,日本把日文编入了Shift_JIS里等等,这样造成的结果就是会发生冲突,因此,Unicode应运而生。
Unicode
Unicode把所有符号都统一到一套编码里,这样就不会再有乱码问题了(Unicode 兼容了ASCII码)。 Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
ASCII和Unicode的区别
ASCII编码是1个字节,而Unicode编码通常是2个字节,举例如下。
字母 A 用ASCII编码是十进制的65,二进制的01000001;
字符 0 用ASCII编码是十进制的48,二进制的00110000,注意字符 ‘0’ 和整数 0 是不同的;
汉字 中 已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。
如果把ASCII编码的 A 用Unicode编码,只需要在前面补0就可以,因此, A 的Unicode编码是00000000 01000001。
UTF-8
考虑到一个问题:如果文件里都是由英文字符组成,如果由Unicode编码,那么会浪费整整一倍的空间(因为英文是由ASCII码表示,所以前八位都是0)。又出现了把Unicode编码转化为“可变长编码”的UTF-8编码,UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字一般编为3个字节。
字符 | ASCII | Unicode | UTF-8 |
---|---|---|---|
A | 01000001 | 00000000 01000001 | 01000001 |
中 | - | 01001110 00101101 | 11100100 10111000 10101101 |
从上面的表格可以发现UTF-8编码一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
强调一下,unicode是一种编码方式,和ascii是同一个概念,而UTF-8,UTF-16等是一种存储方式,在存储和传输上节约空间、提高性能的一种编码形式。
计算机内部使用通用编码方式
在C++的std::string
中使用的是UTF-8格式,可以通过下面代码验证:
#include <iostream>
using namespace std;
int main(){string s = "你好啊abb";cout << s.size() << endl;for(int i=0; i<s.size(); i++){cout << "s[" << i << "] = " << s[i] << " ,s[" << i << "].size() = " << sizeof(s[i]) << endl;printf("0x%02x ", (unsigned char)s[i]);cout << endl;}
}
结果:
首先,字符串s
的size是12,一个中文3个字节,所以总共是12个字节。另外,cout
默认会用ASCII码打印出字符,所以前面9个字节打印出来是乱码,不过我们可以打印出对应的十六进制编码,如结果中所示,汉字“中”打印出来的结果就是 0xe4bda0
,我们可以利用一些网站来查询字符对应的编码,比如
查看字符UTF-8编码
查询字符Unicode编码
UFT-8 编码对照表
可以查到,汉字“中”对应的UTF-8编码就是0xE4BDA0
那么,现在有了一个问题:当我们拿到内存中的 UTF-8 数据,该怎么去读取?是分一个字节读取,还是两个字节,三个字节?
如何对 UTF-8 数据进行decode
还是回到ASCII码,ASCII码由一个字节表示,一个字节最多可表示256个符号,但是,ASCII中只包含128个符号,也就是00000000 - 011111111
,所以可以通过字符的首位进行判断(个人猜测,当初设计的时候,应该也是考虑到了识别问题,所以将首位设为0,只表示128种符号)。事实上计算机确实是按这个来进行识别的:
UTF-8 规定:
- 单字节的字符,字节的第一位设为0,对于英语文本,UTF-8码只占用一个字节,和ASCII码完全相同;
- n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0,后面字节的前两位都设为10,这n个字节的其余空位填充该字符unicode码,高位用0补足。
这样就形成了如下的UTF-8标记位:
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
中文一般都是三个字节表示,即上面第三行的格式。
其他字符集 GB2312、GBK等
为什么在unicode和UTF-8大行其道的同时,GB2312和GBK仍在广泛使用 ?
- 原因就在于UTF-8表示中文的时候,需要3个字节,如果是全中文的文件,这样对于双字节的编码方法,会多浪费50%的额外空间。所以,GB2312和GBK仍在广泛使用
日常随笔——如何判断字符是汉字、字母、还是拼音? 在C++中又该如何判断?相关推荐
- Python中判断字符是否为字母、数字、字母和数字组合,验证回文串(LeetCode125)
判断字符串是否为字母.数字 函数str.isdigit()判断字符是否为数字,函数str.isalpha()判断字符是否为字母,函数isalnum()判断字符是否为数字字母组合. 上代码: str1 ...
- 判断字符是否为字母或者数字
判断是否为大小写字母 返回的是int型 int tolower(int c) {if ((c >= 'A') && (c <= 'Z'))return c + ('a' - ...
- java 判断是否字母_java判断字符是否为字母的方法
java判断字符是否为字母的方法 发布时间:2020-06-29 18:01:37 来源:亿速云 阅读:239 作者:Leah 这篇文章运用简单易懂的例子给大家介绍java判断字符是否为字母的方法,代 ...
- java如何判断字符是否是字母?
关于java判断字符的文章早已是非常多了,本文是对我个人过往学习java,理解及应用java的一个总结.此文内容涉及java如何判断字符是否是字母的基本方法,希望对大家有所帮助. java如何判断字符 ...
- c语言判断字符是否为某字母,判断字符是否为字母
问题一:java 判断一个字符是否为字母int start,end,i=0; char[] ch = s.toCharArray(); while(!Character.isLetter(ch[i]) ...
- python判断是不是字母_python判断字符是否为字母和数字
在使用python语言中的字符串方法时,可以使用它们判断字符串中是否有字母或数字或其他的构成.下面利用几个实例说明字符串方法的用法,操作如下:python学习网,大量的免费python视频教程,欢迎在 ...
- python判断字符是英文字母怎么回事_python判断字符串是否包含字母
第一种方法:使用正则表达式判断字符串是否包含字母#-*- coding:utf-8 -*-import re def check(str): my_re = re.compile(r'[A-Za-z] ...
- python判断字符是否是数字和字母_python判断字符是否为字母和数字
在使用python语言中的字符串方法时,可以使用它们判断字符串中是否有字母或数字或其他的构成.下面利用几个实例说明字符串方法的用法,操作如下:云海天教程网,大量的免费python教程,欢迎在线学习!s ...
- python怎么识别字母数字的_python判断字符是否为字母和数字
在使用python语言中的字符串方法时,可以使用它们判断字符串中是否有字母或数字或其他的构成.下面利用几个实例说明字符串方法的用法,操作如下: str_1 = "123" str_ ...
- 判断字符是否为字母c语言,C程序检查字符是否为字母
C程序检查字符是否为字母 在此示例中,您将学习检查用户输入的字符是否为字母. 要理解此示例,您应该了解以下C语言编程主题: 在C语言编程中,字符变量保存的是ASCII值(0到127之间的整数),而不是 ...
最新文章
- Linux System Programming --Chapter Five
- [J2ME] Signing a midlet suite的讨论稿[Update]
- Oracle常用的几个父栓
- 机器学习之 sklearn.preprocessing 模块
- linux怎么运行g77,Linux安装g77编译器的技巧
- 作者:石勇(1956-),男,中国科学院大学经济管理学院教授、博士生导师
- SpringCloud Consul注册中心介绍及配置使用
- nginx 根据目录指定root_CentOS(7.6)基本操作与Nginx配置
- [转]OpenGL基础技术讲座--发展历史
- mysql 主从的几个参数
- 计算机网络的创新创业计划书,互联网创新创业计划书.doc
- 百度翻译api和SpringBoot集成
- 开源电子书项目FBReader初探(五)
- github国内镜像站
- java 后台管理模板_后台管理系统模板 - WEB源码|JSP源码/Java|源代码 - 源码中国
- 《Python编程:从入门到实践》配套资源 官方网站免费下载
- 为什么一个数的平方,会变负数?结果令人惊讶(sq代码解析)
- 第一章:快乐的老青蛙
- 大学matlab选择试题和答案,Matlab与信息处理-中国大学mooc-试题题目及答案
- 读《活在网络里 大升级时代的人类新进化》
热门文章
- 赶紧换掉windows系统自带记事本
- 河北师范大学汇华学院计算机类,河北师范大学汇华学院
- 2022年泰迪杯数据分析_B题:银行客户忠诚度分析赛题数据_任务五
- [阿里DIN] 从论文源码学习 之 embedding层如何自动更新
- 从甲骨文中国研发中心大裁员细说技术人员的未来
- 新概念英语(1-99)Ow!
- 初遇Flarum_搭建安装的遇坑填坑过程
- 事件10016,RuntimeBroker无法编辑
- 一文彻底理解I/O多路复用
- 论文阅读 Performance Comparison Between Linux Containers and Virtual Machines