2017-10-16 12 views
1

Actuellement, j'ai le code suivant ci-dessous. char **arr est initialement défini sur NULL. alors il stocke dans les mots tout en lisant d'un dossier. Je ai juste choisi au hasard un grand nombre comme 5000 parce que je ne comprends pas comment faire malloc affaires correctement, même après avoir regardé en ligne et en essayant d'apprendre.Comment correctement malloc et gratuit char ** lors de la lecture à partir du fichier (longueur inconnue)?

Aussi, lorsque je tente de freechar **arr (la dernière partie de mon code), parfois je me segmentation faults, parfois abort traps, etc. Si quelqu'un pouvait me montrer comment faire quelque chose comme ça bien qui serait très apprécié! Merci!

char **arr = NULL 

File *fp = fopen("file.txt", "r") 
char string[3000]; 
char counter = 0; 


//to store 
while(fscanf(fp, "%s", string)!=EOF){ 
    arr = realloc(arr, 5000); //arbitrarily used a large number like 5000 
    arr[counter] = malloc(5000); 
    strcpy(arr[counter++], string); 
} 

//to free 

for(i=0; i<counter; i++){ 
    free(arr[i]) 
} 
free(arr); 
+1

Copie possible de [Comment puis-je obtenir la taille d'un fichier en C?] (Https://stackoverflow.com/questions/238603/how-can-i-get-a-files-size-in-c) –

+0

Compilez avec toutes les informations d'avertissement et de débogage: 'gcc -Wall -Wextra -g' avec [GCC] (http://gcc.gnu.org/), puis ** utilisez le débogueur **' gdb' et [valgrind] (http://valgrind.org/). Lisez aussi la documentation de [malloc] (http://man7.org/linux/man-pages/man3/malloc.3.html) et des informations connexes –

+0

Veuillez fournir quelques explications à [MCVE]. Votre question fix-my-code est hors sujet –

Répondre

4

N'utilisez pas de nombres arbitraires.

L'argument size passé à realloc est le nouveau nombre d'octets à allouer. Dans votre cas, il peut s'agir de (counter + 1) * sizeof(char *) octets. Si le fichier contient plus d'un millier de mots, 5000 ne suffira pas. Pour ne pas mentionner vous appelez realloc pour ne pas modifier la taille après le premier appel.

Et n'utilisez pas non plus de valeurs arbitraires pour l'appel malloc. Utilisez soit strlen(string) + 1, soit, si disponible, vous pouvez utiliser strdup à la place.


Enfin, ne pas revenir à réattribuer la variable que vous passez comme pointeur vers realloc. Si realloc échoue et renvoie NULL, vous aurez perdu votre pointeur d'origine.

utiliser à la place une variable temporaire que vous vérifiez avant d'attribuer backt o la variable pointeur d'origine:

char **temp = realloc(arr, ...); 
if (temp == NULL) 
{ 
    // ERRORO: Do something appropriate 
} 

arr = temp; 
+1

Je recommanderais plutôt quelque chose comme une progression 'newsize = 4 * oldsize/3 + 10;', et un 'realloc' avec' newsize'. Bien sûr, la taille allouée actuelle doit être explicitement conservée. –

+0

@Someprogrammerdude que signifie exactement le dernier? Ne pas réaffecter à la variable ... etc – novice

+0

@novice Mise à jour avec un exemple –

1

Vérifiez la manual de getline(), cette fonction alloue la ligne pour vous si le * est NULL. Utilisez cette fonction pourrait être une bonne façon de le faire au lieu d'utiliser strlen et fscanf.