Version Finale (Sans erreur de traitement)

This commit is contained in:
name 2019-12-16 01:16:02 +01:00
parent c8a0b3f359
commit 81a2a61221
No known key found for this signature in database
GPG key ID: 03E8F3CF3183323A
11 changed files with 445 additions and 236 deletions

View file

@ -5,143 +5,12 @@
#include "gestion_des_fichiers/gestion_fichiers.h"
#include "main_compress.h"
#include "arbre_de_codage/arbre_binaire.h"
#ifdef DEBUG
#define DEBUG 1
#endif
#define ASCII_EXT 256
// main_compress.c [nom_du_fichier_a_compresser]
/*#########################################################################################################*/
/* Partie Fonction pour compression */
/*#########################################################################################################*/
void init_tab(arbre T[], int n){
int i;
for(i=0;i<n;i++){
T[i]=creer_feuille(-1,-1);
}
}
void frequence(arbre T[], FILE *file){
int c;
while((c=fgetc(file))!=EOF){
if(T[c]->poids!=-1){
T[c]->poids++;
}
else{
T[c]->elt=c;
T[c]->poids=1;
}
}
}
void tri_tab(arbre T[],int n){
int i,j;
arbre tmp;
for(i=0;i<n-1;i++){
for(j=i+1;j<n;j++){
if(T[i]->poids>T[j]->poids){
tmp=T[i];
T[i]=T[j];
T[j]=tmp;
}
}
}
}
int compteur_tab(arbre T[], int n){
int i,compteur;
compteur=0;
for(i=0;i<n;i++){
if(T[i]->poids != -1){
compteur++;
}
}
return compteur;
}
void afficher_tab(arbre T[], int n){
printf("\n");
int i;
for (i=0;i<n;i++){
printf("T[%d] = %d (%c)\n",i,T[i]->poids,T[i]->elt);
}
}
arbre huffman(arbre T[]){
// Création de l'arbre de codage de Huffman en considérant une liste avec les fréquences d'apparition des caractères ordonnée croissante
// récupérer les deux plus petits poids (cf : deux premieres occurences)
arbre H = malloc(sizeof(arbre));
H=creer_arbre_vide();
int i;
i=0;
while(T[i]->poids==-1){
i++;
}
int Index;
Index=i;
while(Index<ASCII_EXT-1){
arbre tmp=malloc(sizeof(noeud*));
tmp->elt=NULL;
tmp->fils_gauche=T[Index];
tmp->fils_droit=T[Index+1];
tmp->poids=T[Index]->poids +T[Index+1]->poids;
T[Index+1]=tmp;
printf("%d (%c | %c)\n",tmp->poids,tmp->fils_gauche->elt,tmp->fils_droit->elt);
Index++;
tri_tab(T,ASCII_EXT);
}
return T[Index];
}
void get_lexique(FILE *file, plex Code[], arbre huff){
int c_int;
char c_char;
rewind(file);
while((c_int=fgetc(file))!=EOF){
c_char = c_int;
if(Code[c_int]->lettre!=c_char){
Code[c_int]->lettre=c_char;
char s[9]="";
int f[1]={0};
arbre_rechercher(huff,c_char,s,0,f);
printf("Code %c : %s\n",c_int,s);
Code[c_int]->code=s;
}
}
}
void init_codage(plex Code[], int n){
int i;
for(i=0;i<n;i++){
lex * tmp = malloc(sizeof(lex));
tmp->code=NULL;
tmp->lettre=NULL;
Code[i]=tmp;
}
}
void compression(plex *Code,int n){
Bin_file *cmp;
cmp=Ouv_Bit("cmp.txt",'w');
printf("%s",(Code[0]->code)[0]);
int i;
for(i=0;i<n;i++){
char *s;
s=Code[i]->code;
while(s!='\0'){
Ec_Bit(cmp,s);
s++;
}
}
}
/*#########################################################################################################*/
/* Partie Gestion de fichiers */
/*#########################################################################################################*/
@ -149,51 +18,57 @@ void compression(plex *Code,int n){
Bin_file *Ouv_Bit(char *p,char mode)
{
/*Ouverture d'un fichier et initialisation de la structure Bin_file*/
Bin_file *A;
A=malloc(sizeof(Bin_file)); //On libère l'espace suffisant pour un élèment de type Bin_files
A->mode=mode; //On récupére le mode d'ouverture du fichier et on le rentre dansle struct
if(mode=='r') //suivant le mode (écriturer w ou lecture r) on va ouvrir le fichier a l'aide de fopen et on
{ //enregistre cela dans lestruct Bin_files
A->file=fopen(p,"rb");
A=malloc(sizeof(Bin_file)); //Libération de l'espace
A->mode=mode; //Récupération du mode (ouverture ou écriture)
if(mode=='r')
{
A->file=fopen(p,"rb"); //Ouverture en mode rb/wb. Le b est nécessaire sur windows là où les tests ont été effectués
}
else
{
A->file=fopen(p,"wb");
}
A->record_length=0; //On va ensuite initialiser tous les élèments du struct.
A->record_length=0; //Initialisation du struct
A->i_record=0;
A->i_octet=0;
A->nb_octets=0;
return A;
}
void Ec_Bit(Bin_file *output,char bit) // On veux une fonction capable d'écrire un bit dans un fichier
void Ec_Bit(Bin_file *output,char bit)
{
unsigned char octet,b; // On utilise deux variables octet et b qui vont permettre de récupérer les élèmets a écrire.
/*Ecriture bit à bit dans un fichier*/
unsigned char octet,b;
int i;
output->octet[output->i_octet]=bit; // On va mettre le premier élèment du tableau octet de la struct Bin_file a la valeur de bit
output->i_octet++; //On incremente aussi i_octet pour ne pas réecrire surcette valeur
if (output->i_octet==8) //Si le tableau octet est plein on va aller écire dans le tableau record
{
octet=0; //on passe octet a 0 et b a 0x80 soit 1000 0000
b=0x80; // cela permet de toujoursgarder 1 en bit de poids fort dans b apre les décalages a droite
output->octet[output->i_octet]=bit; //Stockage de bit dans le premier élément libre du tableau octet
output->i_octet++; //Passage à l'élément suivant
if (output->i_octet==8) //Ecriture dans record
{
octet=0; //octet et b vont permettre de passer les bits du tableau octet sous forme de chaine de caractères dans octet
b=0x80;
for(i=0;i<8;i++)
{
if(output->octet[i]=='1') //si on a un '1' dans le tableau octet on va mettre dans octet le résultats de octet ou b
if(output->octet[i]=='1')
{
octet=octet|b; // On va alors creer une "copie" du tableau octet dans octet
octet=octet|b;
}
b=b>>1;
b=b>>1; //Décalage de b à droite pour garder le 1 au bon endroit de la comparaison
}
output->i_octet=0;
output->record[output->i_record]=octet; // On va apres le for remetre i_octet a 0 puis on passe dans record la valeur du char octet pour conserver
output->i_record++; //ce que l'on veut écrire
output->nb_octets++; //On incrémente aussi i record pour passer a l'élèment suivant et nb_octets car on en a traiter un autre
if(output->i_record==BLOCK_SIZE) //On vérifie ensuite que record qui sert de buffer soit plein avant d'écrire sont contenue.
output->record[output->i_record]=octet; //Stockage de octet dans record
output->i_record++; //Incrémentation de i_record (passage à l'élément suivant) et du nombre d'octet
output->nb_octets++;
if(output->i_record==BLOCK_SIZE) //Vérification de l'état du buffer (plein ou non).
{
fwrite(output->record,1,BLOCK_SIZE,output->file);
output->i_record=0; //si on éceit on reinitialise i record pour passer auxélèments suivant
fwrite(output->record,1,BLOCK_SIZE,output->file); //Ecriture de record dans le fichier et réinitialisation de i_record(retour au début du buffer)
output->i_record=0;
}
}
@ -202,57 +77,59 @@ void Ec_Bit(Bin_file *output,char bit) // On veux u
char Lec_Bit(Bin_file*input)
{
char bit; //On veut lire un fichier bit a bit. Pourcela on va vérifier si la record length est nul ou non
unsigned char x, b=0x80; // Ici on déclare de char, x va permettre de récupérer un octet de record
// b vas servir de masque. Il nous permettra de savoir quelle valeur possède les bits des élèment de record
int i; //i est un compteur utiliser pour les boucles for
/*Lecture d'un fichier bit par bit*/
char bit;
unsigned char x, b=0x80;
int i;
if (input->record_length==0){ // Si le buffer (record),est vide on va aller chercher lesélèments du fichier
if (input->record_length==0){ //Vérification de l'état du buffer
input->record_length = fread(input->record,1,BLOCK_SIZE,input->file); //Pour cela on récupère dans record_length le nombre d'élèment de input-file et on les écrit dans record
input->i_record=0; //On réinitialise l'indice de record pour recommencerdepuis le début.
input->record_length = fread(input->record,1,BLOCK_SIZE,input->file); //Lecture du fichier et récupération du nombre d'élément
input->i_record=0;
x = input->record[input->i_record] ; //On réupère la valeurde record[i_record] dans x
x = input->record[input->i_record] ; //Copie de l'élément à lire dans x
for(i=0;i<8;i++) {
if(x&b) input->octet[i]='1'; //On va alors tester les bits de x grace a x&b. Cela permet de renvoyer 1 si lesdeux bits sont a 1
else input->octet[i]='0'; // si le test est vrai on ajoute le char 1 dans octet sinon 0
b=b>>1; //On décale ensuite b de 1 bit a droite pourconserver le 1 a l'endroit que l'on veut tester
if(x&b) input->octet[i]='1'; //Comparaison des bits de x à 1 et récupération de la valeur du bit
else input->octet[i]='0';
b=b>>1; //Décalage b à droite (1 est conservé comme élément de comparaison)
}
input->octet[8]=0; //On passe le derneir élèment de octet a 0 pour marquer la fin de chaine de caractère
input->i_record++; //on incrémente i record pour aller a l'élèment suivant on réinitialise i_octet et
input->octet[8]=0; //Mise à 0 du dernier élément du tableau octet (fin de chaine de caractère)
input->i_record++; //Passage à l'élément suivant et réinitialisation de i_octet
input->i_octet=0;
input->nb_octets=input->nb_octets+input->record_length; //On ajoute la taille du record dans nb_octets pour conserver le bon nombred'élèment traité
input->nb_octets=input->nb_octets+input->record_length; //Mise à jour du nombre d'éléments
}
bit=input->octet[input->i_octet]; //On passe alors bit a la valeur de octet[0]
input->i_octet++; //on incrémente ensuite le compteur
if(input->i_octet==8){ // Si on a écrit huit bit dans octet on va aller tester l'élèment suivant de record
x = input->record[input->i_record] ;
bit=input->octet[input->i_octet]; //Récupération de l'élément i_octet dans bit
input->i_octet++; //Incrémentation de i_octet
if(input->i_octet==8){
x = input->record[input->i_record] ; //Même fonctionnement qu'au dessus
for(i=0;i<8;i++) {
if(x&b) input->octet[i]='1';
else input->octet[i]='0';
b=b>>1;
}
input->octet[8]=0;
input->octet[8]=0; //Actualisation des éléments du struct
input->i_record++;
input->i_octet=0;;
if(input->i_record==BLOCK_SIZE){ //si on a parcouru tous le buffer on repasse a 0 la longueur
if(input->i_record==BLOCK_SIZE){ //Vérification de l'état du buffer et réinitialisation
input->record_length=0;
}
}
return bit; // on renvoie le bit
return bit; //Récupération du bit lu
}
int Ferm_Bit(Bin_file *fichier)
{
unsigned char octet,b; // On déclare deux unsigned char octet et b qui auront la même utilité que dans Ec_Bit
/*Fermeture du fichier et écriture de la fin du buffer*/
unsigned char octet,b;
int nb_octets=fichier->nb_octets;
if(fichier->mode="w") // Si le fichier a été ouvert en mode écriture on va aller écrire la fin du buffer
{ // dans le fichier.
if(fichier->i_octet!=0) //Pour cela on répète le même principe que dans Ec_Bit
if(fichier->mode=='w') //Vérification du mode d'ouverture
{
if(fichier->i_octet!=0) //Ecriture du buffer (même principe que Ec_Bit)
{
octet=0;
b=0x80;
@ -274,7 +151,7 @@ int Ferm_Bit(Bin_file *fichier)
fwrite(fichier->record,1,BLOCK_SIZE,fichier->file);
}
}
fclose(fichier->file); //On ferme ensuite le fichier et on libère l'espace occupé par le srtuct Bin_File.
fclose(fichier->file); //Fermeture du fichier et libération du sruct
free(fichier);
return nb_octets;
}
@ -352,32 +229,19 @@ void free_arbre(arbre a)
}
void arbre_rechercher(arbre a, Elt c, char s[], int s_len, int found[]){
/*
De ce que j'ai testé, ça marche de temps en temps même en ne changeant pas le caractère recherché, je pense qu'il y a un problème avec VSCode encore une fois LOL (Yûki)
*/
#ifdef DEBUG
printf("\nDEBUG ARBRE RECHERCHER : \n");
printf(" est_arbre_vide(a) : %d\n",est_arbre_vide(a));
printf(" est_feuille(a) : %d\n",est_feuille(a));
printf(" racine(a) : %c\n",racine(a));
printf(" c : %c\n",c);
printf(" est_arbre_vide(fils_gauche(a)) : %d\n",est_arbre_vide(fils_gauche(a)));
printf(" est_arbre_vide(fils_droit(a)) : %d\n",est_arbre_vide(fils_droit(a)));
printf(" S : %s\n",s);
printf("--FIN DEBUG ARBRE RECHERCHER--\n");
#endif
/*recherche d'un élément du texte dans l'arbre et récupération de son codage*/
if(!est_arbre_vide(a)){
if((a->fils_gauche==NULL)&&(a->fils_droit==NULL)&&(racine(a)==c)){
found[0]=1;
s[s_len]='\0';
found[0]=1; //Indication de la fin de recherche
s[s_len]='\0'; //Ajout du caractère d'échappement en fin de chaîne
return ;
}
if(!est_arbre_vide(fils_gauche(a))&&(found[0]==0)){
if(!est_arbre_vide(fils_gauche(a))&&(found[0]==0)){ //Passage au fils gauche et ajout de '0' dans la chaîne de caractère
s[s_len]='0';
arbre_rechercher(fils_gauche(a),c,s,s_len+1,found);
arbre_rechercher(fils_gauche(a),c,s,s_len+1,found); //Appel récursif avec passage a l'élément suivant de la chaîne.
}
if(!est_arbre_vide(fils_droit(a))&&(found[0]==0)){
if(!est_arbre_vide(fils_droit(a))&&(found[0]==0)){ //Même principe mais en ajoutant '1'
s[s_len]='1';
arbre_rechercher(fils_droit(a),c,s,s_len+1,found);
}
@ -385,6 +249,230 @@ void arbre_rechercher(arbre a, Elt c, char s[], int s_len, int found[]){
}
}
void serialisation(arbre a,FILE*file){
/*Création de la chaine de caractère qui permettra de décompresser le fichier*/
if(est_feuille(a)){
char s1[1],s2[64]; //Création des chaînes de caractère qui récupéreront l'élément de la racine et la valeur du poids en char
s1[0]=a->elt;
fwrite(s1,1,1,file); //écriture de l'élément
sprintf(s2, "%d", a->poids); //récupération du poids sous forme de char
int count = 0; //Recherche du nombre de char dans s2
while (a->poids != 0) {
a->poids /= 10;
++count;
}
fwrite(s2,count,1,file); //Ecriture de s2 et de '|'
fwrite("|",1,1,file);
}
if(!est_arbre_vide(a->fils_gauche)){ //Appels récursif sur fils droit et gauche
serialisation(a->fils_gauche,file);
}
if(!est_arbre_vide(a->fils_droit)){
serialisation(a->fils_droit,file);
}
}
void deserialisation(arbre T[], FILE*file){
/*Récupération de la chaîne de la caractère en début de fichier compréssé pour recreer le tableau de frequence*/
char c,b;
rewind(file); //retour au début du fichier
while((c=fgetc(file))!='|'&&(b=fgetc(file))!='|'){ //Recherche des caractères des ||| qui servent de carctère d'échappement
char num[64]="";
int i;
i=0;
while(b!='|'){ //Incrementation de i tant que le troisième caractère n'est pas trouvé
num[i]=b;
b=fgetc(file);
i++;
}
int poids;
char *end;
poids = strtol(num, &end, 10); //Récupération de la cahine de caractère et contruction du tableau
printf(" %c%d%c\n",c,poids,b);
T[c]->elt=c;
T[c]->poids=poids;
}
b=fgetc(file);
}
/*#########################################################################################################*/
/* Partie Fonction pour compression */
/*#########################################################################################################*/
void init_tab(arbre T[], int n){
/*Initialisaion d'un tableau composé d'arbre*/
int i;
for(i=0;i<n;i++){
T[i]=creer_feuille(-1,-1); //Initialisation des poids à -1. Les poids des caractères présents étant forcément positifs
}
}
void frequence(arbre T[], FILE *file){
/*Recherche des caractères et de leurs fréquences dans le texte*/
int c;
while((c=fgetc(file))!=EOF){ //Boucle jusqu'à la fin du fichier
if(T[c]->poids!=-1){ //Vérification du poids, le caractère a t-il été trouvé ?
T[c]->poids++; //Incrémentation du poids
}
else{
T[c]->elt=c; //Initialisation du poids à 1
T[c]->poids=1;
}
}
}
void tri_tab(arbre T[],int n){
/*Tri à bulle effectué sur les poids des éléments du tableau*/
int i,j;
arbre tmp;
for(i=0;i<n-1;i++){
for(j=i+1;j<n;j++){
if(T[i]->poids>T[j]->poids){
tmp=T[i];
T[i]=T[j];
T[j]=tmp;
}
}
}
}
void afficher_tab(arbre T[], int n){
/*Fonction de test. Affichage des éléments du tableau*/
printf("\n");
int i;
for (i=0;i<n;i++){
printf("T[%d] = %d (%c)\n",i,T[i]->poids,T[i]->elt);
}
}
arbre huffman(arbre T[]){
/*Création de l'arbre de codage de Huffman en considérant une liste avec les fréquences d'apparition des caractères ordonnée croissante*/
arbre H = malloc(sizeof(arbre)); //Libération de l'espace mémoire pour un arbre
H=creer_arbre_vide(); //Initialisation de l'arbre
int i;
i=0;
while(T[i]->poids==-1){ //Recherche du nombre de caractères effectivement présents dans le tableau
i++;
}
int Index;
Index=i; //Initialisation de Index, début effectif du tableau
while(Index<ASCII_EXT-1){
arbre tmp=malloc(sizeof(noeud*)); //Initialisation d'un arbre tmp qui aura pour fils les plus petits éléments du tableau
tmp->elt='0';
tmp->fils_gauche=T[Index];
tmp->fils_droit=T[Index+1];
tmp->poids=T[Index]->poids +T[Index+1]->poids; //Actualisation du poids de tmp.
T[Index+1]=tmp; //Mise à jour de la valeur de T[Index+1] vers tmp
printf("%d (%c | %c)\n",tmp->poids,tmp->fils_gauche->elt,tmp->fils_droit->elt); //Ligne de test
Index++; // Incrémentation de Index car un élément doit être supprimé du tableau
tri_tab(T,ASCII_EXT); //Nouveaux tri une fois les deux plus petites valeurs enlevées. tmp est mis a la bonne place
}
return T[Index]; //Renvoi du dernier élément du tableau correspondant à l'arbre final
}
void init_codage(plex Code[], int n){
/*Initialisation de la table récupérant les codes de chaque lettre*/
int i;
int j;
for(i=0;i<n;i++){
lex * tmp = malloc(sizeof(lex));
for(j=0;j<ASCII_EXT;j++){
tmp->code[j]='0';
}
tmp->lettre='0';
Code[i]=tmp;
}
}
void get_lexique(FILE *file, plex Code[], arbre huff){
/*Création du tableau des correspondances lettre/code */
int i;
char c_char;
rewind(file); //Reprise de la lecture du fichier au début
i=0;
char s[ASCII_EXT]="";
while((c_char=fgetc(file))!=EOF){ //Parcours du fichier jusqu'à la fin de ce dernier
Code[i]->lettre=c_char; //Attribution de la lettre à une case. A chaque apparition, on stocke une lettre dans une nouvelle case
int f[1]={0};
arbre_rechercher(huff,c_char,s,0,f); //Attribution du code associé à la lettre
strcpy(Code[i]->code,s);
printf("Code %c : %s\n",c_char,Code[i]->code); //Ligne de test
i++;
}
}
void compression(plex Code[],int n,arbre a){
/*Ecriture dans un nouveau fichier des lettres avec leurs nouveaux codes*/
Bin_file* cmp;
cmp=Ouv_Bit("cmp.txt",'w'); //Ouverture d'un fichier différent en écriture (évite d'écraser le contenu)
int i;
int j;
char tmp;
serialisation(a,cmp->file); //Lancement de la sérialisation : écriture de l'arbre en début de fichier
fwrite("||",2,1,cmp->file); // Mise en place de ||| qui serviront de délimitaion entre arbre et contenu
for(i=0;i<n;i++){
j=0;
while(Code[i]->code[j]!='\0'){ //écriture des bits composant le code de chaque lettre
tmp=Code[i]->code[j];
if (tmp=='0'){
Ec_Bit(cmp,'0');
}else if(tmp=='1'){
Ec_Bit(cmp,'1');
}
j++;
}
}
Ferm_Bit(cmp); // femeture du fichier compressé
}
void decompression(arbre a,Bin_file*input){
char bit='0'; //Initialisation de bit a une valur ne posant pas de conflit
Bin_file*dest; //OUverture d'un fichier où écrire la version décompressé
dest=Ouv_Bit("ucmp.txt",'w');
int i=0;
char s[1]; //chaine de caractère contenant la lettre a écrire
for(i=0;i<a->poids;i++){
arbre tmp=malloc(sizeof(arbre)); //Création d'un arbre temporaire, copie de a
tmp=a;
while(!est_feuille(tmp)){ //Parcours l'arbre tant tmp n'est pas une feuille
bit=Lec_Bit(input);
if(bit=='0'){
tmp=tmp->fils_gauche;
}else if(bit=='1'){
tmp=tmp->fils_droit;
}
}
s[0]=tmp->elt; //on écrit la valeur trouvé
fwrite(s,1,1,dest->file);
}
Ferm_Bit(dest);
}
/*#########################################################################################################*/
/* Main */
@ -397,7 +485,7 @@ int main(int argc, char **argv){
char *filename = argv[1];
char mode= 'r';
// Vérification de l'existance du second argument (Nom du fichier à compresser)
// Vérification de l'existence du second argument (Nom du fichier à compresser)
printf("Argc : %d\n",argc);
if(argc != 2){
printf("\nErreur : Veuillez mettre en argument un nom de fichier à compresser (Ex: %s text.txt)\n",argv[0]);
@ -409,32 +497,66 @@ int main(int argc, char **argv){
printf("\nErreur : Fichier %s inexistant\n",filename);
return -2;
}
printf("Tableau : \n");
arbre N[ASCII_EXT]; // Initialisation de l'arbre
printf("Entrez C pour une compression ou D pour une décompression:");
char Mode;
Mode='G';
while((Mode!='C')&&(Mode!='D')){
scanf("%c",&Mode);
printf("Rentrez C ou D\n");
}
if(Mode=='C'){
printf("\n");
printf("Tableau : \n");
arbre N[ASCII_EXT]; // Initialisation de l'arbre
printf("Tableau initialisé -1: \n");
init_tab(N,ASCII_EXT); // On initialise l'arbre avec des poids de -1
printf("Tableau initialisé -1: \n");
init_tab(N,ASCII_EXT); // On initialise l'arbre avec des poids de -1
printf("Tableau get freq : \n");
printf("Tableau get freq : \n");
frequence(N,p->file); // On récupère la fréquence d'apparition des lettres du fichiers
frequence(N,p->file); // On récupère la fréquence d'apparition des lettres du fichier
printf("Tableau tri : \n");
tri_tab(N,ASCII_EXT); // On fait un tri à bulle sur ce tableau
printf("Tableau tri : \n");
tri_tab(N,ASCII_EXT); // On fait un tri à bulle sur ce tableau
printf("Tableau affichage : \n");
afficher_tab(N,ASCII_EXT);
printf("Tableau affichage : \n");
afficher_tab(N,ASCII_EXT); //Ligne de test
arbre huff;
printf("Huffman : \n");
huff = huffman(N);
printf("Arbre :\n");
int found[1]={0};
plex Codage[ASCII_EXT];
init_codage(Codage,ASCII_EXT);
get_lexique(p->file, Codage,huff);
Ferm_Bit(p);
arbre huff;
printf("Huffman : \n");
huff = huffman(N); //Création de l'arbre de Huffman
printf("Arbre :\n");
int found[1]={0};
int taille=huff->poids; // Récupération du nombre d'éléments
plex Codage[taille]; //Création de la table de codage
init_codage(Codage,taille);
printf("Lexique:\n");
get_lexique(p->file, Codage,huff);
printf("Compression %s : \n",Codage[0]->code);
compression(Codage,taille,huff); //Lancement de la compression
printf("Fermeture:\n");
Ferm_Bit(p); //fermeture du fichier
}
else if(Mode=='D'){
printf("\n");
printf("Tableau : \n");
arbre D[ASCII_EXT];
init_tab(D,ASCII_EXT); // On initialise l'arbre avec des poids de -1
printf(" Tableau get freq FROM FILE : \n");
deserialisation(D, p->file);
printf(" Tableau tri : \n");
tri_tab(D,ASCII_EXT); // On fait un tri à bulle sur ce tableau
printf(" Tableau affichage : \n");
afficher_tab(D,ASCII_EXT);
arbre huff;
printf("Huffman : \n");
huff = huffman(D); //Reconstitution de l'abre
printf("FIN\n");
decompression(huff,p); //Décompression et femeture du fichier
Ferm_Bit(p);
}
return 0;
}

17
a.exe.stackdump Normal file
View file

@ -0,0 +1,17 @@
Exception: STATUS_ACCESS_VIOLATION at rip=00100401FE2
rax=0000000180151130 rbx=00000000FFFFC340 rcx=0000000600000010
rdx=000000000000007C rsi=0000000000000011 rdi=00000000FFFFC280
r8 =00000000FFFFC10C r9 =0000000180151130 r10=0000000100000000
r11=000000010040208D r12=0000000000000011 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
rbp=00000000FFFFC1C0 rsp=00000000FFFFC140
program=D:\Info3A\projet C\Projet-C-Huffman-master\a.exe, pid 1844, thread main
cs=0033 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
000FFFFC1C0 00100401FE2 (000FFFFC2D0, 0060006A9E0, 000FFFFC310, 0060006AA00)
000FFFFC3C0 0010040272D (000FFFFCC70, 30001010100FF00, 0018004A7AA, 001800497F0)
000FFFFCCD0 0018004A816 (00000000000, 00000000000, 00000000000, 00000000000)
00000000000 00180048353 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180048404 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace

View file

@ -3,6 +3,11 @@
#include <assert.h>
#include <string.h>
#include "arbre_binaire.h"
#ifdef DEBUG
#define DEBUG 1
#endif
arbre creer_arbre_vide (void)
{
@ -70,6 +75,21 @@ void free_arbre(arbre a)
}
void arbre_rechercher(arbre a, Elt c, char s[], int s_len, int found[]){
/*
De ce que j'ai testé, ça marche de temps en temps même en ne changeant pas le caractère recherché, je pense qu'il y a un problème avec VSCode encore une fois LOL (Yûki)
*/
#ifdef DEBUG
printf("\nDEBUG ARBRE RECHERCHER : \n");
printf(" est_arbre_vide(a) : %d\n",est_arbre_vide(a));
printf(" est_feuille(a) : %d\n",est_feuille(a));
printf(" racine(a) : %c\n",racine(a));
printf(" c : %c\n",c);
printf(" est_arbre_vide(fils_gauche(a)) : %d\n",est_arbre_vide(fils_gauche(a)));
printf(" est_arbre_vide(fils_droit(a)) : %d\n",est_arbre_vide(fils_droit(a)));
printf(" S : %s\n",s);
printf("--FIN DEBUG ARBRE RECHERCHER--\n");
#endif
if(!est_arbre_vide(a)){
if((a->fils_gauche==NULL)&&(a->fils_droit==NULL)&&(racine(a)==c)){
found[0]=1;
@ -86,4 +106,18 @@ void arbre_rechercher(arbre a, Elt c, char s[], int s_len, int found[]){
}
}
}
}
/*
void fillTable(char codeTable[], arbre tree, char Code){
if (tree->elt<27)
codeTable[(int)tree->elt] = Code;
else{
fillTable(codeTable, tree->fils_gauche, Code*10+1);
fillTable(codeTable, tree->fils_droit, Code*10+2);
}
return;
}*/

View file

@ -1,16 +1,17 @@
#ifndef __ARBRE_BINAIRE__
#define __ARBRE_BINAIRE__
typedef char Elt;
typedef int bool;
struct znoeud {
Elt elt ;
char elt ;
int poids;
struct znoeud *fils_gauche;
struct znoeud *fils_droit;
};
typedef struct znoeud noeud ;
typedef struct znoeud * arbre;
typedef char Elt;
arbre creer_arbre_vide(void);
arbre creer_arbre_huffman(Elt e, int p, arbre fg, arbre fd);
@ -22,5 +23,6 @@ bool est_arbre_vide(arbre a);
arbre creer_feuille(Elt e, int p) ;
bool est_feuille(arbre a) ;
void arbre_rechercher(arbre a, Elt c, char s[], int s_len, int found[]);
void serialisation(arbre a,FILE *file);
void serialisation(arbre a,FILE*file);
#endif

1
cmp.txt Normal file
View file

@ -0,0 +1 @@
00/ 100/n1/.1/s1000/i1/u10/c1/C10/e1/t123½PgÉCç

View file

@ -7,6 +7,9 @@
#include <string.h>
#include "gestion_fichiers.h"
Bin_file *Ouv_Bit(char *p,char mode)
{
Bin_file *A;
@ -49,13 +52,11 @@ void Ec_Bit(Bin_file *output,char bit) // On veux u
output->i_octet=0;
output->record[output->i_record]=octet; // On va apres le for remetre i_octet a 0 puis on passe dans record la valeur du char octet pour conserver
output->i_record++; //ce que l'on veut écrire
output->nb_octets++;
printf("ouput : %d %d\n",output->i_record,output->nb_octets); //On incrémente aussi i record pour passer a l'élèment suivant et nb_octets car on en a traiter un autre
output->nb_octets++; //On incrémente aussi i record pour passer a l'élèment suivant et nb_octets car on en a traiter un autre
if(output->i_record==BLOCK_SIZE) //On vérifie ensuite que record qui sert de buffer soit plein avant d'écrire sont contenue.
{
printf("test\n");
fwrite(output->record,1,BLOCK_SIZE,output->file);
output->i_record=0; //si on éceit on reinitialise i record pour passer auxélèments suivant
fwrite(output->record,1,BLOCK_SIZE,output->file);
output->i_record=0; //si on éceit on reinitialise i record pour passer auxélèments suivant
}
}
@ -139,4 +140,32 @@ int Ferm_Bit(Bin_file *fichier)
fclose(fichier->file); //On ferme ensuite le fichier et on libère l'espace occupé par le srtuct Bin_File.
free(fichier);
return nb_octets;
}
}
/*
void main()
{
Bin_file *p;
char s[16];
int i;
p=Ouv_Bit("test.txt",'r');
printf("%i\n",p->record_length);
for (i=0;i<16;i++){
s[i]=Lec_Bit(p);
}
for(i=0;i<16;i++){
printf("%c",s[i]);
}
Ferm_Bit(p);
p=Ouv_Bit("pute.txt",'w');
Ec_Bit(p,'0');
Ec_Bit(p,'1');
Ec_Bit(p,'0');
Ec_Bit(p,'0');
Ec_Bit(p,'0');
Ec_Bit(p,'1');
Ec_Bit(p,'1');
Ec_Bit(p,'0');
Ferm_Bit(p);
}
*/

View file

@ -3,16 +3,16 @@
*/
#ifndef __GESTION_FICHIERS__
#define __GESTION_FICHIERS__
#define BLOCK_SIZE 1 //il faut changer sa valeur pour les tests avec blocsize = nb d'octet qu'on veut écrire
#define BLOCK_SIZE 4096 //Une petite valeur est utile pour les tests sur de petits fichiers.
typedef struct
{
FILE *file; // Identificateur fichier
FILE *file; //Identificateur fichier
char mode; //Mode de lecture r ou w
unsigned char record[BLOCK_SIZE]; //Tampon pour lire ou écrire
int record_length; //nombre d'élèments du tampon
int i_record; //indice dans le tampon
char octet[9]; //On découpe l'octet en 8 caractère
char octet[9]; //Octet coupé en 9 caractère, 8 pour les bit et 1 pour le caractère d'échappement
int i_octet; //indice dansl'octet
int nb_octets; //Nb octet lis/écrit

1
lorem_ipsum.txt Normal file
View file

@ -0,0 +1 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc auctor eros sed odio tristique pulvinar. Nam facilisis pellentesque cursus. Integer eu iaculis odio. Pellentesque dapibus metus sit amet ante tempor, in commodo nunc feugiat. Vestibulum ac facilisis nulla, bibendum sagittis mauris. Sed tincidunt imperdiet lorem ut scelerisque. Sed dapibus nulla quam, non tempus elit dictum eu.Etiam a lectus eu nulla feugiat lobortis. Suspendisse porta augue eros, vel convallis metus euismod eget. Curabitur maximus ligula eu lacus pellentesque, nec iaculis erat ultricies. Nulla bibendum tortor sed ex consectetur, quis accumsan arcu cursus. Ut finibus porttitor commodo. Cras pellentesque lorem eget neque pharetra molestie. Mauris ultricies molestie mattis. Etiam volutpat sit amet massa et congue. Nunc non venenatis nisl, sit amet finibus est. In vitae fermentum orci. Integer quis sem et est mollis aliquet. Mauris lacus arcu, aliquet non vulputate fringilla, pellentesque hendrerit mauris metus.

View file

@ -4,9 +4,9 @@
#include "arbre_de_codage/arbre_binaire.h"
#include "gestion_des_fichiers/gestion_fichiers.h"
struct lexique{
struct lexique{ //Struct permettant d'associer une lettre et son code
char lettre;
char code[256];
char code[256]; //N'ayant
};
typedef struct lexique lex;
typedef struct lexique* plex;
@ -18,5 +18,6 @@ void afficher_tab(arbre T[], int n);
void init_tab(arbre T[], int n);
void get_lexique(FILE *file, plex Code[], arbre huff);
void init_codage(plex Code[], int n);
void decompression(arbre a,Bin_file*input);
#endif

1
test.txt Normal file
View file

@ -0,0 +1 @@
Ceci est un test.

1
ucmp.txt Normal file
View file

@ -0,0 +1 @@
Ceci est un test.