1

「1001 name surname 10 20 30」、生徒数、名前、姓、および 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

PS はい、これは誰もが尋ねる前の宿題です。私は時間がなくなってきており、何日もしっかりと進歩していないのに本当に努力しています。主に聞かれたのは」

  1. 選択した試験の成績を降順で並べ替えます。出力ファイルには、選択した試験の名前、姓、およびスコアの 3 つの列のみが含まれます。
  2. 「student」という名前の構造体を定義して、各学生の名前、姓、およびスコアを同じ変数名で格納します。したがって、ファイル内のすべてのデータは、「学生」という名前の新しいデータ型の配列に格納されます。」
4

2 に答える 2

5

このコードには多くの問題があります。セクションごとに変更した内容について説明します。これは宿題なので、完全に変更されたプログラムを投稿するつもりはありませんが、あなた (または将来これを見つけた人) がコードを機能させるために使用できる情報だけを掲載します。

まず、型定義の構造は必要ありません。構造体を宣言するだけです:

これを変える:

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

2 つ目の問題は、比較関数のプロトタイプが正しくないことです。qsort()は、コールバックが type の正確に 2 つの引数を取ることを想定しているため、次のconst void*ように変更します。

int comp(const void * aa, const void * bb)

これにより、表示される警告は取り除かれますが、実際には単なる警告でした。qsort()正しい引数で呼び出していません。それについては後で説明しますが、プログラムの実行中に他の問題が見つかりました。

3 番目の問題は、ファイルを開けないことです。その結果、セグメンテーション違反が発生します (教師は通常、セグメンテーション違反に対して悪い評価を与えます)。その代わりに、次のようにします。

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

4 番目の問題は、ファイルから偽の入力を読み取っていて、それをテストしていないことです。sscanf()ではなくバッファ and を使用することを好みます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[]&namesurname

次に、このコード:

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、2 番目の引数は だけでかまいません。i3 番目の引数は、整数のサイズではなく、並べ替えるメンバーのサイズである必要があります (そのパスをどのようにさまよったかはよくわかりません)。これが、ソートされた構造が切り捨てられていた理由です。

マニュアルページから:

   void qsort(void *base, size_t nmemb, size_t size,
              int(*compar)(const void *, const void *));

説明 qsort() 関数は、サイズ size の nmemb 要素で配列をソートします。base 引数 > は、配列の先頭を指します。

ご覧のとおり、次のものが必要です (この順序で):

  • 何を並べていますか?
  • メンバーは何人ですか?
  • 各メンバーのサイズは?
  • 決定を下すためにどのコールバック関数を使用すればよいですか?

コールバックに出入りするので、それを変更する必要が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;
}

詳細については、この回答を参照してください。

引数を期待していないので、最終的な nit は でmainある必要があります。int main(void)

他にも必要な変更がいくつかあります。または、私が提供したフィードバックに基づいて、既存のものをすぐに修正することもできます。未使用の値、割り当てた構造体 (何のためにあるのか不明) をすべて取り除き、実際にクリーンアップしました。良い成績を取りたい場合は、同じことをすることをお勧めします。

この答えはすでに十分に長く、あなたの側でこれ以上の研究を短絡させたくないので、私が完全に説明しなかったこともたくさんあります.

于 2012-08-11T15:01:55.240 に答える
0

比較関数は、student への 2 つのポインターを取る必要があります。次のようになります。

 int comp(const Student * a, const Student * B)
 {
 if (a->midterm1==b->midterm1)
 return 0;
 else
 if (a->midterm1 < B->midterm1)
        return -1;
 else
  return 1;
 }

また、qsort呼び出しは次のようにする必要があります

qsort(students, 10, sizeof(Student), comp);

最後に、qsort に 10 を渡す理由は、ファイルから読み取った実際の生徒数でなければなりません。

于 2012-08-11T11:56:36.200 に答える