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

CLion无法正确读取TXT文件中中文菜品名的技术求助

问题描述

我是计算机相关专业的中国大学生,正在完成餐厅管理系统大作业。代码完成后发现CLion无法正确读取TXT文件中的菜品名称。

尝试过以下方法均无效:

  • 使用%s输入字符串
  • 使用%49[^,]读取逗号前内容
  • 改用\n读取换行符前内容

已确认TXT文件编码为GBK,CLion项目编码也为GBK,除JSON方式外已尝试多种方法,仍无法通过scanf将TXT内容正确读取到菜单结构体中。

相关代码

版本1(按换行解析)

void loadMenuFromFile(const char *filename) {
    setlocale(LC_ALL, "zh_CN.GBK");
    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        perror("无法打开文件");
        return;
    }

    // 初始化 itemCount 为 0

    char line[100]; // 用于存储读取的整行数据

    // 读取文件,直到文件末尾
    while (fgets(line, sizeof(line), file)) {
        printf("读取行: %s\n", line);  // 打印读取的行

        int result = sscanf(line, "菜品ID: %d\n 名称: %49[^\n]\n 价格: %f\n 成本: %f\n",
                             &menu.items[count].id,
                             menu.items[count].name,
                             &menu.items[count].price,
                             &menu.items[count].cost);

        if (result == 4) {
            printf("成功解析: ID=%d, 名称=%s, 价格=%.2f, 成本=%.2f",
                   menu.items[count].id,
                   menu.items[count].name,
                   menu.items[count].price,
                   menu.items[count].cost);
            count++;  // 成功解析后增加 itemCount
        } else {
            printf("解析失败,读取行内容: %s\n", line);
        }
    }
    fclose(file);
    printf("菜单数据已从文件 %s 加载,读取了 %d 个菜品\n", filename, count);
}

版本2(按逗号分隔解析)

void loadMenuFromFile(const char *filename) {
    setlocale(LC_ALL, "zh_CN.GBK");
    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        perror("无法打开文件");
        return;
    }

    // 初始化 itemCount 为 0

    char line[100]; // 用于存储读取的整行数据

    // 读取文件,直到文件末尾
    while (fgets(line, sizeof(line), file)) {
        printf("读取行: %s\n", line);  // 打印读取的行

        int result = sscanf(line, "菜品ID: %d, 名称: %49[^,], 价格: %f ,成本: %f",
                             &menu.items[count].id,
                             menu.items[count].name,
                             &menu.items[count].price,
                             &menu.items[count].cost);

        if (result == 4) {
            printf("成功解析: ID=%d, 名称=%s, 价格=%.2f, 成本=%.2f",
                   menu.items[count].id,
                   menu.items[count].name,
                   menu.items[count].price,
                   menu.items[count].cost);
            count++;  // 成功解析后增加 itemCount
        } else {
            printf("解析失败,读取行内容: %s\n", line);
        }
    }
    fclose(file);
    printf("菜单数据已从文件 %s 加载,读取了 %d 个菜品\n", filename, count);
}

void saveMenuToFile(const char *filename){
    FILE *file = fopen(filename, "w");
    if (file == NULL) {
        perror("无法打开文件");
        return;
    }

    // 将菜单项写入文件
    for (int i = 0; i < count; i++) {
        fprintf(file, "菜品ID: %d 名称: %s 价格: %.2f 成本: %.2f",
                menu.items[i].id, menu.items[i].name, menu.items[i].price, menu.items[i].cost);
    }

    fclose(file);
    printf("菜单数据已保存到文件 %s\n", filename);
}
解决方案

核心问题是读写格式不匹配:你的saveMenuToFile写入的是无分隔符的连续文本,但两个loadMenuFromFile分别按换行、逗号分隔解析,完全对应不上。

具体修正步骤:

  1. 统一文件读写格式
    修改写入函数,让每个菜品占一行,字段用逗号分隔,保证格式可解析:

    void saveMenuToFile(const char *filename){
        FILE *file = fopen(filename, "w");
        if (file == NULL) {
            perror("无法打开文件");
            return;
        }
    
        for (int i = 0; i < count; i++) {
            // 每个菜品一行,字段用逗号分隔,格式和解析串严格对应
            fprintf(file, "菜品ID: %d, 名称: %s, 价格: %.2f, 成本: %.2f\n",
                    menu.items[i].id, menu.items[i].name, menu.items[i].price, menu.items[i].cost);
        }
    
        fclose(file);
        printf("菜单数据已保存到文件 %s\n", filename);
    }
    
  2. 修正解析格式
    调整sscanf的格式串,和写入格式完全一致,去掉多余空格:

    int result = sscanf(line, "菜品ID: %d, 名称: %49[^,], 价格: %f, 成本: %f",
                         &menu.items[count].id,
                         menu.items[count].name,
                         &menu.items[count].price,
                         &menu.items[count].cost);
    
  3. 基础细节检查

    • 确保menu.items[count].name的数组大小≥50(%49[^,]需要留一个位置存字符串结束符\0)
    • 将setlocale(LC_ALL, "zh_CN.GBK");移到程序入口(比如main函数开头),避免编码处理不一致
    • 打印sscanf的返回值result,快速定位哪个字段解析失败(返回1=仅匹配ID,返回2=匹配ID+名称,以此类推)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:29:49