background image

Tomasz Sarba 

Grupa: I7x2n1 

Teoria Informacji i Kodowania 

Sprawozdanie z pierwszych zajęć laboratoryjnych. 

 

Celem  zajęć  jest  napisanie  programu  tworzącego  histogram  wyznaczający  częstość 

występowania wszystkich znaków ASCII w pliku tekstowym. 

 

Kod wykorzystamy rozszerzenie kodu ASCII o dodatkowy bit, więc wszystkie dostępne znaki 

będą zapisywane na 8 bitach, co daje nam 256 znaków. 

 

Aby  stworzyć  histogram,  musimy  gdzieś  przechować  te  znaki,  oraz  ilość  ich  wystąpień. 

Posłużymy  się  do  tego  tablicą  struktur,  w  których  przechowywać  będziemy  znak,  oraz  ilość  jego 
wystąpień.  Warto  będzie  również  zapamiętywać  ile  z  tych  znaków  w  naszym  przypadku  zostało 
wykorzystanych, do tego posłużymy się zmienna „ile”. 

     int ile=0; //ilość znaków w pliku 
     struct symbol{ //struktura przechowywojąca znalezione znaki oraz ich częstotliwośc występowania 
           char znak; 
           int czest; 
           }wystepowanie[256]; 

 

 

Program 

powinien 

posiadać 

procedury 

wyznaczające 

częstość 

występowania 

(TworzHistogram) oraz zapisującą dane do pliku (ZapiszDoPliku). 

