PDA

Visualizza la versione completa : C++ Codice di huffmann codifica file


Chupacabras
06-03-2009, 19:23
Ciao ragazzi!
ho bisogno che qualcuno mi aiuti prima che io vada a finire alla neuro!!!
allora di seguito vi posto il mio codice in c++.
L'algoritmo utilizzanto è quello di huffman ed il programma dovrebbe comprimere un file e poi decomprimerlo.
Badate bene a quello che mi succede se cerco di codificare un file testo....(intendiamoci parlo di file di poche righe che ho fatto girare in modo da poter controllare in tutto col debug)
succede che quando nel primo ciclo while di letture di 8 bit per volta io mi vado a leggere tutto il file la cosa procede bene...ma quando nella fase di decodifica vado a leggere il file codificato,in particolare l'header dove ho salvato per ogni carattere le corrispottiva sequenza,il while con la file.get(ch) mi si blocca quando incontra un '.' (46 in ascii)
la cosa proprio non la capisco! :berto:
cioè sono due cicli while identici che fanno la stessissima cosa ma uno dei due si blocca quando incontra un '.'
se qualcuno potesser dare un'occhiata....premetto,il codice non è ben scritto assolutamente,almeno dal punto di vista formale...ho inizato a lavorarci solo da un paio di giorni e diciamo anche abbastanza di getto...sicuramente ci saranno un sacco di cose inutili ed insomma...non è un bel codice,ma per ora mi interessa che funzioni!
Quello che vi posso assicurare che la codifica e la decodifica viene fatta bene,l'ho provata col debug carta e penna...ma non capisco proprio perchè mi si blocca alla fine quel while!!è identico al precedente...ormai ci perdo la testa!!!!


#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>
#include <time.h>
#include <queue>
#include <math.h>
using namespace std;
string deco="";
map<char,string> codec;
map<char,string> ::iterator ptr2;
class NodoHuff {
private:
char value;
char key;
const NodoHuff *f_destro;
const NodoHuff * f_sinistro;
public:
NodoHuff(char a =0,char b=0){ value=a;key=b;f_destro=0;f_sinistro=0;}
NodoHuff(const NodoHuff *destro,const NodoHuff *sinistro)
{key=destro->key+sinistro->key;
f_destro=destro;f_sinistro=sinistro;}
bool operator>(const NodoHuff &a)const
{return key>a.key;}
void trovacodifica (string code ="") const
{
if(f_sinistro)
{
f_sinistro->trovacodifica(code+"0");
f_destro->trovacodifica(code+"1");
}
else
codec[value]=code;
;}
string decodifica (string ss,NodoHuff nodo_corrente,int n)
{
short i=0;
NodoHuff *ptr = new NodoHuff (nodo_corrente);
*ptr=nodo_corrente;
int j=0;
while(i!=ss.size()&&j<n)
{
if(ss[i]=='0')
if(ptr->f_sinistro!= 0)
{
*ptr=*(ptr->f_sinistro);
i++;
}
else
{
deco=deco+(ptr->value);
j++;
*ptr=nodo_corrente;
}
if(ss[i]=='1')
if(ptr->f_destro!=0)
{
*ptr=*(ptr->f_destro);
i++;
}
else
{
deco=deco+(ptr->value);
j++;
*ptr=nodo_corrente;
}
}
return deco;
}


};

string recupera_codice(char x1)
{
string value;
char mask=1,i=0;
unsigned char x=(unsigned char)x1;
while (i<8)
{
if((x%2)==1)
{
value ="1"+value;
mask=mask<<1;
}
else
{
value="0"+value;
}
x=x/2;
i++;

}
return value;
};
string calcola_binario (string ss)
{
char j,x=8-(ss.size()%8);
for(j=0;j<x;j++)
ss=ss+'0';
short i=1;
string code="";
char value =0;
while(i!=ss.size())
{
if (ss[i-1]=='1')
value=value+(char)pow(2.F,8-(i%8));
if((i%8)==0 && i!=1)
{
if(ss[i-1]=='1')
value=value+1;
code=code+value;
value=0;
}
i++;
}
code=code+value;
return code;
}


