Commit 41d1b930da7a42594625b95e518bbbebffc2f686

Authored by sdardenn
2 parents d13d6b7a 3ace7fa7

Merge branch 'develop-seb' into 'master'

Develop seb

See merge request !1
Makefile 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +#
  2 +# Makefile - Project de Programmation Avancee IMA3 : Correcteur Orthographique
  3 +
  4 +# compilateur
  5 +CC = clang
  6 +
  7 +# "drapeau" en paramètres
  8 +# ajouter "-O0" si besoin d'utiliser valgrind
  9 +# -ggdb3 pour les information de debugging
  10 +CFLAGS = -ggdb3 -O0 -Wall -Werror
  11 +
  12 +# Nom de l'executable
  13 +EXE = correcteur
  14 +
  15 +# Liste des headers
  16 +HDRS = dictionnaire.h
  17 +
  18 +# Liste des sources
  19 +SRCS = correcteur.c dictionnaire.c
  20 +
  21 +# Generation automatique des .o
  22 +OBJS = $(SRCS:.c=.o)
  23 +
  24 +# Commande de compilation
  25 +$(EXE): $(OBJS) $(HDRS) Makefile
  26 + $(CC) $(CFLAGS) -o $@ $(OBJS)
  27 +
  28 +# dependances
  29 +$(OBJS): $(HDRS) Makefile
  30 +
  31 +# nettoyage
  32 +clean:
  33 + rm -f core $(EXE) *.o
