汉字字符编码问题。

千梦一生 2020-03-12 09:13:45
关于汉字、乱码这些的编码问题我确实纠结过很久。
看过不少资料,讲解。但仍然有点绕:
所以我想整理一下我的困惑,清晰地通过一个场景一一列出来,望大佬们能帮助我一下,谢谢。

首先比如:
代码

char* str= "A中文"//
printf("%s\n",str);

1、我认为就这里代码中所显示的中文一定有一个编码(比如0011010101110...)的。这么说对吧?比如是某个字符集A的"A中文"的编码
2、如果我在1中的想法是正确的,那么,我如何去找他的编码在哪里(A是在那里设置的)?
3、拓展一下,比如某个文档有字符,但是是乱码,肯定是使用的字符集不匹配。那么如何才能知道这个文档使用的是哪个字符集呢?是靠经验然后,猜测、尝试吗?

4、接着就是运行了,如果没有记错的话,我记得,这个程序打印出来的字符串就有可能使乱码。这是为什么?难道使用的不是同一个字符集A吗?如果不是,那么程序在解码这个(0011010101110...)的时候,采用的字符集(B)我是如何知道它的采用地是字符集B呢(在哪里看到的,B是在哪里设置的)?

5、中文那么多字符集。加入当我遇到了(程序中、文档中、网页上、代码中等等)乱码、正确地解决姿势应该是如何的呢?

暂时理清的问题就以上了。希望能不吝教导。谢谢大家了
...全文
178 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
千梦一生 2020-03-14
  • 打赏
  • 举报
回复
引用 10 楼 qybao 的回复:
[quote=引用 5 楼 千梦一生 的回复:]
您好,谢谢您的回复。
希望继续向您请教一下这个问题:
我的意思是比如我写了char a = "A中文"。那么在内存中一定有个地方存了我这么一个字符串。也就是一段数字(比如011101100...)
那么计算机把我写的"A中文"转换为011101100...这应该是有一个映射关系的吧。比方说是使用的utf-8编码的映射规则(而不是GB2312或者其它啥啥)。然后我运行跑起来。控制台却打印出了乱码。是不是就证明它翻译这川字符串的时候所依据的码表不是utf-8。而是另外的,比如GBK啥啥啥的。所以翻译出来的字符就不是希望的字符。以上则是我的理解。
如果确实如此,那么上面的utf-8是在哪里可以找到。编译环境设置?还是系统那儿定下的?亦或者其它。如何操作即可让字符串"A中文"在内存中保存的数值不再是011101100......以及上面的GBK是在哪里可以找到。怎么操作即可更换解码(内存中的数值)映射表。
谢谢


这个应该是跟着你文件的编码吧。比如你的文件用GB2312保存,那就是GB2312编码,是utf-8就是utf-8编码。
这个你可以自己测试一下,比如用GB2312保存文件,编译,运行输出内存信息,再以utf-8保存文件,编译,运行输出信息,看看是否不一样。
char* str= "A中文"//
while (*str != '\0') {
printf("%02X", (*str & 0x00FF));
str++;
}

[/quote]
谢谢老师的回答。这样一下子搞明白了很多。
院里有座山 2020-03-12
  • 打赏
  • 举报
回复
我的回答有错误,回来修改
gouyanfen 2020-03-12
  • 打赏
  • 举报
回复
第三个问题,统一的编码规则是Unicode,其它的用的都是区域码,你的文档生成时按照你操作系统的区域和编码设定。 第四个问题,程序运行中显示输出依赖操作系统的区域和编码设定,你也可单独指定串的格式,但是输出需要符合系统设定。比如控制台,输出时需要调用对应字库提取字模,然后显示在屏幕上,编码错误就会提取错误的字模,你看起来就是乱码。
gouyanfen 2020-03-12
  • 打赏
  • 举报
回复
引用 楼主 千梦一生 的回复:
关于汉字、乱码这些的编码问题我确实纠结过很久。 看过不少资料,讲解。但仍然有点绕: 所以我想整理一下我的困惑,清晰地通过一个场景一一列出来,望大佬们能帮助我一下,谢谢。 首先比如: 代码

