结构体数组qsort排序输出异常问题排查(附代码)
问题分析与修复方案
嘿,你的输出混乱和奇怪垃圾值的问题,主要是几个代码细节踩坑了,咱们一步步捋清楚:
1. 核心问题:错误使用NUM_ITEMS遍历数据
你定义的NUM_ITEMS是数组items的总容量(100),但实际从CSV读取的有效数据行数是循环里的i(读了多少行,i就是多少)。用NUM_ITEMS当遍历上限时,会把数组里未初始化的空元素也输出——那些像nummer: 1966644114的奇怪数值,就是未初始化内存的垃圾值。
修复方法:
用一个单独的变量(比如count)保存实际读取的行数,避免循环变量被覆盖,输出时只遍历有效数据:
int count = 0; // 读取CSV的循环 for (count = 0; count < 100 && fgets(envara, 512, fp); count++) { // 原有的字段读取逻辑... } // 排序只针对有效数据 qsort(items, count, sizeof(struct vara), nummer_sortering); // 输出循环只遍历有效行数 for (int j = 0; j < count; j++) { // 输出逻辑... }
2. free(oneline)的位置完全错了
你现在把free(oneline)放在输出循环里,但oneline是每行读取时分配的内存,应该在处理完当前行后立刻释放,而不是等到输出阶段。当前写法会导致内存泄漏,甚至重复释放野指针。
修复方法:
把free(oneline)移到读取每行的循环末尾:
for (count = 0; count < 100 && fgets(envara, 512, fp); count++) { envara[strcspn(envara, "\n")] = '\0'; oneline = strdup(envara); // 所有字段读取逻辑... // 处理完当前行就释放内存 free(oneline); }
3. 函数嵌套定义不符合C标准
你在读取数据的循环内部定义了nummer_sortering函数,这在标准C里是不允许的(虽然部分编译器支持扩展,但容易出问题)。
修复方法:
把排序函数移到main函数外面,作为全局函数,同时优化排序逻辑避免整数溢出:
// 排序函数放在全局位置 int nummer_sortering(const void* n1, const void* n2) { const struct vara *item1 = (const struct vara*)n1; const struct vara *item2 = (const struct vara*)n2; // 用比较代替减法,避免大数值溢出 if (item1->nummer < item2->nummer) return -1; if (item1->nummer > item2->nummer) return 1; return 0; } int main() { // 原有的代码逻辑... }
4. 修复后的完整代码片段
#include <stdio.h> #include <stdlib.h> #include <string.h> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((b)>(a)?(a):(b)) struct vara { int nummer; char namn[100]; float pris; float volym; char typ[100]; char stil[100]; char forpackning[20]; char land[20]; char producent[50]; float alkoholhalt; } items[100]; // 排序函数放在全局位置 int nummer_sortering(const void* n1, const void* n2) { const struct vara *item1 = (const struct vara*)n1; const struct vara *item2 = (const struct vara*)n2; if (item1->nummer < item2->nummer) return -1; if (item1->nummer > item2->nummer) return 1; return 0; } int main() { char *oneline, *tok; char envara[512]; char delim[] = ","; FILE *fp; int count = 0; if ((fp = fopen("varor.csv", "r")) == NULL) { fprintf(stderr, "Filen varor.csv gick inte att öppna\n"); exit(-1); } for (count = 0; count < 100 && fgets(envara, 512, fp); count++) { envara[strcspn(envara, "\n")] = '\0'; oneline = strdup(envara); tok = strtok(oneline, delim); items[count].nummer = atoi(tok); tok = strtok(NULL, delim); strncpy(items[count].namn, tok, sizeof(items[count].namn)); items[count].namn[sizeof(items[count].namn) - 1] = 0; tok = strtok(NULL, delim); items[count].pris = atof(tok); tok = strtok(NULL, delim); items[count].volym = atof(tok); tok = strtok(NULL, delim); strncpy(items[count].typ, tok, sizeof(items[count].typ)); items[count].typ[sizeof(items[count].typ) - 1] = 0; tok = strtok(NULL, delim); strncpy(items[count].stil, tok, sizeof(items[count].stil)); items[count].stil[sizeof(items[count].stil) - 1] = 0; tok = strtok(NULL, delim); strncpy(items[count].forpackning, tok, sizeof(items[count].forpackning)); items[count].forpackning[sizeof(items[count].forpackning) - 1] = 0; tok = strtok(NULL, delim); strncpy(items[count].land, tok, sizeof(items[count].land)); items[count].land[sizeof(items[count].land) - 1] = 0; tok = strtok(NULL, delim); strncpy(items[count].producent, tok, sizeof(items[count].producent)); items[count].producent[sizeof(items[count].producent) - 1] = 0; tok = strtok(NULL, delim); items[count].alkoholhalt = atof(tok); free(oneline); } fclose(fp); printf("\n\nVaror sorterade på varunummer:\n"); qsort(items, count, sizeof(struct vara), nummer_sortering); for (int j = 0; j < count; j++) { printf("nummer: %d\n" "namn: %s\n" "pris: %f\n" "volym: %f\n" "typ: %s\n" "stil: %s\n" "forpackning: %s\n" "land: %s\n" "producent: %s\n" "alkoholhalt: %f\n\n", items[j].nummer, items[j].namn, items[j].pris, items[j].volym, items[j].typ, items[j].stil, items[j].forpackning, items[j].land, items[j].producent, items[j].alkoholhalt ); } return 0; }
这样修改后,就能正确读取CSV数据、按nummer排序,并且只输出有效内容,不会再出现奇怪的垃圾值了。
内容的提问来源于stack exchange,提问作者emano12
相关产品推荐
相关产品推荐

