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
-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
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;
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;
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;
}