Blame view

dictionnaire.c 6.49 KB
babbbfbe   Corto Callerisa   ajout makefile
1
2
3
4
5
6
  /**
   * dictionnaire.c
   *
   * Implémente l'importation et la libération d'un dictionnaire en mémoire
   * depuis un fichier texte.
   */
b2c30e82   Corto Callerisa   Push code des vac...
7
8
9
10
  
  #include <stdbool.h>
  #include <stdio.h>
  #include <stdlib.h>
babbbfbe   Corto Callerisa   ajout makefile
11
  /* ctype.h pour les fonctions isalpha, tolower, isdigit et isspace */
b2c30e82   Corto Callerisa   Push code des vac...
12
13
14
  #include <ctype.h>
  #include <string.h>
  
babbbfbe   Corto Callerisa   ajout makefile
15
  #include "dictionnaire.h"
b2c30e82   Corto Callerisa   Push code des vac...
16
  
b2c30e82   Corto Callerisa   Push code des vac...
17
18
  
  
babbbfbe   Corto Callerisa   ajout makefile
19
  /* Variables globales */
b2c30e82   Corto Callerisa   Push code des vac...
20
  
babbbfbe   Corto Callerisa   ajout makefile
21
22
  // Declaration du Noeud racine
  Noeud *racine;
b2c30e82   Corto Callerisa   Push code des vac...
23
  
babbbfbe   Corto Callerisa   ajout makefile
24
25
  // Déclaration de reserve_noeud : permet d'allouer la taile du dictionnaire en une fois, simplifie la gestion
  // mémoire.
b2c30e82   Corto Callerisa   Push code des vac...
26
27
  Noeud *reserve_noeuds;
  
babbbfbe   Corto Callerisa   ajout makefile
28
29
30
31
32
33
34
  // 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;
b2c30e82   Corto Callerisa   Push code des vac...
35
  
babbbfbe   Corto Callerisa   ajout makefile
36
37
38
39
40
  /**
   * 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
b2c30e82   Corto Callerisa   Push code des vac...
41
  {
babbbfbe   Corto Callerisa   ajout makefile
42
43
      // Déclaration du pointeur parcourant le trie et initialisation a NULL
      Noeud *nd_parcours_tmp = NULL;
b2c30e82   Corto Callerisa   Push code des vac...
44
  
babbbfbe   Corto Callerisa   ajout makefile
45
46
47
      // 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;
b2c30e82   Corto Callerisa   Push code des vac...
48
  
babbbfbe   Corto Callerisa   ajout makefile
49
      // Variable pour iterer char par char dans un mot
b2c30e82   Corto Callerisa   Push code des vac...
50
51
      int i = 0;
  
babbbfbe   Corto Callerisa   ajout makefile
52
      // Vérifie que le le mot entré correspond à un parcours de l'arbre se terminant par mot_fini = True
b2c30e82   Corto Callerisa   Push code des vac...
53
      while (mot[i] != '\0') {
babbbfbe   Corto Callerisa   ajout makefile
54
55
56
57
58
59
60
          // 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];
          }
b2c30e82   Corto Callerisa   Push code des vac...
61
  
babbbfbe   Corto Callerisa   ajout makefile
62
63
64
65
66
67
68
69
70
          // 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];
          }
b2c30e82   Corto Callerisa   Push code des vac...
71
  
babbbfbe   Corto Callerisa   ajout makefile
72
73
74
75
76
          // 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) {
b2c30e82   Corto Callerisa   Push code des vac...
77
78
                  return false;
              }
babbbfbe   Corto Callerisa   ajout makefile
79
80
              // Sinon on passe à la lettre suivante dans le dico
              nd_parcours_tmp = nd_parcours_tmp->enfants[c - 'a'];
b2c30e82   Corto Callerisa   Push code des vac...
81
          }
babbbfbe   Corto Callerisa   ajout makefile
82
          // On avance dans le mot à vérifier
b2c30e82   Corto Callerisa   Push code des vac...
83
84
          i++;
      }
babbbfbe   Corto Callerisa   ajout makefile
85
86
87
  
      // Retourne True si le mot existe dans le dictionnaire
      return nd_parcours_tmp->mot_fini;
b2c30e82   Corto Callerisa   Push code des vac...
88
89
  }
  
babbbfbe   Corto Callerisa   ajout makefile
90
91
92
93
94
  /**
   * Importe le dictionnaire en mémoire.
   * Retourne True en cas de succes et False sinon.
   */
  bool importer_dict(const char *nom_dic)
