2013-02-23 5 views
0

J'ai une affectation où je veux implémenter un tableau croissant dynamiquement, mais je semble avoir quelques problèmes avec realloc(). Mon code fonctionne tant que je ne parviens pas à la partie realloc(), où, pour une raison quelconque, seules certaines valeurs spécifiques sont changées pour quelque chose de différent. Maintenant, je m'attendrais à ce que les lignes soient complètement différentes si j'écrivais/lisais hors des limites, mais je n'arrive pas à le localiser. Le problème semble se situer entre les lignes 30-40. Voici le code:Comportement non intentionnel après realloc() avec le tableau dynamique

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 } 

Voici le fichier d'entrée J'utilise:

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 

Le résultat attendu est la suivante (que je faire obtenir aussi longtemps que N est élevé, à savoir. plus que le nombre réel de lignes et ne provoque pas realloc() à invoquer):

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 

Cependant, si je mets N = 3, je reçois le texte suivant:

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 

Je suis tout à fait à une perte de ce qui se passe. J'ai essayé d'examiner la pile et les valeurs locales en utilisant gdb, mais je n'ai pas encore eu beaucoup de chance. Je suis également en conflit quant à la raison pour laquelle la carte d'identité est la seule chose à être corrompue. Serait-il nécessaire de faire une fonction séparée qui retournerait un pointeur vers le nouvel espace que j'obtiendrais par realloc()? Je voulais garder mon code aussi compact que possible, donc j'ai opté pour l'essayer de cette façon d'abord comme la page de manuel semblait sauvegarder mon hypothèse sur la façon dont fonctionne realloc(). Je vous remercie.

+4

Ce n'est pas votre problème principal, mais 'S = realloc (S, sizeof (étudiant) * N);' devrait être 'S = realloc (S, sizeof (étudiant *) * N);'. La mémoire que vous attribuez contient des pointeurs aux étudiants, pas aux étudiants. –

+0

'feof' ne fonctionne pas comme vous le pensez ... –

+0

Pour amplifier ce que dit Carl Norum, vous ne pouvez pas utiliser' feof' pour prédire si une future lecture réussira. Vous devriez vérifier la valeur de retour de 'fscanf'. Cependant, encore une fois, ce n'est probablement pas votre problème principal. –

Répondre

1
 unsigned long ID; 

D'accord, ID est un unsigned long.

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

Hmm, est %d le spécificateur de format pour un unsigned long? Je ne pense pas.

En outre, feof ne prévoit pas qu'une future lecture réussira, elle vous indique seulement ce qui s'est déjà passé. Vous devez vérifier la valeur de retour de fscanf pour voir si la lecture a réussi.

Enfin, votre appel realloc alloue trop de mémoire. Vous essayez seulement de contenir des pointeurs dans S lui-même.

+0

Merci pour votre réponse, et le commentaire ci-dessus. Je vais juste marquer cela comme la réponse depuis que vous l'avez fourni. Sur le point: J'ai plusieurs de ces fichiers avec des fonctions différentes, et j'ai en fait utilisé% lu pour ces fichiers. Je ne sais pas pourquoi celle-ci n'est pas mise à jour, mais merci pour la prise! – user991710