【问题标题】:How to access an element in the structure which not the first - Qsort如何访问结构中不是第一个的元素 - Qsort
【发布时间】:2020-11-18 23:24:16
【问题描述】:

我正在尝试对以下结构进行排序。我正在使用 qsort 根据最新发布的日期对书籍进行排序。我完全不明白为什么指针不能访问 date-published 元素。

#include <string.h>
#include <stdlib.h>
#include "problem5.h"

int int_cmp(const void *a, const void *b)
{
    //const int *ia = (const int *)a;
    //const int *ib = (const int *)b;
    //return *ia - *ib;
    return (*(int*)a - *(int*)b);
}


int main()
{
  struct book* books = NULL;     // no books at all initially so we initialize to NULL
                                 // so we can simply use realloc
  int numberofbooks = 0;
  int programend = 0;

  while (programend == 0)
  {
    printf("1. Add Book\n");
    printf("2. View Books\n");
    printf("3. Quit\n");
    int command;
    int i, j;
    scanf("%d", &command);

    if (command == 1)
    {
      getchar();   // consume Enter key (due su scanf)

      // allocate memory for one more book
      books = realloc(books, sizeof(struct book) * (numberofbooks + 1));

      printf("Enter Name\n");
      gets(books[numberofbooks].name);

      printf("Enter Author\n");
      gets(books[numberofbooks].author);

      printf("Enter Year Published\n");
      scanf("%d", &books[numberofbooks].year_published);

      numberofbooks++;   // increment number of books
      printf(books.year_published);
    }
    else if (command == 2)
    {

      qsort(books->year_published, numberofbooks, sizeof(int), int_cmp);
      for (i = 0; i < numberofbooks; i++)
      {
        printf("%d - %s by %s\n", books[i].year_published, books[i].name, books[i].author);
      }
    }
    else if (command == 3)
    {
      programend = 1;
    }
    //else if and the else will prevent infinite loop when the user enters invalid choice in the beginning.
    else if (command != 1 || command != 2 || command != 3)
    {
      printf("Invalid choice!\n");
    }
    else {return 0;}
  }
  free(books);

  return 0;
}

我认为问题在于 qsort() 中的指针,但我不知道如何纠正。我尝试使用 qsort(books, numberofbooks, sizeof(int), int_cmp);但这些书没有按预期订购。

【问题讨论】:

  • 提示:了解 switch 以及它如何简化您的 command 分支。
  • 提示:不要预先声明i 之类的东西,将其放在使用它的上下文中,例如for (int i = 0; ...)。这意味着定义近在咫尺,无需寻找它们来验证它们是否正确,也没有机会在其他地方使用它们。
  • 提示:如果您有一个 if 链,其中包含条件 A、B 和 C,那么根据定义,最后一个条件将是 !A &amp;&amp; !B &amp;&amp; !C。没有必要重复测试。只需使用else
  • 您想按整个记录列表排序。可能有多个键。假设它是year_published(例如)。你想要:qsort(books,numberofbooks,sizeof(struct book),cmp_record);int cmp_record(const void *a,const void *b) { const struct book *booka = a; const struct book *bookb = b; return booka-&gt;year_published - bookb-&gt;year_published; }
  • 从不使用gets

标签: c


【解决方案1】:

这里是一个多键排序的例子:

int
cmp_multikey(const void *a,const void *b)
{
    const struct book *booka = a;
    const struct book *bookb = b;
    int cmp;

    do {
        // sort by year published
        cmp = booka->year_published - bookb->year_published;
        if (cmp)
            break;

        // sort by author
        cmp = strcmp(booka->author,bookb->author);
        if (cmp)
            break;

        // sort by title
        cmp = strcmp(booka->name,bookb->name);
        if (cmp)
            break;
    } while (0);

    return cmp;
}

调用:

qsort(books,numberofbooks,sizeof(struct book),cmp_multikey);

其他一些技巧...

[正如其他人提到的]永远不要使用gets。使用switch/case 而不是if/else 阶梯。

尽量避免混淆scanffgets

就我个人而言,我更喜欢 [总是] 使用 fgets。这是gets 的[安全] 替换和scanf("%d",&amp;num); 的替换:

int
getstr(const char *prompt,char *buf,int buflen)
{
    char *cp;

    printf("%s",prompt);
    fflush(stdout);

    cp = fgets(buf,buflen,stdin);
    if (cp == NULL) {
        fprintf(stderr,"unexpected EOF\n");
        exit(1);
    }

    // find newline
    cp = strchr(buf,'\n');

    // ensure we had enough space
    if (cp == NULL) {
        fprintf(stderr,"response too large for buffer\n");
        exit(1);
    }

    // strip newline
    *cp = 0;
}

int
getnum(const char *prompt)
{
    char buf[1000];
    int num;

    getstr(prompt,buf,sizeof(buf));

    num = atoi(buf);

    return num;
}

【讨论】:

  • 我使用了您在评论中编写的 qsort() 代码,它对我来说效果很好。感谢 fgets() 和 switch/case 建议。它们比我的初始代码工作得更好。我也大致了解了 C 中的排序。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 2020-05-09
  • 1970-01-01
  • 2021-09-20
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多