Desktop/Daniele/Program Editing/Progetto di informatica 2/componenti/decompressore.cpp

00001 
00002 #include "decompressore.h"
00003 /* funzione che eleva a potenza b un intero a */
00004 int decompressore::elevato (int a, int b)
00005 {
00006 if (a == 0) return 0;
00007 int app = 1;
00008 for (int i = 0; i < b; i++)
00009     app *= a;
00010 return app;
00011 }
00012 
00013 /*questa funzione è necessaria per come è implementata la traduzione da
00014 carattere a intero, infatti in certi casi i valori sono completamente
00015 errati, definisco questa funzione per operare direttamente sui bit*/
00016 int decompressore::traduci (char c)
00017 {
00018 int a = 0;
00019 for (int i = 0; i < 8; i++)
00020     a = a + ((c >> (i)) & 1) * elevato(2,i);
00021 return a;
00022 }
00023 //#define DEBUG true
00024     #if DEBUG
00025     #include <iostream>
00026     #endif
00027     
00028     #if DEBUG
00029     namespace dec
00030     {
00031     void preorderp (node* tree)
00032     {
00033     if (tree == 0) return;
00034     cout << tree -> left << ' ' << tree -> right << endl;
00035     preorderp (tree -> left);
00036     preorderp (tree -> right);
00037     }
00038     void preorder (node* tree)
00039     {
00040     if (tree == 0) return;
00041     cout << tree -> c << ' ' << tree -> freq << endl;
00042     preorder (tree -> left);
00043     preorder (tree -> right);
00044     }
00045     void postorder (node* tree)
00046     {
00047     if (tree == 0) return;
00048     postorder (tree -> left);
00049     postorder (tree -> right);
00050     cout << tree -> c << ' ' << tree -> freq << endl;
00051     }
00052     void inorder (node* tree)
00053     {
00054     if (tree == 0) return;
00055     inorder (tree -> left);
00056     cout << tree -> c << ' ' << tree -> freq << endl;
00057     inorder (tree -> right);
00058     }
00059     }
00060     #endif
00061 
00062 decompressore::decompressore(const char file[], const char fileo[])
00063 {
00064 stream.open(fileo, ios::out|ios::binary);
00065 if (!stream) throw "apertura";
00066     #if DEBUG
00067     cout << "apertura ultimata" << endl;
00068     system ("PAUSE");
00069     #endif
00070 contatore = 8;
00071 IOl in(file,pf,num); //pf ora punta a un array di 
00072                      //puntatori a frequenze (non ordinato)
00073     #if DEBUG
00074     cout << "vettorizzazione, stampo risultati" << endl;
00075     cout << "vettore pf:" << endl;
00076     for (int i = 0; i < num; i++)
00077         cout << pf[i]->c << ' ' << pf[i]->freq << endl;
00078     system ("PAUSE");
00079     #endif
00080 occorrenze = new int[256];
00081 for (int i = 0; i < 256; i++)
00082     occorrenze [i] = 0;
00083 heap hp(pf,num); //costruisce lo heap dei puntatori (esso è ancora puntato da pf)
00084     #if DEBUG
00085     cout << "generazione heap completata" << endl;
00086     for (int i = 0; i < num; i++)
00087         cout << hp.v[i] -> c << ' ' << hp.v[i]->freq << endl;
00088     system ("PAUSE");
00089     #endif
00090 
00091 int last = hp.lastn();
00092 root = huffman (hp, last);
00093 pun = root;
00094 delete[] pf; //una volta che ho distrutto il contenuto di questo array
00095              //anche l'heap corrispondente è vuoto
00096 pf = 0;
00097     #if DEBUG
00098     cout << "costruzione albero ultimata" << endl;
00099     dec::preorder (root);
00100     cout << "--------" << endl;
00101     dec::postorder (root);
00102     cout << "--------" << endl;
00103     dec::inorder (root);
00104     system ("PAUSE");
00105     #endif
00106 
00107 buffer[0] = in.leggi(); //legge il primo numero se esiste
00108 if (buffer[0] == -1) throw "vuoto"; //altrimenti genera l'eccezione
00109 int p = riempibuffer(in);
00110 if (p == -1) throw "vuoto";
00111     #if DEBUG
00112     cout << "primo riempimento eseguito con successo" << endl;
00113     for (int i = 0; i < 8; i++)
00114         cout << buffer[i] << ' ';
00115     cout << endl;
00116     #endif
00117 traduci(in); //funzione che traduce l'intero file
00118     #if DEBUG
00119     cout << "traduzione terminata" << endl;
00120     #endif
00121 delete[] occorrenze;
00122 occorrenze = 0;
00123 cancella (root);
00124 pun = 0;
00125 }
00126 
00127 node* decompressore::huffman (heap H, int last) //il mio heap va a costruire
00128 {                                               //l'albero di huffman
00129 for(int i = 0; i < last; i++) 
00130     {
00131     node* t = new node;
00132     if (t == 0) throw "memoria";
00133     t->left = H.estrai();
00134     t->right = H.estrai();
00135     t->freq= t->left->freq + t->right->freq; 
00136     H.inserisci(t);     
00137     }
00138 return H.estrai();
00139 }
00140 
00141 int decompressore::riempibuffer(IOl& in) //questa funzione inserisce nel buffer
00142                                          //dal secondo all'ultimo simbolo
00143 {
00144 if (contatore != 8) throw "contatore";
00145 contatore = 0;
00146 for (int i = 1; i < 8; i++)
00147     {
00148     int a = in.leggi();
00149     if (a == -1) return -1;
00150     buffer[i] = a;
00151     }
00152     
00153     #if DEBUG
00154     cout << "riempimento ultimato" << endl;
00155     for (int i = 0; i < 8; i++)
00156         cout << buffer[i] << ' ';
00157     cout << endl;
00158     #endif
00159 return 1;
00160 }
00161 
00162 void decompressore::traduci(IOl& in) 
00163 {
00164 if (root -> left == 0 && root -> right == 0)
00165    { //nel caso avessi un solo carattere nel file
00166    int mem = in.leggi();
00167    while (mem != -1)
00168          {
00169          stream.put (root->c);
00170          if (++contatore == 8)
00171             {
00172             buffer[0] = mem;
00173             riempibuffer(in);
00174             mem = in.leggi();
00175             }
00176          }
00177    if (mem == -1)
00178       while (buffer[contatore++] == 1)
00179             stream.put (root -> c);
00180    return;
00181    }            
00182 int mem = in.leggi(); //ogni volta mi asservo il prossimo numero, in questo modo
00183                       //se esso dovesse essere -1 (file terminato)
00184                       //posso invocare per tempo la funzione ultimo sull'ultimo+
00185                       //buffer completo del file
00186 while (mem != -1)
00187     {   
00188     for (int i = 0; i < 8; i++) //ciclo che stampa il contenuto del buffer
00189         {
00190         if (contatore > 7 || contatore < 0)
00191             throw "contatore";
00192         if (buffer[contatore] == 0) pun = pun -> left;
00193         if (buffer[contatore] == 1) pun = pun -> right;
00194         contatore++;
00195         if (pun -> left == 0 && pun -> right == 0)
00196            {
00197            int intc = traduci (pun -> c);
00198            if(occorrenze[intc] == pun -> freq)
00199                throw "lettura";
00200            occorrenze[intc]++;
00201            stream.put(pun -> c);
00202            pun = root;
00203            }
00204         }
00205     buffer[0] = mem;
00206     riempibuffer(in);
00207     mem = in.leggi();
00208     }
00209 ultimo();
00210 return;
00211 }
00212 
00213 void decompressore::ultimo()
00214 {
00215     #if DEBUG
00216     cout << "ultimo buffer" << endl;
00217     system ("PAUSE");
00218     for (int i = 0; i < 8; i++)
00219         cout << buffer[i] << ' ';
00220     cout << endl;
00221     #endif
00222 for (int i = 0; i < 8; i++) //ciclo che stampa il contenuto del buffer
00223     {
00224     if (contatore > 7 || contatore < 0) throw "contatore";
00225     if (buffer[contatore] == 0) pun = pun -> left;
00226     if (buffer[contatore] == 1) pun = pun -> right;
00227     contatore++;
00228     if (pun -> left == 0 && pun -> right == 0) 
00229        {
00230        int intc = traduci (pun -> c);
00231        if(occorrenze[intc] == pun -> freq) //se si verifica questa con
00232                                                //condizione ho terminato la
00233                                                //traduzione e quindi esco
00234            return;
00235        occorrenze[intc]++;
00236        stream.put(pun -> c);
00237        pun = root;
00238        }
00239     }
00240 }
00241 
00242 void decompressore::cancella(node*& tree) //funzione di appoggio per la
00243                                           //distruzione dell'albero
00244 {
00245 if (tree==0) return;
00246 cancella (tree ->left);
00247 cancella (tree -> right);
00248 delete tree;
00249 tree = 0;
00250 }
00251 
00252 
00253 
00254 
00255     

Generated on Sat May 20 14:57:56 2006 for Huffzip by  doxygen 1.4.6-NO