C语言文件处理:读取文本文件打印异常及乱码问题求助
C语言文件读取打印乱码与内容异常问题排查与解决
问题根源分析
- 字段读取错位:数据中存在带空格的字段(如
Jose Santos、First Class),但fscanf的%s会把空格当作字段分隔符,导致读取时把Santos当成年龄、First当成目的地,类型不匹配直接引发乱码。同时文件开头的/*注释会被当作有效数据,进一步破坏读取逻辑。 - 文件打开未做检查:如果
ticket list.txt不存在或权限不足,fopen返回NULL,此时调用fscanf会触发未定义行为,产生随机乱码。 - 重复打印表头:循环内每次都执行
printxy打印表头,反复覆盖同一区域,干扰正常输出。 - 输入函数混用隐患:
insert里gets和scanf混用,scanf("%d", &age)会留下换行符,后续getch可能读取到换行,导致写入文件的内容错位。 - 缓冲区溢出风险:
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等函数正确处理光标位置,避免输出偏移。
验证效果
修改后重新运行程序:
- 用
B选项插入新记录,确保写入文件的格式正确。 - 用
C选项查看记录,此时带空格的名字和舱位会被正确读取并打印,不会出现乱码或内容错位。
内容的提问来源于stack exchange,提问作者Job Enriquez
相关产品推荐
相关产品推荐

