• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kodowanie słownikowe LZ77 metoda przesuwającego okna

Object Storage Arubacloud
0 głosów
168 wizyt
pytanie zadane 20 listopada 2023 w C i C++ przez sadek121 Nowicjusz (160 p.)

Cześć mam na zadanie na studia napisać program kodowania słownikowego LZ77, podszedłem do tematu prostszym (w teorii) algorytmem przesuwającego się okna, ale program zwraca mi jedynie wynik Pozycja: 0 Dlugosc: 0 Znak: ¨, nie mam pojęcie z czego wynika błąd
 

#include <stdio.h>
#include <string.h>
#define MaxBuforSize 4
#define MaxDictionarySize 8

struct trojkaLZ77
{
int pozycja;
int dlugosc;
char znak;
};

struct okno
{
char slownik[MaxBuforSize];
char bufor[MaxDictionarySize];
char niewykorzystane [60];
struct trojkaLZ77 *wskaznikNaTrojke;
};

char przesunNiewykorzystane(struct okno *okno);

void wczytajDane(struct okno *okno, const char *nazwaPliku)
{
FILE *plik = fopen(nazwaPliku, "r");
if (!plik)
{
perror("Błąd wczytania pliku");

    return;
}
int index = 0;
char znak;
while ((znak = fgetc(plik)) != EOF && index < sizeof(okno->niewykorzystane)-1)
{
    okno->niewykorzystane[index++] = znak;
}
okno->niewykorzystane[index] = '\0';

fclose(plik);
}

void przesuniecieOkna(struct okno *okno)
{
int przesuniecie = okno->wskaznikNaTrojke->dlugosc + 1;

for (int i = 0; i < MaxBuforSize - przesuniecie; i++)
{
    okno->slownik[i] = okno->slownik[i + przesuniecie];
}
for (int i = MaxBuforSize - przesuniecie; i < MaxBuforSize; i++)
{
    // okno->slownik[i] = okno->bufor[0];
    // for (int j = 0; j < MaxDictionarySize; j++)
    // {
    //     okno->bufor[j] = okno->bufor[j + 1];
    // }
    // okno->bufor[MaxDictionarySize - 1] = przesunNiewykorzystane(okno);
    if (i < 0) continue;
    okno->slownik[i] = okno->bufor[0];

    //Przesuniecie calego bufora
    memmove(okno->bufor, okno->bufor + 1, MaxDictionarySize - 1);
    okno->bufor[MaxDictionarySize - 1] = przesunNiewykorzystane(okno);
}
}

char przesunNiewykorzystane(struct okno *okno)
{
int niewykorzystaneDL = strlen(okno->niewykorzystane);
int buforDL = strlen(okno->bufor);
int i;

for ( i = 0; i < MaxDictionarySize - buforDL && i < niewykorzystaneDL; i++)
{
    okno->bufor[buforDL + i] = okno->niewykorzystane[i];
}

// memmove(okno->niewykorzystane, okno->niewykorzystane + i, niewykorzystaneDL - i + 1);

if (niewykorzystaneDL > 0)
{
    char znakDoBufora = okno->niewykorzystane[0];
    memmove(okno->niewykorzystane, okno->niewykorzystane + i, niewykorzystaneDL - i + 1);
    return znakDoBufora;
}
else
{
    return '\0';
}  
}

struct okno kodujLZ77()
{
struct okno noweOkno;
struct trojkaLZ77 trojka = {0,0,noweOkno.bufor[1]};

noweOkno.wskaznikNaTrojke = &trojka;
int MaxDl = 0;
int Poz = 0;

for (int i = 0; i < strlen(noweOkno.slownik); i++)
{
    for (int j = 0; j < strlen(noweOkno.bufor); j++)
    {
        int k = 0;
        while (i + k < MaxBuforSize && j + k < MaxDictionarySize && noweOkno.slownik[i + k] == noweOkno.bufor[j + k]) {
            k++;
        }   
        if (k > MaxDl)
        {
            MaxDl = k;
            Poz = i;
        } 
    }
}
trojka.pozycja = Poz;
trojka.dlugosc = MaxDl;

if (MaxDl < MaxDictionarySize)
{
    trojka.znak = noweOkno.bufor[MaxDl];
}
else
{
    trojka.znak = '\0';
}
//Przesunięcie okna w lewo o długość + 1
przesuniecieOkna(&noweOkno);

return noweOkno;
}

int main()
{
struct okno oknoKompresji;
memset(&oknoKompresji, 0, sizeof(oknoKompresji));

const char *nazwaPliku = "plik.txt";
wczytajDane(&oknoKompresji, nazwaPliku);

//Sprawdzenie czy niewykorzystane dane zostały wczytane
if (strlen(oknoKompresji.niewykorzystane) == 0)
{
    printf("Brak danych do kompresji");
    return 1;
}

//Przetwarzanie danych
struct okno skompresowaneOkno = kodujLZ77(&oknoKompresji);

printf("Pozycja: %d Dlugosc: %d Znak: %c", skompresowaneOkno.wskaznikNaTrojke->pozycja, skompresowaneOkno.wskaznikNaTrojke->dlugosc, skompresowaneOkno.wskaznikNaTrojke->znak);

return 0;
}

 

2 odpowiedzi

+1 głos
odpowiedź 20 listopada 2023 przez adrian17 Ekspert (344,860 p.)

Zacznijmy od tego, że w ogóle nie bierzesz argumentu wejściowego.

struct okno kodujLZ77() // <--
...
kodujLZ77(&oknoKompresji);

Kompilator w trybie C na to nie krzyczy, ale w trybie C++owym już tak.

