C-Qsort:按升序对名称进行排序,按降序对等级进行排序

C-Qsort:按升序对名称进行排序,按降序对等级进行排序,c,sorting,typedef,strcmp,qsort,C,Sorting,Typedef,Strcmp,Qsort,我正在尝试对我的记录进行qsort排序,以便它按名称升序对记录进行排序。如果有同名的名字,它将按降序排列他们的成绩 例如:原始文本文件 simpson bart 25 simpson bart 35 simpson lisa 90 simpson bart 34 期望输出: simpson bart 35 simpson bart 34 simpson bart 25 simpson lisa 90 这就是我所拥有的: int sort_nameasc_gradedes(const void

我正在尝试对我的记录进行qsort排序,以便它按名称升序对记录进行排序。如果有同名的名字,它将按降序排列他们的成绩

例如:原始文本文件

simpson bart 25
simpson bart 35
simpson lisa 90
simpson bart 34
期望输出:

simpson bart 35
simpson bart 34
simpson bart 25
simpson lisa 90
这就是我所拥有的:

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;

    int n1 = strcmp(pp->name.first, qq->name.first);
    int n2 = strcmp(pp->name.last, qq->name.last);

    if (n2 == 0 && n1 != 0) {
        return n1;
    } else if (n2 != 0  && n1 == 0) {
        return n2;
    } else {
        return (pp->score - qq->score);
    }
}
这不能正常工作


提前谢谢。

这应该是您要找的

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;

    int n1 = strcmp(pp->name.first, qq->name.first);
    int n2 = strcmp(pp->name.last, qq->name.last);

    if (n1 != 0) {
        return n1;
    } else if (n2 != 0) {
        return n2;
    } else {
        return (qq->score - pp->score);
    }
}
首先想想你在第一和第二种情况下做了什么。你写道:

if (n2 == 0 && n1 != 0) {
        return n1;
}
如果输入是:

simpson bart 25
taufique hussain 30
此输入的决定应基于名字,但在您的代码中,它将在最后一个
else
条件下决定,并将生成输出

taufique hussain 30
simpson bart 25
而不是

simpson bart 25
taufique hussain 30
现在进入最后一个条件。如果
pp
simpson-bart 25
并且
qq
simpson-bart 30
,那么
pp->score-qq->score
的值是多少<代码>-5对吗?然后在排序数组中,以下是答案:

simpson bart 25
simpson bart 30
而不是你想要的:

simpson bart 30
simpson bart 25

这应该是你要找的

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;

    int n1 = strcmp(pp->name.first, qq->name.first);
    int n2 = strcmp(pp->name.last, qq->name.last);

    if (n1 != 0) {
        return n1;
    } else if (n2 != 0) {
        return n2;
    } else {
        return (qq->score - pp->score);
    }
}
首先想想你在第一和第二种情况下做了什么。你写道:

if (n2 == 0 && n1 != 0) {
        return n1;
}
如果输入是:

simpson bart 25
taufique hussain 30
此输入的决定应基于名字,但在您的代码中,它将在最后一个
else
条件下决定,并将生成输出

taufique hussain 30
simpson bart 25
而不是

simpson bart 25
taufique hussain 30
现在进入最后一个条件。如果
pp
simpson-bart 25
并且
qq
simpson-bart 30
,那么
pp->score-qq->score
的值是多少<代码>-5对吗?然后在排序数组中,以下是答案:

simpson bart 25
simpson bart 30
而不是你想要的:

simpson bart 30
simpson bart 25

你想要更像这样的东西:

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;

    int n2 = strcmp(pp->name.last, qq->name.last);

    if (n2 != 0)
    {
        return n2;
    }
    else
    {
        int n1 = strcmp(pp->name.first, qq->name.first);

        if (n1 != 0)
        {
            return n1;
        }
        else
        {
            return qq->score - pp->score;
        }
    }
}

