dictionnaire.c
6.49 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/**
* dictionnaire.c
*
* Implémente l'importation et la libération d'un dictionnaire en mémoire
* depuis un fichier texte.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* ctype.h pour les fonctions isalpha, tolower, isdigit et isspace */
#include <ctype.h>
#include <string.h>
#include "dictionnaire.h"
/* Variables globales */
// Declaration du Noeud racine
Noeud *racine;
// Déclaration de reserve_noeud : permet d'allouer la taile du dictionnaire en une fois, simplifie la gestion
// mémoire.
Noeud *reserve_noeuds;
// Déclaration du compteur de nombre de mots dans le dictionnaire.
// Est utilise par la fonction taille_dic().
unsigned int nbr_mots;
// Variable global permettant de construire une reserve de noeuds.
// Type "long" pour ne pas être limité.
long taille_fic;
/**
* Teste si un mot appartient au dictionnaire.
* Retourne True si le mot est dans le dictionaire ou False sinon
*/
bool appartient(const char *mot) // Const pour que mot soit en lecture seule, il n'y a pas besoin de le modifier
{
// Déclaration du pointeur parcourant le trie et initialisation a NULL
Noeud *nd_parcours_tmp = NULL;
// Fais pointer nd_parcours_tmp sur la racine
// Pour chaque nouveau nd_parcours_tmp pointe sur la racine pour verifier le mot
nd_parcours_tmp = racine;
// Variable pour iterer char par char dans un mot
int i = 0;
// Vérifie que le le mot entré correspond à un parcours de l'arbre se terminant par mot_fini = True
while (mot[i] != '\0') {
// On convertit le mot en minuscule pour se préoccuper uniquement de l'orthographe
char c;
if (isalpha(mot[i])) {
c = tolower(mot[i]);
} else {
c = mot[i];
}
// Gestion de l'apostrophe
if (c == '\'') {
// On regarde s'il existe un mot comprenant l'apostrophe, sinon le mot n'appartient pas au dico
if (nd_parcours_tmp->enfants[NB_CARAC - 1] == NULL) {
return false;
}
// Sinon on continue le parcours en allant au noeud suivant
nd_parcours_tmp = nd_parcours_tmp->enfants[NB_CARAC - 1];
}
// Gestion des lettres
else if (isalpha(c)) {
// Verifie que le parcours correspondant au lettres du mot existe jusqu'ici.
// Retourne False si ce n'est pas le cas.
if (nd_parcours_tmp->enfants[c - 'a'] == NULL) {
return false;
}
// Sinon on passe à la lettre suivante dans le dico
nd_parcours_tmp = nd_parcours_tmp->enfants[c - 'a'];
}
// On avance dans le mot à vérifier
i++;
}
// Retourne True si le mot existe dans le dictionnaire
return nd_parcours_tmp->mot_fini;
}
/**
* Importe le dictionnaire en mémoire.
* Retourne True en cas de succes et False sinon.
*/
bool importer_dict(const char *nom_dic)
{
// Ouvre le fichier du dictionnaire
// 'b' permet d'avoir un stream de byte et non l'interpretation des caractères d'indentation en fonction du système.
// Cela garantie que fseek determine correctement la taille du fichier.
FILE *dict = fopen(nom_dic, "rb");
// Erreur sur le fichier?
if (dict == false) {
printf("Impossible d'ouvrir le fichier (dictionnaire.c)");
return false;
}
// Determination de la taille_dic du fichier (en bytes)
fseek(dict, 0, SEEK_END);
taille_fic = ftell(dict);
// Remise du pointeur de fichier au debut
fseek(dict, 0, SEEK_SET);
// Initalise reserve_noeuds avec suffisament de mémoire pour différents dictionnaires
reserve_noeuds = calloc(taille_fic, sizeof(Noeud));
// Premier Noeud du dictionnaire
Noeud *prochain_noeud_vide = reserve_noeuds;
// On transfère le fichier depuis un stream dans un tableau
char *buffer = malloc(taille_fic+1); // +1 pour le caractere de terminaison
fread(buffer, 1, taille_fic, dict);
// Marque la fin du fichier
buffer[taille_fic] = '\0';
// Initialisation du Noeud racine du trie
racine = prochain_noeud_vide + 1;
// Déclare et initialise le pointeur sur le Noeud courant
Noeud *nd_courant = NULL;
// Nouveau string permettant de charger les mots dans le trie
char *mots_fichier = buffer;
// Initialise le compteur pour la fonction taille()
nbr_mots = 0;
// On boucle tant que le caractere n'est pas '\0' ou 'NULL'
while (*mots_fichier) {
// Départ du Noeud racine pour chaque mot
nd_courant = racine;
// Insère les mot dans l'espace mémoire pré-allouée.
// Si le char est un saut de ligne le mot est terminé fin d'un mot
for (; *mots_fichier != '\n' && *mots_fichier; mots_fichier++) {
// Gestion des mots avec apostrophe
if (*mots_fichier == '\'') {
// Si le mot avec apostrophe n'existe pas, on l'ajoute
if (nd_courant->enfants[NB_CARAC - 1] == NULL) {
nd_courant->enfants[NB_CARAC - 1] = prochain_noeud_vide++;
}
// Passage au noeud suivant
nd_courant = nd_courant->enfants[NB_CARAC - 1];
}
// Gestion des lettres
else {
// Si le mot n'existe pas, on l'ajoute en prenant le prochain noeud dans la réserve
if (nd_courant->enfants[*mots_fichier - 'a'] == NULL) {
nd_courant->enfants[*mots_fichier - 'a'] = prochain_noeud_vide++;
}
// Passage au noeud suivant
nd_courant = nd_courant->enfants[*mots_fichier - 'a'];
}
}
// On est arrivé sur '\n' donc le mot est fini
nd_courant->mot_fini = true;
// Un mot de plus dans le dico
nbr_mots++;
// On absorbe le saut de ligne
if (*mots_fichier == '\n') {
mots_fichier++;
}
}
// Fermeture proprement du fichier et libération de la mémoire
fclose(dict);
free(buffer);
// Chargement avec succès
return true;
}
/**
* Retourne le nombre de mot dans un dictionnaire (0 si non chargé)
*/
unsigned int taille_dic()
{
// Déjà calculée lors l'importation du dictionnaire
return nbr_mots;
}
/**
* Libération du dictionnaire en mémoire.
* Retourne true en cas de succès et false sinon.
*/
bool decharger()
{
// Avantage de l'appel unique à calloc :
// Un seul appel à free est nécéssaire !
free(reserve_noeuds);
// Libération mémoire avec succès
return true;
}