0

動的に成長する配列を実装したいという割り当てがありますが、realloc()でいくつかの問題が発生しているようです。私のコードは、実際にrealloc()の部分に到達しない限り機能します。この部分では、何らかの理由で、特定の値のみが別の値に変更されています。さて、範囲外で書き込み/読み取りを行っている場合、行は完全に異なると予想されますが、それを正確に特定することはできないようです。問題は30〜40行目にあるようです。コードは次のとおりです。

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 typedef struct __student {
6         unsigned long ID;
7         char fname[33];
8         char lname[33];
9         float grade;
10 } student;
11
12 void partA(FILE *fp) {
13
14         int i, r;
15         i = r = 0;
16         int N = 1000;
17         student **S;
18
19         S = malloc(sizeof(student *) * N);
20
21         // While EOF has not been reached
22         while(!feof(fp)){
23                 // Allocate enough memory to hold each student struct
24                 S[i] = malloc(sizeof(student));
25                 // Get each line and, using a scanset, get corresponding
26                 // data into respective struct fields
27                 fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i]->lname, S[i]->fname,  &S[i]->grade );
28                 i++; // Get next line into a new struct
29
30                 // If array size has been reached...
31                 if(i == N){
32                         N *= 2;
33                         // Double it
34                         S = realloc(S, sizeof(student) * N);
35                         if(S == NULL) {
36                                 // realloc has failed
37                                 printf("Memory reallocation failed; Fatal error.");
38                                 break;
39                         }
40                 }
41         }
42         r = i-1;
43         // Output data
44         printf("Name\t\t\t\t\t\t\t\t  [ID]\t\t:\tGrade\n");
45            printf("___________________________________________________________________________________________________\n");
46         for(i=0; i<r; i++){
47                 printf("%-32s %-32s [%lu]\t:\t%.3f\n", S[i]->fname, S[i]->lname, S[i]->ID, S[i]->grade);
48                 free(S[i]);
49         }
50 }

これが私が使用している入力ファイルです:

58205720 Broke, Jim 95
29571057 Crowe, John 88
12957206 Moore, Kim 22
59376027 Sarasvaki, Joe 79
49027650 Morrigan, Tracy 68
30773967 Trund, Geoffrey 99
34850470 Perry, Tracey 77
70209658 Oatnel, Skye 89

期待される出力は次のとおりです(Nが高い限り、つまり実際の行数よりも多く、realloc()が呼び出されない限り取得します)

Name                                                              [ID]          :       Grade
___________________________________________________________________________________________________
Jim                              Broke                            [58205720]    :       95.000
John                             Crowe                            [29571057]    :       88.000
Kim                              Moore                            [12957206]    :       22.000
Joe                              Sarasvaki                        [59376027]    :       79.000
Tracy                            Morrigan                         [49027650]    :       68.000
Geoffrey                         Trund                            [30773967]    :       99.000
Tracey                           Perry                            [34850470]    :       77.000
Skye                             Oatnel                           [70209658]    :       89.000

ただし、N = 3に設定すると、次のようになります。

Name                                                              [ID]          :       Grade
___________________________________________________________________________________________________
Jim                              Broke                            [58205720]    :       95.000
John                             Crowe                            [29571057]    :       88.000
Kim                              Moore                            [12957206]    :       22.000
Joe                              Sarasvaki                        [59376027]    :       79.000
Tracy                            Morrigan                         [49027650]    :       68.000
Geoffrey                         Trund                            [30773967]    :       99.000
Tracey                           Perry                            [231963084454]        :       77.000
Skye                             Oatnel                           [231998443642]        :       89.000

私は何が起こっているのかについてかなり途方に暮れています。gdbを使用してスタックとローカルの値を調べてみましたが、まだあまりうまくいきませんでした。また、IDが破損する唯一のものである理由についても矛盾しています。realloc()によって取得した新しいスペースへのポインターを返す別の関数を作成する必要がありますか?コードをできるだけコンパクトに保ちたいと思ったので、manページがrealloc()の動作方法に関する私の仮定を裏付けているように見えたので、最初にこの方法で試すことにしました。ありがとうございました。

4

1 に答える 1

1
     unsigned long ID;

さて、IDですunsigned long

     fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i ...

うーん、%dフォーマット指定子はunsigned long?私はそうは思わない。

また、feof将来の読み取りが成功することを予測するのではなく、すでに何が起こったかを通知するだけです。fscanfの戻り値をチェックして、読み取りが成功したかどうかを確認する必要があります。

最後に、realloc呼び出しで割り当てられるメモリが多すぎます。あなたはSそれ自体でポインタを保持しようとしているだけです。

于 2013-02-23T18:12:09.300 に答える