鱼C论坛

 找回密码
 立即注册
查看: 1190|回复: 7

输出中文的时候乱码

[复制链接]
发表于 2023-4-17 10:25:34 | 显示全部楼层 |阅读模式
10鱼币
以下是代码清单
#include <stdio.h>
#include <string.h>

#define MAX 1024

int main()
{
&#160; &#160; char str1[MAX];
&#160; &#160; char *pstr1 = str1;
&#160; &#160; int num, length;

&#160; &#160; printf("请输入一个字符串到 str1 中:");
&#160; &#160; fgets(str1, MAX, stdin);
&#160; &#160; printf("开始拷贝 str1 的内容至 str2 中...\n");
&#160; &#160;
&#160; &#160;
&#160; &#160; printf("请输入需要拷贝的字符个数:");
&#160; &#160; scanf("%d", &length);

&#160; &#160; char str2[length];
&#160; &#160; char *pstr2 = str2;

&#160; &#160; for(num = 0; num < length; num++, pstr1++, pstr2++)
&#160; &#160; {
&#160; &#160; &#160; &#160; *pstr2 = *pstr1;
&#160; &#160; &#160; &#160; if(*pstr1 < 0)
&#160; &#160; &#160; &#160; {
&#160; &#160; &#160; &#160; &#160; &#160; *pstr2 = *pstr1;
&#160; &#160; &#160; &#160; &#160; &#160; *pstr2 = *pstr1;
&#160; &#160; &#160; &#160; }
&#160; &#160; }
&#160; &#160; *pstr2 = '\0';

&#160; &#160; printf("拷贝完毕!现在 str2 中的内容是:%s", str2);

&#160; &#160; return 0;

}

以下是输出结果
请输入一个字符串到 str1 中:鱼c工作室
开始拷贝 str1 的内容至 str2 中...
请输入需要拷贝的字符个数:2
拷贝完毕!现在 str2 中的内容是:&#65533;c

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-17 10:34:02 | 显示全部楼层
这个问题是因为在处理中文字符时,没有正确处理多字节字符。中文字符在 UTF-8 编码中占用 3 个字节,而你的代码中将每个字符都当作一个字节来处理,导致中文字符被截断,输出乱码。

你可以尝试使用以下修改过的代码,这个版本的代码能够正确处理多字节的 UTF-8 字符:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <locale.h>

  4. #define MAX 1024

  5. int main()
  6. {
  7.     setlocale(LC_ALL, "en_US.UTF-8");

  8.     char str1[MAX];
  9.     char *pstr1 = str1;
  10.     int num, length;

  11.     printf("请输入一个字符串到 str1 中:");
  12.     fgets(str1, MAX, stdin);
  13.     printf("开始拷贝 str1 的内容至 str2 中...\n");

  14.     printf("请输入需要拷贝的字符个数:");
  15.     scanf("%d", &length);

  16.     char str2[MAX];
  17.     char *pstr2 = str2;

  18.     for(num = 0; num < length;)
  19.     {
  20.         *pstr2 = *pstr1;

  21.         if((*pstr1 & 0xC0) == 0xC0) // 判断是否为多字节字符的开始
  22.         {
  23.             pstr1++;
  24.             pstr2++;
  25.             *pstr2 = *pstr1;
  26.             num++;
  27.         }
  28.         else if((*pstr1 & 0x80) == 0) // 判断是否为单字节字符
  29.         {
  30.             num++;
  31.         }

  32.         pstr1++;
  33.         pstr2++;
  34.     }
  35.     *pstr2 = '\0';

  36.     printf("拷贝完毕!现在 str2 中的内容是:%s", str2);

  37.     return 0;
  38. }
复制代码


这个版本的代码在处理字符时会检查字符的字节,如果是多字节字符,它会将整个字符(包括所有字节)一起复制。这样就不会出现乱码问题了。注意,在代码开始时,需要调用 setlocale(LC_ALL, "en_US.UTF-8"); 设置地区和字符编码,以便程序正确处理多字节字符。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-17 10:44:41 | 显示全部楼层
isdkz 发表于 2023-4-17 10:34
这个问题是因为在处理中文字符时,没有正确处理多字节字符。中文字符在 UTF-8 编码中占用 3 个字节,而你的 ...

这个输出还是不能正常进行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-21 20:58:01 | 显示全部楼层
本帖最后由 jackz007 于 2023-4-21 21:05 编辑

       问题可能出在 Windows 10+ 系统下,Windows 记事本缺省采用 "UTF-8" 编码,而 CMD 窗口采用的却是 "GBK" 编码,由于二者的汉字编码产生了错位,从而导致汉字乱码。
       用 Windows 记事本打开源代码文件,然后点击 "文件 > 另存为",在 "保存" 按钮左边有一个 "编码" 选项,点击其旁边的下拉菜单,选择 "ANSI",然后点击 "保存",这个时候再重新编译、运行试试。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-1 20:43:20 | 显示全部楼层
这个输出结果的问题在于,被复制到str2中的中文字符是以两个连续的“?”表示的(即"&#65533;"),而不是实际的中文字符。这是因为 printf 无法正确输出UTF-8编码的中文字符串("\xe9\xb1\xbc\xe5\xc|\x67\xe4\xbd\x9c\xe5\xae\xa4"),而将其识别为ASCII字符集中不存在的一些字符,显示成了“?”。

要解决这个问题,可以使用宽字符类型和对应的printf函数wprintf()来输出宽字符的内容。以下是对代码的修改:

  1. #include <stdio.h>
  2. #include <string.h>

  3. #define MAX 1024

  4. int main()
  5. {
  6.     wchar_t str1[MAX];
  7.     wchar_t *pstr1 = str1;
  8.     int num, length;

  9.     wprintf(L"请输入一个字符串到 str1 中:");
  10.     fgetws(str1, MAX, stdin);
  11.     wprintf(L"开始拷贝 str1 的内容至 str2 中...\n\n");

  12.     wprintf(L"请输入需要拷贝的字符个数:");
  13.     scanf("%d", &length);

  14.     wchar_t str2[length];
  15.     wchar_t *pstr2 = str2;

  16.     for (num = 0; num < length; num++, pstr1++, pstr2++) {
  17.         *pstr2 = *pstr1;
  18.         if (*pstr1 < 0) {
  19.             *pstr2 = *pstr1;
  20.             *pstr2 = *pstr1;
  21.         }
  22.     }
  23.     *pstr2 = L'\0';

  24.     wprintf(L"拷贝完毕!现在 str2 中的内容是:%ls", str2);

  25.     return 0;

  26. }
复制代码

需要注意的是,对于宽字符类型,以L开头的字母作为前缀表示。同时,输入字符也需要使用fgetws()函数获取。输出时,可以使用wprintf()和占位符%ls来打印宽字符类型的字符串。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-2 14:58:07 | 显示全部楼层
CHCP 65001
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-3 10:05:09 | 显示全部楼层
666
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-9 08:57:21 From FishC Mobile | 显示全部楼层
vscode 将文件转为 utf8 编码。使用 windows terminal 或其他使用 utf8 编码渲染的终端运行。

二者要匹配。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 18:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表