【问题标题】:Sorting a list of students by name and grade using struct in C使用 C 中的结构按姓名和年级对学生列表进行排序
【发布时间】:2013-05-13 00:14:59
【问题描述】:

我正在编写一个按姓名和年级对学生列表进行排序的程序。我在尝试编译时收到以下错误:

ex11.c:在函数“compareByGrade”中: ex11.c:46:错误:在非结构或联合的情况下请求成员“等级” ex11.c:47:错误:在非结构或联合的情况下请求成员“等级” ex11.c:在函数“compareByName”中: ex11.c:56:错误:在不是结构或联合的东西中请求成员“名称” ex11.c:57:错误:在非结构或联合的情况下请求成员“名称”

这是头文件:

#define CLASS_SIZE 10

struct student {
    char *name;
    int  idnumber;
    char grade;
};

这是主文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ex11.h"

int main(void)
{
    int c, i;
    FILE *data;
    struct student tmp, class[CLASS_SIZE];
    void *nameArray[CLASS_SIZE], *gradeArray[CLASS_SIZE];
    static int compareByGrade(const void *first, const void *second);
    static int compareByName(const void *first, const void *second);

    data = fopen("data", "r");                         /* open data file */

/* Move data into struct */

    for (i = 0; i < CLASS_SIZE; ++i) {
            fscanf(data, "%s%d%c", tmp.name, tmp.idnumber, tmp.grade);
            class[i].name = tmp.name;
            class[i].idnumber = tmp.idnumber;
            class[i].grade = tmp.grade;
    }
    fclose(data);                                     /* close data file */
    qsort(nameArray, CLASS_SIZE, sizeof(*nameArray), &compareByName);
    qsort(gradeArray, CLASS_SIZE, sizeof(*gradeArray), &compareByGrade);
}

/* Function to sorty by grade */

static int compareByGrade(const void *first, const void *second)
{
    const char *firstGrade = (*(const char **) first) -> grade; /* line 46 */
    const char *secondGrade = (*(const char **) second) -> grade; /* line 47 */

    return strcmp(firstGrade, secondGrade);
}

/* Function to sort by name */

static int compareByName(const void *first, const void *second)
{
    const char *firstName = (*(const char **) first) -> name; /* line 56 */
    const char *secondName = (*(const char **) second) -> name; /* line 57 */

    return strcmp(firstName, secondName);
}

我做错了什么?

【问题讨论】:

  • nameArraygradeArray 不设置值。而不是struct student 所以没有成员(gradename
  • 请指出代码中出现错误的行。
  • name的保存区域没有保证。
  • 我会重新投票这个问题。这个问题是合法的,即使没有显示行号并且还有其他问题 - 但这是一个有效的问题是什么导致了编译错误。

标签: c sorting struct


【解决方案1】:

同意xaxxon。 程序处理struct student类,nameArray和gradeArray从不初始化。

顺便说一句,我想不要使用名为 class 的结构,它会与 C++ 的关键字混淆。

grade 是 char,但是 strcmp() 需要字符串来比较。

建议: 在 main() 中,

qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByName);
qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByGrade);

在外面,

int compareByGrade(const void *first, const void *second)
{
    const char firstGrade = ((struct student *)first) -> grade;
    const char secondGrade = ((struct student *)second) -> grade;
    return firstGrade<secondGrade?-1:(firstGrade==secondGrade?0:1);
}

/* Function to sort by name */

int compareByName(const void *first, const void *second)
{
    const char *firstName = ((struct student *)first) -> name;
    const char *secondName = ((struct student *)second) -> name;

    return strcmp(firstName, secondName);
}

compareByGrade() 的返回值表达式与 compareByName() 的作用相同