void main ()
{
int num_b=0;
string codice="",codice2="";
ifstream file,file2,recupero,lettura2;
ofstream compresso,decompresso;
char nome_file[30],nome_compresso[30];
cout <<"Inserire il nome del file da comprimere : ";
cin>>nome_file;
file.open(nome_file);
if(file.fail())
{
cout<<endl<<"Errore in apertura file "<<endl;
exit(1);
}
char ch;
map <char,int> freq;
map <char,int>::iterator ptr;
file.get(ch);
while (!file.eof())//memorizzo per ogni carattere la
frequenza in una mappa ed in questo ciclo tutto funziona
bene anche se ho dei ..
{
ptr=freq.find(ch);
if(ptr==freq.end())
freq[ch]=1;
else
freq[ch]++;
file.get(ch);
num_b++;
}
ptr=freq.find(EOF);
if(ptr!=freq.end())
freq.erase(ptr);
int i=0;

cout<<"Inserire il nome del nuovo file compresso : ";
cin>>nome_compresso;
compresso.open(nome_compresso);
if(compresso.fail())
{
cout<<endl<<"Errore in apertura file "<<endl;
exit(1);
}
priority_queue< NodoHuff, vector<NodoHuff>, greater<NodoHuff> > Que;
for (ptr=freq.begin();ptr!=freq.end();ptr++)//inserisco i nodi nella coda di priorità
{
i++;
NodoHuff(ptr->first,ptr->second);
Que.push(NodoHuff(ptr->first,ptr->second));
}
compresso<<(int)freq.size();
if(i==(int)freq.size())
cout<<"ooook!"<<endl;
i=0;
for (ptr=freq.begin();ptr!=freq.end();ptr++)
{
compresso<<ptr->first<<ptr->second;
cout<<ptr->first<<' '<<ptr->second<<endl;
i++;
}
if(i==(int)freq.size())
cout<<"ooook!"<<endl;
compresso<<" ";
//creo l'albero di huffmann
while (Que.size()>1)
{
NodoHuff *destro = new NodoHuff( Que.top());
Que.pop();
NodoHuff *sinistro = new NodoHuff (Que.top());
Que.pop();
Que.push(NodoHuff(destro,sinistro));
}
Que.top().trovacodifica();
file2.open(nome_file);
while (file2.get(ch))
{
ptr2=codec.find(ch);
codice=codice+ptr2->second;
}
codice = calcola_binario (codice);
compresso<<num_b<<codice;
compresso.close();
file.close();

/******************************************decompre ssione******************************************** **/
map <char,int> freq2;
map <char,int>::iterator ptrfre;
recupero.open(nome_compresso);
if(recupero.fail())
{
cout<<endl<<"Errore in apertura file "<<endl;
exit(1);
}
char ch2;
int x,max,j=0;
recupero>>max;
recupero.get(ch2);
while (j<max)//memorizzo per ogni carattere la
frequenza in una mappa, stesso ciclo di prima stesse istruzioni
e si blocca se trova dei ....
{
recupero>>x;
freq2[ch2]=x;
recupero.get(ch2);
j++;
}
priority_queue< NodoHuff, vector<NodoHuff>, greater<NodoHuff> > Que2;
for (ptrfre=freq2.begin();ptrfre!=freq2.end();ptrfre++ )//inserisco i nodi nella coda di priorità
{

NodoHuff(ptrfre->first,ptrfre->second);
Que2.push(NodoHuff(ptrfre->first,ptrfre->second));
}
while (Que2.size()>1)
{
NodoHuff *destro = new NodoHuff( Que2.top());
Que2.pop();
NodoHuff *sinistro = new NodoHuff (Que2.top());
Que2.pop();
Que2.push(NodoHuff(destro,sinistro));
}
NodoHuff *testa = new NodoHuff(Que2.top());
decompresso.open("decompresso.txt");
recupero>>num_b;
recupero.get(ch2);
while(!recupero.eof())
{
codice2=codice2+recupera_codice(ch2);
recupero.get(ch2);

}
decompresso<<Que2.top().decodifica(codice2,Que2.top(),num_b);
}

YuYevon
06-03-2009, 23:32
Ehilà chupacabras! Il web è piccolo a quanto pare...

Non penso che qualcuno trovi mai il tempo e la voglia di debuggare un codice di 200 righe e più, tanto più se il problema è apparentemente paradossale come lo definisci tu.

Come hai definito questo benedetto header? Puoi postarne un esempio su un file piccolo, anche di pochi caratteri? Non ha alcun senso il fatto che un ciclo iterativo di lettura da un file si fermi quando trova un punto...

