- #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;
- int i=0;
- for(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 0;
- }
- //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;
- int i=0;
- int j=0;
- int k=0;
- unsigned char BUFOR_WEDSCIOWY[BUFOR]; //bufor wykorzystywany przy odczycie danych z pliku
- struct element_zrodla model_pelny[256]; //pelny model zrodla
- for(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(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);
- exit(EXIT_FAILURE);
- }
- 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);
- exit(EXIT_FAILURE);
- }
- else //jezeli udalo sie otworzyc plik
- {
- for(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;
- }
- //funckja porównujaca wartosci 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 sotrujaca model zródla informacji i zapisujaca go do pliku
- int posortuj_symbole(struct element_zrodla model[], int licza_elementow, char* plik_model_posortowany)
- {
- int i=0;
- //wywolanie funkcji sortujacej
- qsort(model, liczba_elementow, sizeof(struct element_zrodla), funckja_porownujaca);
- //wskaznik na plik
- FILE *plik;
- //otwarcie pliku
- plik=fopen(plik_model_posortowany,"wb");
- //jezeli nie udalo sie otworzyc pliku do zapisu binarnego
- if(plik==NULL)
- {
- printf("Blad w trakcie otwierania plku do zapisu posortowanego modelu\n");
- exit(EXIT_FAILURE);
- }
- else
- {
- //petla po ilosci elementów w zródle informacji
- for(i=0; i<liczba_elementow; i++)
- {
- //wypisanie numeru znaku i ilosci jego wystapien
- fprintf(plik, "%d %d \n", model[i].indeks_znaku, model[i].ilosc_wystapien);
- }
- //zamkniecie pliku
- fclose(plik);
- }
- }
- 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;
- }
- //Glowna funkcja programu
- int main(int argc, char *argv[]){
- int dlugosc_pliku = 0;
- char wybor; //zmienna okreslajaca wybór dokonany przez uzytkownika (wpisana wartosc w menu)
- char nazwa_pliku[MAX_PATH]; //zmienna okreslajaca nazwe pliku do kompresji
- char *nazwa_pliku_model; //nazwa pliku dla modelu zródla
- char *nazwa_pliku_sort; //nazwa pliku po sortowani
- 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");
- 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("Dekompresja Huffmana\n");
- printf("Obliczenie CRC32 dla pliku\n");
- printf("Wyswietlenie tablicy CRC\n");
- printf("Inny znak - wyjscie\n");
- //Wczytanie wyboru uzytkownika
- scanf("%d", &wybor);
- 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);
- system("PAUSE");
- }
- }
- }