Merged
Merge Request #1 · created by sdardenn


Develop seb


From develop-seb into master

Merged by sdardenn

Source branch has been removed
1 participants
sdardenn/ima3_projet_pa_2019!1

Assignee: none

Milestone: none


Votes
0 up
0 down

04 May, 2019

3 commits


03 May, 2019

1 commit


30 Apr, 2019

2 commits


Makefile 0 → 100644
@@ -0,0 +1,33 @@ @@ -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 \ No newline at end of file 34 \ No newline at end of file
correcteur 0 → 100755
No preview for this file type
correcteur.c 0 → 100644
@@ -0,0 +1,155 @@ @@ -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 \ No newline at end of file 156 \ No newline at end of file
correcteur.o 0 → 100644
No preview for this file type
  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 #include <stdbool.h> 8 #include <stdbool.h>
3 #include <stdio.h> 9 #include <stdio.h>
4 #include <stdlib.h> 10 #include <stdlib.h>
  11 +/* ctype.h pour les fonctions isalpha, tolower, isdigit et isspace */
5 #include <ctype.h> 12 #include <ctype.h>
6 #include <string.h> 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 Noeud *reserve_noeuds; 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 int i = 0; 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 while (mot[i] != '\0') { 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 return false; 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 i++; 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 if (dict == false) { 102 if (dict == false) {
54 - printf("Could not open this dictionary (dictionary.c file)"); 103 + printf("Impossible d'ouvrir le fichier (dictionnaire.c)");
55 return false; 104 return false;
56 } 105 }
57 106
  107 + // Determination de la taille_dic du fichier (en bytes)
58 fseek(dict, 0, SEEK_END); 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 fseek(dict, 0, SEEK_SET); 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 nbr_mots = 0; 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 else { 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 nbr_mots++; 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 fclose(dict); 180 fclose(dict);
104 free(buffer); 181 free(buffer);
105 182
  183 + // Chargement avec succès
106 return true; 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 return nbr_mots; 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 bool decharger() 200 bool decharger()
115 { 201 {
  202 + // Avantage de l'appel unique à calloc :
  203 + // Un seul appel à free est nécéssaire !
116 free(reserve_noeuds); 204 free(reserve_noeuds);
  205 + // Libération mémoire avec succès
117 return true; 206 return true;
118 } 207 }
dictionnaire.h 0 → 100644
@@ -0,0 +1,52 @@ @@ -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 @@ @@ -0,0 +1,2 @@
  1 +verifier le correcteur avec le texte d'exemple
  2 +Verifier l'orthographe
0 \ No newline at end of file 3 \ No newline at end of file