Bonjour,
dans le cadre de plusieurs projets, afin de faciliter l'implémentation de certaines données on a eu l'idée d'utiliser une structure de données de type HashTable. Vu que la bibliothèque standard du langage C ne propose rien de tel, j'ai commencé à coder une HashTable générique. Ce qui a été commencé est fourni en pièces jointes :
Code main.c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #include <stdio.h> #include <stdlib.h> #include "HashTable.h" struct personne { char* nom; char* prenom; }; int main() { HashTable dico = NULL; int nb = 47; long nb2 = 5432424; double reel = 4.5789; struct personne chuck; chuck.nom = "Norris"; chuck.prenom = "Chuck"; dico = new_HashTable("Test1", "Ceci est une chaine", sizeof("Ceci est une chaine")); addEntry(dico, "Entier", &nb, sizeof(int)); addEntry(dico, "Reel", &reel, sizeof(double)); addEntry(dico, "Entier long", &nb2, sizeof(long)); addEntry(dico, "Structure", &chuck, sizeof(struct personne)); printf("Clef : %s - Valeur : %s\n", dico->key, (char*)dico->value); dico = dico->next; printf("Clef : %s - Valeur : %d\n", dico->key, *(int*)dico->value); dico = dico->next; printf("Clef : %s - Valeur : %f\n", dico->key, *(double*)dico->value); dico = dico->next; printf("Clef : %s - Valeur : %ld\n", dico->key, *(long*)dico->value); dico = dico->next; printf("Clef : %s - Valeur : %s %s\n", dico->key, ((struct personne*)dico->value)->prenom, ((struct personne*)dico->value)->nom); return 0; }
Code HastTable.h : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #ifndef HASHTABLE_H_INCLUDED #define HASHTABLE_H_INCLUDED struct keyvalue { char* key; void* value; size_t size; struct keyvalue* next; }; typedef struct keyvalue* HashTable; HashTable new_HashTable(char* key, void* value, size_t size); int addEntry(HashTable hashtable, char* key, void* value, size_t size); #endif // HASHTABLE_H_INCLUDED
Code HashTable.c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 #include <stdio.h> #include <stdlib.h> #include <string.h> #include "HashTable.h" /* Constructeur d'une HashTable But : Permet d'instancier un dictionnaire Paramètres : clef [char*], associé [void*], taille de l'associé [size_t] (Généralement sizeof(associe)) Retour : Dictionnaire nouvellement créé */ HashTable new_HashTable(char* key, void* value, size_t size){ // Vérifier la conformité des paramètres formels if (key == NULL || value == NULL || size <= 0) return NULL; // Allouer dynamiquement et créer des copies de la clef // et de l'associé char* newKey = (char*)malloc(sizeof(key)); void* newValue = malloc(size); if (newKey == NULL || newValue == NULL) return NULL; strcpy(newKey, key); memcpy(newValue, value, size); // Créer un nouveau dictionnaire HashTable newHashTable = (HashTable)malloc(sizeof(struct keyvalue)); if (newHashTable == NULL) return NULL; newHashTable->key = newKey; newHashTable->value = newValue; newHashTable->size = size; newHashTable->next = NULL; return newHashTable; } /* Fonction addEntry But : Ajouter une nouvelle entrée au dictionnaire passé en paramètre Paramètres : dictionnaire [HashTable], clef [char*], associé [void*], taille de l'associé [size_t] (Généralement sizeof(associe)) Retour : 1 si tout s'est bien déroulé, 0 sinon */ int addEntry(HashTable hashtable, char* key, void* value, size_t size){ // Vérifier la conformité des paramètres formels if (hashtable == NULL || key == NULL || value == NULL || size <= 0) return 0; // Créer une copie du dictionnaire et accéder au dernier // élément du dictionnaire HashTable copy = hashtable; while (copy->next != NULL) copy = copy->next; // Allouer dynamiquement et créer des copies de la clef // et de l'associé char* newKey = (char*)malloc(sizeof(key)); void* newValue = malloc(size); if (newKey == NULL || newValue == NULL) return 0; strcpy(newKey, key); memcpy(newValue, value, size); // Créer une nouvelle entrée dans le dictionnaire struct keyvalue* newKeyvalue = (struct keyvalue*)malloc(sizeof(struct keyvalue)); if (newKeyvalue == NULL) return 0; newKeyvalue->key = newKey; newKeyvalue->value = newValue; newKeyvalue->size = size; newKeyvalue->next = NULL; // Ajouter l'entrée au dictionnaire copy->next = newKeyvalue; return 1; }
Je compile donc le code en "Debug" sous CodeBlocks sous Ubuntu 8.10 (Compilateur gcc), tout se passe bien :
pourtant quand je compile en "Release", j'ai plein d'erreurs qui s'affichent à l'exécution (en l'occurrence un buffer overflow) :Clef : Test1 - Valeur : Ceci est une chaine
Clef : Entier - Valeur : 47
Clef : Reel - Valeur : 4.578900
Clef : Entier long - Valeur : 5432424
Clef : Structure - Valeur : Chuck Norris
J'essaie aussi de compiler "à la main" avec gcc, pas d'erreur apparente :
Quelqu'un saurait d'où pourrait venir ce "bug" svp? Merci d'avance.erosquare@mvk-desktop:~/Documents/HashTable$ gcc *.c -I . -o test
erosquare@mvk-desktop:~/Documents/HashTable$ ./test
Clef : Test1 - Valeur : Ceci est une chaine
Clef : Entier - Valeur : 47
Clef : Reel - Valeur : 4.578900
Clef : Entier long - Valeur : 5432424
Clef : Structure - Valeur : Chuck Norris
erosquare@mvk-desktop:~/Documents/HashTable$
Partager