我试图让程序读取一个文本文件,其中包含“1001姓名姓氏102030”、学生人数、姓名、姓氏和他的3个年级的信息。这是我的代码:

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

 struct Student {
     int number;
     char name[30];
     char surname[30];
     int midterm1,midterm2,midterm3;
 } Student;

 int comp(const void * aa, const void * bb)
 {
    struct Student a = *(struct Student*)aa;
    struct Student b = *(struct Student*)bb;
    if (a.midterm1==b.midterm1)
            return 0;
    else if (a.midterm1 < b.midterm1)
            return -1;
    else
            return 1;
  } // comp


  int main(void)
  {
      int choice,studentnumber,midterm1,midterm2,midterm3,i,n;
      char surname;
      FILE *cfPtr;

      struct student *name;
      name = malloc( 10 * sizeof(Student));

      if ((cfPtr = fopen("grades.txt", "r")) == NULL)
          return 1;

      const int STUDENTSMAX = 100;
      struct Student students[STUDENTSMAX];
      char buff[1024];
      while(1)
      {
          memset(buff, 0, sizeof(buff));
          fgets(buff, sizeof(buff) -1, cfPtr);
          if (feof(cfPtr)) {
              break;
          }
          sscanf(buff, "%d %s %s %d %d %d", &students[i].number, students[i].name, students[i].surname, &students[i].midterm1, &students[i].midterm2, &students[i].midterm3);
          printf("%4d %15s %15s %10d %10d %10d\n", students[i].number, students[i].name, students[i].surname, students[i].midterm1, students[i].midterm2, students[i].midterm3);
          i++;
      } // while

      while (!feof(cfPtr))
      {
          fscanf(cfPtr, "%d%s%s%d%d%d", &students[i].number, &students[i].name,&students[i].surname, &students[i].midterm1, &students[i].midterm2, &students[i].midterm3);
          printf("%4d%15s%15s%10d%10d%10d\n", students[i].number, students[i].name,students[i].surname, students[i].midterm1, students[i].midterm2, students[i].midterm3);
           i++;
      } // while

      printf("What would you like to do? \n"
      "1- Sort according to midterm 1\n"
      "2- Sort according to midterm 2\n"
      "3- Sort according to midterm 3\n"
      "4- Exit\n");
      scanf("%d",&choice);

      scanf("%d",&choice);
      switch (choice) {
          case 1:
              qsort(students, i, sizeof(struct Student), comp);
              for (n = 0;  n < i; n++) {
                  printf("%4d %15s %15s %10d %10d %10d\n", students[n].number, students[n].name, students[n].surname, students[n].midterm1);
              } // for
              break;
          case 2:
              qsort(students, i, sizeof(struct Student), comp);
              for (n = 0;  n < i; n++) {
                  printf("%4d %15s %15s %10d %10d %10d\n", students[n].number, students[n].name, students[n].surname, students[n].midterm2);
              } // for
              break;
          case 3:
              qsort(students, i, sizeof(struct Student), comp);
              for (n = 0;  n < i; n++) {
                  printf("%4d %15s %15s %10d %10d %10d\n", students[n].number, students[n].name, students[n].surname, students[n].midterm3);
              } // for
              break;
      } // switch
  } // main?
  fclose(cfPtr);


  system("PAUSE");
  return 0;
  } // the editor failed to find the corresponding '{' !OP should fix this

当前代码返回我时出现以下错误:
95 C:\Users\UseR\Desktop\main.c [Warning] parameter names (without types) in function declaration
95 C:\Users\UseR\Desktop\main.c [Warning] data definition has no type or storage class
98 C:\Users\UseR\Desktop\main.c syntax error before string constant
98 C:\Users\UseR\Desktop\main.c [Warning] data definition has no type or storage class
 C:\Users\UseR\Desktop\Makefile.win [Build Error]  [main.o] Error 1

程序正在编译和工作,没有任何问题,但它仍然会给出错误,而且根本不会排序。我在这里做错什么了?
编辑:这是我的输入文件;
100201 al beaver 40 50 70
100202 andrew matthews 30 90 75
100203 leah doga 60 55 80
100204 rob kurt 45 80 60
100205 aliah devon 65 70 50
100206 sally pir 70 40 85
100207 eric bekta 75 65 55
100208 nile coul 55 75 65
100209 mina umur 72 60 90
100210 john hot 73 63 87

是的,在别人问之前这是一个家庭作业,我已经没时间了,我已经试了好几天没有任何实质性进展。我被问到的主要问题是
按降序排列所选考试的成绩,输出文件将只包含三列:所选考试的姓名、姓氏和分数。
定义一个名为“student”的结构,将每个学生的姓名、姓氏和分数存储在同一变量名下。所以文件中的所有数据都将存储在一个名为“student”的新数据类型数组中

最佳答案

