聊聊开发中的编码问题

本文是一篇面向计算机小白的科普文。

很多新手在刚刚接触 C 或者 C++ 的打印语句时,都会尝试向其中添加中文,而后看到控制台出现一堆乱码......

下文会和大家仔细介绍问题的由来。

编码问题的产生

计算机当中的数据使用二进制存储,而作为现代计算机使用者的我们,却几乎没有和二进制打过交道,编码在其中占据了重大的功劳。

其实编码这个词听起来很高级,但并不是一个复杂的概念

如果我现在规定 A 等于 \(1\)B 等于 \(2\) ,以此类推,数据 1 16 16 12 5 就可以被解码为 A P P L E

上方的例子中,规定的过程就是编码的过程,而将一堆数据还原成单词就是解码的过程。

英文编码

众所周知,计算机最早发明于英语国家,所以全球的计算机中,英文都遵循着一套叫做 ASCII 的编码规则,当然 ASCII 这套规则不仅仅适用于英文字母,同时也适用于数字和各类控制符号。

下方贴出 ASCII 表:

ascii-1-1

其他语言编码

接下来可以讲讲非英文语言的编码问题了,还记得我们一开始提到的场景吗?我们使用 printf 或者是 cout 语句向控制台输出中文,而控制台输出了一堆乱码,这个其实是一个历史遗留问题,以下我们只介绍中文的场景,其他场景其实和中文并没有本质区别。

早期计算机编码

在现代计算机发明初期,电脑的用户是很少的,而且并没有频繁的跨语言交流需求,于是几乎每个国家都为自己国家的语言制定了一套编码标准。

中文最早的编码标准是 GB2312 ,而后由于早期的编码标准收入的字太少(中文博大精深),又陆续推出了 GBKGB18030 的编码标准,它们都是对前者的扩充,也对前者充分兼容。

与此同时,其他国家在没有任何交流的情况下都纷纷推出了自己的编码标准,Windows 系统也针对了各国的编码做了语言的适配,这乍一听是个百花齐放的好事,但是很快问题就产生了。

还是举个例子,我规定了 A\(1\) ,而另一个人规定 Z\(1\) :我们知道,计算机是只存储数据的,也就是只存储了 \(1\) ,那么同样是数据 \(1\) ,在两个人眼中显示的结果就会完全不一样。

现代计算机编码

为了解决计算机在全球跨文化交流中的需求,Unicode 组织推出了名为 Unicode 的全球码,它几乎收录了全球所有文化的字符,大家各种语言的符号组合在一块终于不会乱码了。

Unicode 的现行常用编码格式为 UTF-8 ,我们而今使用的几乎所有文本编辑器都会默认使用 UTF-8 进行编码。

至此,问题解决了,吗?

可不要忘记了,Windows 的系统编码是基于早期的计算机编码,微软公司称这种编码为 ANSI 编码(这种编码会根据地区适应编码规则)。

而我们在代码文件中所写的所有的非英文字符都使用的是 UTF-8 编码,我们现在终于可以解释最开始的问题了!

因为我们代码的文件是 UTF-8 编码,而大陆地区Windows系统的默认编码是 GBK 编码,自然就会产生乱码。

解决方案

既然知道了问题,解决的方案就很简单了,我们有两个思路:

  1. 把代码文件的 UTF-8 编码改成控制台的 GBK 编码
  2. 把控制台的 GBK 编码改成代码文件的 UTF-8 编码

方案一

在通常情况下,代码的编码显示在右下角,单击以后手动修改为 GBK ,保存即可。

方案二

在代码的开头添加:

// 你的头文件
#include <windows.h>

int main(){
	SetConsoleOutputCP(CP_UTF8);
	SetConsoleCP(CP_UTF8);
	// 你的代码
}

以上代码可以强制将控制台编码修改为 UTF-8

其他问题

由于本篇文章写给小白,并没有提及宽窄字符等问题,也没有详细介绍控制字符和 Windows 平台下的路径乱码问题,交由在未来的开发过程中自行探索。

顺带一提

其实中文乱码的问题主要是 Windows 平台,因为它具有大量的全球用户,具有较重的历史包袱,需要对老版本系统的文件兼容。

LinuxMac OS 已经强制系统全部使用 UTF-8 编码,所以此类问题并不会出现在这两个系统上。

posted @ 2025-09-20 23:03  TPPPP72  阅读(2)  评论(0)    收藏  举报