Tra l'altro, la chiamata all'ultimo metodo (decodifica) mi da questo errore (con Dev):

"`const NodoHuff' as `this' argument of `std::string NodoHuff::decodifica(std::string, NodoHuff, int)' discards qualifiers "

Chupacabras
06-03-2009, 23:43
:dottò: stavo giusto chiedendo al moderatore del forum come fare per modificare il mex per mettere un codice che riassuma il mio problema su piccole dimensioni...sai quando l'ho deciso di postare ero letteralmente in crisi!!
ora però mi hai convinto visto che la cosa non si smuove invece di continuare a vedere sti bit che camminano avanti e indietro vedo di scrivere qualcosa che possa essere compreso anche da altri facilmente in modo da rendere partecipe anche voi dei miei problemi!!

alka
07-03-2009, 02:40
Originariamente inviato da Chupacabras
:dottò: stavo giusto chiedendo al moderatore del forum come fare per modificare il mex per mettere un codice che riassuma il mio problema su piccole dimensioni...sai quando l'ho deciso di postare ero letteralmente in crisi!!
Non è più possibile modificare un messaggio trascorso un certo lasso di tempo...

Se vuoi aggiornare la discussione, basta che scrivi di nuovo riportando le correzioni, le integrazioni o - in questo caso - le riduzioni.

Ciao! :ciauz:

YuYevon
07-03-2009, 14:05
Originariamente inviato da Chupacabras
:dottò: stavo giusto chiedendo al moderatore del forum come fare per modificare il mex per mettere un codice che riassuma il mio problema su piccole dimensioni...sai quando l'ho deciso di postare ero letteralmente in crisi!!
ora però mi hai convinto visto che la cosa non si smuove invece di continuare a vedere sti bit che camminano avanti e indietro vedo di scrivere qualcosa che possa essere compreso anche da altri facilmente in modo da rendere partecipe anche voi dei miei problemi!!

Ecco esatto, cerca di "estrarre" il problema da quella caterva di righe di codice, anche perché è inutile postare un intero progetto per un problemino che riguarda 4-5 righe di codice che tra l'altro non c'entrano nulla con l'algoritmo centrale.

Ah qualche consiglio... so che (come hai detto) questa è ben lungi dall'essere la versione definitiva, ma comunque:

1) cerca di evitare come la peste le variabili globali a meno che usarle non sia proprio una questione di vita o di morte, questo non solo perché puoi avere problemi ma anche perché tu-sai-chi non lo gradirebbe molto;

2) evita l'utilizzo dei vecchi header stile C quando programmi in C++, quindi sostituisci math.h e time.h rispettivamente con cmath e ctime (by the way, sei così sicuro che ti serva cmath solo per la funzione pow() ?);

3) immagino che sai che compressione e decompressione devono avvenire separatamente, e non contestualmente all'interno dello stessa esecuzione del programma... cioè, io comprimo lanciando il programma (magari con un'apposita opzione) e poi DOPO, a programma terminato, decido di rilanciarlo per procedere con la decompressione;

4) quel void main() stile Luigi XVI in accordo con lo standard Visual C++ v.quello-che-è è un pugno nell'occhio per qualsiasi altro compilatore diverso dal suddetto :D

Buon lavoro!

Chupacabras
07-03-2009, 14:16
ti ringrazio ma sono tutte cose che già sapevo di dover cambiare(al dire il vero anche qualcosa in più) francamente sono impegnato per ora a capire perchè non va dopo di che perderò tempo che tutti questo accorgimenti...ho scritto un mezzo codice ma prima di postare preferisco guardarmelo ancora un po e cercare di mettere qualche file più piccolo che da lo stesso problema...ieri notte mi è venuta un'altra idea dell'ipotetica causa del problema e sto percorrendo quest'altra strada prima di postare altro codice brutto!!

grazie comunque!

ciao!!

edit

quel void main() stile Luigi XVI in accordo con lo standard Visual C++ v.quello-che-è è un pugno nell'occhio per qualsiasi altro compilatore diverso dal suddetto

a questo ci sono particolarmente affezionato perchio' sarà sempre presente nelle mie bozze!!!! :prrr:

MItaly
07-03-2009, 16:57
Originariamente inviato da Chupacabras
a questo ci sono particolarmente affezionato perchio' sarà sempre presente nelle mie bozze!!!! :prrr:
http://users.aber.ac.uk/auj/voidmain.shtml

Loading