char* str= "A中文"//
printf("%s\n",str);
1、我认为就这里代码中所显示的中文一定有一个编码(比如0011010101110...)的。这么说对吧?比如是某个字符集A的"A中文"的编码 2、如果我在1中的想法是正确的,那么,我如何去找他的编码在哪里(A是在那里设置的)? 3、拓展一下,比如某个文档有字符,但是是乱码,肯定是使用的字符集不匹配。那么如何才能知道这个文档使用的是哪个字符集呢?是靠经验然后,猜测、尝试吗? 4、接着就是运行了,如果没有记错的话,我记得,这个程序打印出来的字符串就有可能使乱码。这是为什么?难道使用的不是同一个字符集A吗?如果不是,那么程序在解码这个(0011010101110...)的时候,采用的字符集(B)我是如何知道它的采用地是字符集B呢(在哪里看到的,B是在哪里设置的)? 5、中文那么多字符集。加入当我遇到了(程序中、文档中、网页上、代码中等等)乱码、正确地解决姿势应该是如何的呢? 暂时理清的问题就以上了。希望能不吝教导。谢谢大家了
你的1的想法是错的,没有一定有个编码的,关于编码各有各的规范,有的有BOM说明后续字符串编码,比如UTF-8,但并不是强制性的。 第五个问题,网页上数据head部分会有编码说明段,可以指定传输的编码规范。
院里有座山 2020-03-12
  • 打赏
  • 举报
回复
电脑是外国人发明的,最开始,没有定义任何字符。都是系统自己定义的。
系统说某个二进制编码是哪个字符就是哪个字符。
后来又来ascii码,规定了一个char的低128个数值,每个二进制码对应哪个字符。
这样编写的程序就能兼容了。但是这只是针对英文的。
其他语系的字母表示不了。
所以ascii扩展了一次,把高128个数值,也编码了,对应的是拉丁语系的其他字母。

但是,对于其他语系,这256个数值,还是不够用。所以,其他语种用两个128个数值表示一个字符。
最开始的时候,也是大家各自设计。每个系统都默认某个数值,是自己系统对应的字符。
常见的表现就是一个系统的内码,到两外一个系统打开是乱码了。

有两个解决方案,一个是像网页那样,在网页的开头,写明了自己是哪里编码。
另一个像word一样,它读取一个文档的开头,看哪个国家的编码多一些,就判断为哪里编码,这个经常误判。

为了解决这个问题,出现了unicode,他试图把地球上所有的语种都规范起来。
utf-8依然采用的是低128个数值表示英文字符,若干高128个数值表示其他语种数值。
这样英文国家就使用起来很方便,原先多大的文件,还是多大。
utf-16所有字符都至少占两个字节了,但是内码的空间依然不足,只能表示地球上的6万个字母。
所以像ascii码的扩展那样,在高数值的区域,又划分出来一个区域,叫代理区,这样就可以用4个字节表示一个字符了。
utf-32好像进一步扩展了。

在windows系统中,一个Unicodetxt文件的开头有两个字节,表示这是一个Unicode文档。没有这两个字节的是多字节文档。
如果是多字节文档,拿到其他地方,就可能会乱码。
qybao 2020-03-12
  • 打赏
  • 举报
回复
引用 5 楼 千梦一生 的回复:
您好,谢谢您的回复。
希望继续向您请教一下这个问题:
我的意思是比如我写了char a = "A中文"。那么在内存中一定有个地方存了我这么一个字符串。也就是一段数字(比如011101100...)
那么计算机把我写的"A中文"转换为011101100...这应该是有一个映射关系的吧。比方说是使用的utf-8编码的映射规则(而不是GB2312或者其它啥啥)。然后我运行跑起来。控制台却打印出了乱码。是不是就证明它翻译这川字符串的时候所依据的码表不是utf-8。而是另外的,比如GBK啥啥啥的。所以翻译出来的字符就不是希望的字符。以上则是我的理解。
如果确实如此,那么上面的utf-8是在哪里可以找到。编译环境设置?还是系统那儿定下的?亦或者其它。如何操作即可让字符串"A中文"在内存中保存的数值不再是011101100......以及上面的GBK是在哪里可以找到。怎么操作即可更换解码(内存中的数值)映射表。
谢谢


这个应该是跟着你文件的编码吧。比如你的文件用GB2312保存,那就是GB2312编码,是utf-8就是utf-8编码。
这个你可以自己测试一下,比如用GB2312保存文件,编译,运行输出内存信息,再以utf-8保存文件,编译,运行输出信息,看看是否不一样。
char* str= "A中文"//
while (*str != '\0') {
printf("%02X", (*str & 0x00FF));
str++;
}

千梦一生 2020-03-12
  • 打赏
  • 举报