【讨论】:

    【解决方案2】:
    const char *firstGrade = (*(const char **) first) -> grade;
    const char *secondGrade = (*(const char **) second) -> grade;
    

    'first' 被强制转换为指向 char 的双指针,然后取消引用,所以你有一个 char *。然后,您使用 -> 取消对 char 的引用,而 char 不是结构或联合,也没有成员等级(因为它不能)。

    名称同样的问题。

    也就是说,我看不到你在哪里填充 nameArray 或gradeArray,所以即使你修复了编译错误,你也会遇到很多运行时错误。

    【讨论】:

      【解决方案3】:

      你做错了很多事情。其中包括:

      • 通常,您会打印出对数组进行排序的结果(或者对它们进行一些处理,如果只是为了让您验证数组是否已排序)。
      • 您通常会根据结构编写比较函数 - 例程将通过伪装成 const void *const struct student * 传递。
      • 您有一个包含指针的数据结构,但您没有为该指针分配空间来指向。
      • 您读入了未分配的空间。
      • 您没有测试 fopen()fscanf() 是否正常工作。
      • 您的扫描格式字符串不允许在 ID 号和等级之间使用空格。

      这是基于(松散地)您编写的工作代码。

      代码

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      #define CLASS_SIZE 10
      
      struct student
      {
          char name[20];
          int  idnumber;
          char grade;
      };
      
      static int compareByGrade(const void *first, const void *second);
      static int compareByName(const void *first, const void *second);
      static void print_students(const char *tag, const struct student *class, size_t size);
      
      int main(void)
      {
          FILE *data;
      
          if ((data = fopen("data", "r")) == 0)
          {
              fprintf(stderr, "failed to open file data\n");
              exit(1);
          }
      
          struct student class[CLASS_SIZE];
      
          for (int i = 0; i < CLASS_SIZE; ++i)
          {
              char name[20];
              int  idnumber;
              char grade;
              if (fscanf(data, "%19s %d %c", name, &idnumber, &grade) != 3)
              {
                  fprintf(stderr, "failed to read student %d\n", i);
                  exit(1);
              }
              strcpy(class[i].name, name);
              class[i].idnumber = idnumber;
              class[i].grade = grade;
          }
          fclose(data);
      
          qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByName);
          print_students("By name", class, CLASS_SIZE);
          qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByGrade);
          print_students("By grade", class, CLASS_SIZE);
          return 0;
      }
      
      static int compareByGrade(const void *p1, const void *p2)
      {
          const struct student *s1 = (const struct student *)p1;
          const struct student *s2 = (const struct student *)p2;
      
          if (s1->grade > s2->grade)
              return +1;
          else if (s1->grade < s2->grade)
              return -1;
          else
              return strcmp(s1->name, s2->name);
      }
      
      static int compareByName(const void *p1, const void *p2)
      {
          const struct student *s1 = (const struct student *)p1;
          const struct student *s2 = (const struct student *)p2;
      
          return strcmp(s1->name, s2->name);
      }
      
      static void print_students(const char *tag, const struct student *class, size_t size)
      {
          printf("%s (%zu students):\n", tag, size);
          for (size_t i = 0; i < size; i++)
              printf("%2zu: %-20s %4d %c\n", i, class[i].name, class[i].idnumber, class[i].grade);
      }
      

      注意compareByName() 函数如何首先确定年级排名,然后按名称进行比较。

      数据集

      student1 1234 A
      student2 2345 B
      junior03 3456 C
      junior04 4356 D
      sophomore12 5234 F
      sophomore13 6345 B
      senior19 3419 C
      senior99 4399 D
      fresher29 7456 C
      fresher31 8356 A
      

      输出

      By name (10 students):
       0: fresher29            7456 C
       1: fresher31            8356 A
       2: junior03             3456 C
       3: junior04             4356 D
       4: senior19             3419 C
       5: senior99             4399 D
       6: sophomore12          5234 F
       7: sophomore13          6345 B
       8: student1             1234 A
       9: student2             2345 B
      By grade (10 students):
       0: fresher31            8356 A
       1: student1             1234 A
       2: sophomore13          6345 B
       3: student2             2345 B
       4: fresher29            7456 C
       5: junior03             3456 C
       6: senior19             3419 C
       7: junior04             4356 D
       8: senior99             4399 D
       9: sophomore12          5234 F
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多