问题

C语言中汉字如何存储?梳理思路!

答案

在计算机中,一个英文字符占1个字节,汉字占两个字节,如果用char字符数组存储字符时,需要在最后面自动加上一个字节的结束符“\0”

汉字转进制输出

比如:

    //英文字符,占4个字节
char Info[] = "abc";
printf("%s\n",Info);
printf("Info长度:%d\n",sizeof(Info)); //中文,占5个字节
char Han[]="中国";
printf("%s\n",Han);
printf("Han长度:%d\n",sizeof(Han));

不同的编码方式,汉字存储的字节数量不同,比如:

GB2312编码:一个汉字两个字节

UTF-8编码: 一个汉字三个字节

GBK编码:一个汉字两个字节

UTF-16:一个汉字3个字节

GB2312 --> GBK --> GB18030 是中文编码的三套方案,出现的时间从早到晚,收录的字符数目依次增加,并且向下兼容。GB2312 和 GBK 收录的字符数目较少,用 1~2个字节存储;GB18030 收录的字符最多,用1、2、4 个字节存储。
1) 从整体上讲,GB2312 和 GBK 的编码方式一致,具体为:

  • 对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0,这和 ASCII 编码是一致的,所以说 GB2312 完全兼容 ASCII。
  • 对于中国的字符,使用两个字节存储,并且规定每个字节的最高位都是 1。

例如对于字母A,它在内存中存储为 01000001;对于汉字,它在内存中存储为 11010110  11010000。由于单字节和双字节的最高位不一样,所以字符处理软件很容易区分一个字符到底用了几个字节。
2) GB18030 为了容纳更多的字符,并且要区分两个字节和四个字节,所以修改了编码方案,具体为:

  • 对于 ASCII 字符,使用一个字节存储,并且该字节的最高位是 0,这和 ASCII、GB2312、GBK 编码是一致的。
  • 对于常用的中文字符,使用两个字节存储,并且规定第一个字节的最高位是 1,第二个字节的高位最多只能有一个连续的 0(第二个字节的最高位可以是 1 也可以是 0,但是当它是 0 时,次高位就不能是 0 了)。注意对比 GB2312 和 GBK,它们要求两个字节的最高位为都必须为 1。
  • 对于罕见的字符,使用四个字节存储,并且规定第一个和第三个字节的最高位是 1,第二个和第四个字节的高位必须有两个连续的 0。

例如对于字母A,它在内存中存储为 01000001;对于汉字,它在内存中存储为 11010110  11010000;对于藏文གྱུ,它在内存中的存储为 10000001  00110010  11101111  00110000。

字符处理软件在处理文本时,从左往右依次扫描每个字节:

  • 如果遇到的字节的最高位是 0,那么就会断定该字符只占用了一个字节;
  • 如果遇到的字节的最高位是 1,那么该字符可能占用了两个字节,也可能占用了四个字节,不能妄下断论,所以还要继续往后扫描:
    • 如果第二个字节的高位有两个连续的 0,那么就会断定该字符占用了四个字节;
    • 如果第二个字节的高位没有连续的 0,那么就会断定该字符占用了两个字节。

可见,当字符占用两个或者四个字节时,GB18030 编码要检测两次,处理效率比 GB2312 和 GBK 都低。

GBK 于 1995 年发布,这一年也是互联网爆发的元年,国人使用电脑越来越多,也许是 GBK 这头猪正好站在风口上,它就飞起来了,后来的中文版 Windows 都将 GBK 作为默认的中文编码方案。
注意,这里我说 GBK 是默认的中文编码方案,并没有说 Windows 默认支持 GBK。Windows 在内核层面使用的是 Unicode 字符集(严格来说是 UTF-16 编码),但是它也给用户留出了选择的余地,如果用户不希望使用 Unicode,而是希望使用中文编码方案,那么这个时候 Windows 默认使用 GBK(当然,你可以选择使用 GB2312 或者 GB18030,不过一般没有这个必要)。

汉字编码输出

汉字编码并输出示例:

    //汉字编码
unsigned char Han[]="中国";
printf("汉字:%s\n",Han);
printf("十六进制:");
for(int i=0;i<4;i++)
{
printf("%X",Han[i]);
}
printf("\n十进制:");
for(int i=0;i<4;i++)
{
printf("%d",Han[i]);
}

汉字编码输出存储

汉字编码存储示例:

	//汉字编码存储
unsigned char Han[] = "中国";
FILE* fp = fopen("out.txt", "w");//输出
printf("汉字:%s\n", Han);
fputs("十六进制:", fp);
for (int i = 0; i < 4; i++)
{
fprintf(fp, "%X", Han[i]);
}
fseek(fp, 0, SEEK_END);
fputs("\n十进制:", fp);
for (int i = 0; i < 4; i++)
{
fprintf(fp, "%d", Han[i]);
}
fclose(fp);

参考

1、汉字的存储

2、使用数组来储存中文(字符串)

3、C语言:GB2312编码和GBK编码,将中文存储到计算机

4、C语言/C++字符编码方式解析

最新文章

  1. 安装phpredisadmin linux nginx服务器下
  2. 各组对final发布产品的排名
  3. Git - 使用指南
  4. Qt工程转化为Vs工程
  5. 使用lftp传输文件的shell脚本
  6. angular的$scope,这东西满重要的
  7. 登录DA面板出现:License has expired
  8. iOS 工作遇到问题记录
  9. Hbase HRegionServer启动后自动关闭
  10. 【jmeter】Bean shell使用(二)
  11. Hadoop学习笔记(3)——分布式环境搭建
  12. MPMoviePlayerController过期导致视频播放时间条颠倒及AVPlayerViewController的用法
  13. python中列表和字典的高级应用
  14. C# tostring()汇总
  15. 文件操作:fseek函数和ftell函数
  16. jdbc连接sql数据库
  17. UVA 814 The Letter Carrier&#39;s Rounds
  18. Ubuntu 14.04 LTS 下使用源码编译安装 Sagemath 6.7 x64 (小结)
  19. 《Linux内核分析》第七周: 可执行程序的装载
  20. weblogic中部署SSH项目遇到的坑

热门文章

  1. Pass Infrastructure基础架构(上)
  2. windows 设置nginx开机自启动
  3. 像Swing这种已经不太用的技术,大学还在教,到底要不要学?
  4. 技能篇:awk教程-linux命令
  5. mysql的优化_第十一篇(查询计划篇)
  6. Mysql优化(出自官方文档) - 第六篇
  7. Mysql优化(出自官方文档) - 第一篇(SQL优化系列)
  8. 华为云数据库GaussDB(for Cassandra)揭秘第二期:内存异常增长的排查经历
  9. js-动态表单校验-吐血总结最近遇到的变态表单校验2---element+原生
  10. Message、Handler、Message Queue、Looper 之间的关系