你在这段代码中有很多问题,我将一节一节地介绍我修改的内容。因为这是家庭作业,所以我不打算发布完全修改的程序,但是只要有足够的信息你(或者将来有人发现这个)就可以让你的代码工作。
首先,您不需要类型定义的结构。只需声明一个结构:
更改此:

 typedef struct {
 int number;
 char name[30];
 char surname[30];
 int midterm1,midterm2,midterm3;
 } Student;

对此:
struct Student {
        int number;
        char name[30];
        char surname[30];
        int midterm1,midterm2,midterm3;
};

第二个问题是比较函数的原型不正确qsort()要求回调只接受两个const void*类型的参数,因此将其更改为如下所示:
int comp(const void * aa, const void * bb)

这将消除你看到的警告,但它实际上只是一个警告。您没有用正确的参数调用qsort()我们稍后再谈,我在运行你的程序时发现了其他问题。
第三个问题是没有处理无法打开的文件,这会导致分段错误(教师通常对分段错误给出糟糕的分数),因此,不要这样做:
 if ((cfPtr = fopen("grades.txt", "r")) == NULL)
    printf("File cannot be opened.\n");
 else {

只是退出,你不能运行,没有点在缩进的逻辑永远不会达到。例如。:
 if ((cfPtr = fopen("grades.txt", "r")) == NULL) {
      printf("File cannot be opened.\n");
      return 1;
 }

第四个问题是,您从文件中读取的是假的输入,而不是为此进行测试。我更喜欢使用缓冲区和sscanf()而不是fscanf(),但这只是首选。不管怎样,我就是这么做的:
    const int STUDENTSMAX = 100;
    struct Student students[STUDENTSMAX];
    char buff[1024];
    while (1)
    {
            memset(buff, 0, sizeof(buff));
            fgets(buff, sizeof(buff) -1, cfPtr);
            if (feof(cfPtr)) {
                    break;
            }
            sscanf(buff, "%d %s %s %d %d %d", &students[i].number, students[i].name, students[i].surname, &students[i].midterm1, &students[i].midterm2, &students[i].midterm3);
             printf("%4d %15s %15s %10d %10d %10d\n", students[i].number, students[i].name, students[i].surname, students[i].midterm1, students[i].midterm2, students[i].midterm3);
            i++;
    }

注意,如果走那个路线并在每次迭代时使用#include <string.h>重置缓冲区,则必须添加memset()。注意,我不会取消对结构中声明的char[]数组的引用(在解释给定的模式时,请参阅&name中没有surname)。
那么,这个代码:
scanf("%d",&choice);

 while (choice != 4) {


  switch (choice) {

       case 1:
            qsort(students,10,sizeof(int),comp);
        printf("%4d%15s%15s%10d%10d%10d\n", students[i].number, students[i].name,students[i].surname, students[i].midterm1);

   }
   }
   }

... 正在进入一个无限循环一旦他们选择了1,结构将被整理和打印永远如此之快,因为没有选择处理任何其他选项退出,它飞得如此之快,用户不能进入它无论如何。我把它改成了这个,这更合理一点:
    scanf("%d",&choice);
    switch (choice) {
            case 1:
            qsort(students, i, sizeof(struct Student), comp);
            for (n = 0;  n < i; n++) {
                     printf("%4d %15s %15s %10d %10d %10d\n", students[n].number, students[n].name, students[n].surname, students[n].midterm1, students[n].midterm2, students[n].midterm3);
            }
            break;
    }

注意break您以前没有在需要同时执行这两项操作的地方脱离switch()while()。在我修改的代码中,while()周围没有switch()
现在,对qsort()的修改调用应该显示输入未排序的原因你有这个:
qsort(students,10,sizeof(int),comp);

第二个参数可以是i,因为i知道您有多少元素。第三个参数需要是您正在排序的成员的大小,而不是整数的大小(不太确定您是如何沿着这条路径漫游的)。这就是排序结构被截断的原因。
从手册页:
   void qsort(void *base, size_t nmemb, size_t size,
              int(*compar)(const void *, const void *));

说明
函数的作用是:用大小为nmemb的元素对数组进行排序。基参数>指向数组的开头。
如你所见,它想要(按这个顺序):
你在分类什么?
它有多少会员?
每个会员的人数是多少?
我应该用什么回调函数来做决定?
由于要在回调中往返于void *Student,因此需要修改它:
int comp(const void * aa, const void * bb)
{
        struct Student a = *(struct Student*)aa;
        struct Student b = *(struct Student*)bb;
        if (a.midterm1 == b.midterm1)
                return 0;
        else if (a.midterm1 < b.midterm1)
                return -1;
        else
                return 1;
}

请参见this answer以了解有关此的详细信息。
最后一点,main应该是int main(void),因为您不需要参数。
您还需要做一些其他修改,或者您可以根据我提供的反馈快速修复您的问题。我去掉了所有未使用的值、您分配的结构(不确定它的用途)并真正清理了它。如果你想得到好成绩,我建议你也这样做。
还有很多我没有完全解释清楚,因为这个答案已经够长了,我不想让你的研究短路。

关于c - 如何使用结构正确将文件内容传递给qsort?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11914284/

10-11 22:13
查看更多