• 系统:windows 64
  • 编译器:gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
  • 文本编辑器:notepad
  • 控制台:Cmder
  • 编程语言:C、Python

  首先,要想打印汉字,必须考虑到编码问题。在windows下,由于系统使用GBK编码,而GCC解析时使用UTF-8而会导致以下代码运行时出现乱码:

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. char *str = "你好,世界!";
  6.  
  7. printf("%s\n", str);
  8.  
  9. return 0;
  10. }

  解决方法为:使用“-fexec-charset=gbk”命令

  解决了编码问题,我们还需要了解几点:

  • char类型本质上是数字,占据一个字节(即八位),可以通过%d打印编码,通过%c打印字符
  • 在C语言中,一个汉字占据两个char类型
  • 汉字的两个char类型为负数
  • 在打印汉字时,它的两个char必须紧跟着

  根据这几点,我们可以打印出汉字以及它们的编码:

  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main()
  5. {
  6. // str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
  7. char *str = "你好,世界!Hello, world!";
  8. // chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
  9. char *chr = str;
  10.  
  11. printf("%zu %s\n", strlen(str), str);
  12. // 如果遇到'\0',说明字符串结束了
  13. while (*chr != '\0')
  14. {
  15. // 如果chr的编码为负数,则说明遇到了一个汉字
  16. if (*chr < 0)
  17. {
  18. // 打印汉字及汉字的编码
  19. // 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ??
  20. printf("%c%c: %d%d\n", *chr, *(chr+1), *(chr), *(chr+1));
  21. // chr自增两个字节(因为每个汉字都由两个char组成)
  22. chr += 2;
  23. }
  24. else
  25. {
  26. // 打印英文字符
  27. printf("%c: %d\n", *chr, *chr);
  28. // chr自增一个字节
  29. ++chr;
  30. }
  31. }
  32.  
  33. return 0;
  34. }

  从上图,我们可以看出,这个字符串占据了25个字节,4个汉字加2个全角符号占据了12个字节,再加上23个英文字符,总共25个字节。我们可以从下图更清晰地看出str的构造:

  但是,根据我们在网上查询的结果,汉字‘你’的GBK编码应为:C4E3,但是在这里,却打印出了:-60-29,这是为什么呢?

  这里涉及到进制的问题,可能-60-29是十六进制数C4E3的十进制数?

  首先,我们先通过Python看看C4E3的二进制数以及十进制数。这好像跟-60-29根本不沾边。

  我们先看看下面的代码,导入<limits.h>头文件,看看char类型的取值范围为多少:

  1. #include <stdio.h>
  2. #include <limits.h>
  3.  
  4. int main()
  5. {
  6. printf("[%d ~ %d]\n", CHAR_MIN, CHAR_MAX);
  7. printf("%c%c\n", 0xC4, 0xE3);return 0;
  8. }

  我们可以看到:char类型的取值范围为[-128 ~ 127],但是我们却可以打印出汉字”你“。这是为什么呢?明明char的取值范围最多127,而汉字“你”的两个字符分别为:196和227,都超过了这个值。其实这是因为,C语言将这两个数字的二进制数作为负数处理。C中的char类型有1个字节,占8位,而它的最高位为符号位,当它为0时为正,1时则为负。C通过对正数做补码操作得到负数。补码,即对一个二进制数取反,然后再加1。比如,0xC4的二进制数为0b11000100,我们可以看到最高位1,在C中这个数就是负数。我们可以通过对这个二进制数做补码操作,得到0b00111100,即60。所以0b11000100在C中表示为-60。

  从以上,我们可以发现,GBK编码中,一个汉字占两字节。因为C中char类型只占一个字节,所以需要使用两个char类型来表示汉字。因为C中char为有符号类型,char的表示范围为[-128 ~ 127],所以在遇到大于127的数字时,会被char表示为负数。

  其实,我们还可以使用unsigned char来实现。char默认是有符号的,取值范围为:-128 ~127。而unsigned char的取值范围则为:0~255,那么汉字“你”的编码就会被显示为:196和227。

  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main()
  5. {
  6. // str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
  7. unsigned char *str = (unsigned char *)"你好,世界!Hello, world!";
  8. // chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
  9. unsigned char *chr = str;
  10.  
  11. printf("%zu %s\n", strlen(str), str);
  12. // 如果遇到'\0',说明字符串结束了
  13. while (*chr != '\0')
  14. {
  15. // 如果chr的编码大于127,则说明遇到了一个汉字
  16. if (*chr > 127)
  17. {
  18. // 打印汉字及汉字的编码
  19. // 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ??
  20. printf("%c%c: %d %d\n", *chr, *(chr+1), *(chr), *(chr+1));
  21. // chr自增两个字节(因为每个汉字都由两个char组成)
  22. chr += 2;
  23. }
  24. else
  25. {
  26. // 打印英文字符
  27. printf("%c: %d\n", *chr, *chr);
  28. // chr自增一个字节
  29. ++chr;
  30. }
  31. }
  32.  
  33. return 0;
  34. }

