C语言 使用char字符实现汉字处理
- 系统: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而会导致以下代码运行时出现乱码:

#include <stdio.h> int main()
{
char *str = "你好,世界!"; printf("%s\n", str); return 0;
}


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

解决了编码问题,我们还需要了解几点:
- char类型本质上是数字,占据一个字节(即八位),可以通过%d打印编码,通过%c打印字符
- 在C语言中,一个汉字占据两个char类型
- 汉字的两个char类型为负数
- 在打印汉字时,它的两个char必须紧跟着
根据这几点,我们可以打印出汉字以及它们的编码:

#include <stdio.h>
#include <string.h> int main()
{
// str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
char *str = "你好,世界!Hello, world!";
// chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
char *chr = str; printf("%zu %s\n", strlen(str), str);
// 如果遇到'\0',说明字符串结束了
while (*chr != '\0')
{
// 如果chr的编码为负数,则说明遇到了一个汉字
if (*chr < 0)
{
// 打印汉字及汉字的编码
// 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ??
printf("%c%c: %d%d\n", *chr, *(chr+1), *(chr), *(chr+1));
// chr自增两个字节(因为每个汉字都由两个char组成)
chr += 2;
}
else
{
// 打印英文字符
printf("%c: %d\n", *chr, *chr);
// chr自增一个字节
++chr;
}
} return 0;
}


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

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

这里涉及到进制的问题,可能-60-29是十六进制数C4E3的十进制数?
首先,我们先通过Python看看C4E3的二进制数以及十进制数。这好像跟-60-29根本不沾边。

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

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


我们可以看到: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。

#include <stdio.h>
#include <string.h> int main()
{
// str为字符指针,指向一个字符字面量,这个字符字面量由'\0'结尾
unsigned char *str = (unsigned char *)"你好,世界!Hello, world!";
// chr为字符指针,指向str所指向的字符字面量的第一个字符的地址,即'你'字符的两个char中的第一个
unsigned char *chr = str; printf("%zu %s\n", strlen(str), str);
// 如果遇到'\0',说明字符串结束了
while (*chr != '\0')
{
// 如果chr的编码大于127,则说明遇到了一个汉字
if (*chr > 127)
{
// 打印汉字及汉字的编码
// 注意两个char必须紧紧跟着打印(%c%c),否则会打印出 ??
printf("%c%c: %d %d\n", *chr, *(chr+1), *(chr), *(chr+1));
// chr自增两个字节(因为每个汉字都由两个char组成)
chr += 2;
}
else
{
// 打印英文字符
printf("%c: %d\n", *chr, *chr);
// chr自增一个字节
++chr;
}
} return 0;
}


C语言 使用char字符实现汉字处理的更多相关文章
- 黑马程序员——C语言基础 char字符 数组
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)char类型 1)存储细节 ASCII单字节表(双字节GBK\GB2 ...
- Java 语言中一个字符占几个字节?
Java中理论说是一个字符(汉字 字母)占用两个字节. 但是在UTF-8的时候 new String("字").getBytes().length 返回的是3 表示3个字节 作者: ...
- 【转载】C#怎么判断字符是不是汉字
支持并尊重原创!原文地址:http://jingyan.baidu.com/article/2c8c281deb79ed0008252af1.html 判断一个字符是不是汉字通常有三种方法,第1种用 ...
- Atian inputmethod 输入法解决方案 方言与多语言多文字支持 英语汉字汉语阿拉伯文的支持 (au
Atian inputmethod 输入法解决方案 方言与多语言多文字支持 英语汉字汉语阿拉伯文的支持 (au 1.1. Overview概论 支持母语优先的战略性产品,主要是针对不想以及不愿使用普通 ...
- 根据Unicode编码用C#语言把它转换成汉字的代码
rt 根据所具有的Unicode编码用C#语言把它转换成汉字的代码 var s = System.Web.HttpUtility.HtmlDecode(Utf8Str); var o = Newton ...
- Swift3.0语言教程获取字符
Swift3.0语言教程获取字符 Swift3.0语言教程获取字符,在字符串中获取某一下标位置(下标索引)处的字符是很常见的功能,在NSString中使用character(at:)方法实现,其语法形 ...
- 如何利用java把文件中的Unicode字符转换为汉字
有些文件中存在Unicode字符和非Unicode字符,如何利用java快速的把文件中的Unicode字符转换为汉字而不影响文件中的其他字符呢, 我们知道虽然java 在控制台会把Unicode字符直 ...
- Regex 字符是不是汉字
Regex 字符是不是汉字 一. 判断一个字符是不是汉字通常有三种方法: 1.用ASCII码判断 在 ASCII码表中,英文的范围是0-127,而汉字则是大于127 string text = & ...
- C 语言实例 - 查找字符在字符串中出现的次数
C 语言实例 - 查找字符在字符串中出现的次数 C 语言实例 C 语言实例 查找字符在字符串中的起始位置(索引值从 开始). 实例 #include <stdio.h> int main( ...
随机推荐
- java基础---类和对象(1)
一. 类和对象 面向对象:以属性和行为的观点去分析现实生活中的事物,将功能封装进对象, 强调具备了功能的对象,以类/对象为最小单位,考虑谁来做 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做 ...
- Python使用笔记005-文件操作(二)
1.1 打开文件模式 # r r+ r+读是没问题的,写的话,会覆盖原来的内容,文件不存在时会报错# w w+ w+用来新的文件没问题,旧的文件会覆盖原来的内容# a a+ a+写是追加,读不到是因为 ...
- C:汉字存储
问题 C语言中汉字如何存储?梳理思路! 答案 在计算机中,一个英文字符占1个字节,汉字占两个字节,如果用char字符数组存储字符时,需要在最后面自动加上一个字节的结束符"\0" 汉 ...
- C语言:统计字符个数及种类
#include <stdio.h> int main(){ char c; //用户输入的字符 int shu=0;//字符总数 int letters=0, // 字母数目 space ...
- [WPF] 使用 Visual Studio App Center 持续监视应用使用情况和问题
1. 什么是AppCenter Visual Studio App Center 是几个常见移动开发和云集成服务(如持续集成.持续交付和自动 UI 测试等服务)的集合. 这些 App Center 服 ...
- Java集合中的可变参数
可变参数: 1.在JDK1.5之后,如果我们定义一个方法需要接收多个参数,并且多个参数类型一致,我们可以对其简化成如下格式: 修饰符 返回值类型 方法名(参数类型... 形参名){} 其实这个书写完全 ...
- Day3 变量 运算符 及运算符的优先级
变量 什么是变量: 可以变化的量 Java 是一种强类型语言,每个变量都必须声明其类型. Java变量是程序中最基本的存储单位,其要素包括变量名,变量类型,作用域. 注意事项: 每个变量都有类型, 类 ...
- React中组件之间通信的方式
一.是什么 我们将组件间通信可以拆分为两个词: 组件 通信 回顾Vue系列的文章,组件是vue中最强大的功能之一,同样组件化是React的核心思想 相比vue,React的组件更加灵活和多样,按照不同 ...
- POJ1704 Georgia and Bob 题解
阶梯博弈的变形.不知道的话还是一道挺神的题. 将所有的棋子两两绑在一起,对于奇数个棋子的情况,将其与起点看作一组.于是便可以将一组棋子的中间格子数看作一推石子.对靠右棋子的操作是取石子,而对左棋子的操 ...
- Python -- 让程序运行后不立即关闭窗口
程序运行完毕,窗口也跟着关闭.也就是说还没来得及看结果,程序窗口就关闭了. 试着改改代码,在最后加上以下这行代码: raw_input("Press <enter>") ...