• C:汉字存储


    问题

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

    答案

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

    汉字转进制输出

    比如:

        //英文字符,占4个字节
        char Info[] = "abc";
        printf("%s
    ",Info);
        printf("Info长度:%d
    ",sizeof(Info));
    
        //中文,占5个字节
        char Han[]="中国";
        printf("%s
    ",Han);
        printf("Han长度:%d
    ",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
    ",Han);
        printf("十六进制:");
        for(int i=0;i<4;i++)
        {
            printf("%X",Han[i]);
        }
        printf("
    十进制:");
        for(int i=0;i<4;i++)
        {
            printf("%d",Han[i]);
        }
    

    汉字编码输出存储

    汉字编码存储示例:

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

    参考

    1、汉字的存储

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

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

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

    作者: Pam

    出处: https://www.cnblogs.com/pam-sh/>

    关于作者:网安在读

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可邮件(mir_soh@163.com)咨询.

  • 相关阅读:
    kibana We couldn't activate monitoring
    学Redis这篇就够了!
    elasticsearch 官方监控文档 老版但很有用
    java dump 内存分析 elasticsearch Bulk异常引发的Elasticsearch内存泄漏
    Apache Beam实战指南 | 大数据管道(pipeline)设计及实践
    InnoDB一棵B+树可以存放多少行数据?
    函数编程真不好
    面向对象编程灾难
    可能是全网最好的MySQL重要知识点 | 面试必备
    终于有人把elasticsearch原理讲通了
  • 原文地址:https://www.cnblogs.com/pam-sh/p/15034330.html
Copyright © 2020-2023  润新知