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

C语言文件处理:读取文本文件打印异常及乱码问题求助

C语言文件读取打印乱码与内容异常问题排查与解决

问题根源分析

  1. 字段读取错位:数据中存在带空格的字段(如Jose Santos、First Class),但fscanf的%s会把空格当作字段分隔符,导致读取时把Santos当成年龄、First当成目的地,类型不匹配直接引发乱码。同时文件开头的/*注释会被当作有效数据,进一步破坏读取逻辑。
  2. 文件打开未做检查:如果ticket list.txt不存在或权限不足,fopen返回NULL,此时调用fscanf会触发未定义行为,产生随机乱码。
  3. 重复打印表头:循环内每次都执行printxy打印表头,反复覆盖同一区域,干扰正常输出。
  4. 输入函数混用隐患:insert里gets和scanf混用,scanf("%d", &age)会留下换行符,后续getch可能读取到换行,导致写入文件的内容错位。
  5. 缓冲区溢出风险:name[20]等缓冲区长度有限,若输入内容过长会溢出,破坏其他变量内存,引发异常。

修复步骤与代码修改

1. 修正文件内容

移除文件中的/* */注释,确保每条记录格式统一:

UTIC0 Jose Santos 10 Spain First Class
UTIC2 Juan Cruz 18 South Korea Economy Class

2. 重写show函数(核心修复)

改用按行读取+拆分的方式处理带空格字段,添加文件打开检查,优化输出逻辑:

void show(void){
    system("cls");
    int age, row=10;
    // 增大缓冲区避免溢出
    char utic[15], first_name[15], last_name[15], destination[25], class_prefix[15], class_suffix[15];
    char line[128]; // 存储整行内容
    char full_name[30], full_class[25];
    
    // 初始化界面元素
    line2(2,2,78,24);
    line1(3,3,77,5);
    line1(3,7,77,22);
    center(4,"Show Existing Record");
    // 表头只打印一次
    printxy(5,8,"UTIC\tName\t\tAge\tDestination\tClass\t\tDate");
    hline(4,9,76,196);
    
    FILE *textfile = fopen("ticket list.txt", "r");
    // 检查文件是否成功打开
    if(textfile == NULL){
        center(23, "无法打开文件!");
        getch();
        return;
    }
    
    // 按行读取文件
    while(fgets(line, sizeof(line), textfile) != NULL){
        // 跳过空行和注释行
        if(line[0] == '\n' || line[0] == '/') continue;
        
        // 解析整行内容:拆分带空格的名字和舱位
        if(sscanf(line, "%s %s %s %d %s %s %s", utic, first_name, last_name, &age, destination, class_prefix, class_suffix) == 7){
            // 拼接完整名字和舱位
            sprintf(full_name, "%s %s", first_name, last_name);
            sprintf(full_class, "%s %s", class_prefix, class_suffix);
            
            // 输出到对应位置
            gotoxy(5, row);
            printf("%s", utic);
            gotoxy(15, row);
            printf("%s", full_name);
            gotoxy(25, row);
            printf("%d", age);
            gotoxy(35, row);
            printf("%s", destination);
            gotoxy(45, row);
            printf("%s", full_class);
            row++;
        }
    }
    
    getch();
    fclose(textfile);
}

3. 修复insert函数的输入逻辑

替换不安全的gets为fgets,处理换行符避免输入错位:

// 修改insert函数中的输入部分
gotoxy(44,9);
// 读取UTIC,替换gets
fgets(utic, sizeof(utic), stdin);
// 去掉fgets读取的换行符
utic[strcspn(utic, "\n")] = '\0';

gotoxy(44,12);
// 读取名字,替换gets
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = '\0';

// 读取年龄后,清理缓冲区的换行符
scanf("%d", &age);
// 吃掉换行符,避免影响后续getch
while(getchar() != '\n');

4. 其他细节修复

  • 在main函数中初始化option变量:char option = '\0';,避免第一次循环的异常行为。
  • 确保myfunctions.h中的gotoxy、printxy等函数正确处理光标位置,避免输出偏移。

验证效果

修改后重新运行程序:

  1. 用B选项插入新记录,确保写入文件的格式正确。
  2. 用C选项查看记录,此时带空格的名字和舱位会被正确读取并打印,不会出现乱码或内容错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:24:37