⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compress.cpp

📁 我最近写的一个LZW的压缩与解压缩程序。可能有个别地方尚有缺陷
💻 CPP
字号:
// LZW compression

// note changes needed to compile with g++

#include <fstream.h>
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "chash.h"

// constants
const D = 4099,      // hash function divisor
      codes = 4096,  // 2^12
      ByteSize = 8,
      excess = 4,    // 12 - ByteSize
      alpha = 256,   // 2^ByteSize
      mask1 = 255,   // alpha - 1
      mask2 = 15,    // 2^excess - 1
	  mask = 15;
class Celement {
   friend void Compress();
   public:
      operator unsigned long() const {return key;}
      Celement& operator =(unsigned long y)
         {key = y; return *this;}
   private:
      int code;
      unsigned long key;
};
class Delement {
   friend void Decompress();
   friend void Output2(int);
   private:
      int prefix;
      unsigned char suffix;
};

// globals
unsigned char s[codes];  // used to reconstruct text
int size,                // size of reconstructed text
    LeftOver,            // left over bits from last code
    status = 0;          // 0 iff no left over bits
Delement ht[codes];       // dictionary
ifstream in;
ofstream out;

void SetFiles1(int argc, char* argv[])
{// Create input and Output1 streams.
   char OutputFile[50], InputFile[50];
   // see if file name provided
   if (argc >= 2) strcpy(InputFile,argv[1]);
   else {// name not provided, ask for it
         cout << "Enter name of file to compress"
              << endl;
         cout << "File name should have no extension"  
              << endl;
         cin >> InputFile;}

   // name should not have an extension
   if (strchr(InputFile,'.')) {
       cerr << "File name has extension" << endl;
       exit(1);}

   // open files in binary mode
   in.open(InputFile,ios::binary);
   // in.open(InputFile); for g++
   if (in.fail()) {cerr << "Cannot open " << InputFile 
                        << InputFile << endl;
                   exit(1);}
   strcpy(OutputFile,InputFile);
   strcat(OutputFile, ".zzz");
   out.open(OutputFile,ios::binary);
   // out.open(OutputFile); for g++
}

void Output1(unsigned long code);

void Compress()
{// Lempel-Ziv-Welch compressor.
   // define and initialize the code dictionary
   ChainHashTable<Celement, unsigned long> h(D);
   Celement e;
   for (int i = 0; i < alpha; i++) {// initialize
      e.key = i;
      e.code = i;
      h.Insert(e);
      }
   int used = alpha; // number of codes used

   // input and compress
   unsigned char c;
   in.get(c);      // first character of input file
   unsigned long pcode = c; // prefix code
   if (!in.eof()) {// file length is > 1
      do {// process rest of file
          in.get(c);
          if (in.eof()) break;  // finished
          unsigned long k = (pcode << ByteSize) + c;
          // see if code for k is in the dictionary
          if (h.Search(k, e)) pcode = e.code;  // yes
          else {// k not in table
                Output1(pcode);
                if (used < codes) // create new code
                   {e.code = used++;
                    e.key = (pcode << ByteSize) | c;
                    h.Insert(e);}
                pcode = c;}
   	} while(true);

      // output last code(s)
      Output1(pcode);
      if (status) {c = LeftOver << excess;
                   out.put(c);}
      }

   out.close();
   in.close();
}

void Output1(unsigned long pcode)
{// Output1 8 bits, save rest in LeftOver.
   unsigned char c,d;
   if (status) {// 4 bits remain
      d = pcode & mask1; // right ByteSize bits
      c = (LeftOver << excess) | (pcode >> ByteSize);
      out.put(c);
      out.put(d);
      status = 0;}
   else {
      LeftOver = pcode & mask2; // right excess bits
      c = pcode >> excess;
      out.put(c);
      status = 1;}
}

void SetFiles2(int argc, char* argv[])
{// Determine file name.
   char OutputFile[50], InputFile[50];

   // see if file name provided
   if (argc == 2) strcpy(OutputFile,argv[1]);
   else {// name not provided, ask for it
         cout << "Enter name of file to decompress"
              << endl;
         cout << "Omit the extension .zzz"  << endl;
         cin >> OutputFile;}

   // name should not have an extension
   if (strchr(OutputFile,'.'))
      {cerr << "File name has extension" << endl;
       exit(1);}

   strcpy(InputFile, OutputFile);
   strcat(InputFile, ".zzz");

   // open files in binary mode
   in.open(InputFile,ios::binary);
   // in.open(InputFile);  for g++
   if (in.fail()) {cerr << "Cannot open "
                        << InputFile  << endl;
                   exit(1);}
   out.open(OutputFile,ios::binary);
   // out.open(OutputFile); for g++
}

bool GetCode(int& code);
void Output2(int code);

void Decompress()
{// Decompress a compressed file.
   int used = alpha; // codes used so far

   // input and decompress
   int pcode,  // previous code
       ccode;  // current code
   if (GetCode(pcode)){// file is not empty
      s[0] = pcode;   // character for pcode 
      out.put(s[0]);  // output string for pcode
      size = 0; // s[size] is first character of
                // last string output
                
      while(GetCode(ccode)) {// get another code
        if (ccode < used) {// ccode is defined
           Output2(ccode);
           if (used < codes) {// create new code
              ht[used].prefix = pcode;
   	      ht[used++].suffix = s[size];}}
        else {// special case, undefined code
              ht[used].prefix = pcode;
              ht[used++].suffix = s[size];
              Output2(ccode);}
        pcode = ccode;}
        }

   out.close();
   in.close();
}

bool GetCode(int& code)
{// Put next code in compressed file into code.
 // Return false if no more codes.
   unsigned char c, d;
   in.get(c);  // input 8 bits
   if (in.eof()) return false;  // no more codes

   // see if any left over bits from before
   // if yes, concatenate with left over 4 bits
   if (status) code = (LeftOver << ByteSize) | c;
   else {// no left over bits, need four more bits
         // to complete code
         in.get(d);  // another 8 bits
         code = (c << excess) | (d >> excess);
         LeftOver = d & mask;}  // save 4 bits
   status = 1 - status;
   return true;
}
   
void Output2(int code)
{// Output string corresponding to code.
   size = -1;
   while (code >= alpha) {// suffix in dictionary
      s[++size] = ht[code].suffix;
      code = ht[code].prefix;
      }
   s[++size] = code;  // code < alpha

   // decompressed string is s[size] ... s[0]
   for (int i = size; i >= 0; i--)
      out.put(s[i]);
}

void main(int argc, char* argv[])
{
   cout<<"please choose the operates you want:(1.compress files;2.decompress files)"<<endl;
   char c;
   cin>>c;
   if(c=='1')
   {
	   SetFiles1(argc, argv);
       Compress();
   }
   else if(c=='2')
   {
	   SetFiles2(argc, argv);
	   Decompress();
   }
   else
	   cout<<"wrong input!"<<endl;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -