C语言排序文件三列整数时fscanf读取出错问题排查
问题排查
- 读取逻辑冗余且容错性差:三次单独调用
fscanf读三个整数,未判断行完整性,某行字段缺失时会出现字段错位读取。同时你当前代码读取后仅用count统计有效条数,但后续排序、写入逻辑全用传入的参数n做边界,若实际读取条数count < n,未初始化的数组垃圾值会被写入文件、参与排序,表现为读取到错误数值。 - 动态内存申请语法错误:你注释掉的
malloc写法漏掉了乘法运算符,正确写法为int *array = (int *)malloc(n * 3 * sizeof(int));,语法错误导致你改用栈上变长数组,n较大时会触发栈溢出。 - 冒泡排序逻辑完全错误:当前循环边界、比较逻辑不符合冒泡排序规则,会出现排序乱序、重复交换的问题,甚至会操作未初始化的数组空间。
- 无用文件打开操作:你以只读模式打开了
index.txt但全程未读取其内容,属于冗余逻辑。 - 循环提前退出的根因:要么是
record.txt中存在非数字字符/字段数量不足,fscanf匹配失败触发break;要么是你传入的参数n远小于实际文件记录数,触发count==n的break条件;如果是首次运行就出错,也有可能是之前测试时异常写入了非法内容到record.txt中,先手动检查文件内容是否为每行三个整数的合法格式。
修复方案
- 合并三次
fscanf调用为一次,一次性匹配三个整数,返回值不等于3时直接退出循环 - 后续排序、写入的边界统一用实际读取到的有效条数
count,不要用传入的n - 修正
malloc语法,用堆内存存储数组避免栈溢出 - 重写冒泡排序逻辑,确保排序规则正确(当前你写的是按学号降序、相同时按课程号降序,若需要升序自行修改比较运算符)
- 移除无用的
index.txt只读打开逻辑,或者补充对应的读取逻辑
修正后完整代码
void sort_for_bin_search(int n) { FILE *record = fopen("record.txt", "r"); if (!record) return; // 改用堆内存存储数组,避免栈溢出 int *array = (int *)malloc(n * 3 * sizeof(int)); if (!array) { fclose(record); return; } int count = 0; int i=0,temp,id,course,score; while (count < n) { // 一次读取三个整数,容错性更高 if (fscanf(record, "%d %d %d", &id, &course, &score) != 3) break; array[count*3 + 0] = id; array[count*3 + 1] = course; array[count*3 + 2] = score; count++; } fclose(record); // 修正冒泡排序逻辑,边界用实际读取条数count for (i = 0; i < count - 1; i++) { for (int j = 0; j < count - 1 - i; j++) { int cur_j0 = array[j*3 + 0], cur_j1 = array[j*3 + 1]; int cur_jn0 = array[(j+1)*3 + 0], cur_jn1 = array[(j+1)*3 + 1]; int swap_flag = 0; if(cur_jn0 > cur_j0) { swap_flag = 1; } else if(cur_jn0 == cur_j0 && cur_jn1 > cur_j1) { swap_flag = 1; } if(swap_flag) { // 交换学号 temp = array[j*3 + 0]; array[j*3 + 0] = array[(j+1)*3 + 0]; array[(j+1)*3 + 0] = temp; // 交换课程号 temp = array[j*3 + 1]; array[j*3 + 1] = array[(j+1)*3 + 1]; array[(j+1)*3 + 1] = temp; // 交换成绩 temp = array[j*3 + 2]; array[j*3 + 2] = array[(j+1)*3 + 2]; array[(j+1)*3 + 2] = temp; } } } FILE *index2 = fopen("index.txt", "w"); FILE *record2 = fopen("record.txt", "w"); if(index2 && record2) { // 写入边界用实际读取到的count for (i = 0; i < count; i++) { fprintf(index2,"%d\n",array[i*3 + 0]); fprintf(record2,"%d %d %d\n",array[i*3 + 0],array[i*3 + 1],array[i*3 + 2]); } fclose(record2); fclose(index2); } free(array); }
内容的提问来源于stack exchange,提问作者Yodax93
相关产品推荐
相关产品推荐

