2013-11-28 152 views
0

我想排列我的记录,以便按名称按升序对记录进行排序。如果有名称以相同的名称,它会他们的成绩降序排列C - 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); 
    } 
} 

这不能正常工作。

在此先感谢。

+0

要排序的三个领域,但你的描述只谈到2. – woolstar

+0

虽然这是不可能在这里是一个问题,一般来说,你应该避免使用'返回(pp-> score - qq-> score);'因为如果值足够大而导致溢出,则它具有未定义的行为。 –

回答

1

这应该是你在找什么。

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 

现在来到最后一个条件。如果ppsimpson bart 25qqsimpson bart 30,那么pp->score - qq->score的值是多少? -5对不对?然后排序数组中的下将答案:

simpson bart 25 
simpson bart 30 

,而不是你想要的:

simpson bart 30 
simpson bart 25 
1

你想要更多的东西是这样的:

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; 
     } 
    } 
} 
+0

那么“pp-> score - qq-> score”部分呢?你认为它是正确的吗?根据他的要求,我认为它应该是“qq-> score - pp-> score”。 – taufique

+0

好点,我已经更新了上面的例子。 (我正在使用OP的代码而不是要求) – Baldrick

2

你只需要检查一次填写一个字段,并在一对字段不相等时立即返回。所以首先比较name.last并保留strcmp结果;如果它不是零,则返回它,否则继续下一个字段。然后,以相同的方式比较name.first ...如果strcmp结果不为零,则返回。最后,比较score

如果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); 
}