我曾以为老师的话是真的,我曾以为老师会为自己说出的话负责,但事实证明很多时候是照本宣科。

  这次在公司做Fcitx输入法时,想到退格删除的字节数的不同,即退格键一按到底删除的是一个字节还是两个字节或者多个。在测试中我发现,中文汉字占了三个字节,竟然占了三个字节,老师不是经常告诉我们汉字是占两个字节,但现在怎么占了三个字节,是老师的错还是程序的错,亦或本都没错,只是没有探其根本罢了。

  说汉字占两个字节是从以Unicode的编码方式UCS-2来说的,但实际占三个字节,是从Unicode的实现方式UTF-8来说的。

  先介绍下Unicode字符集吧。

  什么是字符?什么是字符集?

  字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

  字符集是多个字符的集合,字符集种类较多,每个字符集合包含的字符个数不同,常见字符集名称:ASCII字符集、Unicode字符集、GB2312字符集、BIG5字符集、GB18030字符集等。

  多年来,许多人一直将文本串作为一系列单字节字符来进行编码,并在结尾处放一个零。对于我们来说,很习惯调用strlen函数来返回以0结尾的单字节字符数组中字符数目。这是我们平时所说的ASCII字符,即单字节字符,一个字符占一个字节,即八位,所以它提供的符号最多不能超过1+28-1=256个字符,但明显单字节是根本不够用的,为此出现了双字节字符集(DBCS)。

  Unicode的编码和实现。

  大概来说,Unicode编码系统可分为编码方式和实现方式两个层次。

  编码方式

  Unicode是国际组织制定的可以容纳世界上所以文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

  通用字符集(Universal Character set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。UCS-2用两个字节编码,UCS-4用4个字节编码。

  实现方式

  在Unicode中:汉字的“字”对应的数字是23383。在Unicode中,有许多方式将数字23383表示成程序中的数据,包括UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:

  BYTE date_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};

  可见,一个汉字以UTF-8编码是占三个字节。

  UTF-8

  UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:

  Unicode编码(16进制)    UTF-8字节流(二进制)

  000000-00007F        0xxxxxxx

  000080-0007FF        110xxxxx  10xxxxxx        

  000800-00FFFF        1110xxxx  10xxxxxx  10xxxxxx

  010000-10FFFF        11110xxx  10xxxxxx  10xxxxxx  10xxxxxx

  UTF-8的特点是对不同范围的字符使用不同长度的编码,所以UTF-8兼容ASCII编码。UTF-8编码的最大长度是4个字节。从上表可以看出,4个字模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。

  从Unicode编码的UTF-8实现方式比较好理解:

  例如,汉字的“汉”字的Unicode编码是0x6C49。0x6C49是在0x800-0xFFFF之间,则对应用UTF-8来实现需要点三个字节,1110xxxx  10xxxxxx  10xxxxxx。

  0x6C49的二进制是0110 1100 0100 1001,用这个比特流依次代替模板中的x,即用0110 1100 0100 1001从低位到高位替代1110xxxx  10xxxxxx  10xxxxxx的x位,不足时用0代替。

  0110 1100 0100 1001  

  1110xxxx  10xxxxxx  10xxxxxx

  11100110  10110001  10001001

  现在谈谈针对是UTF-8编码方式而言退格键的实现。

void utf8_backspace(char *text)
{int n = strlen(text);char *last_byte = text + n - 1;if(!((*last_byte) & 0x80)) {text[n-1] = '\0';} else if(((*(last_byte-1)) & 0xc0) == 0xc0) {text[n-2] = '\0';text[n-1] = '\0';}else if(((*(last_byte-2)) & 0xe0) == 0xe0) {text[n-3] = '\0';text[n-2] = '\0';text[n-1] = '\0';}  else if(((*(last_byte-3)) & 0xf0) == 0xf0) {text[n-4] = '\0';text[n-3] = '\0';text[n-2] = '\0';text[n-1] = '\0';}  else{       printf("[%s]:%d,uft8 backspace error\n",_FILE_,_LINE_);}
}

  UTF-8理论上最多可以是6个字节,这里只考虑4个字节,因为大部分4个字节就已经足够。

  这个实现退格键的前提是你的字符是经过UTF-8,如果是其它的,如GB2312等须先进行编码转换成UTF-8才能用。  

  

  Unicode能显示20901个汉字,范围是从\u4e00到\u9fa5,下面程序是输出Unicode编码下的所有汉字。  

 //C# codechar minHZUnicode = '\u4e00';
char maxHZUnicode = '\u9fa5';for (char c = minHZUnicode; c <= maxHZUnicode; c++)
{Console.Write(c);
}

  

