【问题标题】:C - Qsort: Sort name in ascending order and grade in descending orderC - Qsort:名称升序排序,等级降序排序
【发布时间】:2013-11-28 04:16:32
【问题描述】:

我正在尝试对我的记录进行 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);
    }
}

这不能正常工作。

提前致谢。

【问题讨论】:

  • 您正在对三个字段进行排序,但您的描述仅涉及 2。
  • 虽然这里不太可能出现问题,但通常您应该避免使用return (pp->score - qq->score);,因为如果值大到足以导致溢出,它的行为未定义。

标签: c sorting typedef strcmp qsort


【解决方案1】:

您只需要一次检查一个字段,并在一对字段不相等时立即返回。所以首先比较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);
}

【讨论】:

    【解决方案2】:

    这应该是你要找的。​​p>

    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-&gt;score - qq-&gt;score 的值是多少? -5 对吗?那么在排序后的数组中就是答案:

    simpson bart 25
    simpson bart 30
    

    而不是你想要的:

    simpson bart 30
    simpson bart 25
    

    【讨论】:

      【解决方案3】:

      你想要更像这样的东西:

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

      【讨论】:

      • “pp->score - qq->score”部分呢?你想对了吗?我觉得按照他的要求应该是“qq->score - pp->score”。
      • 好点,我已经更新了上面的例子。 (我使用的是 OP 代码中的内容,而不是要求)
      猜你喜欢
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 2012-11-08
      • 2023-03-07
      • 2012-12-21
      相关资源
      最近更新 更多