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

如何修复qsort对student结构体数组排序无效的问题

修复qsort对结构体数组按sid排序失效的问题

问题现象

运行代码后,排序前后s[0].sid无变化,qsort未对结构体数组按sid字段进行正确排序。

核心错误

问题出在cmpid比较函数的返回值逻辑上:

return (s1->sid > s2->sid) - (s1->sid > s2->sid);

这个表达式的结果永远是0,因为两个相同的布尔值相减为0。qsort会认为所有元素的排序优先级相同,因此不会执行任何排序操作。

修复方案

修改cmpid函数,返回正确的比较结果。有两种可靠的写法:

写法1(适用于sid不会发生整数溢出的场景)

int cmpid(const void *a, const void *b )
{
    const struct student* s1 = (const student *) a; 
    const struct student* s2 =  (const student *) b; 
    return s1->sid - s2->sid;
}

写法2(避免整数溢出,更安全)

int cmpid(const void *a, const void *b )
{
    const struct student* s1 = (const student *) a; 
    const struct student* s2 =  (const student *) b; 
    return (s1->sid > s2->sid) ? 1 : (s1->sid < s2->sid) ? -1 : 0;
}

修改后的完整代码

#define BUFC 1024 
enum {NSTD = 64, NMARK = 100};

typedef struct student{
    int sid;
    int nmarks; /* number grades */
    int marks[NMARK]; /* grades array */
} student;

int cmpid(const void *a, const void *b );
int main(int argc, char **argv){
    char buf[BUFC];
    int i,j, sidx = 0;
    student s[NSTD] = {{.sid = 0,.marks = 0 }};
    
    FILE *fp =  argc > 1 ? fopen(argv[1],"r") : stdin;
    if(!fp){
        fprintf(stderr,"error: file open failed '%s'.\n", argv[1]);
        return 1;
    }
    printf("\nEnter student ID followed by grad (0,100) 101 for next student, 102 when finished.\n");
    for(; sidx < NSTD; ){
        int grade = 0, tries = 0;
        int n;
        int offset;
        
        if(!fgets(buf,BUFC,stdin)){
            fputs("\n(user canceled input)\n",stdout);
            break;
        }
        buf[strcspn(buf,"\n")] = 0;
        char *data = buf;

        while (sscanf(data," %d%n",&n,&offset) == 1)
        {
            s[sidx].marks[s[sidx].nmarks++] = n;
            data = data + offset;
        }
        sidx ++;     
    }
    if(fp != stdin) fclose(fp);
    
    for(i = 0; i < sidx; i++){
        s[i].sid = s[i].marks[0];    
    }
    printf("sidx=%d\n",sidx);
    for(i = 0; i < 2; i++){
        printf("\nStudent ID:%3d\tgrades:",s[i].sid);
    }
    putchar('\n');
    printf("Before Qsort: s[0].sid=%d\n",s[0].sid);
    qsort(s,sidx, sizeof *s,cmpid);
    printf("After Qsort s[0].sid=%d\n",s[0].sid);
    return 0;
}

// 修复后的比较函数
int cmpid(const void *a, const void *b )
{
    const struct student* s1 = (const student *) a; 
    const struct student* s2 =  (const student *) b; 
    return (s1->sid > s2->sid) ? 1 : (s1->sid < s2->sid) ? -1 : 0;
}

验证效果

重新编译运行命令:
gcc array_struct20.c && ./a.out <dat/idmarks.txt

输出会显示排序后s[0].sid变为最小的学生ID(示例中为166),说明qsort已正常生效。

内容的提问来源于stack exchange,提问作者jian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:03:30