I am testing for the very first time hash tables and I get such a weird error.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40
typedef struct snode {
char *nome;
struct snode *next;
} TNode;
typedef TNode *TList;
typedef struct tht {
TList *buckets;
int nbuckets;
} THT;
TList Create_List();
TNode *Create_Node(char *);
TList Insert_List(TList, char *);
THT *Create_THT(int n);
void HT_Print(THT *ht);
THT *Insert_THT(THT *ht, char *name, int key);
int hash(char *name);
void Print_List(TList list);
int main() {
THT *ht = Create_THT(5);
char name[MAX];
int key, contr;
printf("INSERISCI 0 PER USCIRE O INSERIRE NOME \n");
do {
printf("\n INSERIRE NOME : ");
scanf("%s", &name); //AFTER THE SECOND INSERTION FROM THIS LANE VALUES CHANGE INSIDE ht?? why
key = hash(name);
ht = Insert_THT(ht, name, key);
printf("\n Inserisci 1 per continuare 0 per terminare ");
scanf("%d", &contr);
} while (contr != 0);
HT_Print(ht);
return 0;
}
TList Create_List() {
return NULL;
}
TNode *Create_Node(char nome[MAX]) {
TNode *node;
node = malloc(sizeof(TNode));
node->nome = nome;
node->next = NULL;
return node;
}
TList Insert_List(TList list, char info[MAX]) {
TNode *tmp;
TNode *node;
node = Create_Node(info);
tmp = list;
if (list == NULL) {
list = node;
} else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = node;
}
return list;
}
THT *Create_THT(int n) {
int i;
THT *ht = malloc(sizeof(THT));
ht->buckets = malloc(n * sizeof(TList));
for (i = 0; i < n; i++) {
ht->buckets[i] = Create_List();
}
ht->nbuckets = n;
return ht;
}
void HT_Print(THT *ht) {
int i;
for (i = 0; i < ht->nbuckets; i++) {
Print_List(ht->buckets[i]);
}
}
int hash(char *name) {
return (name[0] - 'a');
}
THT *Insert_THT(THT *ht, char name[MAX], int key) {
ht->buckets[key] = Insert_List(ht->buckets[key], name);
return ht;
}
void Print_List(TList list) {
while (list != NULL) {
printf("%s", list->nome);
list = list->next;
}
}
I tested it with the debug. It's ok at the first insertion (for example I insert adam
) but then something weird happens.
The second time when I give as input the name like bob
for example (since it's like a vocabulary of names) and I check the value of ht->buckets
something changes inside.
I dont understand I didn't even get into the functions that modify effectively what's inside my hash table (ht
) and inside it changes . I am getting crazy and I tried to find a solution but I really dont understand how from a command in a main that doesn't have to deal with my HT's struct values change inside that struct...
Unrelated, but using English names and outputs makes it easier for everybody.
Just a guess, but inside Create_Node
, you allocate memory for the new node but don't allocate memory for the name (nome
).
You just copy the pointer to the passed array, which changes every time you insert a new name. Allocating memory for the name and copying the contents instead of the pointer should resolve this issue, e.g.
node->nome = strdup(nome);
Don't forget, that when you use the hash in a larger context, you must cleanup the hash and names eventually, which means freeing the memory for the nodes and names
free(node->nome);
free(node);
Create_Node
receives a pointer to the array name
in main
. This array is reused every time a new name is input. This means, all nodes point to the same array, and so all nodes print the same (last input) name.
Allocating individual memory for each node and copying the array to this memory (strdup
), solves the problem.