Program kompresujący RLE - zawiesza się

0

Witam,

napisałem prosty program, który ma za zadanie kompresować pliki. Pojawiły się 2 problemy:

  1. Ja obliczyć długość pliku - potrzebne do pętli (dlatego przypisałem długość ręcznie int b)
  2. Program zawiesza się po kilku sekundach.
#include <fstream>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <string.h>
#include <bitset>

 
using namespace std;
 
int main()
{

    string str,napis;
    ifstream in;
    in.open("data.txt");
    getline(in,str);
    while ( in ) 
    {
      napis += str;
      getline(in,str);
    }
    
    int a, b, licznik = 0;
    
    //b = napis.length(); // nie działa poprawnie
    b = 78069;
    
    cout << "Dlugosc pliku: " << b << endl;
    
    ofstream myfile;
    myfile.open ("wynik.txt");
    
    for(a=0;a<b;a++)
    {
        if(napis[a] == napis[a+1]) licznik++;
        else
        {
            if(licznik>0) 
            {
               licznik = licznik-1;
               myfile << napis[a];
               myfile << napis[a];
               myfile << licznik;
               licznik = 0;
            }
            else 
            {
               myfile << napis[a]; 
            }       
        }
        cout << a << " / " << b << endl;            

    }

    myfile.close(); 
    
    cout << "Konwersja zakonczona" << endl;
    system("pause");
}
 
0

Problemem w tym wypadku może być występowanie w pliku znaków '\0' (takie przypuszczenie nie sprawdzane, ponieważ wszystko działa dobrze dla normalnych plików tekstowych), zmień sposób pobierania danych wejściowych. Dodatkowo pliki binarne musisz otwierać przez specjalny tryb, ponieważ w innym wypadku będzie sczytywać "\r\n" jako "\n" (getline w ogóle to odrzuci).

Sprawdź, czy po wczytaniu pliku jest ustawiany badbit, failbit, czy eofbit.

0

Super :) Udało się:

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  int length;
  char * buffer;

  ifstream is;
  is.open ("test.txt", ios::binary );

  is.seekg (0, ios::end);
  length = is.tellg();
  is.seekg (0, ios::beg);

  buffer = new char [length];

  is.read (buffer,length);

  is.close();

    int a, b, licznik = 0;
    float postep;
    
    b = length;
    
    ofstream myfile;
    myfile.open ("archiwum.luk");
    
    for(a=0;a<b;a++)
    {
        if(buffer[a] == buffer[a+1]) licznik++;
        else
        {
            if(licznik>0) 
            {
               licznik = licznik-1;
               myfile << buffer[a];
               myfile << buffer[a];
               myfile << licznik;
               licznik = 0;
            }
            else 
            {
               myfile << buffer[a]; 
            }       
        }
    }

    myfile.close(); 
    
    cout << "Konwersja zakonczona" << endl;

}

Jeszcze pytanie. Co zrobić aby móc wpisać nazwę pliku jaki chcę wczytać?

0

Są dwa rozwiązania, możesz wczytać ze standardowego wejścia, lub przekazać jako argument. Podpowiedź: inna wersja main, szukaj argc i argv.

0

A dlaczego masz dwa razy:

myfile << buffer[a];
myfile << buffer[a];

?

0

Tutaj poprawiony kod:

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  int length;
  char * buffer;

  ifstream is;
  is.open ("test.txt", ios::binary );

  is.seekg (0, ios::end);
  length = is.tellg();
  is.seekg (0, ios::beg);

  buffer = new char [length];

  is.read (buffer,length);

  is.close();

    int a, b, licznik = 0;
    float postep;
    
    b = length;
    
    ofstream myfile;
    myfile.open ("archiwum.luk");
    
    for(a=0;a<b;a++)
    {
        if(buffer[a] == buffer[a+1]) licznik++;
        else
        {
            while(licznik>10)
            {
               licznik = licznik-11;   
               myfile << buffer[a];
               myfile << buffer[a];
               myfile << 9;                      
                            
            }                
            
            if((licznik>0) && (licznik<10)) 
            {
               licznik = licznik-1;
               myfile << buffer[a];
               myfile << buffer[a];
               myfile << licznik;
               licznik = 0;
            }
            else 
            {
               myfile << buffer[a]; 
            }       
        }
    }

    myfile.close(); 
    
    cout << "Konwersja zakonczona" << endl;

}
0

A jak wygląda kod dekompresujący? Działa dla np: skompresuj tekst "11234455656555577777" i zdekompresuj. Wyjdzie ok?
Dlaczego zapisujesz ilość powtórzeń dziesiętnie??? Ograniczasz się do 9 znaków. Użyj całej wartości bajta i już możesz mieć 256 znaków (0 to 1, 1 to 2 itp).

0

W sumie można zrobić tak jak podpowiadasz :) 11234455656555577777 -> 11023440550656552773

0

11234455656555577777 -> 11023440550656552773

To chyba źle jest?
Dekompresując: wypisuje 1, wypisuje 1 razy 0, wypisuje 2, 3, 4, 4 razy 0... ? Huh? :]

0

Nie, nie. To, że znak występuje 2 razy obok siebie informuje o tym, że te znaki będą powtarzane (xxn) 2x + n*x razy. ABCCCCDEEEFGGH -> AB CC2 D EE1 F GG0 H (C występuje 4 razy dlatego mamy CC + 2xC, G występuje tylko 2 razy więc mamy GG + 0xG)

1 użytkowników online, w tym zalogowanych: 0, gości: 1