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

结构体数组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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:39:20