// Linux · 2024-12-11

为什么设置为 UTF-8 时 scanf 输入中文会乱码?

在使用 VSCode 开发 C/C++ 程序时,我们经常会设置代码文件和终端的编码为 UTF-8。然而,当程序中使用 scanf 读取中文输入时,却可能会出现乱码问题。本文将从编码原理出发,分析问题原因,并提供解决方案。

问题背景

我们假设以下环境:

  • 源代码文件的编码设置为 UTF-8。
  • VSCode 或其他 IDE 的终端编码也设置为 UTF-8。
  • 程序运行时使用以下代码读取和输出中文:
#include <stdio.h>

int main() {
    char input[100];
    printf("请输入:\n");
    scanf("%s", input);
    printf("您输入的是:%s\n", input);
    return 0;
}

运行程序并输入中文后,输出的结果却是乱码,例如输入“测试”,终端可能显示为“ÎÅʹ”。 在这里插入图片描述

原因分析

问题的根本原因在于 终端编码行为的差异 和 scanf 的处理方式:

  1. 终端的输入和输出编码不一致:

    • 虽然终端显示编码设置为 UTF-8,但输入的中文数据可能以系统的默认编码格式(例如 GBK)传递给程序。
    • 在 Windows 系统中,控制台的默认输入编码通常是 GBK,即使终端显示设置为 UTF-8,也不会改变输入编码行为。
  2. scanf 不支持自动编码转换:

    • scanf 直接将从终端接收到的字节流写入缓冲区,并不处理编码转换。
    • 如果程序假定接收到的是 UTF-8 编码,而终端实际输入的是 GBK 编码,那么解码过程就会失败,从而导致乱码。
  3. 字符输入的特殊性:

    • scanf 中 %s 格式符按空白字符分割输入,仅适用于读取单词。如果输入包含空格(如中文句子),也可能导致数据截断。

解决方案:统一为 GBK 编码

最简单有效的方法是将源代码文件、终端以及程序运行时的编码统一为 GBK,以匹配系统默认行为。这种方式避免了额外的编码转换和复杂配置。

配置步骤

  1. 修改源代码文件编码:

    • 确保 C/C++ 源代码文件的编码为 GBK。可以在 VSCode 中通过右下角状态栏更改文件编码。
  2. 设置终端编码:

    • 在 VSCode 的终端中运行以下命令,将终端编码设置为 GBK:
      chcp 936
      此命令将终端编码切换为 GBK(代码页 936)。
  3. 调整程序设置(可选):

    • 在程序中通过 WinAPI 明确设置输入输出的编码。例如:

      #include <stdio.h>
      #include <windows.h>
      
      int main() {
          // 设置控制台输入输出编码为 GBK
          SetConsoleCP(936);  // 输入编码
          SetConsoleOutputCP(936);  // 输出编码
      
          char input[100];
          printf("请输入:\n");
          scanf("%s", input);
          printf("您输入的是:%s\n", input);
          return 0;
      }

通过以上步骤,可以确保输入和输出的编码一致,解决 scanf 读取中文乱码的问题。

总结

当 scanf 读取中文时出现乱码的主要原因是终端的输入编码与程序假设的编码不一致。通过统一为 GBK 编码,可以有效避免这一问题。虽然 UTF-8 是更通用的编码方案,但在中国地区开发本地化应用时,GBK 更符合系统默认行为且配置简便。

原文 https://blog.csdn.net/2301_79518550/article/details/144400458