int main(){ 
    TworzHistogram(); //Zliczanie znaków 
    ZapiszDoPliku(); //Wypisywanie wyniku 
    return 0; 

 

Na początku zajmijmy się pierwszą funkcją zliczającą znaki 

 

Aby zaoszczędzić sobie czasu i kłopotów, zmienna „ile” oraz struktura „wystepowanie” 

została zadeklarowana globalnie, aby nie musieć importować ich pomiędzy funkcjami. 

 

Dane które mamy przetworzyć znajdują się w pliku „tekst.txt”. Oznacza to iż musimy 

otworzyć ten plik, posłużymy się do tego „FILE *dane”. Plik otwieramy tylko do odczytu. 

 

Tworząc histogram będziemy pobierać znak, przeszukiwać tyle elementów struktury 

„wystepowanie” ile wskazuje zmienna „ile” w poszukiwaniu pobranego znaku. Jeśli odnajdziemy go, 
to zwiększamy o jeden element „czest” jeśli nie odnajdziemy takiego znaku, to zwiększamy o jeden 
zmienną „ile” oraz dodajemy nowy znak do struktury. 

 

Do powyższego użyjemy:  

-zmiennej „znak” w której będzie się znajdował pobrany znak 

background image

-zmiennej i, służącej jako iterator podczas przeszukiwania tablicy 

-zmiennej flaga mówiącej nam czy znaleźliśmy symbol czy nie 

-pętli „While” do momentu w którym nie napotkamy końca pliku („EOF”) 

 

Po zakończeniu tworzenie histogramu zamykamy plik. 

void TworzHistogram(){ //Tworzenie histogramu 
     char znak; 
     int i; 
     int flaga=0; 
     FILE *dane; 
     if((dane=fopen("tekst.txt", "r"))==NULL){ //otwieranie pliku 
                                 puts("otwarcie pliku jest niemożliwe\nUpewnij się, że plik tekst.txt znajduje sie w tym 
folderze"); 
                                 return; 
                                 }   
     while((znak=fgetc(dane))!=EOF){ //wczytywanie pojedynczo znaków 
                                    for(i=0;i<ile;i++){ 
                                                       if(znak==wystepowanie[i].znak){ //poszukiwanie czy ten znak juz 
wcześniej występował 
                                                                                        wystepowanie[i].znak=znak; 
                                                                                        wystepowanie[i].czest+=1; 
                                                                                        flaga=1; 
                                                                                        } 
                                                       } 
                                    if(flaga==0){//dodanie znaku do pamięci 
                                                wystepowanie[ile].znak=znak; 
                                                wystepowanie[ile].czest=1; 
                                                ile+=1; 
                                                } 
                                    flaga=0; 
                                    } 
                       
     fclose(dane);//zamknięcie pliku 
     } 

 

 

Druga funkcja: Zapisująca histogram do pliku 

 

Podobnie jak w poprzednim przypadku nie musimy niczego importować, wszystkie dane 

których potrzebujemy są zadeklarowane jako zmienne globalne. Musimy jedynie otworzyć plik w 
trybie zapisu. Domyślnie jest to „wynik.txt”. 

 

Funkcja przebiega w następujący sposób: 

-Otwieranie pliku 

-Wyświetlenie tekstu który chcemy zapisać 

-Zapisanie tekstu do pliku 

-Przejście do następnego elementu 

background image

 

Wykorzystaliśmy do tego dodatkowo zmienna „i” wskazującą który element właśnie 

zapisujemy, oraz zmienną „ile” mówiącą nam ile elementów mamy do zapisania. Elementów które nie 
występują nie musimy wypisywać. 

 

Po wykonaniu zadania zamykamy plik 

void ZapiszDoPliku(){ //zapisywanie i wyświetlanie danych 
     int i; 
     FILE *dane; 
     if((dane=fopen("wynik.txt", "w"))==NULL){ //otworzenie pliku 
                                 puts("otwarcie pliku jest niemożliwe"); 
                                 return; 
                                 } 
     for(i=0;i<ile;i++){ 
                        printf("%c -> %d \n", wystepowanie[i].znak, wystepowanie[i].czest); //wyświetlenie danych 
                        fprintf(dane, "%c -> %d \n", wystepowanie[i].znak, wystepowanie[i].czest); //zapisanie 
danych 
                        } 
                         
     fclose(dane); //zamknięcie pliku 
     } 

 

Trzecia funkcja: sortująca histogram 

 

Dobrym pomysłem może być posortowanie naszej struktury tak, aby umieścić najczęściej 

występujące elementy z jednej strony, a te których wystąpienie było rzadsze z drugiej strony. 

 

Funkcję tę umieszczam przed funkcją zapisania, aby w pliku tekstowym mieć posortowane 

dane. 

 

Do sortowania będziemy potrzebowali zmiennych pomocniczych, którymi się posłużymy do 

podmiany miejscami dwóch elementów tablicy „wystepowanie”, zmiennej „i” służącej jako iterator do 
przeszukiwania tablicy, oraz zmiennej „ilość” mówiącej nam ile elementów mamy w tablicy. 

 

Sortowanie odbywać się będzie rekurencyjnie: 

-Wyszukujemy element mniejszy od elementu z końca tablicy, jeśli taki znajdujemy to zamieniamy je 
miejscami i przeszukujemy tablicę dalej w poszukiwaniu jeszcze mniejszego elementu. 

-Gdy już mamy element najmniejszy na końcu tablicy, wywołujemy ponownie funkcję sortującą, ale 
zmniejszamy ilość elementów do posortowania o 1. 

 

W rezultacie otrzymujemy tablicę posortowaną z najczęściej występującymi elementami na 

pierwszych miejscach. 

void Sort(int ilosc){ //Sortowanie otrzymanych wyników 
     int i; 
     char temp_znak; 
     int temp_czest; 
     for(i=0;i<ilosc;i++){ 
                          if(wystepowanie[ilosc-1].czest>wystepowanie[i].czest){ 
                                                                          temp_znak=wystepowanie[ilosc-1].znak; 
                                                                          temp_czest=wystepowanie[ilosc-1].czest; 
                                                                          wystepowanie[ilosc-1].znak=wystepowanie[i].znak; 
                                                                          wystepowanie[ilosc-1].czest=wystepowanie[i].czest; 
                                                                          wystepowanie[i].znak=temp_znak; 

background image

                                                                          wystepowanie[i].czest=temp_czest; 
                                                                          } 
                          } 
     if(ilosc>1) 
                Sort(ilosc-1); 
     return; 
     } 

 

Składamy wszystko razem. 

 

Do programu należy już tylko dodać biblioteki z jakich skorzystałem, dopisać funkcję Sort do 

w funkcji main oraz zatrzymać program aby się sam nie wyłączył po wykonaniu zadania funkcją 
getch(). 

Kod całego programu: 

#include <stdio.h> 
#include <conio.h> 
     int ile=0; //ilość znaków w pliku 
     struct symbol{ //struktura przechowywojąca znalezione znaki oraz ich częstotliwośc występowania 
           char znak; 
           int czest; 
           }wystepowanie[256]; 
 
void Sort(int ilosc){ //Sortowanie otrzymanych wyników 
     int i; 
     char temp_znak; 
     int temp_czest; 
     for(i=0;i<ilosc;i++){ 
                          if(wystepowanie[ilosc-1].czest>wystepowanie[i].czest){ 
                                                                          temp_znak=wystepowanie[ilosc-1].znak; 
                                                                          temp_czest=wystepowanie[ilosc-1].czest; 
                                                                          wystepowanie[ilosc-1].znak=wystepowanie[i].znak; 
                                                                          wystepowanie[ilosc-1].czest=wystepowanie[i].czest; 
                                                                          wystepowanie[i].znak=temp_znak; 
                                                                          wystepowanie[i].czest=temp_czest; 
                                                                          } 
                          } 
     if(ilosc>1) 
                Sort(ilosc-1); 
     return; 
     } 
 
void TworzHistogram(){ //Tworzenie histogramu 
     char znak; 
     int i; 
     int flaga=0; 
     FILE *dane; 
     if((dane=fopen("tekst.txt", "r"))==NULL){ //otwieranie pliku 
                                 puts("otwarcie pliku jest niemożliwe\nUpewnij się, że plik tekst.txt znajduje sie w tym 
folderze"); 
                                 return; 
                                 }   
     while((znak=fgetc(dane))!=EOF){ //wczytywanie pojedynczo znaków 
                                    for(i=0;i<ile;i++){ 
                                                       if(znak==wystepowanie[i].znak){ //poszukiwanie czy ten znak juz wcześniej 
występował 
                                                                                        wystepowanie[i].znak=znak; 
                                                                                        wystepowanie[i].czest+=1; 

background image

                                                                                        flaga=1; 
                                                                                        } 
                                                       } 
                                    if(flaga==0){//dodanie znaku do pamięci 
                                                wystepowanie[ile].znak=znak; 
                                                wystepowanie[ile].czest=1; 
                                                ile+=1; 
                                                } 
                                    flaga=0; 
                                    } 
                       
     fclose(dane);//zamknięcie pliku 
     } 
 
void ZapiszDoPliku(){ //zapisywanie i wyświetlanie danych 
     int i; 
     FILE *dane; 
     if((dane=fopen("wynik.txt", "w"))==NULL){ //otworzenie pliku 
                                 puts("otwarcie pliku jest niemożliwe"); 
                                 return; 
                                 } 
     for(i=0;i<ile;i++){ 
                        printf("%c -> %d \n", wystepowanie[i].znak, wystepowanie[i].czest); //wyświetlenie danych 
                        fprintf(dane, "%c -> %d \n", wystepowanie[i].znak, wystepowanie[i].czest); //zapisanie danych 
                        } 
                         
     fclose(dane); //zamknięcie pliku 
     } 
      
 
int main(){ 
    TworzHistogram(); //Zliczanie znaków 
    Sort(ile); //Sortowanie znaków po ilości wystąpień 
    ZapiszDoPliku(); //Wypisywanie i wyświetlanie wyniku 
    getch(); //Zatrzymanie programu 
    return 0;