DRAFT: compress function added!

This commit is contained in:
Mylloon 2021-12-24 15:45:43 +01:00
parent 33e0e3fdb6
commit b745df67f4
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
2 changed files with 59 additions and 21 deletions

43
arbre.c
View file

@ -1,8 +1,10 @@
#include "arbre.h" #include "arbre.h"
void listeVersArbre(Liste *liste) { int listeVersArbre(Liste *liste) {
Cellule *curseur = *liste; Cellule *curseur = *liste;
int nombreLettresDansFichier = 0;
while (curseur != NULL) { // parcours de la liste while (curseur != NULL) { // parcours de la liste
if (curseur->lettre != '\0') nombreLettresDansFichier++; // +1 au compteur si c'est bien une lettre
if (curseur->suivant != NULL) { // on créer un mini-arbre qu'on colle au reste de l'arbre seulement si le suivant existe if (curseur->suivant != NULL) { // on créer un mini-arbre qu'on colle au reste de l'arbre seulement si le suivant existe
Cellule *nouvelleCellule; Cellule *nouvelleCellule;
if ((nouvelleCellule = (Cellule*)malloc(sizeof(Cellule))) == NULL) { // on alloue de la mémoire pour notre nouvelle cellule (mini-racine) if ((nouvelleCellule = (Cellule*)malloc(sizeof(Cellule))) == NULL) { // on alloue de la mémoire pour notre nouvelle cellule (mini-racine)
@ -15,6 +17,8 @@ void listeVersArbre(Liste *liste) {
nouvelleCellule->lettre = '\0'; nouvelleCellule->lettre = '\0';
nouvelleCellule->frequence = nouvelleCellule->gauche->frequence + nouvelleCellule->droite->frequence; nouvelleCellule->frequence = nouvelleCellule->gauche->frequence + nouvelleCellule->droite->frequence;
if (curseur->suivant->lettre != '\0') nombreLettresDansFichier++; // +1 si le suivant est aussi une lettre (membre droit)
curseur = curseur->suivant->suivant; // on va au suivant 2x car on a déjà ajouté le suivant en tant que membre droit curseur = curseur->suivant->suivant; // on va au suivant 2x car on a déjà ajouté le suivant en tant que membre droit
*liste = curseur; // on change le point de départ de notre liste pour ne pas traiter en boucle les anciennes cellules *liste = curseur; // on change le point de départ de notre liste pour ne pas traiter en boucle les anciennes cellules
@ -25,9 +29,11 @@ void listeVersArbre(Liste *liste) {
curseur = curseur->suivant; curseur = curseur->suivant;
} }
} }
return nombreLettresDansFichier;
} }
void assignationCode(Arbre arbre, int codeActuel, int longueur, Lettre *lettresListe, int *i, int *longueurTotale) { void assignationCode(Arbre arbre, int codeActuel, int longueur, Entete *lettresListe, int *i, int *longueurTotale) {
if (arbre->lettre != '\0') { // si c'est une lettre qu'on regarde if (arbre->lettre != '\0') { // si c'est une lettre qu'on regarde
lettresListe[*i].lettre = arbre->lettre; // ajout de la lettre lettresListe[*i].lettre = arbre->lettre; // ajout de la lettre
lettresListe[*i].code = codeActuel; // assignation de son code lettresListe[*i].code = codeActuel; // assignation de son code
@ -44,6 +50,7 @@ void assignationCode(Arbre arbre, int codeActuel, int longueur, Lettre *lettresL
} }
} }
// Libère en mémoire un Arbre
void freeArbre(Arbre arbre) { void freeArbre(Arbre arbre) {
if (arbre->lettre == '\0') { // free aussi les mini-racines if (arbre->lettre == '\0') { // free aussi les mini-racines
freeArbre(arbre->gauche); freeArbre(arbre->gauche);
@ -53,9 +60,9 @@ void freeArbre(Arbre arbre) {
free(arbre); // free du noeud courant free(arbre); // free du noeud courant
} }
Lettre * arbreVersListe(Arbre arbre, int taille, int *tailleTotale) { Entete *arbreVersListe(Arbre arbre, int taille, int *tailleTotale) {
Lettre *lettres; Entete *lettres;
if ((lettres = (Lettre*)malloc(taille * sizeof(Lettre))) == NULL) { // on alloue la liste qui va contenir nos caractères if ((lettres = (Entete*)malloc(taille * sizeof(Entete))) == NULL) { // on alloue la liste qui va contenir nos caractères
printf("Impossible d'allouer de la mémoire supplémentaire (arbreVersListe).\n"); // gestion de l'erreur printf("Impossible d'allouer de la mémoire supplémentaire (arbreVersListe).\n"); // gestion de l'erreur
exit(1); exit(1);
} }
@ -66,10 +73,32 @@ Lettre * arbreVersListe(Arbre arbre, int taille, int *tailleTotale) {
return lettres; return lettres;
} }
Entete *fichierVersListe(FILE *fichier, int *nombreLettresDansFichier, int *tailleTotale) {
char lettre = 'a';
Liste liste = NULL;
while (lettre != EOF) {
lettre = fgetc(fichier);
ajouterLettre(&liste, lettre);
}
rewind(fichier);
trierListe(&liste);
*nombreLettresDansFichier = listeVersArbre(&liste);
return arbreVersListe(liste, *nombreLettresDansFichier, tailleTotale);
}
void compression(FILE *entree, FILE *sortie) { void compression(FILE *entree, FILE *sortie) {
/* fclose temporaire pour supprimer les warnings */ /* fclose temporaire pour supprimer les warnings */
fclose(entree); int nombreLettresDansFichier; // initialisé par `listeVersArbre`
fclose(sortie); int tailleTotale = 0; // taille totale en en bit du fichier en sortie
Entete *entete = fichierVersListe(entree, &nombreLettresDansFichier, &tailleTotale);
// On écrit l'entête du fichier avec la table complète des correspondances
enteteVersFichier(entete, nombreLettresDansFichier, tailleTotale, sortie);
// On écrit les données huffman-isée dans le fichier
huffmanVersFichier(entree, sortie, entete, nombreLettresDansFichier);
} }
void decompression(FILE *entree, FILE *sortie) { void decompression(FILE *entree, FILE *sortie) {

37
arbre.h
View file

@ -9,15 +9,15 @@
// Définition de l'Arbre. // Définition de l'Arbre.
typedef Cellule *Arbre; typedef Cellule *Arbre;
// Définition d'une lettre/caractère au sens large // Définition d'une lettre/caractère pour l'entete
typedef struct lettre { typedef struct entete {
char lettre; // la lettre / caractère char lettre; // la lettre / caractère
int code; // code binaire int code; // code binaire
int longueur; // longueur du code int longueur; // longueur du code
} Lettre; } Entete;
// Convertis une liste (struct Liste) en arbre (struct Arbre). // Convertis une liste (struct Liste) en arbre (struct Arbre) et renvoie la taille des caractères valides de la liste.
void listeVersArbre(Liste *liste); int listeVersArbre(Liste *liste);
// Encode un fichier. // Encode un fichier.
void compression(FILE *entree, FILE *sortie); void compression(FILE *entree, FILE *sortie);
@ -27,19 +27,28 @@ void decompression(FILE *entree, FILE *sortie);
/* /*
Ajoute les valeurs des lettres dans l'arbre récursivement. Ajoute les valeurs des lettres dans l'arbre récursivement.
-> `arbre` l'arbre binaire de huffman - `arbre` l'arbre binaire de huffman
-> `codeActuel` monte progresssivement quand on parcours l'arbre et c'est la valeur assigné aux noeuds - `codeActuel` monte progresssivement quand on parcours l'arbre et c'est la valeur assigné aux noeuds
-> `longueur` la profondeur du noeud dans l'arbre - `longueur` la profondeur du noeud dans l'arbre
-> `lettresListe` notre liste de lettre - `lettresListe` notre liste de lettre
-> `i` nous permet de se balader dans la liste `lettresListe` (c'est l'on se trouve) - `i` nous permet de se balader dans la liste `lettresListe` (c'est l'on se trouve)
-> `longueurTotale` est la longueur totale du code en sortie en bits - `longueurTotale` est la longueur totale du code en sortie en bits
J'essaie de favoriser l'utilisation de pointeur pour éviter de recopier plus fois la même chose en mémoire. J'essaie de favoriser l'utilisation de pointeur pour éviter de recopier plus fois la même chose en mémoire.
Parcours prefixé de l'arbre. Parcours prefixé de l'arbre.
*/ */
void assignationCode(Arbre arbre, int codeActuel, int longueur, Lettre *lettresListe, int *i, int *longueurTotale); void assignationCode(Arbre arbre, int codeActuel, int longueur, Entete *lettresListe, int *i, int *longueurTotale);
// Convertis un arbre (struct Arbre) en liste (struct Lettre). // Convertis un arbre (struct Arbre/Liste) en liste (struct Entete).
Lettre * arbreVersListe(Arbre arbre, int taille, int *tailleTotale); Entete *arbreVersListe(Arbre arbre, int taille, int *tailleTotale);
// Lie le fichier d'entrée pour le transformer en liste (struct Entete) de caractères.
Entete *fichierVersListe(FILE *fichier, int *nombreLettresDansFichier, int *tailleTotale);
// Écrit l'entête avec la table de Huffman dans le fichier.
void enteteVersFichier(Entete *lettres, int nombreLettresDansFichier, int longueurTotale, FILE *fichier);
// Écrit les données une fois traduite après l'algorithme de Huffman dans le fichier de sortie.
void huffmanVersFichier(FILE *entree, FILE *sortie, Entete *listeLettres, int nombreLettresDansFichier);
#endif #endif