Version Finale (Sans erreur de traitement)
This commit is contained in:
parent
c8a0b3f359
commit
81a2a61221
11 changed files with 445 additions and 236 deletions
558
Compress.c
558
Compress.c
|
|
@ -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
|
||||
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; //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
|
||||
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);
|
||||
arbre huff;
|
||||
printf("Huffman : \n");
|
||||
huff = huffman(N); //Création de l'arbre de Huffman
|
||||
|
||||
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);
|
||||
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
17
a.exe.stackdump
Normal 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
|
||||
|
|
@ -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;
|
||||
|
|
@ -87,3 +107,17 @@ 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;
|
||||
}*/
|
||||
|
|
@ -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
1
cmp.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
00/ 100/n1/.1/s1000/i1/u10/c1/C10/e1/t123½PgÉCç
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,3 +141,31 @@ int Ferm_Bit(Bin_file *fichier)
|
|||
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);
|
||||
}
|
||||
*/
|
||||
|
|
@ -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
1
lorem_ipsum.txt
Normal 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.
|
||||
|
|
@ -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
1
test.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Ceci est un test.
|
||||
1
ucmp.txt
Normal file
1
ucmp.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
Ceci est un test.
|
||||
Reference in a new issue