Poza tym, nawet w trybie C, krzyczy na to że w kilku miejscach używasz niezainicjalizowane dane. Zakładając GCC/Clanga, nie zapominaj o flagach -Wall -Wextra.

0 głosów
odpowiedź 20 listopada 2023 przez sadek121 Nowicjusz (160 p.)

Zmieniłem kod i dodatkowo zainicjalizowałem do funkcji kodujLZ77 strukturę okna, program wykonuje się. Jednak w wyniku dalej jest Pozycja: 0 Długość: 0 Znak:. Debuger znajduje breakpoint w inicjalizacji struktury w linii 102 "memset(&oknoKompresji, 0, sizeof(oknoKompresji)); // Inicjalizacja struktury "

#include <stdio.h>
#include <string.h>
#define MaxBuforSize 4
#define MaxDictionarySize 8
#define Min(x, y) ((x) < (y) ? (x) : (y))

struct trojkaLZ77 
{
    int pozycja;
    int dlugosc;
    char znak;
};

struct okno 
{
    char slownik[MaxBuforSize];
    char bufor[MaxDictionarySize];
    char niewykorzystane[60];
    struct trojkaLZ77 trojka; // Teraz trojka jest częścią struktury okno
};

void wczytajDane(struct okno *okno, const char *nazwaPliku) 
{
    FILE *plik = fopen(nazwaPliku, "r");
    if (!plik) 
    {
        perror("Błąd wczytania pliku");
        return;
    }
    int index = 0;
    char znak;
    while ((znak = fgetc(plik)) != EOF && index < sizeof(okno->niewykorzystane) - 1) 
    {
        okno->niewykorzystane[index++] = znak;
    }
    okno->niewykorzystane[index] = '\0';
    fclose(plik);
}

void przesuniecieOkna(struct okno *okno) {
    int przesuniecie = okno->trojka.dlugosc + 1;

    // Przesunięcie słownika
    for (int i = 0; i < MaxBuforSize - przesuniecie; i++) 
    {
        okno->slownik[i] = okno->slownik[i + przesuniecie];
    }

    // Przesunięcie bufora
    memmove(okno->bufor, okno->bufor + przesuniecie, MaxDictionarySize - przesuniecie);

    // Wczytanie nowych danych do bufora z niewykorzystanych
    int iloscDoWczytania = Min(przesuniecie, strlen(okno->niewykorzystane));
    memcpy(okno->bufor + MaxDictionarySize - przesuniecie, okno->niewykorzystane, iloscDoWczytania);

    // Aktualizacja niewykorzystanych
    memmove(okno->niewykorzystane, okno->niewykorzystane + iloscDoWczytania, strlen(okno->niewykorzystane) - iloscDoWczytania + 1);
}

struct okno kodujLZ77(struct okno *wejscioweOkno) 
{
    wejscioweOkno->trojka.pozycja = 0;
    wejscioweOkno->trojka.dlugosc = 0;
    wejscioweOkno->trojka.znak = wejscioweOkno->bufor[0]; 

    int MaxDl = 0, Poz = 0;

    for (int i = 0; i < strlen(wejscioweOkno->slownik); i++) 
    {
        for (int j = 0; j < strlen(wejscioweOkno->bufor); j++) 
        {
            int k = 0;
            while (i + k < MaxBuforSize && j + k < MaxDictionarySize && wejscioweOkno->slownik[i + k] == wejscioweOkno->bufor[j + k]) 
            {
                k++;
            }   
            if (k > MaxDl) 
            {
                MaxDl = k;
                Poz = i;
            } 
        }
    }
    wejscioweOkno->trojka.pozycja = Poz;
    wejscioweOkno->trojka.dlugosc = MaxDl;

    if (MaxDl < MaxDictionarySize) 
    {
        wejscioweOkno->trojka.znak = wejscioweOkno->bufor[MaxDl];
    } else 
    {
        wejscioweOkno->trojka.znak = '\0';
    }
    przesuniecieOkna(wejscioweOkno);

    return *wejscioweOkno;
}

int main() 
{
    struct okno oknoKompresji;
    memset(&oknoKompresji, 0, sizeof(oknoKompresji)); // Inicjalizacja struktury

    const char *nazwaPliku = "plik.txt";
    wczytajDane(&oknoKompresji, nazwaPliku);

    if (strlen(oknoKompresji.niewykorzystane) == 0) 
    {
        printf("Brak danych do kompresji.\n");
        return 1;
    }

    // Przetwarzanie danych
    struct okno skompresowaneOkno = kodujLZ77(&oknoKompresji);

    printf("Pozycja: %d, Długość: %d, Znak: %c\n", skompresowaneOkno.trojka.pozycja, skompresowaneOkno.trojka.dlugosc, skompresowaneOkno.trojka.znak);

    return 0;
}

 

komentarz 20 listopada 2023 przez adrian17 Ekspert (344,860 p.)
To wciąż wygląda mega dziwnie... robisz pętlę po strlen na wejscioweOkno->slownik, ale ten słownik jest zawsze pusty (same zera)?
komentarz 20 listopada 2023 przez sadek121 Nowicjusz (160 p.)
Faktycznie, zapełniłem słownik znakiem x, niby poprawnie porównuje, ale program rozszerza wszystkie tablice i nie znajduje podobiństw

Podobne pytania

0 głosów
1 odpowiedź 1,662 wizyt
pytanie zadane 22 stycznia 2019 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
0 głosów
3 odpowiedzi 1,514 wizyt
pytanie zadane 31 stycznia 2018 w C i C++ przez niezalogowany
0 głosów
0 odpowiedzi 207 wizyt
pytanie zadane 30 stycznia 2018 w C i C++ przez niezalogowany

92,579 zapytań

141,432 odpowiedzi

319,660 komentarzy

61,963 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...