2016-07-22 23 views
-2

Hallo, also ich ein Programm erstellen, das einen Hash verwendet, um Wörter und ihre Anzahl von Vorkommen aus einer Textdatei zu speichern. Das funktioniert wie vorgesehen. Das Problem, das ich habe, kommt von der Freigabe des zugewiesenen Speichers.free() nicht String aus Array von Strukturen befreien

Hier ist meine Hash

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<ctype.h> 
#include"hash.h" 

/* 
struct listnode{ 
    char * word; 
    int count; 
}; 
*/ 

void hashCreate(struct listnode * hashTable[], int size){ 
    int i; 
    for(i=0;i<size;i++){ 
     hashTable[i]=(struct listnode *)malloc(sizeof(struct listnode)); 
     hashTable[i]->count=0; 
    } 
} 

int hash(char * data, int size) { 
    unsigned long hash = 5381; 
    char * p; 
    for (p = data; *p != '\0'; ++p) { 
    hash = (hash * 33) + *p; 
    } 
    return (int)(hash % size); 
} 

void hashAdd(char * data, struct listnode * hashTable[], int size){ 
    int key=hash(data, size); 
    hashTable[key]->word=strdup(data); 
    hashTable[key]->count+=1; 
} 

void hashPrint(struct listnode * hashTable[], int size){ 
    int i; 
    for(i=0;i<size;i++){ 
     if(hashTable[i]->count!=0) 
     printf("%s: %d \n",hashTable[i]->word,hashTable[i]->count); 
    } 
} 

void hashDelete(struct listnode * hashTable[],int size){ 
    int i; 
    for(i=0;i<size;i++){ 
     free(hashTable[i]->word); 
     free(hashTable[i]); 
    } 
} 

Dies ist, was es verwendet

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<ctype.h> 
#include"hash.h" 

/* 
int hash(char * data, int size) { 
    unsigned long hash = 5381; 
    char * p; 
    for (p = data; *p != '\0'; ++p) { 
    hash = (hash * 33) + *p; 
    } 
    return (int)(hash % size); 
} 
*/ 

#define SIZE 1500 


void removePunct(char * str); 
void fileRead(char * filename); 


struct listnode * hashTable[1500]; 

int main(int argc, char ** argv){ 
    int i; 
    if(argc<2) 
     fprintf(stderr,"Enter filename \n"); 

    hashCreate(hashTable, SIZE); 

    for(i=1; i<argc; i++){ 
     fileRead(argv[i]); 
    } 

    hashPrint(hashTable,SIZE); 
    hashDelete(hashTable, SIZE); 
    return 0; 
} 

void fileRead(char * filename){ 
    FILE * file = fopen(filename,"r"); 
    char word[80]; 
    if(!file){ 
     fprintf(stderr,"Error opening file \n"); 
     return; 
     } 
    while(fscanf(file, "%s", word)==1){ 
     removePunct(word); 
     hashAdd(word,hashTable,SIZE); 
    } 
    fclose(file); 
} 

void removePunct(char * str){ 
    int i,p=0; 
    for(i=0; i<strlen(str);i++){ 
     if(isalpha(str[i]) || str[i]==' '){ 
      str[p]=tolower(str[i]); 
      p++; 
     } 
    } 
    str[p]='\0'; 
} 

In meiner hashDelete Funktion werden die Saiten werden nicht befreit, die einen Speicherverlust verursacht. Ich habe es getestet, indem ich die Zeichenfolge in der Funktion hashAdd freigab und es gab keine Speicherlecks, aber es wurden auch keine Zeichenfolgen gedruckt. Ich bin nicht in der Lage, das Problem zu finden, das mich nicht all mein Gedächtnis freigeben lässt. Jede Hilfe wäre willkommen.

Antwort

5

In diesem Code

void hashAdd(char * data, struct listnode * hashTable[], int size){ 
    int key=hash(data, size); 
    hashTable[key]->word=strdup(data); 
    hashTable[key]->count+=1; 
} 

Sie strdup verwenden, um eine neue Zeichenfolge zu erhalten (malloc'ed von strdup). Wenn Sie das bereits einmal für eine gegebene key getan haben, werden Sie Speicher verlieren.

So benötigen Sie einen Scheck wie:

if (hashTable[key]->word == NULL) hashTable[key]->word=strdup(data); 

jedoch, dass es erforderlich, dass Sie word auf NULL initialisiert werden, wenn Sie die Tabelle erstellen.

Von Thema: Normalerweise müssen Sie jedoch identische key Werte mit etwas zusätzlichen Code behandeln. Der data Wert, der dazu führt, dass key möglicherweise identisch mit dem bereits gespeicherten word ist. Etwas, das du überprüfen solltest. Wenn sie identisch sind, können Sie count inkrementieren. Wenn sie sich unterscheiden, müssen Sie eine Methode zum Speichern von zwei verschiedenen Wörtern mit identischen key Werten haben.

Es könnte etwas wie folgt aussehen:

void hashAdd(char * data, struct listnode * hashTable[], int size){ 
    int key=hash(data, size); 
    if (hashTable[key]->word == NULL) { 
     // First time with this key 
     hashTable[key]->word=strdup(data); 
     hashTable[key]->count+=1; 
    } else { 
     // Key already used once 
     if (strcmp(data, hashTable[key]->word) == 0) { 
      // Same word 
      hashTable[key]->count+=1; 
     } else { 
      // Different word 
      // ... 
      // Add code for storing this word in another location 
      // ... 
     } 
    } 
} 
+0

Danke. Ich wusste, dass es etwas sehr einfaches sein musste, was ich nicht bemerkte. Das hat es behoben. –