silver-crow 发表于 2023-4-17 10:25:34

输出中文的时候乱码

以下是代码清单
#include <stdio.h>
#include <string.h>

#define MAX 1024

int main()
{
    char str1;
    char *pstr1 = str1;
    int num, length;

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

    char str2;
    char *pstr2 = str2;

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

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

    return 0;

}

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

isdkz 发表于 2023-4-17 10:34:02

这个问题是因为在处理中文字符时,没有正确处理多字节字符。中文字符在 UTF-8 编码中占用 3 个字节,而你的代码中将每个字符都当作一个字节来处理,导致中文字符被截断,输出乱码。

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

#include <stdio.h>
#include <string.h>
#include <locale.h>

#define MAX 1024

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

    char str1;
    char *pstr1 = str1;
    int num, length;

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

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

    char str2;
    char *pstr2 = str2;

    for(num = 0; num < length;)
    {
      *pstr2 = *pstr1;

      if((*pstr1 & 0xC0) == 0xC0) // 判断是否为多字节字符的开始
      {
            pstr1++;
            pstr2++;
            *pstr2 = *pstr1;
            num++;
      }
      else if((*pstr1 & 0x80) == 0) // 判断是否为单字节字符
      {
            num++;
      }

      pstr1++;
      pstr2++;
    }
    *pstr2 = '\0';

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

    return 0;
}


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

silver-crow 发表于 2023-4-17 10:44:41

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

这个输出还是不能正常进行

jackz007 发表于 2023-4-21 20:58:01

本帖最后由 jackz007 于 2023-4-21 21:05 编辑

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

陶远航 发表于 2023-5-1 20:43:20

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

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

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

#define MAX 1024

int main()
{
    wchar_t str1;
    wchar_t *pstr1 = str1;
    int num, length;

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

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

    wchar_t str2;
    wchar_t *pstr2 = str2;

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

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

    return 0;

}

需要注意的是,对于宽字符类型,以L开头的字母作为前缀表示。同时,输入字符也需要使用fgetws()函数获取。输出时,可以使用wprintf()和占位符%ls来打印宽字符类型的字符串。

Threebody1 发表于 2023-5-2 14:58:07

CHCP 65001

vicoray 发表于 2023-5-3 10:05:09

666

赚小钱 发表于 2023-6-9 08:57:21

vscode 将文件转为 utf8 编码。使用 windows terminal 或其他使用 utf8 编码渲染的终端运行。

二者要匹配。
页: [1]
查看完整版本: 输出中文的时候乱码