由谈退格键的实现来学习字符编码相关推荐

  1. 解决ubuntu20.04下vi编辑器方向键和退格键问题

    在ubuntu中,进入vi命令的插入模式,发现方向键分别对应ABCD以及退格键失效,按方向键不能移动光标,而是会输出ABCD,以及退格键也不能正常删除字符,我们这里提供两种解决方法 方法一 1.先卸载 ...

  2. ubuntu18.04下vi不能使用方向键和退格键

    方法1 使用vi命令时,不能正常编辑文件,使用方向键时老是出现很多字母? 在Ubuntu中,进入vi命令的编辑模式,发现按方向键不能移动光标,而是会输出ABCD,以及退格键也不能正常删除字符.这是由于 ...

  3. 解决Ubuntu中vi命令的编辑模式下不能正常使用方向键和退格键的问题

    在Ubuntu中,进入vi命令的编辑模式,发现按方向键不能移动光标,而是会输出ABCD,以及退格键也不能正常删除字符.这是由于Ubuntu预装的是vim-tiny,而我们需要使用vim-full,解决 ...

  4. python使用退格键时出现^H解决方法

    python使用退格键时出现^H解决方法 参考文章: (1)python使用退格键时出现^H解决方法 (2)https://www.cnblogs.com/effortsing/p/9982040.h ...

  5. 屏蔽鼠标右键、Ctrl+N、Shift+F10、F11、F5刷新、退格键

    <script language="Javascript"><!--   //屏蔽鼠标右键.Ctrl+N.Shift+F10.F11.F5刷新.退格键   //A ...

  6. Linux下使用Vi是方向键变乱码 退格键不能使用的解决方法

    在Linux下编辑一些文件.这就涉及到了vi这个编辑器了.在Linux下,初始使用vi的时候有点问题.就是在编辑模式下使用方向键的时候,并不会使光标移动,而是在命令行中出现[A [B [C [D之类的 ...

  7. 解决ubuntu中vi不能正常使用方向键与退格键的问题

    解决ubuntu中vi不能正常使用方向键与退格键的问题 方案一: 问题: ubuntu中vi在编辑状态下方向键不能用,还有回格键不能删除等我们平时习惯的一些键都不能使用. 解决办法: 可以安装vim ...

  8. linux 使用退格键时出现^H解决方法

    个人博客迁移   更多内容分享请访问 http://www.wpython.com 当我们再和脚本交互的时候 在终端上输错了内容 使用退格键 屏幕上会出现乱码 比如 ^H ^H不是H键的意思,是bac ...

  9. 树莓派vi编辑文件时退格键和方向键无法正常使用的问题

    [问题现象] 树莓派在使用vi编辑文件时,发现退格删除键(Backspace键),无法删除,方向键变成了ABCD(对应上下右左)还自动换行. 现象如下图所示: [问题解决] 此问题根因是树莓派系统预装 ...

最新文章

  1. 杨强 : 迁移学习——人工智能的最后一公里
  2. 白话Elasticsearch68-ES生产集群部署重要的操作系统设置
  3. html5内容切换特效,html5+jQuery图片和文字内容同时左右切换特效
  4. Android(java)学习笔记133:Eclipse中的控制台不停报错Can't bind to local 8700 for debugger...
  5. 测试次数----2018年第九届蓝桥杯C/C++省赛B组 第四题
  6. PyCharm 配置 Git 教程
  7. 基于 Direct3D 电子海图区域绘制方法
  8. dllMain函数的作用
  9. 列举在100到200以内的质数
  10. mysql生成数据字典
  11. 数字鉴相,关于相位差的提取
  12. 【笔记】用Python写百度翻译网络爬虫
  13. python转义字符:‘\‘
  14. HttpClient发送请求时动态替换目标ip
  15. rss 是什么?有什么用?
  16. python爬取微信好友头像_python 使用wxpy实现获取微信好友列表 头像 群成员
  17. 黑群晖 无法关机_教你无U盘引导实现黑群晖6.1.3 15152,打造属于自己的私人云空间...
  18. HTTP请求服务器 statuscode的状态码说明 (statuscode==500)
  19. 原神改文件换服务器,原神B服怎么转成官服
  20. [@vue/compiler-sfc] defineProps is a compiler macro and no longer needs to be imported

热门文章

  1. 领结婚证了,新的人生开始了!
  2. C++ delete 和 delete []的区别
  3. day002-HTML知识点总结:浏览器兼容性之指定IE浏览器使用chrome内核渲染页面
  4. 2016/09/14
  5. 2016.5.27 科学————量子力学初识
  6. 几个SQL命令的使用
  7. 对gridview中的一些操作。
  8. 学习 TTreeView [15] - 连接数据库 (作为给 丁永其 和 DELPHI万岁 两位朋友的回复)...
  9. VirtualBox安装kali linux过程及安装后无法全屏问题解决方法(2)
  10. 同一DIV内,两个行内块元素不对齐的解决方案