回复
引用 1 楼 m0_46108109 的回复:
电脑是外国人发明的,最开始,没有定义任何字符。都是系统自己定义的。
系统说某个二进制编码是哪个字符就是哪个字符。
后来又来ascii码,规定了一个char的低128个数值,每个二进制码对应哪个字符。
这样编写的程序就能兼容了。但是这只是针对英文的。
其他语系的字母表示不了。
所以ascii扩展了一次,把高128个数值,也编码了,对应的是拉丁语系的其他字母。

但是,对于其他语系,这256个数值,还是不够用。所以,其他语种用两个128个数值表示一个字符。
最开始的时候,也是大家各自设计。每个系统都默认某个数值,是自己系统对应的字符。
常见的表现就是一个系统的内码,到两外一个系统打开是乱码了。

有两个解决方案,一个是像网页那样,在网页的开头,写明了自己是哪里编码。
另一个像word一样,它读取一个文档的开头,看哪个国家的编码多一些,就判断为哪里编码,这个经常误判。

为了解决这个问题,出现了unicode,他试图把地球上所有的语种都规范起来。
utf-8依然采用的是低128个数值表示英文字符,若干高128个数值表示其他语种数值。
这样英文国家就使用起来很方便,原先多大的文件,还是多大。
utf-16所有字符都至少占两个字节了,但是内码的空间依然不足,只能表示地球上的6万个字母。
所以像ascii码的扩展那样,在高数值的区域,又划分出来一个区域,叫代理区,这样就可以用4个字节表示一个字符了。
utf-32好像进一步扩展了。

在windows系统中,一个Unicodetxt文件的开头有两个字节,表示这是一个Unicode文档。没有这两个字节的是多字节文档。
如果是多字节文档,拿到其他地方,就可能会乱码。


谢谢您的回复,确实您所言的一些知识对我也有帮助
千梦一生 2020-03-12
  • 打赏
  • 举报
回复
引用 6 楼 gouyanfen 的回复:
这个问题在你定义"A中文"的时候,这段文字就己经编码了,假如你是用vs2010,那么你在文档中输入这个的时候就己经确认了编码,你的文档用的是什么编码,那么char a *="A中文"就会最终映射到内存对应的编码,你运行的时候要看你输出环境的字符环境定义,假如相同,就不乱码,假如不同就会乱码。

谢谢这位老师,您的指点对我有极大的帮助。谢谢
院里有座山 2020-03-12
  • 打赏
  • 举报
回复

#include<stdio.h>
int main()
{
int m, n;
char* str = "A中文";
m=strlen(str);
for (int i = 0; i < m; i++) {
n = str[i];
printf("%d\n", n);
}
return 0;
}

可以看出字母A和汉字编码位置是不同的,
gouyanfen 2020-03-12
  • 打赏
  • 举报
回复
这个问题在你定义"A中文"的时候,这段文字就己经编码了,假如你是用vs2010,那么你在文档中输入这个的时候就己经确认了编码,你的文档用的是什么编码,那么char a *="A中文"就会最终映射到内存对应的编码,你运行的时候要看你输出环境的字符环境定义,假如相同,就不乱码,假如不同就会乱码。
千梦一生 2020-03-12
  • 打赏
  • 举报
回复
引用 3 楼 gouyanfen 的回复:
第三个问题,统一的编码规则是Unicode,其它的用的都是区域码,你的文档生成时按照你操作系统的区域和编码设定。
第四个问题,程序运行中显示输出依赖操作系统的区域和编码设定,你也可单独指定串的格式,但是输出需要符合系统设定。比如控制台,输出时需要调用对应字库提取字模,然后显示在屏幕上,编码错误就会提取错误的字模,你看起来就是乱码。

您好,谢谢您的回复。
希望继续向您请教一下这个问题:
我的意思是比如我写了char a = "A中文"。那么在内存中一定有个地方存了我这么一个字符串。也就是一段数字(比如011101100...)
那么计算机把我写的"A中文"转换为011101100...这应该是有一个映射关系的吧。比方说是使用的utf-8编码的映射规则(而不是GB2312或者其它啥啥)。然后我运行跑起来。控制台却打印出了乱码。是不是就证明它翻译这川字符串的时候所依据的码表不是utf-8。而是另外的,比如GBK啥啥啥的。所以翻译出来的字符就不是希望的字符。以上则是我的理解。
如果确实如此,那么上面的utf-8是在哪里可以找到。编译环境设置?还是系统那儿定下的?亦或者其它。如何操作即可让字符串"A中文"在内存中保存的数值不再是011101100......以及上面的GBK是在哪里可以找到。怎么操作即可更换解码(内存中的数值)映射表。
谢谢

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