b2c30e82   Corto Callerisa   Push code des vac...
95
  {
babbbfbe   Corto Callerisa   ajout makefile
96
97
98
99
      // 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");
b2c30e82   Corto Callerisa   Push code des vac...
100
  
babbbfbe   Corto Callerisa   ajout makefile
101
      // Erreur sur le fichier?
b2c30e82   Corto Callerisa   Push code des vac...
102
      if (dict == false) {
babbbfbe   Corto Callerisa   ajout makefile
103
          printf("Impossible d'ouvrir le fichier (dictionnaire.c)");
b2c30e82   Corto Callerisa   Push code des vac...
104
105
106
          return false;
      }
  
babbbfbe   Corto Callerisa   ajout makefile
107
      // Determination de la taille_dic du fichier (en bytes)
b2c30e82   Corto Callerisa   Push code des vac...
108
      fseek(dict, 0, SEEK_END);
babbbfbe   Corto Callerisa   ajout makefile
109
      taille_fic = ftell(dict);
b2c30e82   Corto Callerisa   Push code des vac...
110
  
babbbfbe   Corto Callerisa   ajout makefile
111
      // Remise du pointeur de fichier au debut
b2c30e82   Corto Callerisa   Push code des vac...
112
113
      fseek(dict, 0, SEEK_SET);
  
babbbfbe   Corto Callerisa   ajout makefile
114
115
      // Initalise reserve_noeuds avec suffisament de mémoire pour différents dictionnaires
      reserve_noeuds = calloc(taille_fic, sizeof(Noeud));
b2c30e82   Corto Callerisa   Push code des vac...
116
  
babbbfbe   Corto Callerisa   ajout makefile
117
118
      // Premier Noeud du dictionnaire
      Noeud *prochain_noeud_vide = reserve_noeuds;
b2c30e82   Corto Callerisa   Push code des vac...
119
  
babbbfbe   Corto Callerisa   ajout makefile
120
      // On transfère le fichier depuis un stream dans un tableau
187c0e67   Corto Callerisa   ajout images pour...
121
      char *buffer = malloc(taille_fic+1); // +1 pour le caractere de terminaison
babbbfbe   Corto Callerisa   ajout makefile
122
      fread(buffer, 1, taille_fic, dict);
b2c30e82   Corto Callerisa   Push code des vac...
123
  
babbbfbe   Corto Callerisa   ajout makefile
124
125
      // Marque la fin du fichier
      buffer[taille_fic] = '\0';
b2c30e82   Corto Callerisa   Push code des vac...
126
  
babbbfbe   Corto Callerisa   ajout makefile
127
128
      // Initialisation du Noeud racine du trie
      racine = prochain_noeud_vide + 1;
b2c30e82   Corto Callerisa   Push code des vac...
129
  
babbbfbe   Corto Callerisa   ajout makefile
130
131
      // Déclare et initialise le pointeur sur le Noeud courant
      Noeud *nd_courant = NULL;
b2c30e82   Corto Callerisa   Push code des vac...
132
  
babbbfbe   Corto Callerisa   ajout makefile
133
134
      // Nouveau string permettant de charger les mots dans le trie
      char *mots_fichier = buffer;
b2c30e82   Corto Callerisa   Push code des vac...
135
  
babbbfbe   Corto Callerisa   ajout makefile
136
      // Initialise le compteur pour la fonction taille()
b2c30e82   Corto Callerisa   Push code des vac...
137
138
      nbr_mots = 0;
  
babbbfbe   Corto Callerisa   ajout makefile
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
      // 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];
              }
b2c30e82   Corto Callerisa   Push code des vac...
156
  
babbbfbe   Corto Callerisa   ajout makefile
157
              // Gestion des lettres
b2c30e82   Corto Callerisa   Push code des vac...
158
              else {
babbbfbe   Corto Callerisa   ajout makefile
159
160
161
                  // 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++;
b2c30e82   Corto Callerisa   Push code des vac...
162
                  }
babbbfbe   Corto Callerisa   ajout makefile
163
164
                  // Passage au noeud suivant
                  nd_courant = nd_courant->enfants[*mots_fichier - 'a'];
b2c30e82   Corto Callerisa   Push code des vac...
165
166
167
              }
          }
  
babbbfbe   Corto Callerisa   ajout makefile
168
169
170
          // On est arrivé sur '\n' donc le mot est fini
          nd_courant->mot_fini = true;
          // Un mot de plus dans le dico
b2c30e82   Corto Callerisa   Push code des vac...
171
172
          nbr_mots++;
  
babbbfbe   Corto Callerisa   ajout makefile
173
174
175
          // On absorbe le saut de ligne
          if (*mots_fichier == '\n') {
              mots_fichier++;
b2c30e82   Corto Callerisa   Push code des vac...
176
177
178
          }
      }
  
babbbfbe   Corto Callerisa   ajout makefile
179
      // Fermeture proprement du fichier et libération de la mémoire
b2c30e82   Corto Callerisa   Push code des vac...
180
181
182
      fclose(dict);
      free(buffer);
  
babbbfbe   Corto Callerisa   ajout makefile
183
      // Chargement avec succès
b2c30e82   Corto Callerisa   Push code des vac...
184
185
186
      return true;
  }
  
babbbfbe   Corto Callerisa   ajout makefile
187
188
189
190
  /**
   * Retourne le nombre de mot dans un dictionnaire (0 si non chargé)
   */
  unsigned int taille_dic()
b2c30e82   Corto Callerisa   Push code des vac...
191
  {
babbbfbe   Corto Callerisa   ajout makefile
192
      // Déjà calculée lors l'importation du dictionnaire
b2c30e82   Corto Callerisa   Push code des vac...
193
194
195
      return nbr_mots;
  }
  
babbbfbe   Corto Callerisa   ajout makefile
196
197
198
199
  /**
   * Libération du dictionnaire en mémoire.
   * Retourne true en cas de succès et false sinon.
   */
b2c30e82   Corto Callerisa   Push code des vac...
200
201
  bool decharger()
  {
babbbfbe   Corto Callerisa   ajout makefile
202
203
      // Avantage de l'appel unique à calloc :
      // Un seul appel à free est nécéssaire !
b2c30e82   Corto Callerisa   Push code des vac...
204
      free(reserve_noeuds);
babbbfbe   Corto Callerisa   ajout makefile
205
      // Libération mémoire avec succès
b2c30e82   Corto Callerisa   Push code des vac...
206
207
      return true;
  }