C:汉字存储
问题#
C语言中汉字如何存储?梳理思路!
答案#
在计算机中,一个英文字符占1个字节,汉字占两个字节,如果用char字符数组存储字符时,需要在最后面自动加上一个字节的结束符“\0”
汉字转进制输出#
比如:
1 2 3 4 5 6 7 8 9 | //英文字符,占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,不过一般没有这个必要)。
汉字编码输出#
汉字编码并输出示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | //汉字编码 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]); } |
汉字编码输出存储#
汉字编码存储示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //汉字编码存储 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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <stdio.h> #include <string.h> #define MAX_LINE 100 //每行最大字节数 void main() { unsigned char strLine[MAX_LINE]; int len = 0; FILE *fp = fopen ( "D:\\code\\vc\\C\\plaintext_keywords.txt" , "r" ); if (NULL == fp) { printf ( "failed to open dos.txt\n" ); } while (! feof (fp)) { fgets (strLine,7,fp); printf ( "%s" ,strLine); } fclose (fp); printf ( "\n" ); system ( "pause" ); } |
参考#
1、汉字的存储
作者:Hang Shao
出处:https://www.cnblogs.com/pam-sh/p/15034330.html
版权:本作品采用「知识共享」许可协议进行许可。
声明:欢迎交流! 原文链接 ,如有问题,可邮件(mir_soh@163.com)咨询.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)