Marcin Kędzierski gr. 14 Zasady programowania Dokumentacja Wstęp 1) Temat: Przeszukiwanie pliku za pomocą drzewa. 2) Założenia projektu: a) Program ma pobierać dane z pliku wskazanego przez użytkownika b) Tekst ma być zapamiętany w formie drzewa c) Program ma wyszukiwać wyrazy w tekście d) Program ma być łatwy w obsłudze 3) Omówienie tematu: a) Głównymi zadaniami mojego programu jest zapamiętanie pliku tekstowego w aplikacji za pomocą zaawansowanej struktury dynamicznej takiej jak drzewo i wyszukiwanie fraz w tym tekście. 4) Opis założeń a) Drzewo pamiętające tekst będzie listą list, która będzie jedynie pamiętać numery słów. Dzięki takiemu rozwiązaniu można zapamiętać większe pliki i szybciej w nich wyszukiwać b) Słowa będą zapamiętywane w liście pamiętającej samo słowo. c) Zmienną łańcuchową string traktuję jako zmienną standardową i do każdego modułu ją dołączam. Dzięki temu program będzie miał prostszy zapis.
Opis projektu 5) Sposób działania programu: a) Najpierw program prosi o niezbędne informacje dotyczące pliku b) Program tworzy drzewo: pierwszy akapit, zdanie i miejsce na słowo. Pień drzewa Słownik Akapit 1 Akapit 2 Akapit.. Akapit n Zdanie 1 Zdanie 2 Zdanie.. Zdanie n Słowo 1 Słowo 2 Słowo Słowo n c) Otwiera plik i zaczyna go analizować i zapisywać w drzewie. d) Odnalezione słowo zostaje zapamiętane w liście, a w zdaniu zostaje zapamiętany tylko pozycja w liście. e) Napotkanie na znak kropki powoduje utworzenie nowego zdania, a znak akapitu nowego akapitu itp f) Następnie program pyta o to co ma z tym plikiem zrobić, szukać frazy, albo wyświetlić go. g) W czasie wyszukiwania program najpierw sprawdza czy słowo znajduję się w liście słów, potem sprawdza, gdzie wystąpiło. Na koniec wyświetla czas wyszukiwania. h) W czasie wyświetlania pobiera numery zawarte w zdaniach i dopasowuje im słowa z listy słów. 6) Główne moduły a) plik.cpp - główny plik programu, on zawiera funkcję main b) komunikator.cpp plik zawierające funkcje odpowiedzialne za komunikację z użytkownikiem i komputerem. Funkcje wyświetlające, pobierające dane z klawiatury. c) drzewo.cpp plik obsługujący drzewo pamiętające tekst, zawiera również funkcje do otwarcia pliku. d) slownik.cpp plik obsługujący słownik 7) Użyte biblioteki a) iostream biblioteka konieczna do obsługi klawiatury i monitora b) ifstream biblioteka, która będzie odpowiedzialna za operację na plikach c) conio biblioteka, która ułatwi komunikacje programu z użytkownikiem d) string biblioteka pomagające w obsłudze łańcuchów znaków e) system biblioteka konieczna do wskazania czasu wyszukiwania (z dokładnością do milisekundy 8) Główne zmienne a) drzewo zmienna wskaźnikowa wskazująca na początek drzewa zawierająca zapamiętany plik, drzewo również zawiera wskaźnik na jego słownik.
9) Schemat blokowy: Start Programu Pobranie informacji o pliku Tworzenie drzew Otwarcie pliku Analiza pliku i rozbudowa drzew Jeżeli wybrano wyświetlenie tekstu Pobranie numeru słowa z drzewa Zapamiętanie słowa ze słownika odpowiadającemu numerowi Pytanie o kolejne zadanie Jeżeli wybrano wyszukiwanie Pobranie wyszukiwanego tekstu Sprawdzenie czy słowo wystąpiło Jeżeli wybrano koniec pracy programu Zwolnienie pamięci Wyświetlenie słowa Pętla do puki nie przewinięto całego drzewa Odnalezienie wystąpienia słowa Podanie, gdzie słowo wystąpiło Koniec programu
10) Rozkład modułowy programu main.cpp Moduły drzewo.cpp komunikator.cpp Biblioteki string Funkcje i procedury int main; komunikator.cpp Biblioteki string iostream conio Funkcje i procedury void wyswietl(string text); void wyswietlslowo(string text); string czytaj(); char pobierzznak(); slownik.cpp Biblioteki string Funkcje i procedury void utworzslownik(sslownik *&slownik); int podajnrslowa(sslownik *&slownik, string slowo); int czyjestslowo(sslownik *&slownik, string slowo); int dodajslowo(sslownik *&slownik, string slowo); string dajslowo(sslowo *slownik, int nrslowa); void zwolnijslownik(sslownik *&glowa); Struktury Sslownik: Sslowo *slowo; int iloscslow; Sslowo: String tresc; Sslowo *next; drzewo.cpp Moduły slownik.cpp Biblioteki fstream string system Funkcje i procedury void utworzpoczatekdrzewa(sdrzewo *&pien); bool utworzdrzewo(string plik, Sdrzewo *&pien); void rozrostdrzewa(char ostznak, char bznak, string wyswietldrzewo(sdrzewo *pien, string znajdzslowo(sdrzewo *pien, string slowo); void zwolnijdrzewo(sdrzewo *&pien); void ustawpoczatek(sdrzewo *pien, string wytnijostznak(string slowo); Struktury Sbudowadrzewa int akapit; int zdanie; int slowo; Sdrzewo: Sakapit *akapit; Sslownik *slownik; Saktualny Sakapit *akapit; Szdanie *zdanie; Swyraz *wyraz; Sakapit: Szdanie *zdanie; Sakapit *next; Szdanie: Swyraz *wyraz; Szdanie *next; Swyraz: int nrwyrazu; Swyraz*nexta
11) Pseudo kod main.cpp int main: Pobierz dane; Załaduj drzewo(plik); Pętla do puki użytkownik zadaje pytania Zapytaj o zadanie; Wyszukaj: Pętla aż znaleziony akapit będzie zero Wyświetl pozycje słowa; Koniec pętli; Koniec pętli; Zwolnij pamięć; Zakończ program; slownik.cpp void utworzslownik(sslownik *&slownik); Utwórz pierwszy element słownika; int podajnrslowa(sslownik *&slownik, string slowo); Sprawdź numer słowa Jeżeli numer słowa > ilość słów to dodajslowo(slownik, slowo); Zwróć numer słowa; Wyświetl: Pętla aż drzewo powie, że koniec Wyświetl słowa z drzewa; Koniec pętli; int czyjestslowo(sslownik *&slownik, string slowo); Pętla Przesuń aktualny element list na następny; Zapamiętaj pozycje elementu listy; Koniec pętli, gdy napotka słowo lub element będzie pusty Zwróć element listy int dodajslowo(sslownik *&slownik, string slowo); Utwórz nowy element listy; Zapisz w nim słowo; string dajslowo(sslowo *slownik, int nrslowa); Przewiń słownik do nrsłowa; Zwróć tekst z elementu nrslowa; void zwolnijslownik(sslownik *&glowa); Zwolnij pamięć zajętą przez słownik; komunikator.cpp string czytaj: Zwróć wartość z klawiatury; void wyswietlslowo(string text); Wyświetl tekst z zmiennej text; char pobierzznak(); Pobierz znak z klawiatury i go zwróć; void wyswietl(string tekst): Wyświetl tekst z zmiennej tekst i koniec akapitu; drzewo.cpp void utworzpoczatekdrzewa(sdrzewo *&pien); Utwórz pierwszy akapit, zdanie i słowo Drzewa; utworzslownik(pien->slownik); bool utworzdrzewo(string plik, Sdrzewo *&pien); utworzpoczatekdrzewa(pien); Otwórz plik plik; Jeżeli się nie udało to zwróć FALSE; Pętla, aż będzie END OF FILE Wyciągnij słowo z tekstu; Zapamiętaj znak po słowie w bznak; Zapamiętaj ostatni znak w ostznak; Jeżeli ostatni znak jest specjalny: Zapamiętaj znak nr znaku specjalnego; rozrostdrzewa(ostznak, bznak, aktualny); slowo = wytnijostznak(slowo); Uzyskaj numer słowa; Zapamiętaj numer słowa w wyrazie drzewa rozrostdrzewa(ostznak, bznak, aktualny); Koniec pętli; void rozrostdrzewa(char ostznak, char bznak, Jeżeli znak po słowie to: SPACJA Utwórz nowy wyraz; ENTER Utwórz nowy akapit; Utwórz w nim pierwsze zdanie; Utwórz w nim pierwszy wyraz; string wyswietldrzewo(sdrzewo *pien, Wyciągnij słowo z drzewa; Aktualny element przesuń na następny; Zwróć słowo z drzewa; KROPKA Utwórz nowe zdanie; Utwórz w nim pierwszy wyraz; END OF FILE Zakończ pętle; string znajdzslowo(sdrzewo *pien, string slowo); Zapytaj słownik o numer słowa; Przejrzyj drzewo gdzie ten numer wystąpił; Wyniki zwróć; void zwolnijdrzewo(sdrzewo *&pien); Zwolnij pamięć zarezerwowaną przez drzewo; void ustawpoczatek(sdrzewo *pien, Ustawia aktualny ba wskazywał na pierwszy akapit, zdanie i wyraz drzewa; string wytnijostznak(string slowo); Wytnij słowo bez ostatniego znaku; Zwróć wartość;
12) Poglądowy opis działania algorytmów a) Plik po otwarciu będzie pobierał wyraz, aż do białego znaku i zapamiętany w zmiennej string. Następnie wyodrębniony zostanie ostatni znak słowa i rodzaj białego znaku. W zależności od ostatniego znaku zostaną utworzone 2 słowa w przypadku znaku specjalnego, albo nowe zdanie, gdy jest to kropka. Jeżeli białym znakiem jest nowy akapit, to jest on tworzony. Zapamiętane słowo zostanie sprawdzone, czy zostało już użyte, jeżeli nie, zostanie dodane do słownika. W drzewie z zapisanym tekstem zostanie jedynie zapamiętany numer słowa. Schemat: bool utworzdrzewo(string nazwa_pliku, Sdrzewo *&pien) string slowo; int podajnrslowa(sslownik *&slownik, string slowo) char ostznak, bznak; Saktualny aktualny, temp; int nrslowa = czyjestslowo(slownik, slowo); if(nrslowa < 1)return dodajslowo(slownik, slowo); do return nrslowa; plik >> slowo; plik.get(bznak); ostznak = slowo[slowo.size()-1]; for(int i=0; i < znakispecjalne; i++) if(ostznak == znaki[i]) slowo = wytnijostznak(slowo); aktualny.wyraz->nrwyrazu = podajnrslowa(pien->slownik, slowo); rozrostdrzewa(' ', ' ', aktualny); slowo = ostznak; break; aktualny.wyraz->nrwyrazu = podajnrslowa(pien->slownik,slowo); rozrostdrzewa(ostznak, bznak, aktualny); while(!plik.eof()); void rozrostdrzewa(char ostznak, char bznak, Saktualny &aktualny) if(bznak == '\n') aktualny.akapit->next = new Sakapit; aktualny.akapit->zdanie = new Szdanie; aktualny.zdanie->wyraz = new Swyraz; else if((ostznak == '.') (ostznak == '!') (ostznak == '?')) aktualny.zdanie->next = new Szdanie; aktualny.zdanie->wyraz = new Swyraz; else if(bznak == ' ') aktualny.wyraz->next = new Swyraz;
b) Wyświetlanie pliku będzie polegało na przewijaniu drzewa. Pobieraniu z niego numerów słów i wyświetlaniu przypisanym im tekstów. Schemat: do tekst = wyswietldrzewo(pien, aktualny); wyswietlslowo(tekst); while(tekst!= ""); string wyswietldrzewo(sdrzewo *pien, Saktualny &aktualny) string tekst; if(aktualny.wyraz->next!= NULL) tekst = dajslowo(pien->slownik->slowo, aktualny.wyraz->nrwyrazu); aktualny.wyraz = aktualny.wyraz->next; if(aktualny.wyraz->nrwyrazu < znakispecjalne) return tekst; tekst += " "; return tekst; if(aktualny.zdanie->next!= NULL) if(aktualny.akapit->next!= NULL) return ""; c) Wyszukiwanie tekstu sprawdza czy czy słowo wystąpiło, jeżeli zwrócona wartość jest większa od ilości słów w drzewie to program poinformuje, że słowa niema. W przeciwnym wypadku poda akapit, zdanie i numer słowa gdzie słowo wystąpiło. string znajdzslowo(sdrzewo *pien, string slowo) while(aktualny.akapit!= NULL) while(aktualny.zdanie!= NULL) while(aktualny.wyraz!= NULL) if(aktualny.wyraz->nrwyrazu == nrslowa) itoa(pozycja.akapit, int2str, 10); tekst += "Akapit: "; tekst += int2str; itoa(pozycja.zdanie, int2str, 10); tekst += ", zdanie: "; tekst += int2str; itoa(pozycja.slowo, int2str, 10); tekst += ", wyraz: "; tekst += int2str; tekst += "\n"; if(aktualny.wyraz->nrwyrazu >= znakispecjalne) pozycja.slowo++; aktualny.wyraz = aktualny.wyraz->next; return tekst; char *itoa(int value, char *string, int radix); funkcja zamienia zmienną int na zmienną char *.
13) Format danych wejściowych: a.txt 1 jednak 14) Format Danych Wyjściowych Slowo znaleziono: Akapit: 9, zdanie: 3, wyraz: 8 Akapit: 10, zdanie: 9, wyraz: 3 Akapit: 10, zdanie: 11, wyraz: 14 Podsumowanie 15) Zrealizowane a) Program wykorzystuje struktury dynamiczne do obsługi pliku tekstowego. b) Program daje możliwość przeglądania go i wyszukiwania w nim słów. c) Program liczy czas wyszukiwania d) Pomimo interfejsu tekstowego program jest łatwy w obsłudze. 16) Rozwiązania na przyszłość a) Zoptymalizować program b) Dodać obsługę obiektową programu c) Możliwość edycji pliku d) Możliwość ustawienia interpretacji znaków