C语言读取dist.txt按NDist排序输出异常应如何排查修复?
问题根因排查
你的代码存在4处核心错误,直接导致字段错位、空数据异常:
- 未初始化
f变量就判断while(f != EOF),且f定义为char类型无法正确存储EOF值(EOF是int类型的-1,char为无符号时会截断为255,永远不等于EOF) - 读取文件的循环逻辑完全错误:你没有判断
fscanf的返回值,哪怕文件读取失败、已经到末尾,仍会执行v++,大量未初始化的结构体垃圾值被纳入排序和输出流程 fgetc的多余操作破坏了读取指针位置:fscanf读完一行后已经自动跳过空白符(包括换行),你额外读一个字符会吞掉下一行的第一个字符,直接导致后续字段错位- 读取字符串时没有做长度限制,
SCode只有5字节长度,一旦输入的编码超过4个字符就会发生缓冲区溢出,破坏内存数据
修正后代码
struct sortD { char supply[50], SCode[8], Cdonator[50]; // 给SCode多留冗余空间避免溢出 int IDd; double NDist; }mp[300]; void sortD() { struct sortD rmp; int v=0, size1, q; int read_ret; // 存储fscanf返回值判断读取结果 FILE * fpp = fopen("dist.txt", "r"); if (fpp == NULL) { printf ("\nCan not open file.\n"); return; } // 修正循环逻辑:用fscanf返回值判断读取是否成功,同时限制数组最大长度避免越界 while (v < 300) { read_ret = fscanf(fpp, "%d %49s %7s %49s %lf", &mp[v].IDd, mp[v].supply, mp[v].SCode, mp[v].Cdonator, &mp[v].NDist); if (read_ret != 5) break; // 没有读满5个字段说明读取失败/到达文件末尾,退出循环 v++; } fclose(fpp); // 读取完成后关闭文件释放资源 size1 = v; // 冒泡排序逻辑微调适配实际读取到的元素数量 for (v=0;v<size1-1;++v){ for (q=0;q<size1 - 1 - v;q++){ if (mp[q+1].NDist > mp[q].NDist) { rmp=mp[q]; mp[q]=mp[q+1]; mp[q+1]=rmp; } } } for (v=0;v<size1;v++){ printf ("ID: %d Name of Supply: %s, Supply Code: %s, Donator: %s, Number Donated (Million): %lf\n", mp[v].IDd, mp[v].supply, mp[v].SCode,mp[v].Cdonator, mp[v].NDist); } }
补充说明
如果你的dist.txt里的物资名称、捐赠方名称包含空格,那%s格式符无法正确读取(遇到空格就截断),需要换成%[^\t]或者按行读取后拆分字段,你可以根据实际文件的分隔规则调整读取逻辑。
内容的提问来源于stack exchange,提问作者user17401982
相关产品推荐
相关产品推荐