你想要更像这样的东西:

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;

    int n2 = strcmp(pp->name.last, qq->name.last);

    if (n2 != 0)
    {
        return n2;
    }
    else
    {
        int n1 = strcmp(pp->name.first, qq->name.first);

        if (n1 != 0)
        {
            return n1;
        }
        else
        {
            return qq->score - pp->score;
        }
    }
}

您只需一次检查一个字段,并在一对字段不相等时立即返回。因此,首先比较
name.last
并保留
strcmp
结果;如果它不是零,则返回它,否则继续下一个字段。然后,比较
名称。首先,用同样的方法。。。如果strcmp
结果不是零,则返回。最后,比较
得分

如果
score
是有符号的,并且不会接近所使用的数据类型的极端值,您可以像以前一样在测试中使用减法,但是如果没有符号或者减法可以换行,则需要另一种测试

类似以下的方法可能会起作用:

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;
    int r;

    if ((r = strcmp(pp->name.last, qq->name.last)) != 0)
        return r;
    if ((r = strcmp(pp->name.first, qq->name.first)) != 0)
        return r;
    /* return pp->score - qq->score; */
    return (pp->score < qq->score) ? 1 : ((pp->score > qq->score) ? -1 : 0);
}
int-sort\u-nameasc\u-gradedes(常量无效*p,常量无效*q)
{
常数记录*pp=p;
常数记录*qq=q;
INTR;
如果((r=strcmp(pp->name.last,qq->name.last))!=0)
返回r;
如果((r=strcmp(pp->name.first,qq->name.first))!=0)
返回r;
/*返回pp->score-qq->score*/
返回(pp->scorescore)?1:((pp->score>qq->score)?-1:0);
}

您只需一次检查一个字段,并在一对字段不相等时返回。因此,首先比较
name.last
并保留
strcmp
结果;如果它不是零,则返回它,否则继续下一个字段。然后,比较
名称。首先,用同样的方法。。。如果strcmp
结果不是零,则返回。最后,比较
得分

如果
score
是有符号的,并且不会接近所使用的数据类型的极端值,您可以像以前一样在测试中使用减法,但是如果没有符号或者减法可以换行,则需要另一种测试

类似以下的方法可能会起作用:

int sort_nameasc_gradedes(const void *p, const void *q)
{
    const record *pp = p;
    const record *qq = q;
    int r;

    if ((r = strcmp(pp->name.last, qq->name.last)) != 0)
        return r;
    if ((r = strcmp(pp->name.first, qq->name.first)) != 0)
        return r;
    /* return pp->score - qq->score; */
    return (pp->score < qq->score) ? 1 : ((pp->score > qq->score) ? -1 : 0);
}
int-sort\u-nameasc\u-gradedes(常量无效*p,常量无效*q)
{
常数记录*pp=p;
常数记录*qq=q;
INTR;
如果((r=strcmp(pp->name.last,qq->name.last))!=0)
返回r;
如果((r=strcmp(pp->name.first,qq->name.first))!=0)
返回r;
/*返回pp->score-qq->score*/
返回(pp->scorescore)?1:((pp->score>qq->score)?-1:0);
}

您正在对三个字段进行排序,但您的描述仅涉及2个字段。虽然这不太可能是一个问题,但通常您应该避免使用
返回(pp->score-qq->score)因为如果值大到足以导致溢出,则它具有未定义的行为。您在三个字段上排序,但您的描述仅涉及2。虽然在这里不太可能出现问题,但通常应避免使用
return(pp->score-qq->score)因为如果值大到足以导致溢出,它有未定义的行为。那么“pp->score-qq->score”部分呢?你觉得对吗?根据他的要求,我认为应该是“qq->score-pp->score”。很好,我已经更新了上面的示例。(我用的是OP的代码,而不是要求)关于“pp->score-qq->score”部分呢?你觉得对吗?根据他的要求,我认为应该是“qq->score-pp->score”。很好,我已经更新了上面的示例。(我所遵循的是OP的代码,而不是要求)