You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言读取含韩文的CSV文件时字符乱码问题求助

解决C语言读取含韩文CSV文件的乱码问题

问题背景

我有一个包含韩文的CSV文件,内容如下:

name,hp,damage
대학오리,20,5
대학냥이,30,10
시계탑기린,100,20

编写了如下C语言代码读取并打印该文件:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[1000];
    int hp;
    int damage;
} Monster;

typedef struct {
    char header1[sizeof "name"];
    char header2[sizeof "hp"];
    char header3[sizeof "damage"];
} Header;
int main()
{
    FILE* fp = fopen("entityData.csv", "r");
    if (!fp) {
        printf("Error opening file\n");
        return 1;
    }

    Monster monsters[100];
    int num_records = 0;

    char line[100];
    Header header;
    fgets(line, sizeof line, fp);
    strncpy(header.header1, strtok(line, ","), sizeof header.header1);
    strncpy(header.header2, strtok(NULL, ","), sizeof header.header2);
    strncpy(header.header3, strtok(NULL, "\n"), sizeof header.header3);

    while (fgets(line, sizeof(line), fp))
    {
        char* token = strtok(line, ","); //, 기준으로 나눠서 token에 저장
        strncpy(monsters[num_records].name, token, 20);

        token = strtok(NULL, ",");
        monsters[num_records].hp = atoi(token);

        token = strtok(NULL, ",");
        monsters[num_records].damage = atoi(token);

        num_records++;
    }

    for (int i = 0; i < num_records; i++)
    {
        printf("%s:%s %s:%d %s:%d\n",
            header.header1, monsters[i].name,
            header.header2, monsters[i].hp,
            header.header3, monsters[i].damage);
    }
        

    fclose(fp);
    return 0;
}

期望输出:

name:대학오리 hp:20 damage:5
name:대학냥이 hp:30 damage:10
name:시계탑기린 hp:100 damage:20

实际运行时韩文名称出现乱码,尝试使用wchar_t但出错,请求解决方法。


解决方案

韩文属于Unicode字符,通常以UTF-8编码存储(每个韩文占2-3字节),乱码主要源于控制台编码不匹配或宽字符处理流程错误,以下是两种可行方案:

方案1:保持UTF-8字节流处理,修正控制台编码

如果CSV文件是UTF-8编码,直接用char存储韩文是可行的,只需确保控制台输出使用UTF-8编码:

  • Windows环境:在代码开头添加system("chcp 65001 >nul");(>nul用于隐藏编码切换的输出信息);
  • Linux/macOS环境:控制台默认大多支持UTF-8,无需额外设置。

修改后的核心代码片段:

int main()
{
    // Windows下切换控制台为UTF-8编码
    system("chcp 65001 >nul");

    FILE* fp = fopen("entityData.csv", "r");
    // 后续代码保持不变...
}

说明:strtok、strncpy等函数仅处理字节流,不会解析字符编码,只要控制台编码与文件编码匹配,就能正确显示韩文。

方案2:使用宽字符(wchar_t)规范处理

若需严格按宽字符处理Unicode,需使用对应版本的文件操作、字符串处理函数:

  1. 用_wfopen打开文件,指定UTF-8编码;
  2. 使用fgetws读取宽字符行;
  3. 使用wcstok分割宽字符串;
  4. 使用wprintf输出宽字符内容;
  5. 结构体中name字段改为wchar_t类型。

完整示例代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>

typedef struct {
    wchar_t name[1000];
    int hp;
    int damage;
} Monster;

typedef struct {
    wchar_t header1[sizeof L"name"];
    wchar_t header2[sizeof L"hp"];
    wchar_t header3[sizeof L"damage"];
} Header;

int main()
{
    // Windows下切换控制台为UTF-8编码
    system("chcp 65001 >nul");

    // 以宽字符模式打开UTF-8编码的文件
    FILE* fp = _wfopen(L"entityData.csv", L"r, ccs=UTF-8");
    if (!fp) {
        wprintf(L"Error opening file\n");
        return 1;
    }

    Monster monsters[100];
    int num_records = 0;

    wchar_t line[100];
    Header header;
    fgetws(line, sizeof line / sizeof(wchar_t), fp);
    
    // 分割宽字符串表头
    wchar_t* token = wcstok(line, L",");
    wcsncpy(header.header1, token, sizeof(header.header1)/sizeof(wchar_t));
    token = wcstok(NULL, L",");
    wcsncpy(header.header2, token, sizeof(header.header2)/sizeof(wchar_t));
    token = wcstok(NULL, L"\n");
    wcsncpy(header.header3, token, sizeof(header.header3)/sizeof(wchar_t));

    while (fgetws(line, sizeof(line)/sizeof(wchar_t), fp))
    {
        token = wcstok(line, L",");
        wcsncpy(monsters[num_records].name, token, sizeof(monsters[num_records].name)/sizeof(wchar_t));

        token = wcstok(NULL, L",");
        monsters[num_records].hp = _wtoi(token); // 宽字符串转整数

        token = wcstok(NULL, L",");
        monsters[num_records].damage = _wtoi(token);

        num_records++;
    }

    for (int i = 0; i < num_records; i++)
    {
        wprintf(L"%s:%s %s:%d %s:%d\n",
            header.header1, monsters[i].name,
            header.header2, monsters[i].hp,
            header.header3, monsters[i].damage);
    }

    fclose(fp);
    return 0;
}

说明:

  • _wfopen的ccs=UTF-8参数指定文件编码,确保读取时正确转换为宽字符;
  • 所有字符串操作均使用宽字符版本函数(wcstok、wcsncpy、wprintf等);
  • _wtoi用于将宽字符串转换为整数,替代atoi。

内容的提问来源于stack exchange,提问作者Mr Cake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:32:07