diff --git a/main.c b/main.c index 0ece9e7..a125c71 100644 --- a/main.c +++ b/main.c @@ -10,8 +10,8 @@ int main(int argc, char *argv[]) { init_pgrm(); Node tree = NULL; - int error = 0; - int correct = 0; + int error = 0; // compteur d'erreurs + int correct = 0; // compteur de corrections effectuées FILE* fp_lib; FILE* fp_txt; @@ -21,8 +21,8 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - fp_lib = fopen(argv[argc-2], "r"); - fp_txt = fopen(argv[argc-1], "r+"); + fp_lib = fopen(argv[argc-2], "r"); // ouverture du fichier bibliothèque en mode lecture + fp_txt = fopen(argv[argc-1], "r+"); // ouverture du fichier à analyser en mode lecture/écriture if(fp_lib==NULL || fp_txt==NULL) { @@ -30,22 +30,24 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - init_tree(&tree); - read_lib(fp_lib, &tree); - read_txt(fp_txt, &tree, &error, &correct); + init_tree(&tree); // initialisation de l'arbre indexé + read_lib(fp_lib, &tree); // lecture de la bibliothèque + read_txt(fp_txt, &tree, &error, &correct); // analyse du fichier et corrections éventuelles // Si vous souhaitez imprimer l'arbre indexé complet : //char word[MAX] = ""; //print_tree(tree, 0, word); + // Impression du nombre d'erreurs if(error<2) printf("Dans le texte %s, %d mot n'est pas dans le dictionnaire %s.\n", argv[argc-1], error, argv[argc-2]); else printf("Dans le texte %s, %d mots ne sont pas dans le dictionnaire %s.\n", argv[argc-1], error, argv[argc-2]); + // Impression du nombre de corrections if(correct<2) printf("%d a été corrigé.\n", correct); else printf("%d ont été corrigés.\n", correct); - free_tree(&tree); - fclose(fp_lib); + free_tree(&tree); // Libération de l'espace mémoire + fclose(fp_lib); // Fermeture des fichiers texte fclose(fp_txt); return EXIT_SUCCESS; } diff --git a/texte.txt b/texte.txt index 146a215..4c6f175 100644 --- a/texte.txt +++ b/texte.txt @@ -6,7 +6,7 @@ The ant and the cicada In the summer, the ant families were very busy. They knew that in the winter they would have to stay in their anthill. They wanted to have enough food for the whole winter. - While the ants worked hard, the cicadas didn't do anything. They sang and danced all day. When they were hungry, they coud fly to the farm and get something to eat. + While the ants worked hard, the cicadas didn't do anything. They sang and danced all day. When they were hungry, they could fly to the farm and get something to eat. One day the cicadas were singing and dancing. They saw a long line of ants bringing food to their anthill. The cicadas said, Stop, my silly friends. It's a very nice day. Come and dance with us. The ants said, Don't you know about winter? If you don't work now, you'll have trouble later. @@ -24,3 +24,7 @@ The ant and the cicada + + + + diff --git a/tree.c b/tree.c index d973e8c..0b64d70 100644 --- a/tree.c +++ b/tree.c @@ -27,7 +27,7 @@ void init_tree(Node* Tree) if(is_empty_tree(*Tree)) { *Tree = malloc(sizeof(node)); - (*Tree)->letter = 7; // + (*Tree)->letter = 7; // caractère sans utilité (* Tree)->endWord = false; for(int i=0; inext[i] = NULL; // initialisation du tableau 'next' à un tableau de pointeurs NULL @@ -35,13 +35,11 @@ void init_tree(Node* Tree) } // Détermine l'indice de rangement dans le tableau 'next' du caractère 'letter' -int find_caract_indice(char letter) // Ne fonctionne pas pour les caractères accentués +int find_caract_indice(char letter) { - //printf("__%d__\n", letter); if(letter>=97 && letter<=122) return letter-'a'; if(letter>=65 && letter<=90) return letter-'A'; if(letter == 39) return letter-13; // l'apostrophe est placée en 27ème position - //if(letter>=192) {printf("%d", letter-166); return letter-166;} //-192+26 } // Fonction d'ajout d'un mot 'word' dans la structure 'tree' de type 'arbre indexé' @@ -52,38 +50,34 @@ void add_in_tree(Node Tree, char word[]) Node Tree2 = Tree; while(word[j] != '\0') // on parcourt tout le mot 'word' { - /*if(is_leaf(Tree2)) // a retirer - printf("empty\t");*/ char letter = word[j]; - ind = find_caract_indice(letter); - if(Tree2->next[ind]!=NULL) // si le pointeur du tableau 'next' corresdant au caractère lu n'est pas NULL, on s'insère dans cette 'branche' de l'arbre indexé et on continue avec le caractère suivant + ind = find_caract_indice(letter); // on récupère l'indice de rangement de 'letter' + + if(Tree2->next[ind]!=NULL) // si le pointeur du tableau 'next' correspondant au caractère lu n'est pas NULL, on s'insère dans cette 'branche' de l'arbre indexé et on continue avec le caractère suivant { Tree2 = Tree2->next[ind]; - /* printf("%c %d\t", letter, ind); - printf("okA %d\n", j);*/ } else // sinon, on ajoute une nouvelle cellule de type 'struct node' et on y insère les informations concernant le caractères { Node new = NULL; new = malloc(sizeof(node)); - new->letter = letter; // le caractère - for(int i=0; iletter = letter; + for(int i=0; inext[i]=NULL; } new->endWord = false; + Tree2->next[ind] = new; // on fait pointé le tableau du caractère précédent vers cette cellule (vers ce caractère) - if(!(Tree2->endWord)) // si le caractère n'est pas un caractère de fin, on le met à 'false' -> UTILITE ? + if(!(Tree2->endWord)) // si le caractère précédent n'est pas un caractère de fin, on lui donne la valeur 'false' Tree2->endWord = false; Tree2=Tree2->next[ind]; // on se place au niveau du caractère suivant dans l'arbre indexé - /*printf("%c %d\t", letter, ind); - printf("okB %d\n", j);*/ } j++; if(word[j]=='\0') // si le caractère suivant est la fin de la chaîne, on dit que le caractère précédent est un caractère de fin Tree2->endWord = true; } - //printf("ok\n"); } // Fonction qui détermine si le caractère est un caractère de fin de mot (espace, ',', ';', '.', etc..) @@ -103,168 +97,172 @@ char max_index(char word[]) return index; } -void scan_word(Node Tree, char word[], int* error, FILE* fp_txt, int* correct) // si un mot démarre juste après un caractère de fin, la fonction ne lit pas les mots séparément +// Fonction qui scanne les mots du fichier à vérifier et les analyse +void scan_word(Node Tree, char word[], int* error, FILE* fp_txt, int* correct) { - bool endWord = false; - bool stop = false; - int ind = 0; - int indice; + bool endWord = false; // true : le caractère est un caractère de fin, false : le caractère n'est pas un caractère de fin + bool stop = false; // permet de ne pas compte 2 fois certaines erreurs + int ind = 0; // indice dans le mot 'word' + int indice; // indice de rangement de letter dans le tableau 'next' char letter; Node Tree2 = Tree; - while(!is_end_caract(word[ind])) + while(!is_end_caract(word[ind])) // si 'word[ind]' n'est pas un caractère de fin { stop = false; letter = word[ind]; - indice = find_caract_indice(letter); + indice = find_caract_indice(letter); // récupération de l'indice de rangement - if(Tree2 != NULL && Tree2->next[indice]!=NULL) + if(Tree2 != NULL && Tree2->next[indice]!=NULL) // si l'arbre n'est pas vide et que la case correspondant à la lettre dans l'arbre n'est pas vide { - ind++; - Tree2 = Tree2->next[indice]; + ind++; // on passe à la lettre suivante + Tree2 = Tree2->next[indice]; // on se met dans la case de la lettre qui vient d'être vérifiée endWord = Tree2->endWord; } else { - add_error(error, word, ind, Tree2, fp_txt, correct); - //printf("%d\n", ind); - ind = max_index(word); - //printf("%d\n", ind); + add_error(error, word, ind, Tree2, fp_txt, correct); // si l'abre est vide ou que la case de l'arbre correspondant à la lettre est vide, on ajoute une erreur + ind = max_index(word); // on se place à la fin du mot pour ne pas continuer de vérifier ses lettres stop = true; endWord = false; } } - if(!endWord && !stop) + if(!endWord && !stop) // si un mot manque d'au moins une lettre (endWord == false alors qu'on a atteint la fin du mot à scanner) { - add_error(error, word, ind, Tree2, fp_txt, correct); + add_error(error, word, ind, Tree2, fp_txt, correct); // on ajoute une erreur } } +// Ajoute une erreur, donne le type d'erreur et lance le processus de correction void add_error(int* error, char word[], int index, Node Tree, FILE* fp_txt, int* correct) { (*error)++; - if(index==0) + if(index==0) // si la première lettre n'est pas reconnu, on ne propose pas de correction { printf("Le mot '%s' ne correspond à aucun mot du dictionnaire.\n\n", word); return; } - else if(indexdernier+1; i++) - printf("%d. %s\n", i+1, liste->mots[i]); - printf("\n"); - choix = -1; - printf("Quel mot voulez-vous sélectionner ? (Entrez %d pour ne pas corriger le mot)\n", (liste->dernier)+2); - while(choix<1 || choix>liste->dernier+2) - { - scanf("%d", &choix); - } - if(choix==(liste->dernier)+2) - { - printf("\n"); - return; - } - (*correct)++; - char word[MAX]; - strcpy(word, liste->mots[choix-1]); - printf("Le mot %s a été sélectionné.\n\n", word); - if(testEnd) add_caract(word, end); - correct_word(word, fp_txt, longueur); + int choix; + printf("Voici les mots possibles pour corriger ce mot :\n"); + for(int i=0; idernier+1; i++) // on propose tous les mots de la liste contigüe + printf("%d. %s\n", i+1, liste->mots[i]); + printf("\n"); + choix = -1; + printf("Quel mot voulez-vous sélectionner ? (Entrez %d pour ne pas corriger le mot)\n", (liste->dernier)+2); // exemple : 3 mots possibles. Si on entre 4, alors on ne veut pas corriger + while(choix<1 || choix>liste->dernier+2) // vérifie que la valeur entrée est correcte + { + scanf("%d", &choix); + } + if(choix==(liste->dernier)+2) // si on ne corrige pas + { + printf("\n"); + return; + } + (*correct)++; // on incrémente un compteur de corrections + char word[MAX]; // contiendra le mot choisi + strcpy(word, liste->mots[choix-1]); + printf("Le mot %s a été sélectionné.\n\n", word); + if(testEnd) add_caract(word, end); // s'il y a un caractère de fin, on l'ajoute + correct_word(word, fp_txt, longueur); // processus de remplacement } +// Remplace le mot comportant une erreur par le mot choisi dans choice_word void correct_word(char word[], FILE* fp_txt, int longueur) { - FILE* fp_tamp; - fp_tamp = fopen("tampon.txt", "w+"); - if(fp_tamp==NULL) - { - printf("Erreur lors de l'ouverture du fichier tampon.\n"); - return; - } - int position = ftell(fp_txt)-longueur; - rewind(fp_txt); - char tempo; - while(ftell(fp_tamp)dernier = -1; - for(int i=0; imots[i], ""); - } + if((*liste)!=NULL) + { + printf("Déjà initialisé.\n"); + return; + } + *liste = malloc(sizeof(struct liste)); + (*liste)->dernier = -1; + for(int i=0; imots[i], ""); + } } +// Affichage void init_pgrm(void) { printf("\n------------------------------------------\n"); @@ -273,6 +271,7 @@ void init_pgrm(void) printf("------------------------------------------\n\n"); } +// Renvoie true si 'word' ne comprend pas d'accent, false sinon bool no_accent(char word[]) { int index_max = max_index(word); @@ -281,102 +280,104 @@ bool no_accent(char word[]) return true; } +// Lecture du fichier à analyser void read_txt(FILE* fp, Node* Tree, int* error, int* correct) { char word[MAX]; while(1) { - if(fscanf(fp, "%s", word)!=1) + if(fscanf(fp, "%s", word)!=1) // tant qu'on a pas fini la lecture du fichier break; - if(no_accent(word)) // !!! MOTS AVEC ACCENTS NON PRIS EN COMPTE - scan_word(*Tree, word, error, fp, correct); + if(no_accent(word)) // on ne prend pas en compte les mots accentués (voir compte-rendu pour explications) + scan_word(*Tree, word, error, fp, correct); // on scanne le mot } if(feof(fp)) printf("Fin de la lecture du fichier à scanner.\n\n"); if(ferror(fp)) printf("Erreur lors de la lecture du fichier à scanner.\n\n"); } +// Lecture du dictionnaire void read_lib(FILE* fp, Node* Tree) { char word[MAX]; while(1) { - if(fscanf(fp, "%s", word)!=1) + if(fscanf(fp, "%s", word)!=1) // tant qu'on a pas fini la lecture du fichier break; - // printf("--%s--\n", word); - //fflush(stdout); - if(no_accent(word)) - add_in_tree(*Tree, word); + if(no_accent(word)) // on ne prend pas en compte les mots accentués (voir compte-rendu pour explications) + add_in_tree(*Tree, word); // on ajoute le mot dans l'arbre indexé } if(feof(fp)) printf("Fin de la lecture de la bibliothèque.\n\n"); if(ferror(fp)) printf("Erreur lors de la lecture de la bibliothèque.\n\n"); } +// Affichage de l'arbre indexé (inutile pour le code, fonction d'aide) void print_tree(Node Tree, int index, char word[]) { - if(is_empty_tree(Tree)) - return; - add_caract(word, Tree->letter); - if(is_leaf(Tree)) - { - printf("%s\n", word); - supp_caract(word); - return; - } - if(Tree->endWord) - printf("%s\n", word); - while(index < NB_CARAC) + if(is_empty_tree(Tree)) // si l'arbre est vide, rien a imprimer + return; + add_caract(word, Tree->letter); // sinon, on stocke le caractère dans une chaine + if(is_leaf(Tree)) // si on atteint une feuille, on imprime et on supprime le dernier caractère car il n'est plus utile + { + printf("%s\n", word); + supp_caract(word); + return; + } + if(Tree->endWord) // si on est à la fin d'un mot, on l'imprime mais on enlève pas de lettre car il peut y avoir des mots plus grands de même racine + printf("%s\n", word); + while(index < NB_CARAC) // on parcourt tout le tableau de pointeur de chaque cellule + { + if(!is_empty_tree(Tree->next[index])) // si la case du tableau n'est pas vide { - if(!is_empty_tree(Tree->next[index])) - { - print_tree(Tree->next[index], 0, word); - } - index++; + print_tree(Tree->next[index], 0, word); // on relance la fonction en partant de la case } - supp_caract(word); - return; + index++; + } + supp_caract(word); // on supprime le dernier caractère stocké car il n'est plus utile + return; } -void make_tree_correct(Node Tree, int index, char word[], char start[], correction liste) +// Comme son nom l'indique, cette fonction sélectionne les mots possibles pour la correction du mot 'word' et les ajoute dans la liste contigüe +void make_tree_correct(Node Tree, int index, char word[], char start[], correction liste) // même principe que la fonction d'affichage de l'arbre indexé { - if(is_empty_tree(Tree)) - return; - add_caract(word, Tree->letter); - if(is_leaf(Tree)) - { - //printf("%s%s\n", start, word); - add_in_liste(liste, start, word); - supp_caract(word); - return; - } - if(Tree->endWord) - { - //printf("%s%s\n", start, word); - add_in_liste(liste, start, word); - } - while(index < NB_CARAC) + if(is_empty_tree(Tree)) // si l'arbre est vide, il n'y a pas de correction possible + return; + add_caract(word, Tree->letter); // on ajoute le caractère à la chaine de stockage + if(is_leaf(Tree)) // si on arrive au bout d'une branche, on ajoute le mot dans la liste et on supprime le dernier caractère stocké + { + add_in_liste(liste, start, word); + supp_caract(word); + return; + } + if(Tree->endWord) // si on arrive à la fin d'un mot, on l'ajout dans la liste + { + add_in_liste(liste, start, word); + } + while(index < NB_CARAC) // on parcourt le tableau de chaque cellule + { + if(!is_empty_tree(Tree->next[index])) // si la case n'est pas vide { - if(!is_empty_tree(Tree->next[index])) - { - make_tree_correct(Tree->next[index], 0, word, start, liste); - } - index++; + make_tree_correct(Tree->next[index], 0, word, start, liste); // on relance la fonction à partir de cette case } - supp_caract(word); - return; + index++; + } + supp_caract(word); // on supprime le dernier caractère stocké, inutile maintenant + return; } +// Ajoute les mots de correction dans la liste contigüe void add_in_liste(correction liste, char start[], char word[]) { - char temp[MAX]; - strcpy(temp, start); - strcat(temp, word); - if(liste->dernierdernier)++; - strcpy(liste->mots[liste->dernier], temp); - } + char temp[MAX]; + strcpy(temp, start); // on concatène le debut du mot (avant l'erreur) avec la suite envoyée dans 'word' + strcat(temp, word); + if(liste->dernierdernier)++; + strcpy(liste->mots[liste->dernier], temp); + } } +// Ajoute un caractère à une chaine de caractères void add_caract(char word[], char caract) { char str[2]; @@ -385,11 +386,13 @@ void add_caract(char word[], char caract) strcat(word, str); } +// Supprime un caractère d'une chaine de caractères void supp_caract(char word[]) { word[strlen(word)-1]='\0'; } +// Désalloue la mémoire utilisée par l'arbre indexé void free_tree(Node* Tree) { if(*Tree!=NULL) diff --git a/tree.h b/tree.h index f0ae9ea..7042d38 100644 --- a/tree.h +++ b/tree.h @@ -9,10 +9,12 @@ #include #include #include + +// Définition des constantes #define MAX 30 // taille maximale d'une chaîne lue dans un fichier -#define NB_CARAC 27 // nombre de caractères différents pouvant être identifiés -> 89 avec accentués +#define NB_CARAC 27 // nombre de caractères différents pouvant être identifiés #define NB_MOT_CORRECTION 15 // nombre de mots pour la correction -#define MAX_READ 1000 +#define MAX_READ 1000 // nombre de caractères maximums dans une ligne lue lors de la connexion // Déclaration de la structure 'trie' ou 'arbre indexé', ainsi que des pointeurs associés typedef struct node* Node; @@ -23,7 +25,7 @@ typedef struct node { bool endWord; }node; -// Déclaration de la structure contenant les mots possible pour la correction +// Déclaration de la liste contigüe contenant les mots possible pour la correction typedef struct liste* correction; typedef struct liste { @@ -76,7 +78,7 @@ void add_error(int*, char*, int, Node, FILE*, int*); // Corrige les erreurs void make_correction(char *, int, Node, FILE*, int*); -// Initialise le programme +// Initialise le programme (affichage) void init_pgrm(void); // Ajoute un caractère à une chaine de caractères @@ -85,10 +87,10 @@ void add_caract(char*, char); // Supprime le dernier caractère d'une chaine void supp_caract(char*); -// Initialise le tableau contenant les mots de correction +// Initialise la liste contigüe contenant les mots de correction void init_correction(correction*); -// Imprime les mots possibles pour la correction +// Récupère les mots possibles pour la correction void make_tree_correct(Node, int, char*, char*, correction); // Ajoute un mot dans une liste contigûe -- libgit2 0.21.2