Resistance is Futile!

C语言 使用char字符实现汉字处理的更多相关文章

  1. 黑马程序员——C语言基础 char字符 数组

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)char类型 1)存储细节 ASCII单字节表(双字节GBK\GB2 ...

  2. Java 语言中一个字符占几个字节?

    Java中理论说是一个字符(汉字 字母)占用两个字节. 但是在UTF-8的时候 new String("字").getBytes().length 返回的是3 表示3个字节 作者: ...

  3. 【转载】C#怎么判断字符是不是汉字

    支持并尊重原创!原文地址:http://jingyan.baidu.com/article/2c8c281deb79ed0008252af1.html 判断一个字符是不是汉字通常有三种方法,第1种用 ...

  4. Atian inputmethod 输入法解决方案 方言与多语言多文字支持 英语汉字汉语阿拉伯文的支持 (au

    Atian inputmethod 输入法解决方案 方言与多语言多文字支持 英语汉字汉语阿拉伯文的支持 (au 1.1. Overview概论 支持母语优先的战略性产品,主要是针对不想以及不愿使用普通 ...

  5. 根据Unicode编码用C#语言把它转换成汉字的代码

    rt 根据所具有的Unicode编码用C#语言把它转换成汉字的代码 var s = System.Web.HttpUtility.HtmlDecode(Utf8Str); var o = Newton ...

  6. Swift3.0语言教程获取字符

    Swift3.0语言教程获取字符 Swift3.0语言教程获取字符,在字符串中获取某一下标位置(下标索引)处的字符是很常见的功能,在NSString中使用character(at:)方法实现,其语法形 ...

  7. 如何利用java把文件中的Unicode字符转换为汉字

    有些文件中存在Unicode字符和非Unicode字符,如何利用java快速的把文件中的Unicode字符转换为汉字而不影响文件中的其他字符呢, 我们知道虽然java 在控制台会把Unicode字符直 ...

  8. Regex 字符是不是汉字

    Regex   字符是不是汉字 一. 判断一个字符是不是汉字通常有三种方法: 1.用ASCII码判断 在 ASCII码表中,英文的范围是0-127,而汉字则是大于127 string text = & ...

  9. C 语言实例 - 查找字符在字符串中出现的次数

    C 语言实例 - 查找字符在字符串中出现的次数 C 语言实例 C 语言实例 查找字符在字符串中的起始位置(索引值从 开始). 实例 #include <stdio.h> int main( ...

随机推荐

  1. DL基础补全计划(三)---模型选择、欠拟合、过拟合

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  2. Rust安装-运行第一个程序-hello_world

    Rust官网:https://rust-lang.org/ 安装 点击install,选择版本 选择相对应的版本进行下载 我这里下载的是windows系统,运行下载好的exe文件,根据需要选择选对应的 ...

  3. [008] - JavaSE面试题(八):集合

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [008] - JavaSE面试题(八):集合 第1问:说一下集合的体系? 单列集合: 双列集合: ...

  4. [刘阳Java]_了解BeanFactory_第4讲

    为什么说我们这篇文章只是说了解一下BeanFactory.因为BeanFactory内在的机制与代码实现实在是太强大了,在这一点我确实不敢滥竽充数. 1. 那么我们又如何去了解BeanFactory, ...

  5. PAT乙级:1094 谷歌的招聘 (20分)

    PAT乙级:1094 谷歌的招聘 (20分) 题干 2004 年 7 月,谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌(如下图)用于招聘.内容超级简单,就是一个以 .com 结尾的网址,而前面 ...

  6. Cesium加载地形数据只显示半个地球

    Cesium第0级地形包括两个瓦片:0/0/0.terrain,0/1/0.terrain,分别为左半球和右半球(具体参考:https://blog.csdn.net/u013929284/artic ...

  7. HttpRunner3源码阅读: 1. 目录结构分析

    初衷 身处软件测试行业的各位应该都有耳闻HttpRunner 开源测试工具/框架(接口测试),作者博客 为什么出这系列? 不少测试同行都建议阅读HttpRunner,源码学习其设计思想. 社区当下Py ...

  8. 大数据学习(04)——MapReduce原理

    前两篇文章介绍了HDFS的原理和高可用,下面再来介绍Hadoop的另外一个模块MapReduce.它的思想是很多技术的鼻祖,值得一学. MapReduce是什么 MapReduce是一个分布式计算系统 ...

  9. RAID磁盘阵列和RAID配置

    目录 一.RAID磁盘阵列介绍 二.RAID磁盘阵列分类 2.1.RAID 0(条带化存储) 2.2.RAID 1(镜像存储) 2.3.RAID 5 2.4.RAID 6 2.5.RAID 1+0和0 ...

  10. Java 在Word中创建多级项目符号列表和编号列表

    本文分享通过Java程序代码在Word中创建多级项目符号列表和编号列表的方法.程序运行环境如下: IntelliJ IDEA 2018(JDK 1.8.0) Word 2013 Word Jar包:F ...