//pierwsza
#include <stdio.h>
#include <stdlib.h>
#define kropka 46
#define BUFOR 1000
#define MAX_PATH 256
//struktura zawierajaca kod znaku oraz iolos jego wystapien
struct element_zrodla {
int indeks_znaku;
int ilosc_wystapien;
};
//struktura o rozmiarze 256
struct element_zrodla model[256];
//licznik elementów zródla
int licznik_symboli = 0;
//funkcja zmieniajaca nazwe pliku
int stworz_nazwe_pliku(char *nazwa_pliku, char *rozszerzenie, char *nazwa_pliku_z_nowym_rozszerzeniem) {
int i = 0; //zmienna pomocnicza
int n = 0; //zmienna pomocnicza
while((nazwa_pliku[n]!= kropka)&&(nazwa_pliku[n]!= '\0'))
n++;
for(i = 0; i<n;i++)
nazwa_pliku_z_nowym_rozszerzeniem[i] = nazwa_pliku[i];
nazwa_pliku_z_nowym_rozszerzeniem[i] = kropka;
n=0;
i++;
while(rozszerzenie[n] != '\0'){
nazwa_pliku_z_nowym_rozszerzeniem[i] = rozszerzenie[n];
i++;
n++;
}
nazwa_pliku_z_nowym_rozszerzeniem[i] = 0;
return 0;
}
int utworz_model_niepelny_Huffman(struct element_zrodla model[], struct element_zrodla model_pelny[256]) {
int n=0;
for(int i = 0; i < 256; i++){
if(model_pelny[i].ilosc_wystapien > 0){
model[n].indeks_znaku = model_pelny[i].indeks_znaku;
model[n].ilosc_wystapien = model_pelny[i].ilosc_wystapien;
n++;
}
}
return n;
}
//druga
//metoda obliczajaca ilosci wystapien poszczegolnych znakow
int policz_symbole(char *nazwa_pliku, char *nazwa_pliku_model, char *nazwa_pliku_wynik, struct element_zrodla model[])
{
int liczba_znakow = 0; //zmienne pomocnicze
int n=0;
unsigned char BUFOR_WEDSCIOWY[BUFOR]; //bufor wykorzystywany przy odczycie danych z pliku
struct element_zrodla model_pelny[256]; //pelny model zrodla
for(int i = 0; i < 256; i++) //petla po pelnym modelu zrodla
{
model_pelny[i].indeks_znaku = i; // przypisanie kodu znaku
model_pelny[i].ilosc_wystapien = 0; // ustawienie ilosci wystapien na 0
}
FILE *plik; //wskaznik do pliku
plik
= fopen(nazwa_pliku
, "rb"); //otwarcie pliku w trybie "read-binary"
if (plik == NULL) //jezeli nie udalo sie otworzyc pliku do odczytu
printf ("Nie udalo sie otworzyc pliku zrodlowego\n");
else //jezeli udalo sie otworzyc plik
{
printf("Odczytuje plik zrodlowy\n");
while (n
= fread(BUFOR_WEDSCIOWY
, sizeof(unsigned char), BUFOR
, plik
)) //dopoki sa odczytywane znaki pliku
{
for(int j = 0; j < n; j++) //petla od 0 do n
{
model_pelny[BUFOR_WEDSCIOWY[j]].ilosc_wystapien++; //zwiekszenie ilosci wystapien odczytanego znaku z pliku
}
liczba_znakow += n; //zwiekszenie liczby znakow w pliku
}
printf("W pliku wejsciowym bylo %d znakow\n", liczba_znakow
);
fclose(plik
); //zamkniecie pliku
plik
= fopen(nazwa_pliku_wynik
, "wb"); //otwarcie pliku do zapisu binarnego (plik z iloscia znakow)
if(plik == NULL) //jezeli nie udalo sie otworzyc pliku
{
printf("Nie mozna otworzyc pliku %d", nazwa_pliku_wynik
);
}
else //jezeli udalo sie otworzyc plik
{
fprintf(plik
,"%d \n", liczba_znakow
); //wypisanie ilosci znakow do pliku
fclose(plik
); //zamkniecie pliku
}
licznik_symboli = utworz_model_niepelny_Huffman(model, model_pelny); //wywolanie metody wyznaczajacej niepelny model Huffmana
plik
= fopen(nazwa_pliku_model
, "wb"); //otwarcie pliku do zapisu binarnego
if(plik == NULL) //jezeli nie udalo sie otworzyc pliku
{
printf ("Nie udalo sie otworzyc pliku %d\n", nazwa_pliku_model
);
}
else //jezeli udalo sie otworzyc plik
{
for(int k = 0; k < licznik_symboli; k++) //petla po ilosci symboli odczytanych z pliku
fprintf(plik
, "%d %d \n", model
[k
].
indeks_znaku, model
[k
].
ilosc_wystapien); //wypisanie kodu znaku i ilosci wystapien do pliku
fclose(plik
); //zamkniecie pliku
}
}
return 0;
}
//trzecia
//funckja porównująca wartości modelu, wykorzystywana przez quicksort
int funkcja_porownujaca(const void *element1, const void *element2)
{
const struct element_zrodla *p1=(const struct element_zrodla*) element1;
const struct element_zrodla *p2=(const struct element_zrodla*) element2;
if((p1->ilosc_wystapien)==(p2->ilosc_wystapien))
return 1;
else if((p1->ilosc_wystapien)<(p2->ilosc_wystapien))
return 1;
else
return -1;
}
//funkcja sotrująca model źródła informacji i zapisująca go do pliku
int posortuj_symbole(struct element_zrodla model[], int liczba_elementow, char* plik_model_posortowany)
{
//wywołanie funkcji sortującej
qsort(model
, liczba_elementow
, sizeof(struct element_zrodla
), funkcja_porownujaca
);
//wskaźnik na plik
FILE *plik;
//otwarcie pliku
plik
=fopen(plik_model_posortowany
,"wb");
//jeżeli nie udało sie otworzyć pliku do zapisu binarnego
if(plik==NULL)
{
printf("Blad w trakcie otwierania plku do zapisu posortowanego modelu\n");
}
else
{
//pętla po ilości elementów w źródle informacji
for(int i=0; i<liczba_elementow; i++)
{
//wypisanie numeru znaku i ilości jego wystąpień
fprintf(plik
, "%d %d \n", model
[i
].
indeks_znaku, model
[i
].
ilosc_wystapien);
}
//zamkniecie pliku
}
}
int model_zrodla_informacji(char *nazwa_pliku, char *nazwa_pliku_model, char *nazwa_pliku_drzewo, char *nazwa_pliku_sort, struct element_zrodla model[])
{
policz_symbole(nazwa_pliku, nazwa_pliku_model, nazwa_pliku_drzewo, model);
posortuj_symbole(model, licznik_symboli, nazwa_pliku_sort);
return 0;
}
//ostatnia
//Glowna funkcja programu
int main(int argc, char *argv[])
{
int dlugosc_pliku = 0;
char wybor; //zmienna okreslajaca wybór dokonany przez użytkownika (wpisana wartość w menu)
char nazwa_pliku[MAX_PATH]; //zmienna określająca nazwę pliku do kompresji
char *nazwa_pliku_model; //nazwa pliku dla modelu źródła
char *nazwa_pliku_sort; //nazwa pliku po sortowaniu
char *nazwa_pliku_drzewo; //nazwa pliku z drzewem kodowania
char rozszerzenie_modelu[] = "model"; //rozszerzenie pliku z modelem
char rozszerzenie_sort[] = "sort"; //rozszerzenie modelu po sortowaniu
char rozszerzenie_drzewo[] = "tree"; //rozszerzenie pliku z drzewem kodowania
printf("Teoria Informacji i Kodowania\n");
printf("Program do kodowania i dekodowania Huffmana\n");
printf("oraz obliczania CRC32\n");
wybor = 1;
while(wybor == 1 || wybor == 2 || wybor == 3)
{
printf("1. Kompresja Huffmana\n");
printf("2. Dekompresja Huffmana\n");
printf("3. Obliczenie CRC32 dla pliku\n");
printf("4. Wyswietlenie tablicy CRC\n");
printf("Inny znak - wyjscie\n");
//Wczytanie wyboru użytkownika
if (wybor == 1)
{
printf("Podaj nazw pliku do kompresji wraz z rozszerzeniem\n");
scanf("%s", &nazwa_pliku
);
while ((nazwa_pliku[dlugosc_pliku] != '\0' && nazwa_pliku[dlugosc_pliku] != kropka))
dlugosc_pliku++; //zwiekszanie zmiennej pomocniczej
//okreslenie dlugosci tablic
nazwa_pliku_model
= (char*)malloc(sizeof(char) * (dlugosc_pliku
+ 1 + (sizeof(rozszerzenie_modelu
) / sizeof(rozszerzenie_modelu
[0]))));
nazwa_pliku_sort
= (char*)malloc(sizeof(char) * (dlugosc_pliku
+ 1 + (sizeof(rozszerzenie_sort
) / sizeof(rozszerzenie_sort
[0]))));
nazwa_pliku_drzewo
= (char*)malloc(sizeof(char) * (dlugosc_pliku
+ 1 + (sizeof(rozszerzenie_drzewo
) / sizeof(rozszerzenie_drzewo
[0]))));
stworz_nazwe_pliku(nazwa_pliku, rozszerzenie_modelu, nazwa_pliku_model);
printf("Nazwa pliku z modelem: %s\n", nazwa_pliku_model
);
stworz_nazwe_pliku(nazwa_pliku, rozszerzenie_sort, nazwa_pliku_sort);
printf("Nazwa pliku z posortowanym modelem: %s\n", nazwa_pliku_sort
);
stworz_nazwe_pliku(nazwa_pliku, rozszerzenie_drzewo, nazwa_pliku_drzewo);
printf("Nazwa pliku z drzewem kodowania: %s\n", nazwa_pliku_drzewo
);
model_zrodla_informacji(nazwa_pliku, nazwa_pliku_model, nazwa_pliku_drzewo, nazwa_pliku_sort, model);
}
}
}