Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Dekompresja RLE z pliku

Ostatnio zmodyfikowano 2016-11-01 16:59
Autor Wiadomość
Wojtek1243
Temat założony przez niniejszego użytkownika
Dekompresja RLE z pliku
» 2016-10-31 17:39:30
Witam.
W jaki sposób z pliku pobrać dane do dekompresji np A10B2. Tak aby program wiedział, że ma powtórzyć litere A 10 razy, jeśli program pobiera tekst z pliku znak po znaku?
Program najpierw pobierze 1 potem 0 i tu powstaje problem. Czy istnieje jakiś sposób aby pobrać liczbę w całości?

Próbowałem metodą if'ów na wyłapywanie cyfr i jeśli następny znak tez jest liczbą to mnoży te pierwszą razy 10 i dodaje te drugą pobraną, np 12 to 1*10+2 ale to sie nie sprawdza.

Pozdrawiam
P-153118
michal11
» 2016-10-31 17:46:33
No to pokaż co masz, generalnie z tego co opisałeś to wystarczy traktować wczytywane znaki od litery do litery jako cyfrę.
P-153120
Wojtek1243
Temat założony przez niniejszego użytkownika
» 2016-10-31 17:58:04
C/C++
void compression_rle()
{
    vector < char > data_vector;
    vector < char >::iterator it;
   
    ///funkcja wczytuje dane z pliku znak po znaku i umieszcza w vektorze
    file_to_vector_char( "to_compression_rle.a", data_vector );
   
    cout << "Do kompresji" << endl << endl;
    print_vector( data_vector, it );
   
   
   
   
    ///otworzyć plik do zapisu i zapisac w nim skompresowane dane
    ofstream compressed_data_rle;
    compressed_data_rle.open( "compressed_rle.a", ios::trunc );
    if( compressed_data_rle.is_open() )
    {
       
        ///przejdz przez caly wektor czytajac znaki
        ///jesli znaki sa rozne to wypisz
        ///jesli dwa znaki sa takie same to wylicz ile jeszcze dalej jest takich samych znakow i wpisz
        ///Właściwa kompresja
        unsigned int nrepeats = 0;
        for( it = data_vector.begin() + 1; it != data_vector.end(); it++ )
        {
            if( * it != *( it - 1 ) ) ///sprawdza od drugiego znaku jesli byl on róźny od poprzedniego
            {
                if( nrepeats == 0 )
                {
                    ///znaki obok siebie rozne wiec wrzuc pierwszy znak do pliku
                    compressed_data_rle << *( it - 1 );
                }
                else
                {
                    ///skonczyl sie ciag powtarzajacych sie znakow
                    compressed_data_rle << nrepeats + 1;
                    compressed_data_rle << *( it - 1 );
                    nrepeats = 0;
                }
            }
            else
            {
                ///jesli sie powtarzaja to zlicz
                nrepeats++;
            }
        }
    }
    else cout << "File doesn't exist" << endl;
   
    compressed_data_rle.close();
   
   
   
    cout << "Po kompresji " << endl << endl;
    print_file( "compressed_rle.a" );
   
}

w ten sposób kompresuje.
Pobieram z pliku znak po znaku do vectora char. i teraz przy dekompresji 'odwiedzam' kazdy element vectora i teraz pytanie jeśli mam do dekompresji np A12 to wyjdzie cos w stylu 'A', '1', '2' i nie mam pomysłu jak wyłuskać te liczbę 12 do zmiennej int żeby powtórzyć znak 'A' 12 razy
P-153123
j23
» 2016-10-31 18:32:31
Coś w ten deseń:
C/C++
auto i1 = data_vector.begin();
auto i2 = data_vector.end();

while( i1 != i2 )
{
    char ch = * i1++; // <--- litera
    int rep = 0; // <--- liczba powtórzeń
   
    do
    {
        rep *= 10;
        rep += * i1++ - '0';
    }
    while( i1 != i2 && isdigit( * i1 ) );
   
    ...
   
}
P-153128
Wojtek1243
Temat założony przez niniejszego użytkownika
» 2016-10-31 19:24:48
Dzięki. Wypróbuje to co zaproponowałeś
P-153135
Wojtek1243
Temat założony przez niniejszego użytkownika
» 2016-10-31 22:11:35
Ok napisałem. Mam jeszcze problem z wyliczaniem powtorzeń większych niz 99 przy dekompresji
Używam kodu

C/C++
for( it = data_vector.begin(); it != data_vector.end(); it++ )
{
    ///wyszukuje liczbe jesli znaleziono to jest sekwencja powtarzajacych sie znakow
    if( isdigit( * it ) )
    {
        if( !isdigit( *( it + 1 ) ) ) ///jesli nastepny znak nie jest liczba tzn ze powtorzen jest mniej niz 10
        {
            ...
        }
        else ///jesli jednak nastepny znak to tez liczba...
        {
           
            int next_digit = conv_char_to_int( *( it + 1 ) );
            nrepeats =( nrepeats * 10 ) + next_digit;
            if( isdigit( *( it + 2 ) ) ) continue;
           
            to_repeat = *( it + 2 );
           
            for( int i = 0; i < nrepeats - 1; i++ )
                 decompressed_data_rle << to_repeat;
           
        }
    }
    else
    {
        decompressed_data_rle << * it; ///wypisuj pojedyncze znaki
       
    }
}


Chodzi o część kodu gdy następny znak jest tez liczba.
Otóź mając liczbe powtorzen np 123 pobieranych z wektora jako '1', '2', '3'
W załoźeniu program ma

1) najpierw pobrać aktualny znak (liczbe)
2) zorientowac sie ze nastepny znak to liczba pobrac ja do 'next_digit'
3) wyliczyc nrepeats mnożąc go razy 10 i dodajac nastepna liczbe
4) jesli jest wiecej liczb to wywolac continue przesuwajac iterator i wrocic do punktu 1)

np chcac wyliczyc 123 wtedy:
w pierwszej iteracji for  1*10+2 wyjdzie mu 12
potem contunue i druga iteracja 12*10+3 wyjdzie docelowe 123

co jest zle w kodzie i jak mógłbym to naprawić?
Pozdrawiam
P-153145
j23
» 2016-11-01 10:13:03
A co, mój kod nie działa?

Oczywiście przy takim sposobie kodowania kompresja ciągów cyfr nie wchodzi w grę.
P-153155
Wojtek1243
Temat założony przez niniejszego użytkownika
» 2016-11-01 16:59:28
Spróbuje to jakoś przez write zapisywać te dane jeśli chodzi o kompresje.
P-153182
« 1 »
  Strona 1 z 1