0 34 \ No newline at end of file
... ...
correcteur 0 → 100755
No preview for this file type
correcteur.c 0 → 100644
... ... @@ -0,0 +1,155 @@
  1 +/**
  2 + * correcteur.c
  3 + *
  4 + *
  5 + */
  6 +
  7 +#include <ctype.h>
  8 +
  9 +#include <stdio.h>
  10 +#include <stdbool.h>
  11 +// Permet d'utiliser EXIT_FAILURE et non exit(1)
  12 +// EXIT_FAILURE est plus portable
  13 +#include <stdlib.h>
  14 +
  15 +#include "dictionnaire.h"
  16 +
  17 +// Choix du dictionnaire par default
  18 +#define DICTIONNAIRE_DEF "words"
  19 +
  20 +int main(int argc, char* argv[])
  21 +{
  22 + // Verification du nombre d'arguments
  23 + if (argc != 2 && argc != 3)
  24 + {
  25 + printf("Utilisation: correcteur [fichier_dictionnaire] texte\n");
  26 + return EXIT_FAILURE;
  27 + }
  28 +
  29 + // Determine le dictionnaire à utiliser
  30 + char* nom_dict = (argc == 3) ? argv[1] : DICTIONNAIRE_DEF;
  31 +
  32 + // Charge le dictionnaire
  33 + bool est_charge = importer_dict(nom_dict);
  34 +
  35 +
  36 + // Verification de l'importation du dictionnaire
  37 + if (!est_charge)
  38 + {
  39 + printf("Erreur lors de l'importation du dictionnaire %s.\n", nom_dict);
  40 + return EXIT_FAILURE;
  41 + }
  42 +
  43 +
  44 + // Ouverture du texte
  45 + char* text = (argc == 3) ? argv[2] : argv[1];
  46 + FILE* fp = fopen(text, "r");
  47 + // Vérifie si l'ouverture est possible
  48 + if (fp == NULL)
  49 + {
  50 + printf("Erreur lors de l'ouverture du fichier %s.\n", text);
  51 + decharger();
  52 + return 1;
  53 + }
  54 +
  55 + printf("\nMots malorthographiés\n\n");
  56 + int nb_malorthographie;
  57 + int nb_mots;
  58 + print_erreurs(fp, &nb_malorthographie, &nb_mots);
  59 +
  60 + // Vérifie que la lecture s'est terminée sans erreurs
  61 + if (ferror(fp))
  62 + {
  63 + fclose(fp);
  64 + printf("Erreur lors de la lecture du fichier %s.\n", text);
  65 + decharger();
  66 + return 1;
  67 + }
  68 +
  69 + // Fermeture du fichier
  70 + fclose(fp);
  71 +
  72 +
  73 +
  74 + if (!decharger())
  75 + {
  76 + printf("Erreur lors de la liberation memoire%s.\n", nom_dict);
  77 + return 1;
  78 + }
  79 +
  80 + // On affiche les informations sur les mots
  81 + printf("\nMots malorthographiés: %d\n", nb_malorthographie);
  82 + printf("Mots dans le dictionnaire: %d\n", taille_dic());
  83 + printf("Mots dans le texte: %d\n", nb_mots);
  84 +
  85 + return 0;
  86 +}
  87 +
  88 +void print_erreurs(FILE *fp, int *malorthographies, int *mots)
  89 +{
  90 + (*malorthographies) = 0;
  91 + (*mots) = 0;// initialisation des variables
  92 + int index = 0;
  93 + char mot[LONG_MAX+1];
  94 +
  95 + // Verification de l'orthographe
  96 + int nb_mots_ligne = 0;
  97 + for (int c = fgetc(fp); c != EOF; c = fgetc(fp))
  98 + {
  99 + // On ne traite que les caracteres et les apostrophes
  100 + if (isalpha(c) || (c == '\'' && index > 0))
  101 + {
  102 + // Ajout du caractere dans le mot temporaire en construction
  103 + mot[index] = c;
  104 + index++;
  105 +
  106 + // On annule la verification du mot s'il depasse la limite
  107 + if (index > LONG_MAX)
  108 + {
  109 + // On passe le reste du mot
  110 + while ((c = fgetc(fp)) != EOF && isalpha(c));
  111 +
  112 + // Reinitialisation du mot temporaire
  113 + index = 0;
  114 + }
  115 + }
  116 +
  117 + // On ignore les mots avec des chiffres
  118 + else if (isdigit(c))
  119 + {
  120 + // On passe le reste du mot
  121 + while ((c = fgetc(fp)) != EOF && isalnum(c));
  122 +
  123 + // Reinitialisation du mot temporaire
  124 + index = 0;
  125 + }
  126 +
  127 + // On prend un mot en entier
  128 + else if (index > 0)
  129 + {
  130 + // fin d'un mot
  131 + mot[index] = '\0';
  132 +
  133 + // On incremente le compteur
  134 + (*mots)++;
  135 +
  136 + // Vérifie si le mot est bien orthographie
  137 + bool malorthographie = !appartient(mot);
  138 +
  139 +
  140 + // On affiche les mots mal orthographies
  141 + if (malorthographie)
  142 + {
  143 + printf("%s\n", mot);
  144 + if (nb_mots_ligne == 2) {
  145 + printf("\n");
  146 + nb_mots_ligne = 0;
  147 + }
  148 + (*malorthographies)++;
  149 + }
  150 +
  151 + // On passe au mot suivant
  152 + index = 0;
  153 + }
  154 + }
  155 +}
0 156 \ No newline at end of file
... ...
correcteur.o 0 → 100644
No preview for this file type
dictionnaire.c
  1 +/**
  2 + * dictionnaire.c
  3 + *
  4 + * Implémente l'importation et la libération d'un dictionnaire en mémoire
  5 + * depuis un fichier texte.
  6 + */
1 7  
2 8 #include <stdbool.h>
3 9 #include <stdio.h>
4 10 #include <stdlib.h>
  11 +/* ctype.h pour les fonctions isalpha, tolower, isdigit et isspace */
5 12 #include <ctype.h>
6 13 #include <string.h>
7 14  
  15 +#include "dictionnaire.h"
8 16  
9   -Noeud *racine;
10   -
11   -long fileSize;
12 17  
13 18  
14   -unsigned int nbr_mots;
  19 +/* Variables globales */
15 20  
  21 +// Declaration du Noeud racine
  22 +Noeud *racine;
16 23  
  24 +// Déclaration de reserve_noeud : permet d'allouer la taile du dictionnaire en une fois, simplifie la gestion
  25 +// mémoire.
17 26 Noeud *reserve_noeuds;
18 27  
  28 +// Déclaration du compteur de nombre de mots dans le dictionnaire.
  29 +// Est utilise par la fonction taille_dic().
  30 +unsigned int nbr_mots;
  31 +
  32 +// Variable global permettant de construire une reserve de noeuds.
  33 +// Type "long" pour ne pas être limité.
  34 +long taille_fic;
19 35  
20   -bool appartient(const char *mot)
  36 +/**
  37 + * Teste si un mot appartient au dictionnaire.
  38 + * Retourne True si le mot est dans le dictionaire ou False sinon
  39 + */
  40 +bool appartient(const char *mot) // Const pour que mot soit en lecture seule, il n'y a pas besoin de le modifier
21 41 {
22   -
23   - Noeud *trav = NULL;
  42 + // Déclaration du pointeur parcourant le trie et initialisation a NULL
  43 + Noeud *nd_parcours_tmp = NULL;
24 44  
25   -
26   - trav = racine;
  45 + // Fais pointer nd_parcours_tmp sur la racine
  46 + // Pour chaque nouveau nd_parcours_tmp pointe sur la racine pour verifier le mot
  47 + nd_parcours_tmp = racine;
27 48  
28   -
  49 + // Variable pour iterer char par char dans un mot
29 50 int i = 0;
30 51  
31   -
  52 + // Vérifie que le le mot entré correspond à un parcours de l'arbre se terminant par mot_fini = True
32 53 while (mot[i] != '\0') {
  54 + // On convertit le mot en minuscule pour se préoccuper uniquement de l'orthographe
  55 + char c;
  56 + if (isalpha(mot[i])) {
  57 + c = tolower(mot[i]);
  58 + } else {
  59 + c = mot[i];
  60 + }
33 61  
34   - char c = tolower(mot[i]);
35   -
36   - if (isalpha(c)) {
  62 + // Gestion de l'apostrophe
  63 + if (c == '\'') {
  64 + // On regarde s'il existe un mot comprenant l'apostrophe, sinon le mot n'appartient pas au dico
  65 + if (nd_parcours_tmp->enfants[NB_CARAC - 1] == NULL) {
  66 + return false;
  67 + }
  68 + // Sinon on continue le parcours en allant au noeud suivant
  69 + nd_parcours_tmp = nd_parcours_tmp->enfants[NB_CARAC - 1];
  70 + }
37 71  
38   - if (trav->enfants[c - 'a'] == NULL) {
  72 + // Gestion des lettres
  73 + else if (isalpha(c)) {
  74 + // Verifie que le parcours correspondant au lettres du mot existe jusqu'ici.
  75 + // Retourne False si ce n'est pas le cas.
  76 + if (nd_parcours_tmp->enfants[c - 'a'] == NULL) {
39 77 return false;
40 78 }
41   - trav = trav->enfants[c - 'a'];
  79 + // Sinon on passe à la lettre suivante dans le dico
  80 + nd_parcours_tmp = nd_parcours_tmp->enfants[c - 'a'];
42 81 }
  82 + // On avance dans le mot à vérifier
43 83 i++;
44 84 }
45   - return trav->mot_fini;
  85 +
  86 + // Retourne True si le mot existe dans le dictionnaire
  87 + return nd_parcours_tmp->mot_fini;
46 88 }
47 89  
48   -bool charger_dict(const char *dictionary)
  90 +/**
  91 + * Importe le dictionnaire en mémoire.
  92 + * Retourne True en cas de succes et False sinon.
  93 + */
  94 +bool importer_dict(const char *nom_dic)
49 95 {
  96 + // Ouvre le fichier du dictionnaire
  97 + // 'b' permet d'avoir un stream de byte et non l'interpretation des caractères d'indentation en fonction du système.
  98 + // Cela garantie que fseek determine correctement la taille du fichier.
  99 + FILE *dict = fopen(nom_dic, "rb");
50 100  
51   - FILE *dict = fopen(dictionary, "rb");
52   -
  101 + // Erreur sur le fichier?
53 102 if (dict == false) {
54   - printf("Could not open this dictionary (dictionary.c file)");
  103 + printf("Impossible d'ouvrir le fichier (dictionnaire.c)");
55 104 return false;
56 105 }
57 106  
  107 + // Determination de la taille_dic du fichier (en bytes)
58 108 fseek(dict, 0, SEEK_END);
59   - fileSize = ftell(dict);
  109 + taille_fic = ftell(dict);
60 110  
  111 + // Remise du pointeur de fichier au debut
61 112 fseek(dict, 0, SEEK_SET);
62 113  
63   - reserve_noeuds = calloc((fileSize), sizeof(Noeud));
  114 + // Initalise reserve_noeuds avec suffisament de mémoire pour différents dictionnaires
  115 + reserve_noeuds = calloc(taille_fic, sizeof(Noeud));
64 116  
65   - Noeud *nextFreeNode = reserve_noeuds;
  117 + // Premier Noeud du dictionnaire
  118 + Noeud *prochain_noeud_vide = reserve_noeuds;
66 119  
67   - char *buffer = malloc(fileSize + 1);
68   - fread(buffer, 1, fileSize, dict);
  120 + // On transfère le fichier depuis un stream dans un tableau
  121 + char *buffer = malloc(taille_fic); // +1 pour le caractere de terminaison
  122 + fread(buffer, 1, taille_fic, dict);
69 123  
70   - buffer[fileSize] = '\0';
  124 + // Marque la fin du fichier
  125 + buffer[taille_fic] = '\0';
71 126  
72   - racine = nextFreeNode + 1;
  127 + // Initialisation du Noeud racine du trie
  128 + racine = prochain_noeud_vide + 1;
73 129  
74   - Noeud *trav = NULL;
  130 + // Déclare et initialise le pointeur sur le Noeud courant
  131 + Noeud *nd_courant = NULL;
75 132  
76   - char *words = buffer;
  133 + // Nouveau string permettant de charger les mots dans le trie
  134 + char *mots_fichier = buffer;
77 135  
  136 + // Initialise le compteur pour la fonction taille()
78 137 nbr_mots = 0;
79 138  
80   - while (*words) {
81   -
82   - trav = racine;
  139 + // On boucle tant que le caractere n'est pas '\0' ou 'NULL'
  140 + while (*mots_fichier) {
  141 + // Départ du Noeud racine pour chaque mot
  142 + nd_courant = racine;
  143 +
  144 + // Insère les mot dans l'espace mémoire pré-allouée.
  145 + // Si le char est un saut de ligne le mot est terminé fin d'un mot
  146 + for (; *mots_fichier != '\n' && *mots_fichier; mots_fichier++) {
  147 + // Gestion des mots avec apostrophe
  148 + if (*mots_fichier == '\'') {
  149 + // Si le mot avec apostrophe n'existe pas, on l'ajoute
  150 + if (nd_courant->enfants[NB_CARAC - 1] == NULL) {
  151 + nd_courant->enfants[NB_CARAC - 1] = prochain_noeud_vide++;
  152 + }
  153 + // Passage au noeud suivant
  154 + nd_courant = nd_courant->enfants[NB_CARAC - 1];
  155 + }
83 156  
84   - for (; *words != '\n' && *words; words++) {
85   -
  157 + // Gestion des lettres
86 158 else {
87   - if (trav->enfants[*words - 'a'] == NULL) {
88   - trav->enfants[*words - 'a'] = nextFreeNode++;
  159 + // Si le mot n'existe pas, on l'ajoute en prenant le prochain noeud dans la réserve
  160 + if (nd_courant->enfants[*mots_fichier - 'a'] == NULL) {
  161 + nd_courant->enfants[*mots_fichier - 'a'] = prochain_noeud_vide++;
89 162 }
90   -
91   - trav = trav->enfants[*words - 'a'];
  163 + // Passage au noeud suivant
  164 + nd_courant = nd_courant->enfants[*mots_fichier - 'a'];
92 165 }
93 166 }
94 167  
95   - trav->mot_fini = true;
  168 + // On est arrivé sur '\n' donc le mot est fini
  169 + nd_courant->mot_fini = true;
  170 + // Un mot de plus dans le dico
96 171 nbr_mots++;
97 172  
98   - if (*words == '\n') {
99   - words++;
  173 + // On absorbe le saut de ligne
  174 + if (*mots_fichier == '\n') {
  175 + mots_fichier++;
100 176 }
101 177 }
102 178  
  179 + // Fermeture proprement du fichier et libération de la mémoire
103 180 fclose(dict);
104 181 free(buffer);
105 182  
  183 + // Chargement avec succès
106 184 return true;
107 185 }
108 186  
109   -unsigned int taille()
  187 +/**
  188 + * Retourne le nombre de mot dans un dictionnaire (0 si non chargé)
  189 + */
  190 +unsigned int taille_dic()
110 191 {
  192 + // Déjà calculée lors l'importation du dictionnaire
111 193 return nbr_mots;
112 194 }
113 195  
  196 +/**
  197 + * Libération du dictionnaire en mémoire.
  198 + * Retourne true en cas de succès et false sinon.
  199 + */
114 200 bool decharger()
115 201 {
  202 + // Avantage de l'appel unique à calloc :
  203 + // Un seul appel à free est nécéssaire !
116 204 free(reserve_noeuds);
  205 + // Libération mémoire avec succès
117 206 return true;
118 207 }
... ...
dictionnaire.h 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +/**
  2 + * dict.h
  3 + *
  4 + * Declaration des fonctions de manipulation d'un dictionnaire
  5 + */
  6 +
  7 +#ifndef DICT_H
  8 +#define DICT_H
  9 +
  10 +#include <stdbool.h>
  11 +
  12 +#define NB_CARAC 27 // TODO 27 si gestion de l'apostrophe
  13 +
  14 +/*
  15 + * La structure principale du programme est un trie ou chaque Noeud possède jusqu'a
  16 + * 26 enfants ainsi qu'un booleen indiquant si le noeud termine un mot valide.
  17 + */
  18 +typedef struct Noeud {
  19 + bool mot_fini;
  20 + struct Noeud *enfants[NB_CARAC];
  21 +} Noeud;
  22 +
  23 +// Longueur maximum d'un mot :
  24 +// Ex peur des mots long = Hippopotomonstrosesquippedaliophobie, 36 Lettres
  25 +#define LONG_MAX 36
  26 +
  27 +/*
  28 + * Retourne True si le mot est dans le dictionnaire, False sinon.
  29 + */
  30 +bool appartient(const char *mot);
  31 +
  32 +/*
  33 + * Charge le dictionnaire, retourne True si le dictionnaire est charge, False sinon
  34 + */
  35 +bool importer_dict(const char *nom_dic);
  36 +
  37 +/*
  38 + * Retourne le nombre de mots d'un dictionnaire.
  39 + */
  40 +unsigned int taille_dic(void);
  41 +
  42 +/*
  43 + * Quitte le dictionnaire, retourne True si le dictionnaire est quitte, False sinon
  44 + */
  45 +bool decharger(void);
  46 +
  47 +/*
  48 + * Affiche les mots mal orthographies dans le fichier
  49 + */
  50 +void print_erreurs(FILE *fp, int *malorthographies, int *mots);
  51 +
  52 +#endif
... ...
dictionnaire.o 0 → 100644
No preview for this file type
remarques.txt 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +verifier le correcteur avec le texte d'exemple
  2 +Verifier l'orthographe
0 3 \ No newline at end of file
... ...