ELEMENTY INFORMATYKI Podręcznik Ewa Gurbiel Ewa Kołczyk Helena Krupicka Krzysztof Łukojć Zdzisław Płoski Maciej M. Sysło Jerzy Witkowski Roman Zuber pod redakcją Macieja M. Sysły wydanie trzecie zmienione Warszawa 1993 Wydawnictwo Naukowe PWN Książka ta jest zmienioną i rozszerzoną wersją książki: W. Dańko, E. Gurbiel, Z. Jarzębowski, E. Kolczyk, H. Krupicka, K. Łukojć, Z. Płoski, M.M. Sysło, R. Zuber, Elementy informatyki. Podręcznik pod redakcją M.M. Sysły; Wydanie pierwsze - Wydawnictwo Uniwersytetu Wrocławskiego, Wrocław 1988; Wydanie drugie - OFEK, Jelenia Góra 1990. Książka zalecana przez Ministra Edukacji Narodowej do użytku szkolnego i wpisana do zestawu książek pomocniczych do nauki informatyki na poziomie klasy I szkoły średniej. Numer w zestawie 314/93. Okładka i strony tytułowe: Maryna WiŚNIEWSKA Ilustracja na okładce: MAŁGORZATA FlLEW Redaktor: Agnieszka Grabarczyk Redaktor techniczny: JOLANTA ClBOR Skład komputerowy w TgX-u: Autorzy Copyright © by Wydawnictwo Naukowe PWN Sp. z o.o. Warszawa 1993 ISBN 83-01-11366-9 Następujące nazwy produktów i nazwy firm, do których odwołujemy się w tej książce są zastrzeżonymi znakami i nazwami handlowymi odpowiednich firm: IBM PC, AT, 386 - International Business Machines Corp.; MS-DOS, Windows - Micro- soft Corp.; The Norton Commander - Peter Norton Computing, Inc.; XTree, XTreeGold - Executive Systems, Inc.; AC-Logo - AdvaCom, Poznań; Turbo Pascal i Quattro Pro - Borland International, Inc.; dBASE, dBASE III - Ashton-Tate Co.; TAG - InfoSendce, Gdańsk; ChiWriter - Horstmann Software Design Co.; TgX - American Mathematical Society; Pizazz, Pizazz Plus - Application Technics, Inc.; CorelDraw - Corel Systems Corp. SPIS TREŚCI Wstęp 9 17 18 32 Czym jest informatyka. Elementy historii 1.1. Czym jest informatyka 17 1.2. Elementy historii informatyki Jak działa komputer 31 2.1. Dwójkowy system pozycyjny Wewnątrz komputera 34 Urządzenia zewnętrzne 36 Komputer w roli maszyny do pisania System operacyjny 45 Podstawowe zlecenia systemu MS-DOS Wokół komputera 59 Przy komputerze - pierwsze spotkanie 63 2.2. 2.3. 2.4. 2.5. 2.6. 2.7. 2.8. 38 49 Zadania 65 69 71 3. Nauka i zabawa - grafika żółwia 3.1. Pierwszy rysunek 70 Pierwotne instrukcje graficzne Procedury 73 Wyrażenia 78 Zstępująca metoda projektowania algorytmów Rysowanie za pomocą procedur rekurencyjnych Struktury danych - listy 93 3.2. 3.3. 3.4. 3.5. 3.6. 3.7. 81 88 Zadania 102 4. Od problemu do programu - elementy programowania w języku Pascal 106 Podstawowe instrukcje 108 4.1. 4.2. 4.3. 4.4. 4.5. Zadania 154 Od problemu do programu 124 Funkcje i procedury 128 Strukturalne typy danych 133 Dynamiczne struktury danych 147 Spis treści 5. Zakładamy własny katalog - bazy danych 158 5.1. Zakładamy bazę danych. Pliki 158 5.2. Co już wiemy o plikach 165 5.3. Aktualizacja bazy danych 167 5.4. Systemy baz danych 174 5.5. Wprowadzenie do systemu dBASE 179 Zadania 187 6. Obliczenia w matematyce - metody numeryczne 189 6.1. Zadania numeryczne 189 6.2. Błędy zaokrągleń 190 6.3. Schemat Homera. Wzory rekurencyjne 195 6.4. Stabilność algorytmów 198 6.5. Interpolacja 203 6.6. Całkowanie numeryczne 211 6.7. Wyznaczanie pierwiastków równania 214 Zadania 222 7. Liczyć szybciej - efektywność algorytmów 225 7.1. Złożoność obliczeniowa 225 7.2. Złożoność algorytmu a czas działania programu 226 7.3. Dwa algorytmy optymalne 229 7.4. Porządkowanie ciągów 234 7.5. Porządkowanie przez scalanie 237 7.6. Niezbędna liczba porównań w algorytmach porządkowania Zadania 245 8. Bez kartki i ołówka - przetwarzanie tekstów 250 8.1. O sztuce opracowywania tekstów 250 8.2. Redagujemy tekst za pomocą komputera 251 8.3. Uruchomienie edytora 254 8.4. Trzy warstwy edytora TAG 254 8.5. Użytkowniku, pomóż sobie sam! 257 8.6. Okna i ich zastosowanie 258 8.7. Komputerowy "brudnopis", manewrowanie kursorem 8.8. Usuwanie i wstawianie tekstu 260 8.9. Operacje na blokach tekstu 262 8.10. Wyszukiwanie i zamiana tekstów 264 8.11. Wycofywanie pochopnych decyzji 265 8.12. Składowanie informacji 266 8.13. Przeglądanie plików 266 8.14. Zakończenie pracy 267 8.15. Inne własności edytorów 268 241 259 Spis treści Zadania 269 9. Łatwe i sprawne zarządzanie firmą - arkusz kalkulacyjny 271 9.1. Co to właściwie jest arkusz kalkulacyjny? 272 9.2. Rozpoczynamy pracę 274 9.3. Sposoby wyświetlania liczb, zasięg działania poleceń 277 9.4. Nieco o wyrażeniach 278 9.5. Prosty model symulacyjny 279 9.6. Nanoszenie poprawek 280 9.7. Zakończenie pracy 282 9.8. Skomputeryzowane przyznawanie premii 282 9.9. Graficzna prezentacja danych 285 9.10. Funkcje logiczne 287 9.11. Arkusz a metody numeryczne 289 9.12. Nowy system programowania? 292 9.13. Podsumowanie 293 Zadania 294 Dodatek. Kody ASCII 295 Omówienie literatury uzupełniającej 296 Skorowidz 298 WSTĘP Książka ta jest wprowadzeniem do informatyki i jako podręcznik może być wyko- rzystywana na zajęciach z elementów informatyki w szkołach średnich. Może być także pomocna w nauczaniu podstaw informatyki w szkołach pomatural- nych i na niektórych kierunkach studiów, w szczególności na studiach nauczyciel- skich: dziennych i podyplomowych. Książka jest pierwszą częścią opracowania pod wspólnym tytułem Elementy informatyki - do tej części odwołujemy się dalej przez EI-I. Dwie następne części to: Rozwiązania zadań (EI-II) oraz Przewodnik metodyczny (EI-III). Do całego opracowania w trzech częściach odwołujemy się przez EL W związku z zasadniczym przeznaczeniem tej książki przyjęto, że Czytelnik dysponuje mikrokomputerem, który - zakładamy - jest zgodny z komputerem osobistym IBM PC1 oraz odpowiednim dla niego oprogramowaniem, w tym: systemem operacyjnym MS-DOS (w wersji 4.0 lub wyższej), systemami pro- gramowania AC-Logo i Turbo Pascal (w wersji 6.0 lub późniejszej), edytorem tekstów TAG i arkuszem kalkulacyjnym Quattro Pro. Książka ta nie jest jednak podręcznikiem obsługi któregokolwiek z wymienionych systemów oprogramowa- nia. Podajemy w niej tylko najważniejsze informacje umożliwiające korzystanie w szkole z komputerów i z ich oprogramowania. Dokładne informacje o wykorzy- stywanych przez nas systemach można znaleźć w leksykonach lub podręcznikach poświęconych wyłącznie tym systemom. Informacje i rozważania w tej książce, chociaż są specyficzne dla komputera IBM PC i jego oprogramowania, nie wykluczają możliwości posługiwania się nią na zajęciach prowadzonych z wykorzystaniem innych komputerów i innego opro- gramowania. Wiodącym tematem książki, wokół którego skupia się nasza uwaga, są algo- rytmy. Metody konstruowania algorytmów ilustrujemy na przykładach wybra- nych z kilku podstawowych dziedzin informatycznych: grafiki żółwia, struktur i baz danych, porządkowania, metod numerycznych, korzystania z arkusza kal- kulacyjnego i komputerowego opracowywania tekstów. Omawiamy poprawność 1W dalszych fragmentach tej książki oraz w EI-II i EI-III komputery zgodne z IBM PC są nazywane po prostu IBM PC. 10 Wstęp działania algorytmów i przedstawiamy ich realizacje w wybranym języku pro- gramowania. Poświęcamy także -wiele miejsca efektywności obliczeń. Książka ta jest wprowadzeniem do algorytmicznego myślenia, które jest sednem informa- tyki i podstawą istotnych zastosowań komputerów oraz metod informatycznych w innych dziedzinach wiedzy i działalności człowieka. Książka składa się ze wstępu, dziewięciu rozdziałów, dodatku, zawierającego tabelę kodów ASCII, omówienia literatury uzupełniającej i skorowidza. Przed- stawmy w skrócie zawartość kolejnych rozdziałów. W pierwszym rozdziale próbujemy odpowiedzieć na pytanie, czym jest infor- matyka, jak się kształtowały związane z nią pojęcia w trakcie rozwoju myśli ora2 innych osiągnięć człowieka i jaka jest jej rola we współczesnym społeczeństwie. W przypadku stosowania komputerów i ich oprogramowania sprawdzenien słuszności obranej drogi rozwiązywania postawionego zadania jest uruchomieni na komputerze programu poprawnie rozwiązującego to zadanie. Dlatego możliwi* jak najwcześniej należy zapoznać się z komputerem, który jest podstawową po mocą naukową na lekcjach informatyki. Jest temu poświęcony rozdział 2 zawie rający najważniejsze informacje o budowie, działaniu i obsłudze komputera IB]V PC oraz o systemie operacyjnym MS-DOS. Omówiono w nim sposoby przy gotowywania komputera do pracy i korzystania z niego. Niektóre z zastosował komputerów wymienione w tym rozdziale, takie jak maszynopisanie, są omówion szerzej w dalszych rozdziałach. Z punktu widzenia użytkownika, komputer służy do wykonywania programów Niektóre programy, zwłaszcza ogólnego przeznaczenia, są dostarczane zwykł wraz z komputerem, natomiast programy rozwiązujące konkretne zadania p szemy sami, korzystając często z możliwości, jakie dają te pierwsze. W k( lejnych rozdziałach omawiamy informatyczne metody rozwiązywania niektóryc grup zadań, posługując się przy tym wybranymi systemami oprogramowania. Rozdział 3 jest poświęcony grafice żółwia, na przykładzie wybranych el< mentów języka Logo, w wersji AC-Logo. Rozdział ten nie jest jednak zbiorę] lekcji o języku Logo, lecz zwartym opisem niektórych konstrukcji tego język które umożliwiają tworzenie nawet dość skomplikowanych ilustracji graficznyc i przy okazji ułatwiają zapoznanie się z zasadami programowania. Sporządzan rysunków komputerowych jest w tym rozdziale pretekstem do uczenia system tycznych metod rozwiązywania zadań, począwszy od właściwego sformułowań zadania, poprzez ułożenie algorytmu jego rozwiązywania aż do zapisania alg rytmu w języku programowania. Rozdział ten jest więc wprowadzeniem do po stawowych konstrukcji algorytmicznych i programistycznych w ich najprostss postaci, rozwiniętych i wzbogaconych następnie w rozdziałach 4-6. Zgodnie z tytułem rozdział 4 prowadzi drogą od podania opisu zadania, cz; jego specyfikacji, do otrzymania gotowego programu, tym razem w języku P WSTCP 11 scal. Podobnie jak w odniesieniu do języka Logo w rozdziale tym są omówione tylko podstawowe instrukcje i typy danych języka Pascal. Programy (i ich fragmenty) napisane w języku Pascal i zamieszczone w opra- cowaniach El są poprawne w sensie systemu Turbo Pascal (w skrócie TP), począwszy od wersji 4.0. Zakres wiadomości o języku Pascal w zasadzie nie wy- kracza poza standardową wersję tego języka. Z tych względów posługujemy się jednym określeniem "język Pascal". Określenia "język Turbo Pascal" używamy tylko przy omawianiu fragmentów programów, które korzystają ze specyficznych cech systemu TP. W rozdziale 5 są omówione czynności związane z tworzeniem, aktualizowa- niem i korzystaniem z bazy danych na przykładzie zbioru informacji o prywat- nej bibliotece książek. Czynności te są zapisane w języku Pascal. Rozważania w tym rozdziale stanowią uzupełnienie poprzedniego rozdziału o informacje do- tyczące plików i operacji na nich. Ponadto zilustrowano wykonanie tych samych czynności za pomocą systemu obsługi baz danych dBASE. W rozdziale 6 są opisane podstawowe sposoby rozwiązywania prostych zadań obliczeniowych z matematyki takich, jak: obliczanie wartości wielomianu i całki oraz znajdowanie pierwiastków równania. Matematyka jest jednym z tych przed- miotów szkolnych, który najbardziej nadaje się do stosowania komputerów jako pomocy naukowych. Lektura tego rozdziału powinna jednak uzmysłowić, że właściwie zaprojektowane algorytmy i programy rozwiązywania zadań obliczenio- wych (matematycznych) najczęściej nie polegają na prostym wykonaniu działań występujących we wzorach definiujących wynik obliczeń. Co więcej, niewłaściwe posługiwanie się wzorami może prowadzić do otrzymywania rezultatów daleko odbiegających od prawdziwych wartości. Rozdział 7 jest rozwinięciem i pogłębieniem rozważań o algorytmach, ze szcze- gólnym uwzględnieniem efektywności ich działania. Na przykładach podstawo- wych zadań, takich jak szukanie najmniejszego elementu w ciągu i porządkowanie ciągu liczb, omówiono elementarne własności algorytmów rozwiązywania tych zadań, które wiążą się z szybkością wykonywania obliczeń. Komputer jest urzą- dzeniem dość uniwersalnym i szybkim, ale łatwo można znaleźć przykłady zadań pokazujące, że nie przemyślane do końca jego wykorzystanie może prowadzić do bardzo długich obliczeń. Co więcej, w przypadku niektórych zadań nawet super- komputery nie są w stanie nam pomóc. Rozdział 8 jest rozszerzeniem informacji o posługiwaniu się klawiaturą kompu- tera (podanych w rozdz. 2) do w miarę pełnego omówienia najważniejszych cech wspólnych dla większości edytorów tekstów. Rozważania są ilustrowane opisem obsługi edytora TAG. Komputer jako urządzenie osobiste jest w dużej mie- rze używany do opracowywania tekstów i ta umiejętność stanowi dzisiaj trwały element podstawowego przygotowania do pracy z komputerem. 12 Wstęp Wykorzystanie komputera jako urządzenia wspomagającego tradycyjne po- moce w typowych obliczeniach rachunkowych jest tematem rozdziału 9. Omó- wiono w nim system Quattro Pro, należący do grupy programów zwanych ar- kuszami kalkulacyjnymi. Są to drugie pod względem popularności (po edy- torach tekstów) gotowe programy używane na komputerach osobistych. Dzięki swojej uniwersalności programy te mogą być stosowane w wielu dziedzinach wy- kraczających poza ich początkowe przeznaczenie, którym była mechanizacja prac biurowych. Na końcu każdego rozdziału (z wyjątkiem pierwszego) jest umieszczony zbiór zadań do samodzielnego rozwiązania. Ich celem jest sprawdzenie, utrwalenie oraz pogłębienie zdobytej wiedzy i umiejętności. Wiele z nich polega na napisaniu fragmentu (lub całego) programu, dlatego mogą być także materiałem na zajęcia w laboratorium komputerowym. Rozwiązania wszystkich zadań, skomentowane i uzupełnione dodatkowymi informacjami, są zebrane w części EI-II. Książka ta, jako podręcznik do zajęć z elementów informatyki, zawiera wiele fragmentów, w których materiał i skala jego trudności mogą wykraczać poza ramy przyjętego programu nauczania tego przedmiotu. Co więcej, stopnie trud- ności materiału w poszczególnych rozdziałach nie są rozłożone równomiernie. Na przykład materiał zawarty w rozdziałach 6 i 7 wymaga pewnego przygotowania matematycznego i może być zbyt trudny dla uczniów z młodszych klas licealnych. Sądzimy, że będzie trudno zrealizować wszystkie omówione w książce zagadnie- nia w trakcie zajęć odbywających się w podstawowym wymiarze czasu (tj. 2 go dziny tygodniowo przez jeden rok). Dlatego osoba wykorzystująca tę książkę jak< podręcznik powinna zadecydować o odpowiednim doborze materiału w zależność od przygotowania uczniów2. Dla ułatwienia, na rys. 0.1 przedstawiamy schemat zależności między pc szczególnymi rozdziałami. Linia ciągła między rozdziałami a i 6 oznacza, że prze przejściem do lektury rozdziału b należy przerobić rozdział a. Linia przerywan oznacza dodatkowo zalecaną kolejność rozdziałów. Podkreślmy jeszcze raz, ta książka nie jest przewodnikiem po którymkolwit z przedstawionych systemów oprogramowania. Nie jest także podręcznikiem pn gramowania ani w języku Logo, ani w języku Pascal. Zamieszczone programy i jedynie zapisem omawianych algorytmów w wybranym języku programowani W wielu przypadkach programy nie są w pełni gotowe do wykonywania na koi puterze, gdyż ze względu na ograniczoną objętość książki nie umieszczono w ni na przykład należytej obsługi wprowadzania danych i wyprowadzania otrzym wanych wyników. Książce towarzyszy dyskietka z tekstami prezentowanych programów i pc programów w językach Logo i Pascal. Programy w języku Logo zostały prze 2Piszemy o tym dokładnie w części EI-III. Wstęp 13 Rys. 0.1. Schemat zależności między rozdziałami stowane w systemie AC-Logo, a programy w języku Pascal - w systemie Turbo Pascal 6.0. Podręcznik EI-I jest zmienioną i rozszerzoną wersją książki, której dane znaj- dują się na stronie czwartej. Większość zmian i uzupełnień wynikła z wymiany komputerów w szkołach - mikrokomputer Elwro 800 Junior został zastąpiony komputerem zgodnym z IBM PC i odpowiednio zostały wymienione także sy- stemy oprogramowania, o których jest mowa w książce. Uzupełnieniem dwóch pierwszych części EI-I i EI-II, które są przeznaczone zarówno dla uczniów, jak i dla nauczycieli, jest część trzecia EI-III, Przewodnik metodyczny, adresowana przede wszystkim do nauczycieli. Część EI-III zawiera omówienie materiału z dwóch pierwszych części oraz propozycje jego rozkładu pod kątem bezpośredniego wykorzystania na lekcjach. Ponadto, w EI-III zamie- szczono propozycje programu nauczania przedmiotu elementy informatyki oraz rozkładu materiału dla klas z różną liczbą godzin zajęć z tego przedmiotu. Wyróżnienia w tekście Dla poprawienia czytelności autorzy przyjęli następujące zasady użycia różnych krojów i wielkości czcionek w tekście: 1. Wrszystkie teksty wyświetlane na ekranie lub drukowane na drukarce, wpro- wadzane przez użytkownika lub wyprowadzane przez programy, są wydru- kowane w książce pismem maszynowym, tzn. każdy znak takiego tekstu zaj- 14 Wstęp muje na papierze tyle samo miejsca. W szczególności pismem maszynowyr są wydrukowane programy (i ich fragmenty) w językach programowani Logo i Pascal oraz zawartości pól w arkuszu kalkulacyjnym. Ponadto: - Słowa kluczowe oraz nazwy procedur i funkcji standardowych w jęz; kach i systemach programowania są pisane wielkimi literami. - W nazwach (m.in. zmiennych i procedur), każda część mnemoniczi (tj. mająca brzmienie i znaczenie jakiegoś słowa) rozpoczyna się ( wielkiej litery, a pozostałe litery w nazwach są małe. - W programach w języku Logo mogą występować nazwy zawierają litery z polskimi znakami diakrytycznymi, gdyż język AC-Logo akce tuje takie litery. - Programy i polecenia w pozostałych systemach oprogramowania w korzystanych w tej książce (w ich standardowej wersji) mogą zawiei nazwy złożone jedynie z liter alfabetu łacińskiego. 2. Zlecenia i komunikaty systemu operacyjnego MS-DOS są pisane także smem maszynowym i wielkimi literami. 3. Pismem pochyłym są pisane m.in.: - pojęcia metajęzykowe w definicjach konstrukcji programistycznych - nazwy opcji i operacji wzięte z oferty arkusza kalkulacyjnego lub nych systemów oprogramowania. 4. Nazwy klawiszy są wyróżnione wzięciem w ramkę. 5. Informacje o nazwach plików zawierających programy na dyskietce zi dują się w tekście obok znaku przypominającego dyskietkę (zobacz ot umieszczonego na marginesie. Pliki mają nazwy pochodzące od nazw gramów a ich rozszerzenia zależą od użytego systemu programowania i procedur w języku AC-Logo są LOG, dla programów w języku Turbo Pć - PAS, a dla arkuszy kalkulacyjnych systemu Quattro Pro - WQ1. Plik wierające programy z rozdziału x są zgrupowane na dyskietce w kartc R0ZDZx. Podziękowania W opracowaniach El zawarliśmy nasze doświadczenia zdobyte w trakcie wadzenia zajęć z elementów informatyki z uczniami III Liceum Ogólnoks cącego we Wrocławiu i innych szkół, z podstaw informatyki z przyszłymi czycielami na niektórych nieinformatycznych kierunkach studiów Uniwers Wrocławskiego oraz na kursach i Studiach Podyplomowych z Informatyki dl uczycieli. Słuchaczom tych zajęć składamy gorące podziękowania za współ] Jesteśmy wdzięczni naszym kolegom z Instytutu, Jerzemu Kucharcz; oraz Jerzemu Szczepkowiczowi, za dyskusje i sugestie dotyczące treści tej k jak i za pomoc w posługiwaniu się systemem TgK, w którym ta książka z Wstęp 15 złożona. Dziękujemy także Grażynie Hardt-Olejniczak i Adamowi Szustalewi- czowi za pomoc przy opracowywaniu rozdz. 6, a Urszuli Gładysz - za prace edytorskie, zwłaszcza nad rozdziałem 6. Dziękujemy również Recenzentom, Pani Iwonie Krajewskiej i Panu Witoldowi Kranasowi oraz Panu Janowi Madeyowi za bardzo wnikliwą lekturę tekstu i wiele cennych uwag, które przyczyniły się do ulepszenia zawartości książki i prezentacji materiału. Panu Zbigniewowi Książczakowi dziękujemy za uwagi dotyczące strony językowej tekstu. Chcielibyśmy podziękować także naszym dwóm współautorom dwóch poprze- dnich wersji tej książki3, Wiktorowi Dańce i Zdzisławowi Jarzębowskiemu, za ich wkład widoczny także w obecnej wersji. Książka jest wynikiem współpracy dość dużego zespołu autorskiego. Autorami rozdziałów są: E. Gurbiel - rozdz. 5, E. Kolczyk - rozdz. 4, H. Krupicka - rozdz. 3, K. Łukojć - rozdz. 2, Z. Płoski - p. 2.4 i rozdz. 8, M. M. Sysło - rozdz. 1 i 7, J. Witkowski - rozdz. 9, R. Zuber - rozdz. 6. Całość zredagował merytorycznie Maciej M. Sysło. Pani Redaktor Annie Szemberg z Wydawnictwa Naukowego PWN dziękujemy za pomoc i życzliwość okazane nam w trakcie powstawania opracowań El w ich ostatecznej postaci. Autorzy Wrocław, 19 sierpnia 1993 3Pełne dane o poprzednich wydaniach tej książki znajdują się na czwartej stronie. 1. CZYM JEST INFORMATYKA ELEMENTY HISTORII 1.1. Czym jest informatyka Informatyka jest najczęściej kojarzona z komputerami, programowaniem oraz algorytmami, a w ostatnich latach również z całą sferą działalności związanej z mikrokomputerami, zwanymi także komputerami osobistymi. Jako najbardziej zwięzłe określenie tego, czym jest informatyka, podaje się, iż jest to dziedzina wiedzy (ang. computer science) i działalności zajmująca się gro- madzeniem, przetwarzaniem i wykorzystywaniem informacji (czyli różnego ro- dzaju danych o otaczającej nas rzeczywistości), a ta obróbka informacji odbywa się za pomocą komputerów. Chociaż główny nacisk w tej definicji jest położony na informację i na różne jej aspekty, to jednak wprost lub pośrednio możemy odnaleźć w niej także wymienione na początku pojęcia: komputery - gdyż są to urządzenia do obróbki informacji, programowanie - gdyż jest narzędziem umożliwiającym i usprawniającym komunikowanie się użytkownika z kompute- rem, algorytmy - gdyż są tymi przepisami, według których przekształcamy in- formacje, by osiągnąć zamierzony cel. Każde z wymienionych pojęć może z kolei posłużyć do podania innej definicji informatyki. I tak, wiele osób za najważniejsze obiekty zainteresowań w informatyce uważa komputery wraz z całą gamą za- gadnień związanych z ich projektowaniem, konstruowaniem i wykorzystywaniem. Jest to zbyt jednostronne, techniczne spojrzenie na informatykę. Najczęściej in- formatyka bywa utożsamiana z programowaniem komputerów, a pośrednio także z językami programowania. Ta książka stara się przekonać, że pogląd ten jest wyraźnym zawężeniem zakresu dziedziny. Nam najbardziej odpowiada następujące określenie informatyki: informatyka jest dziedziną wiedzy i działalności zajmującą się algorytmami 2 — Elementy informatyki 18 1. Elementy historii informatyki Wyróżniliśmy tę ostatnią definicję, gdyż naszym zdaniem najtrafniej oddaji przewodnią myśl większości rozważań na tematy dotyczące informatyki. W tyn określeniu można odnaleźć także pozostałe pojęcia stosowane do definiowani informatyki: komputery - jako urządzenia za pomocą których są wykonywań algorytmy, informację - jako materiał, który przetwarzają i produkują algorytm i programowanie - jako metodę zapisywania algorytmów. Chociaż w tej defin cji główny nacisk jest położony tym razem na algorytmy, pozostałe jej aspekt są nie mniej ważne do właściwego traktowania zarówno algorytmów, jak i cał dziedziny. Znaczenie pojęć: algorytm, program, komputer, informacja omawiamy w na tępnym punkcie na tle ich historycznego rozwoju. 1.2. Elementy historii informatyki Zalew komputerów, który obserwujemy wokół nas, jest jedną z oznak rewolu mikrokomputerowej. Komputery nie pojawiły się jednak nagle i niespodziewar a pojęcia i wiedza składające się na informatykę były gromadzone przez dłu lata wraz z rozwojem innych nauk i działalności człowieka. Chcemy tutaj przybliżyć tylko te wydarzenia i osoby z historii informatj które według nas miały największy wpływ na tempo rozwoju i obecny jej st Naszą uwagę skupimy przede wszystkim na tych faktach, które odegrały najwi szą rolę w rozwoju podstawowych pojęć: algorytm, komputer i programowa: Na zakończenie odniesiemy się także krótko do obecnej, stale rosnącej roli in matyki w społeczeństwie. Pierwsze ślady informatyki można odnaleźć w historii matematyki i to c odległej. Zastanówmy się najpierw, co składa się na matematykę. Wys czy, jeśli rozróżnimy, bez specjalnego zagłębiania się w jej istotę, dwa rod działalności matematycznej: dowodzenie i obliczanie1. Matematyczny dowód uzasadnieniem słuszności faktu sformułowanego najczęściej w ogólnej, abstral nej postaci. Na przykład w twierdzeniu Pitagorasa jest mowa o zależności, spełniają długości boków w dowolnym trójkącie prostokątnym, czyli dotyczy wszystkich takich trójkątów. Za obliczenia zaś przyjęło się uznawać wyŁ nie na liczbach zaznaczonych działań. Dowody są wytworami umysłu noszą duży ładunek oryginalności i niepowtarzalności. Obliczenia natomiast w jej tradycyjnej postaci (tj. zapisywane ołówkiem na kartce papieru) są cig elementarnych działań, których różnorodność jest ograniczona do kilku po wowych operacji arytmetycznych. Bardzo trudno jest znaleźć w otaczaj lrTo rozróżnienie zaciera się ostatnio w wielu przypadkach i w matematyce znanych jes dowodów, które w znacznym stopniu polegają na wykonaniu obliczeń. Istnieją także koi rowe dowody twierdzeń. Od Starożytności do Średniowiecza 19 nas świecie odpowiedniki większości pojęć i pomysłów występujących w dowo- dach, liczby zaś (zwłaszcza naturalne) dają się łatwo przedstawiać za pomocą najróżniejszych obiektów, rzeczy i wielkości. Dlatego od najdawniejszych czasów próbowano pomagać sobie w liczeniu, np. kamieniami. Od Starożytności do Średniowiecza W wykopaliskach między Mezopotamią i Indiami odnaleziono ślady stosowanych już w X wieku p.n.e. systematycznych metod znajdowania wyniku najprostszych operacji za pomocą specjalnie przygotowanych i poukładanych kamieni. Począt- kowo kamienie układano w rzędach na piasku tworząc w ten sposób plansze obli- czeniowe, które nazywamy abakami (lub abakusami). Później zaczęto nawlekać kamienie na pręty, tworząc liczydła, czyli kompletne i przenośne przyrządy do obliczeń. W obu przypadkach, abakusa i liczydła, stan obliczeń określało rozmie- szczenie elementów ruchomych (czyli kamieni) na piasku lub na prętach. Liczydła przeżywały swój renesans w wiekach średnich. Wtedy na przykład ukształtował się japoński soroban w swej obecnej postaci. Rys. 1.1. Japoński soroban Na rys. 1.1. jest pokazany szkic współczesnego sorobanu w pozycji przygo- towanej do rozpoczęcia pracy. Cztery guziki na dole w każdym rzędzie służą do odkładania kolejnych jedności 1, 2, 3 i 4 przez przesuwanie ich w kierunku środka. Przejście od 4 do 5 polega na cofnięciu czterech jedności na pozycje początko- we i przesunięcie górnego guzika do środka. Zachęcamy do opracowania metody dodawania dwóch liczb za pomocą tego liczydła. Soroban jest jeszcze dzisiaj dość powszechnie stosowanym liczydłem w Japo- nii. Jego obsługi, w tym wykonywania na nim czterech podstawowych działań arytmetycznych, nadal uczą się japońskie dzieci w szkole podstawowej. Nierzadko można także spotkać urzędników (np. na poczcie) lub sprzedawców w małych skle- pikach, którzy obliczają należności korzystając z pomocy sorobanu. Soroban - jak każde liczydło - ma wady, które zostały naprawione częściowo w kalkulatorze, a ostatecznie dopiero w komputerach. Służy on bowiem tylko do odnotowania bieżących wyników obliczeń, gdyż nie ma w nim miejsca ani na pamiętanie wy- ników pośrednich, ani na pamiętanie kolejno wykonywanych działań. 20 _. 1. Elementy historii informatyki Cofnijmy się jeszcze do poprzedniej ery. W rozdziale 4 omawiamy metodę w; znaczania największego wspólnego dzielnika dwóch liczb. Metodę tę podał Eukl des, żyjący w latach 400-300 p.n.e., w swoim fundamentalnym dla matematy' (a zwłaszcza dla geometrii) dziele Elementy. Jego metoda jest dzisiaj powszecl nie nazywana algorytmem Euklidesa. Staraliśmy się unikać na początku tej akapitu słowa algorytm, gdyż w czasach, gdy żył i działał Euklides, i przez wie wieków po nim, nie używano jeszcze tej nazwy. Słowo algorytm pochodzi od brzmienia fragmentu nazwiska arabskiego m tematyka, żyjącego na przełomie VIII i IX wieku. Muhammad ibn Musa a -Chorezmi, bo o nim tutaj mowa, jest uznawany za prekursora obliczeniowy! metod w matematyce. Napisał na ten temat kilka dzieł, a z fragmentu tytu jednej z jego ksiąg pochodzi inne jeszcze słowo - algebra. Upowszechnił także s stem dziesiętny i stosowanie zera jako pojęcia i symbolu, z którym wielu żyjący przed nim nie umiało sobie poradzić. Nie wyobrażano sobie bowiem by coś (cz; jakikolwiek znak, np. 0) mogło oznaczać nic. A co to jest algorytm? Nie podamy wyczerpującej odpowiedzi na to pytań Nie udało się bowiem do dzisiaj ująć w jednolite ramy jednego pojęcia wszystki tych procesów, które są opatrywane nazwą algorytm. W dalszych rozważania będziemy przyjmować, że algorytm jest przepisem rozwiązywania postawionego zadania, bę- dącym dokładnie określonym układem elementarnych instrukcji wraz z porządkiem ich wykonywania. Każda instrukcja ma precyzyjnie określoną interpretację za pomocą podstawowych operacji arytme- tycznych i logicznych, a jej wykonanie jest skończone i ma jednoznacz- nie określony efekt końcowy2. Jako elementy komunikacji ze światem w algorytmie można wyróżnić: dane, na których są wykonywane obli- czenia i wyniki, które są oczekiwanym rezultatem działań. Algorytm, jako opis sposobu rozwiązywania zadania jest często zapisywć w języku programowania by umożliwić jego wykonanie za pomocą kompute Dzięki precyzji określenia danych i wyników (w algorytmie i w odpowiadając mu programie), algorytm może być stosowany nawet w sytuacjach, gdy oso zainteresowanej rozwiązaniem nie jest znane dokładne jego działanie - wystari znajomość postaci danych i interpretacji wyników. Wiek XVII i XVIII Na początku XVII wieku John Neper opublikował najpierw swoje dzieło o lo rytmach a następnie przedstawił system wspomagający wykonywanie mnożei 2W tej definicji niezupełnie mieszczą się algorytmy niedeterministyczne i probabilistyc o których jednak nie mówimy w tej książce. Wiek XVII i XVIII 21 zwany pałeczkami Nepera. Genialność tego systemu polegała na sprowadzeniu mnożenia do serii dodawań. Pomysł Nepera wykorzystało wielu konstruktorów urządzeń liczących, jemu współczesnych i żyjących po nim. Za twórcę pierwszej w historii mechanicznej maszyny do liczenia jest uzna- wany Wilhelm Schickard (1592-1635), który przez długie lata był zupełnie za- pomniany. Schickard opisał projekt swojej czterodziałaniowej maszyny, wykorzy- stującej udoskonalone pałeczki Nepera w postaci walców, w liście do Keplera, któremu miała ona pomóc w jego astronomicznych (dosłownie i w przenośni) rachunkach. Niestety jedyny zbudowany egzemplarz maszyny spłonął w nie- wyjaśnionych okolicznościach, a dzisiejsze jej repliki zostały odtworzone dopiero niedawno na podstawie opisu z listu do Keplera. W XVII wieku żyli i tworzyli wielcy matematycy Gottfried Wilhelm Leib- niz (1646-1716) i Blaise Pascal (1623-1662). Leibniz jest uznawany za jednego z twórców rachunku różniczkowego i całkowego, a osiągnięcia Pascala można znaleźć w bardzo wielu działach nauk ścisłych. Dobrze jest znany trójkąt Pa- scala, który tworzą współczynniki w dwumianie Newtona dla kolejnych wykładni- ków potęg. Zainteresowania teoretyczne nie przeszkodziły tym światłym umysłom na zajęcie się także praktycznymi obliczeniami i dzisiaj obaj są znani również ze zbudowanych przez siebie maszyn liczących. Pascal zainteresował się zbudowaniem maszyny liczącej z myślą o dopomoże- niu swojemu ojcu, który był poborcą podatkowym. Wyprodukowano około 50 egzemplarzy Pascaliny - maszyny według pomysłu Pascala. Kilka egzempla- rzy istnieje w muzeach do dzisiaj; część z nich była przeznaczona do obliczeń w różnych systemach monetarnych, a część - dla różnych miar odległości i po- wierzchni (z przeznaczeniem dla geodetów). Pascal, który zbudował maszynę wykonującą tylko dwa działania (dodawanie i odejmowanie) przez ponad trzysta lat uchodził niesłusznie za wynalazcę pierwszej mechanicznej maszyny do liczenia. Schickard i Pascal wprowadzili w swoich maszynach mechanizm do przeno- szenia cyfr przy dodawaniu i odejmowaniu. Obie maszyny miały także pewne możliwości zapamiętywania niektórych wyników pośrednich. Leibniz odkrył na nowo pochodzący ze starożytnych Chin system dwójkowy (zwany także binarnym) do zapisu liczb. Przypisuje się jemu także zbudowanie pierwszej mechanicznej maszyny mnożącej. Chociaż w tym czasie istniała już Pascalina i Leibniz miał możność zapoznania się z nią w Paryżu, projekt swojej "żywej ławy do liczenia" opisał przed pierwszą wizytą w Paryżu. W maszynie tej wprowadził wiele części, które zostały użyte w późniejszych maszynach biuro- wych. Leibniz wiązał z systemem binarnym także swoje idee filozoficzne. Wierzył bowiem, że język matematyki, za pomocą skończonej liczby symboli i pojęć, może wyrazić wszystkie możliwe twierdzenia (lub ogólniej, słuszne sądy). Dopiero Kurt Godeł wykazał w latach trzydziestych naszego wieku, że jest to niewykonalne. 22 1. Elementy historii informatyki Maszyny Schickarda, Pascala i Leibniza wymagały od użytkownika manual- nej pomocy w wielu czynnościach związanych z kolejnymi krokami obliczeń. Za pomocą tych maszyn nie było jeszcze można w pełni automatycznie i w całości wykonać prostego działania na dwóch liczbach. W tym miejscu wypada wspomnieć o udziale naszego rodaka w dziele tworze- nia maszyn liczących. Abraham Stern (1769-1842), z zawodu zegarmistrz, wy- konał serię maszyn, które poza czterema działaniami podstawowymi, wyciągał} także pierwiastki kwadratowe. Jedna z jego maszyn, raz uruchomiona, potrafił? wykonać za pomocą mechanizmu zegarowego wszystkie operacje bez ingerencj człowieka. Maszyny skonstruowane przez Sterna okazały się jednak mało prak tyczne ze względu na wyjątkowo delikatną budowę. Charles Babbage (1791-1871) Za najwybitniejszego twórcę maszyn liczących, żyjącego przed erą elektroniczni uważa się Anglika Charlesa Babbage'a. Około 1820 r. spotkał on francuskie^ barona de Prony, który dla sporządzenia tablic logarytmicznych i trygonom trycznych utworzył specjalną "manufakturę logarytmów" i wzorując się na id ach szkockiego ekonomisty Adama Smitha zastosował podział pracy. W ty celu wynajął 6 wybitnych matematyków (wśród nich był Legendre) do oprać wywania formuł obliczeń, 8 przeszkolonych matematyków do przygotowywali poszczególnych etapów obliczeń i 60 rachmistrzów. Ci ostatni mieli jedynie d dawać i odejmować. Dzięki temu praca, która zajęłaby całe jedno życie, zost; ukończona w kilka lat. Babbage posunął się dalej i postanowił zbudować n szynę liczącą, która mogłaby wyręczyć człowieka i automatycznie wykonywać ] wtarzające się działania. Swoją pierwszą maszynę nazwał maszyną różnico\ gdyż wykonywała obliczenia metodą różnicową3. Nie będziemy dokładnie opisywać tutaj metody różnicowej. Zilustrujemy tylko na przykładzie obliczania wartości funkcji y = x2 dla kolejnych argumeni a; = l,2,3,... Zauważmy następującą prawidłowość: kwadrat kolejnej liczby naturalnej jest sumą kwadratu poprzedniej liczby naturalnej i kolejnej nieparzystej liczby naturalnej. Korzystając z tej zależności otrzymujemy schemat obliczeń przedstawi na rys. 1.2 (strzałki oznaczają kolejność obliczeń i przekazywania wyznaczał wartości). Zatem do policzenia kwadratów kolejnych liczb naturalnych wystarczy: 3Pierwszy projekt automatycznej maszyny do wykonywania obliczeń metodą różnicową J.H.Miiller w 1786 roku - jednak wydaje się, że ani baron de Prony, ani Babbage nie znal Miillera. n Charles Babbage 23 1. Ustawić O, 1 i 2 jako początkowe wartości. 2. Dla policzenia kwadratu kolejnej liczby naturalnej, wykonać dwa dodawa- nia: - otrzymać kolejną liczbę nieparzystą przez zwiększenie o dwa poprze- dniej liczby nieparzystej (jest to wykonywane w trzeciej i czwartej kolumnie na rys. 1.2), — otrzymaną liczbę nieparzystą dodać do kwadratu poprzedniej liczby naturalnej (dwie pierwsze kolumny na rys. 1.2). kolejne kwadraty kolejne liczby nieparzyste =9+7 — początkowe wartości Rys. 1.2. Obliczanie kwadratów kolejnych liczb naturalnych Podaliśmy bardzo prosty przykład obliczeń wykonanych metodą różnicową. Dla uzasadnienia znaczenia tej metody w automatycznych obliczeniach dodajmy, że w podobny sposób można tworzyć tablice wartości dla większości funkcji ele- mentarnych spotykanych w obliczeniach. W tym celu należy skorzystać z wie- lomianu, który dobrze przybliża tablicowaną funkcję oraz policzyć bezpośrednio kilka jej pierwszych wartości. Wszystkie następne działania są już tylko dodawa- niami pewnych liczb tworzonych także tylko za pomocą dodawań. I właśnie ten ostatni etap obliczeń automatyzowała maszyna różnicowa. Babbage konstruował swoją pierwszą maszynę przez ponad 10 lat. Trapiony jednak wieloma kłopotami rodzinnymi i finansowymi oraz nie mogąc do końca porozumieć się ze swoim głównym wykonawcą-konstruktorem Clementem, za- przestał dalszych prac nad maszyną różnicową w 1842 roku. Zmontowaną część maszyny (podobno nadal sprawną!) można oglądać w Muzeum Nauk w Lody- nie. Należy dodać, że w odróżnieiu od maszyn Leibniza i Pascala, po ręcznym ustawieniu początkowego stanu, dalsze działania maszyny różnicowej nie wyma- gają już żadnej ingerencji użytkownika poza kręceniem korbą. Prace Babbage'a zainspirowały wielu jemu współczesnych, którzy, jak na przykład Szwedzi George 24 1. Elementy historii informatyki i Edward Scheutzowie, często z większym powodzeniem ukończyli swoje, możi mniej ambitne ale nadal praktyczne konstrukcje maszyn różnicowych. Ale Babbage nie poprzestał na próbie skonstruowania maszyny różnicowe; Marzył o maszynie, która mogłaby rozwiązywać bardziej złożone zadania. Ta narodził się jeszcze w trakcie prac nad maszyną różnicową pomysł zbudowani maszyny analitycznej, którym Babbage żył do śmierci. Było to przedsięwzięć: czysto abstrakcyjne - przewidywane przeszkody techniczne i trudności finansów nie pozwoliły nawet na rozpoczęcie prac konstrukcyjnych . W projekcie Babbaj zawarł jednak wiele pomysłów zrealizowanych dopiero we współczesnych kompi terach. Między innymi rozdzielił pamięć (zwaną magazynem) od jednostki licząc (młyna), czyli miejsce przechowywania danych od jednostki wykonującej na nii działania. Obie te części maszyny analitycznej miały być sterowane za pomo< dodatkowego urządzenia kontrolnego, które otrzymywało polecenia na karta perforowanych, udoskonalonych i rozpowszechnionych przez Jacąuarda do pi gramowania maszyn tkackich. Można więc uznać maszynę analityczną Babbeg< za pierwszy pomysł kalkulatora sterowanego programem zewnętrznym. Opis działania maszyny analitycznej trafił w ręce Ady (jej pełne nazi sko: Ada Augusta hrabina Lovelace), córki Byrona, znanej w owych czas? z błyskotliwego umysłu. Urzeczona doskonałością projektu uważała, że "... n szyna analityczna tkać będzie wzory algebraiczne, tak jak krosna Jacąuarda tk liście i kwiaty ...". Nie czekając na skonstruowanie maszyny (czego jak wie i tak by się nie doczekała), Ada zajęła się sporządzaniem opisów jej używa do rozwiązywania konkretnych zadań obliczeniowych. Opisy te nazwalibyś dzisiaj programami, dlatego uważa się ją za pierwszą programistkę komputer Dla uczczenia zasług Ady na tym polu nazwano jej imieniem jeden z najbard uniwersalnych języków programowania. Przełom XIX i XX wieku Koniec XIX wieku był początkiem rozwoju urządzeń mechanograficznych, któi głównym przeznaczeniem było usprawnienie rachunków statystycznych, ksi wych i biurowych. Zaczęło się w Stanach Zjednoczonych od Hermana Hc ritha, który postanowił zautomatyzować prace statystyczne związane ze sp ludności przeprowadzanym wtedy w Stanach co dziesięć lat. Hollerith sięgnf elektryczność, jako źródło impulsów i energii, rozwinął postać karty perforow; na której zapisywano dane i zbudował elektryczny czytnik-sorter kart. Oli mim sukcesem Holleritha okazał się spis w 1890 roku, którego wyniki zo 4Po śmierci Babbage, projekty maszyny analitycznej odziedziczył jego syn Henry, ktć ich podstawie skonstruował tzw. młyn maszyny, odpowiadający jednostce liczącej w dzisie komputerach. Projekty maszyny analitycznej i prototyp młyna są przechowywane w M\ Nauk w Londynie. Alan Turing 25 całkowicie opracowane za pomocą jego urządzeń na podstawie danych zebranych na jego kartach. W następnych latach Hollerith dostarczał lub wypożyczał swoje urządzenia do przeprowadzenia spisów w wielu krajach, w tym także w Europie, między innymi w Rosji. Na przełomie XIX i XX wieku powstało wiele firm, które początkowo ofe- rowały maszyny sterowane kartami perforowanymi i z latami zyskiwały na swo- jej potędze a wiele z nich przetrwało do dzisiaj, jak na przykład IBM, Buli, Remington-Rand, Burroughs, a także NCR (kasy) i Bell (telefony). Udoskonalona i znormalizowana karta perforowana przez wiele dziesięcioleci była uniwersalnym nośnikiem informacji, a pierwsze maszyny mechaniczne do przetwarzania danych zapoczątkowały stale rosnący popyt na przetwarzanie infor- macji. Wniosło to także zmiany w stosunkach międzyludzkich, a w szczególności między państwem (posiadaczem maszyn do obróbki informacji) i obywatelem. Początek XX wieku Od przełomu XIX i XX wieku można zaobserwować wśród matematyków wzrost zainteresowania problemami obliczeniowymi i obliczalnością. Dla przykładu, wiel- ki matematyk niemiecki David Hilbert (1862-1943), wśród wielu problemów naji- stotniejszych dla rozwoju matematyki w XX wieku, umieścił także pytanie o ist- nienie uniwersalnej metody znajdowania pierwiastków równań o współczynnikach całkowitych będących liczbami całkowitymi. Zainteresowania te doprowadziły do powstania wielu teorii, których celem było dostarczenie teoretycznych podstaw obliczeń. W teoriach tych można na przykład ściśle określić, co to jest algorytm. Przy badaniu wzajemnych związków między teoretycznymi modelami obliczeń okazało się, że zdecydowana ich większość jest równoważna sobie, obejmuje bowiem te same klasy zadań dających się rozwiązy- wać za pomocą konstruowanych w tych teoriach algorytmów. Alan Turing (1912-1954) Wśród modeli obliczeń powstałych w pierwszej połowie XX w. największą po- pularność zdobyły maszyny Turinga. W swojej fundamentalnej pracy z 1936 roku Alan Turing bardzo przystępnie opisał tok myślenia prowadzący od obliczeń wykonywanych ręcznie do obliczeń wykonywanych przez bardzo prostą maszynę. Przytoczymy tutaj ten opis. Obliczenia ręczne są najczęściej wykonywane na pokratkowanej kartce pa- pieru, której pojedyncze kratki są wypełniane cyframi i symbolami działań. Dys- ponujemy tylko skończoną liczbą znaków (cyfr, np. 0 raz 1 i symboli działań), które mogą być wpisywane w kratki. To, co robimy w ustalonej chwili, zależy od znaków, które obserwujemy i od działania, jakie podjęliśmy. Możemy przyjąć. 26 1. Elementy historii informatyki że liczba kratek obserwowanych w danej chwili jest ograniczona. Przejrzenie zaś większej ich liczby sprowadza się do wykonania ciągu obserwacji. Możemy także założyć, że liczba wszystkich stanów, w jakich może znaleźć się nasz umysł wy- konujący obliczenia, chociaż duża, jest skończona. Turing doszedł do koncepcji swojej maszyny wprowadzając pewne uproszcze- nia i uściślenia w działaniach na kartce i nad nią. Po pierwsze, zapis obliczer na kartce papieru (a dokładniej na dwuwymiarowym układzie kratek) możne sprowadzić do zapisu na jednowymiarowej pokratkowanej kartce, czyli na taśmi< podzielonej na kratki. Wystarczy w tym celu treść obliczeń wypełniających kartk' zapisać wierszami. Traci się przy tym na czytelności, ale zyskuje redukcję wy miaru kartki. Po drugie, umysł wykonujący obliczenia można zastąpić prze obiekt bardziej fizyczny zwany głowicą, która znajduje się nad taśmą, może si poruszać w obie strony taśmy, a w danej chwili widzi jedynie symbol umieszczon w kratce, nad którą zawisła. Działanie głowicy jest określone przez ustalony zbić instrukcji, zgodnie z którymi może poruszać się w lewo, w prawo lub stać w mie scu, potrafi rozpoznawać symbole i może zmieniać zawartość kratki, nad którą s znajduje. Wykonanie instrukcji przez maszynę Turinga jest działaniem głowic uzależnionym od stanu, w jakim się znajduje i co widzi. Obliczenia wykonywane za pomocą maszyny Turinga zależą od początkowe zapisu symboli na taśmie i od przyjętego zestawu dozwolonych instrukcji. Z tem działa ona podobnie jak dzisiejsze komputery - wyniki obliczeń zależą zapisanych w pamięci komputera danych i od zestawu wykonywanych intrukc Zawartość taśmy po zatrzymaniu się maszyny zależy od obu tych czynnikć Nieodparcie nasuwa się pytanie o to, co możemy policzyć za pomocą tak p stych maszyn. Okazuje się, że bardzo wiele. Sam Turing sformułował tezę, iż maszynie tego typu można zrealizować każdy algorytm. Do dzisiaj nie obalono tezy. Zauważmy, że w związku z tym można przyjąć, iż algorytmem jest dowo opis wykonania obliczeń na maszynie Turinga. Analizując moc swoich maszyn, Turing doszedł jednak do wniosku, że istn funkcje, których wartości nie mogą one obliczać. Nakreślił w ten sposób grai możliwości obliczeń. Działo się to w latach, gdy w matematyce, inny gen: XX wieku, Kurt Gódel nakreślił granice możliwości dowodu matematyczni Wykazał on bowiem, że nie z każdego skończonego układu aksjomatów mc wyprowadzić wszystkie zgodne z nimi (czyli prawdziwe) fakty. Wspomnijmy tutaj jeszcze o dwóch innych dziedzinach działalności Turi ściśle związanych z automatyzacją obliczeń i komputerami. W latach II w światowej Turing został włączony do grupy specjalistów zajmujących się w \ kiej Brytanii deszyfracją kodów Enigmy - maszyny, którą Niemcy używa kodowania meldunków i rozkazów rozsyłanych swoim jednostkom na wszysi frontach. W 1941 roku działalność tej grupy przyczyniła się do zredukowania Pierwsze komputery 27 tyjskich strat na morzach o 50%. Brytyjscy specjaliści korzystali z materiałów (wśród których był egzemplarz Enigmy oraz maszyna deszyfruj ąca zwana bombą) przekazanych im w 1939 roku przez grupę Polaków kierowaną przez Mariana Re- jewskiego, zajmujących się od pięciu lat skonstruowaniem maszyny deszyfrującej. Chociaż Brytyjczycy udoskonalili maszynę deszyfrującą otrzymaną od Polaków, pozostawała ona nadal maszyną mechaniczną i jej działanie nie nadążało za ciągle udoskonalanymi i zmienianymi przez Niemców egzemplarzami Enigmy. Ocenia się, że w szczytowym okresie II wojny światowej Niemcy używali ponad 70 tysięcy maszyn szyfrujących Enigma. Prace nad maszyną deszyfrującą Enigmę przyczyniły się do powstania pod koniec wojny w Wielkiej Brytanii kalkulatorów elektronicznych5. Powstało kilka wersji maszyny o nazwie Coloss, których głównym konstruktorem był T.H. Fo- wers. Były to już maszyny elektroniczne, w których zastosowano arytmetykę binarną, sprawdzane były warunki logiczne (a więc można było projektować obli- czenia z rozgałęzieniami), zawierały rejestry, mogły wykonywać programy (po- przez uruchamianie tablic rozdzielczych) i wyprowadzać wyniki na elektryczną maszynę do pisania. Pierwsze komputery Pierwsze komputery zbudowano dopiero w naszym stuleciu, chociaż pomysły, jakie w nich zrealizowano, pojawiły się przynajmniej sto lat wcześniej, już za czasów Babbage'a. Zastosowane w komputerach środki techniczne pojawiły się bowiem dopiero w latach międzywojennych. Za największego inspiratora po- wstania komputera w jego obecnej postaci uważa się Johna von Neumanna. Ale zanim powiemy o jego dziele, oddajmy właściwe miejsce twórcom rzeczywiście najwcześniejszych konstrukcji, pretendujących do miana komputera. Pojawienie się większości z nich przyspieszyła II wojna światowa. W 1941 roku Konrad Zuse ukończył w Niemczech prace nad maszyną Z3, która wykonywała obliczenia na liczbach binarnych zapisanych w reprezenta- cji, nazywanej dzisiaj zmiennopozycyjną (zob. rozdz. 6), sterowane programem zewnętrznym podawanym za pomocą perforowanej taśmy filmowej. Maszyna Z3 została całkowicie zniszczona w czasie bombardowania w 1945 roku. Następny model maszyny Zusego, Z4 przetrwał i działał do końca lat pięćdziesiątych. Maszyny Zusego były kalkulatorami przekaźnikowymi. W tym czasie znane już były prace Claude Shannona dotyczące realizacji działań binarnych (logicz- nych) za pomocą układów elektronicznych zgodnie z regułami algebry Boole'a. 5O brytyjskich osiągnięciach w zakresie deszyfracji Enigmy i o powstaniu kalkulatorów elek- tronicznych świat dowiedział się dopiero po 1975 roku, gdyż wszystkie informacje na ten temat były objęte trzydziestoletnią tajemnicą państwową. Elementy historii informatyki 28 W roku 1942 zespól specjalistów pod kierunkiem J.W. Mauchly'ego i J.P. Ec- kerta zaprojektował i zbudował maszynę ENIAC ( ang. Electronic Numerical In- tegrator And Computer). Pierwsze obliczenia maszyna ta wykonała w listopadzie 1945 roku. Maszyna ENIAC jest uznawana powszechnie za pierwszy kalkulator elektroniczny, chociaż w 1976 roku okazało się, że wcześniej zaczęły pracować w Wielkiej Brytanii maszyny Coloss I i II. Maszyna ENIAC była monstrualną konstrukcją złożoną z 50 szaf o wysokości 3 metrów zawierających około 20 tysięcy lamp. Słabością tej maszyny było: użycie zwykłego systemu dziesiętnego do pamiętania liczb, brak rozdziału między funk- cjami liczenia i pamiętania oraz bardzo uciążliwy sposób zewnętrznego progra mowania. Wady te zostały usunięte dopiero w projekcie EDVAC. John von Neumann (1903-1957) I tak dotarliśmy do postaci numer jeden w historii informatyki, której inforrn? tyka zawdzięcza dzisiaj tak wiele. John von Neumann, z pochodzenia Węgie był w swoich czasach jednym z najwybitniejszych matematyków. Współpracow m.in. z Hilbertem, a poza matematyką poświęcał swoją uwagę wielu innym dzi dzinom nauk przyrodniczych i wniósł duży wkład w ich rozwój. W 1946 roi zainspirował on prace w projekcie EDVAC (ang. Electronic Discrete Var\ ble Automatic Computer), których celem było zbudowanie komputera bez w poprzednich konstrukcji. Zaproponowano architekturę, zwaną odtąd von ne mannowską, według której buduje się komputery do dzisiaj. W komputerze von Neumanna można wyróżnić przynajmniej następujące < menty: pamięć złożoną z elementów przyjmujących stan 0 lub 1, arytmom zdolny wykonywać działania arytmetyczne, logiczne i inne, sterowanie, wpro1 dzanie danych i wyprowadzanie wyników. Program, czyli zbiór instrukcji, wed których mają odbywać się obliczenia, jest wpisywany do pamięci. Kolejne rozls programu są pobierane przez jednostkę sterującą komputerem w takt centrali zegara i rozpoznawane zgodnie z mikroprogramem wpisanym w układ elek niczny. Podkreślmy, że program jest przechowywany w pamięci komputera i działanie może zmieniać zawartość dowolnego obszaru pamięci (programy n się także same modyfikować). Fizycznie nie ma żadnej różnicy między dai i programami przechowywanymi w pamięci komputera: są podobnie kodo1 jako ciąg zer i jedynek i tak samo zrealizowane technicznie. Można więc p< dzieć, że celem działania komputera von neumannowskiego jest przejście w zegara od jednego stanu zawartości pamięci (danego na początku) do in zawierającego oczekiwany wynik. Zauważmy podobieństwo tego spojrzeń komputer von Neumanna do maszyny Turinga. Nie ma w tym nic dziw gdyż von Naumann bardzo dobrze znał osiągnięcia Turinga. Ostatnie lata 29 Ostatnie lata Większość budowanych dzisiaj komputerów ma nadal architekturę niewiele odbie- gającą od zaproponowanej przez von Neumanna. Nie do poznania zmieniło się natomiast wykonanie komputerów dzięki olbrzymiemu postępowi w miniatury- zacji i przyspieszaniu działania podstawowych elementów konstrukcyjnych. Naj- pierw, u schyłku lat czterdziestych wynaleziono tranzystor i zastosowano w kom- puterach. Pod koniec lat siedemdziesiątych rozpoczęła się pogoń za miniatury- zacją elektroniki i jednocześnie za coraz większą szybkością jej działania, możliwą m.in. dzięki specjalnym materiałom i zmniejszeniu wielkości elementów oraz od- ległości między nimi. W pewnym miejscu rozwoju komputerów konieczne było odejście od modelu von neumannowskiego, gdyż stwarzał zbyt duże ograniczenia dla coraz większych szybkości. Dzisiaj powszechne stały się komputery o archi- tekturze równoległej, w których nie ma centralnego zegara, a jego rolę przejęła synchronizacja obliczeń gwarantująca, że w każdej chwili żądane wielkości znaj- dują się w określonym miejscu pamięci. Jeśli przypomnimy sobie historię z obliczeniami wartości wypełniającymi ta- blice logarytmiczne, to dziwić może, dlaczego Babbage został zainspirowany do zaprojektowania jedynie maszyny różnicowej i maszyny analitycznej, których ce- lem była automatyzacja obliczeń szeregowych (tj. element po elemencie), a nie równoległych (czyli niezależnie jeden od drugiego), chociaż manufaktura loga- rytmów barona de Prony była przykładem współbieżnie wykonywanych obliczeń. Zarzucona w latach siedemdziesiątych nazwa komputera mózg elektronowy przeżywa dzisiaj swój renesans za sprawą coraz większych technicznych możli- wości zrealizowania późniejszych koncepcji von Neumanna. Podstawowe różnice między ludzkim mózgiem a komputerem w dzisiejszej postaci są łatwe do uchwy- cenia: mózg zawiera 10-100 mld neuronów, a więc tysiące razy więcej niż kom- puter ma bitów. Z drugiej strony komputery działają szybciej niż mózg, tzn. mi- liony razy szybciej wykonują podstawowe operacje, jak np. mnożenie dwóch liczb. (Zauważmy tutaj pewną uniwersalność komputera, który z taką samą szybkością mnoży dowolne dwie liczby jednocyfrowe i dziesięciocyfrowe z ustalonego zakresu reprezentacji. Przeciętny mózg zaś w najlepszym razie radzi sobie biegle z ta- bliczką mnożenia liczb jednocyfrowych.) O wiele istotniejszą różnicą między mózgiem a komputerem jest to, że większość komputerów działa szeregowo, czyli wykonuje jedną operację w danej chwili, podczas gdy w mózgu bardzo wiele pro- cesów przebiega jednocześnie. Poza tym neurony w mózgu mają znacznie więcej połączeń między sobą (około 10 tysięcy) niż bajty w pamięci komputera. Obli- czenia w komputerze widziane jako ciąg działań na bitach - to zmiany stanu elementów elektronicznych odbywające się zgodnie z prawami fizyki. W móz- gu natomiast - istotniejsze znaczenie mają procesy chemiczne, nie w pełni do- tychczas poznane. Można powiedzieć, że komputer jest systemem luźno ze sobą 1. Elementy historii informatyki 30 powiązanych elementów elektronicznych i charakteryzuje się dużą szybkością wy- konywania operacji na niewielkich danych. Mózg zaś jest zbiorem dość mocne ze sobą powiązanych i komunikujących się neuronów działających z mniejsz; szybkością, za to na olbrzymich ilościach informacji. W ostatnich latach powstab projekty neurokomputerów, w których mają być uwzględnione najlepsze cech; mózgu i komputera, a więc w uproszczeniu - ma to być szybka, elektroniczna rea lizacja pracy mózgu, czyli olbrzymiej liczby wszechstronnie powiązanych ze sob elektronicznych neuronów. Komputery a społeczeństwo Niemal każda sfera działalności człowieka podlega dzisiaj komputeryzacji. Kor puterom przypisuje się nie tylko ewolucyjną, ale i rewolucyjną rolę. Pierwsza i wolucja przemysłowa, związana m.in. z wynalezieniem maszyny parowej i silni elektrycznego, zwielokrotniła siłę mięśni ludzkich i zwierzęcych zaangażowany w produkcję. Druga natomiast, związana z użyciem komputerów do przetwar: nia informacji, potęguje zdolności umysłowe człowieka do granic obecnie niew; brażalnych. Rewolucja informacyjna to początek ery rosnącego wpływu przetwarzania formacji i wiedzy na rozwój społeczeństw i życia codziennego. Postęp i stand życia stają się coraz bardziej zależne od naszej zdolności do efektywnego ot cowywania, utrzymywania i wykorzystywania zasobów informacji i wiedzy. więcej, ich znaczenie staje się większe niż rola zasobów naturalnych. Kompu już dzisiaj umożliwiają powstawanie klasy posiadaczy informacji. Byli i są wi nas właściciele środków produkcji, kapitału i władzy a nadchodzi era posiad; informacji. Jest wiele słuszności w powiedzeniu, że kto ma informacje, ten władzę. Informatyka jest obszerną i podstawową dziedziną o zasadniczym znacs dla społeczeństwa w dobie rewolucji informacyjnej. Jej głównym celem jest b nie praw i ich zasięgu, praw rządzących procesami informacyjnymi i ich rei cjami. Dodatkowym celem informatyki jest opracowywanie nowych i skutec2 narzędzi intelektualnych, niezbędnych do rozwiązywania problemów przeto nia informacji we wszystkich dziedzinach aktywności ludzkiej. Informatyk teraz ma znaczący wpływ na rozwój innych nauk, na przemysł i nowoc technologię, na rolnictwo, ekonomię, kształcenie, a także na poszerzanie \ pojmowania wszechświata. m- re- dka ych rza- ?yo- ain- dard )pra- . Co utery wśród daczy >n ma czeniu i bada- ?ealiza- icznych twarza- yka już oczesną 3 granic 2. JAK DZIAŁA KOMPUTER Komputery służą przede wszystkim do przetwarzania bardzo szeroko pojmowanej informacji. Proces przetwarzania wymaga uprzedniego wprowadzenia informacji i zapamiętania ich. Informacje są wprowadzane do komputera najczęściej w po- staci ciągów znaków, którymi są na ogół liczby lub teksty. Zbiór akceptowanych przez komputer znaków można traktować jako szerzej pojęty alfabet, którego za- wartość i liczebność zależy od przeznaczenia. Znaki klucza wiolinowego, pauzy i ćwierćnuty nie będą potrzebne matematykowi, z kolei kompozytor muzyki roc- kowej nie skorzysta raczej z symbolu całki czy pierwiastka kwadratowego. Kom- putery wspomagają w pracy zarówno matematyka, jak i muzyka. Zatem alfabet informatyki powinien mieć uniwersalny charakter i umożliwiać wyrażanie w nim wszystkich podstawowych symboli z wielu — nieraz odległych - dziedzin życia. W dalszej części tego rozdziału dowiemy się, jaki jest ogólnie przyjęty zestaw znaków używanych w komunikacji z komputerem. Wprowadzanie do kompu- tera znaków w nie zmienionej postaci graficznej byłoby wygodne dla człowieka, ale wymagałoby stosowania bardzo skomplikowanych urządzeń odczytujących, przetwarzających i zapisujących. Dlatego każdy znak jest w komputerze kodo- wany , czyli otrzymuje jednoznaczną reprezentację liczbową. Obecnie najczęściej jest używany kod ASCII (ang. American Standard Code for Information Inter- change), w którym określono kody 128 znaków stanowiących wspomniany wyżej uniwersalny alfabet informatyki (zob. Dodatek). Kody 128 podstawowych znaków (o wartościach od 0 do 127) odpowiadają znakom widocznym na standardowej klawiaturze oraz znakom sterującym. Po- nadto określono kody o wyższych wartościach (od 128 do 255) i przydzielono je m.in. znakom semigraficznym (umożliwiającym np. tworzenie tabel) i naro- dowym. Zestaw tych znaków i odpowiadających im kodów na ogół zależy od producenta komputerów oraz od kraju ich przeznaczenia. Również liczby wymagają w czasie komputerowego przetwarzania reprezen- tacji różnej od tradycyjnej. Na co dzień posługujemy się liczbami zapisanymi w dziesiętnym układzie pozycyjnym, zwanym po prostu układem dziesiętnym. Do przedstawienia w nim dowolnej liczby wystarczy trzynaście znaków. Są to 2. Jak działa komputer 32 cyfry od 0 do 9, kropka dziesiętna oddzielająca część całkowitą od ułamkowi (w informatyce zrezygnowano praktycznie z przecinka - z uwagi na stosowar w krajach anglosaskich notację - jako znaku występującego w liczbach) or; znaki minus i plus. Taki system zapisu wartości liczbowych jest używany w k munikacji człowieka z komputerem, ale jest on zbyt skomplikowany dla urządź' technicznych. Dlatego w komputerach jest stosowany najprostszy z możliwy systemów - system dwójkowy (zwany także binarnym), w którym występi tylko dwie cyfry, zero i jeden. Cyfry dwójkowe nazywamy bitami (bit jest tal nazwą najmniejszej jednostki informacji). Jak się dalej przekonamy, z reprezen cji liczb można wyeliminować znaki: minus, plus oraz kropka dziesiętna. Ozna< to, że dowolną liczbę będziemy mogli zapisywać używając jedynie dwóch znaki 0 i 1. Wcześniej stwierdziliśmy, że znaki alfabetu, w tym także znaki specjalne numerowane. Widać zatem, że każdą interesującą nas informację można prs stawić w postaci skończonego ciągu zer i jedynek. 2.1. Dwójkowy system pozycyjny Liczby naturalne (czyli nieujemne liczby całkowite) w systemie dziesiętnyi reprezentowane przez ciągi cyfr dziesiętnych. Liczba n-cyfrowa w systemie i siętnym ma postać gdzie dn_i,..., di, do są cyframi dziesiętnymi, czyli należą do zbioru {0,1,.. i oznacza wartość dn_! • lO""1 + • • • + di • 101 + d0 • 10°. Reprezentacja liczby naturalnej, zwana także jej rozwinięciem, w syf dwójkowym przybiera podobną postać. Jedyną różnicą jest zmiana pods z 10 na 2 oraz - w konsekwencji - ograniczenie zestawu dopuszczalnych c dwóch: 0 i 1. Napis cn_i ni gdzie cn_i,..., ci, co są bitami, czyli cyframi dwójkowymi 0 lub 1, oznacz tość cn_i-2n-1 + --- + c1-21 + c0-20. Na przykład liczba 11001 w systemie dwójkowym oznacza zatem liczbę dziesiętną 24 + 23 + 2° = 25. 2.1. Dwójkowy system pozycyjny 33 Liczba ujemna w systemie dziesiętnym jest poprzedzana znakiem minus, na- tomiast w komputerach znak liczby jest reprezentowany przez dodatkową cyfrę dwójkową, zwaną bitem znaku, która poprzedza właściwe cyfry liczby. Cyfra 1 na pozycji bitu znaku zastępuje tradycyjny minus w zapisie liczb ujemnych, a 0 występuje zawsze przed liczbami nieujemnymi. Znaku liczby w reprezentacji binarnej nie można pominąć. Zgodnie z tą umową liczba 25 ma postać binarną 011001, natomiast liczba —25 jest reprezentowana przez 111001. Zauważmy, że po wstawieniu 0 na początku ostatniej liczby otrzymujemy za- pis 0111001 reprezentujący liczbę 57, czyli liczbę o przeciwnym znaku i o innej wartości. Wyeliminowanie kropki dziesiętnej z reprezentacji binarnej również nie na- stręcza większych trudności. Wystarczy przyjąć, że część całkowita i ułamkowa liczby zajmują zawsze jednakową liczbę bitów. Załóżmy na przykład, że na część całkowitą liczby przeznaczono n bitów, a na ułamkową - k bitów. Wówczas binarna reprezentacja liczby będzie miała następującą postać: CnCn-l . ..ClCQC_l (1) gdzie cn - jest bitem znaku liczby, cn_i,..., co - są kolejnymi cyframi binarnego rozwinięcia części cał- kowitej liczby, c_i,...,c_fc - są kolejnymi cyframi binarnego rozwinięcia części ułam- kowej liczby. Ciąg bitów o postaci (1) reprezentuje liczbę dziesiętną równą (-2 • cn + 1) ? (cn-i • 2n~x + • ? ? + co • 2° + c_i • 2"1 + ? • • + c_fc • 2~k), gdzie pierwszy czynnik (—2 • cn + 1) służy do nadania znaku liczbie, ponieważ -2 • cn + 1 = -1, gdy cn = 1, 1, gdy cn = 0. Przykład 2.1. Załóżmy, że na część całkowitą i ułamkową liczby przeznaczono po osiem cyfr. Wówczas liczba 12.625 będzie miała następujące rozwinięcie binarne 0 00001100 10100000. I — Elementy informatyki 2. Jak działa komputer 34 Dla przejrzystości oddzielono poszczególne części odstępami. Pojedyncza cyfra 0 leżąca najbardziej na lewo, oznacza znak liczby; ciąg cyfr 00001100 oznacza częś( całkowitą liczby równą 23 + 22 = 12, a ciąg 10100000 - część ułamkową równi 2-i + 2~3 = 0.625. W tej samej reprezentacji ciąg 1 01111111 01010000 oznacza liczbę -127.3125. Nie jest to jedyna reprezentacja liczb używana w komputerach. Częściej st suje się kod uzupełnieniowy (por. zad. 2.5). Zauważmy jedno bardzo istotne ograniczenie w komputerowej reprezenta liczb: rozwinięcie każdego ułamka jest skończone, co oznacza, że większość lic rzeczywistych nie ma dokładnej reprezentacji w komputerach (por. zad. 2.4, 2J O konsekwencjach tego ograniczenia piszemy dokładniej w rozdziale 6, omawia; obliczenia komputerowe, tak zwane obliczenia numeryczne. .2. Wewnątrz komputera Komputer jest urządzeniem zdolnym do przechowywania (częściej mówim pamiętania) i przetwarzania informacji. W tym celu jest wyposażony w pani: która - w odróżnieniu od pamięci ludzkiej - pełni jedynie rolę magazynu in macji. Znane są układy elektroniczne, które mogą znajdować się w jednym z > stanów i pozostają w nim dopóty, dopóki nie doprowadzi się do nich prądu j kraczającego pewną graniczną wartość. Przechodzą wówczas w stan przecr Mogą zatem służyć jako nośnik jednego bitu. Pojedyncze układy odpowie ze sobą połączone tworzą większe jednostki informacji. Najmniejszą jedne złożoną jest bajt, składający się z ośmiu bitów. Łatwo policzyć, że w jed bajcie można zapisać 256 różnych informacji (będących ciągami ośmiu zer i nek), co skojarzone ze wspomnianym wyżej kodem ASCII oznacza, że baji komputerowym odpowiednikiem znaku. Bajt stanowi podstawową jednostl formacji w mikrokomputerach. W większych komputerach rolę bajtu prze, kilkakrotnie dłuższe słowo maszynowe. Wielkość pamięci komputera, czy jemność pamięci, wyrażamy w bajtach lub w słowach. Dostęp do infor znajdującej się w pamięci wymaga określenia jej pozycji. Wszystkie baji słowa są zatem ponumerowane - mówimy, że mają ustalone adresy w pa Adresowanie zapewniają odpowiednie układy elektroniczne pełniące rolę wodnego listonosza, który zawsze bezbłędnie trafia pod wskazany adres i to w niewyobrażalnie krótkim czasie. 2.2. Wewnątrz komputera 35 Pamięć znajdująca się w komputerze nazywa się pamięcią wewnętrzną i składa się z pamięci operacyjnej oraz pamięci stałej. W tej pierwszej, w cza- sie pracy komputera są umieszczane informacje będące bieżącym obiektem prze- twarzania. Niekiedy z pamięci operacyjnej wyodrębnia się pamięć buforową, która jest wykorzystywana do przyspieszania wymiany większej ilości informa- cji. W pamięci stałej są przechowywane często używane, niezmienne informacje wspomagające prawidłowe działanie komputera. Mówiąc o pamięci operacyjnej mikrokomputerów używamy niekiedy określenia pamięć RAM (ang. Random Access Memory), czyli pamięć o swobodnym dostępie (tzn. odczytanie lub zapisa- nie pojedynczej porcji informacji w dowolnym miejscu tej pamięci jest jednakowo łatwe i trwa tyle samo czasu). Natomiast pamięć stała jest określana terminem pamięci ROM (ang. Read Only Memory) i można z niej tylko czytać informacje. Pamięć RAM jest pamięcią ulotną - jej zawartość ginie po wyłączeniu komputera, w przeciwieństwie do pamięci ROM, która jest pamięcią trwałą. procesor centralny pamięć wewnętrzna arytmometr pamięć stała jednostka sterująca pamięć operacyjna rejestry kanał monitor klawiatura dysk drukarka Rys. 2.1. Schemat logicznej budowy komputera Jądrem komputera odpowiedzialnym za przetwarzanie informacji jest nie- wielki układ elektroniczny nazywany procesorem centralnym, połączony bez- pośrednio z pamięcią wewnętrzną (por. rys. 2.1). Składa się on z arytmometru, jednostki sterującej oraz rejestrów. W arytmometrze odbywają się wszyst- kie obliczenia realizowane przez komputer. Jednostka sterująca odpowiada za dostarczanie arytmometrowi danych do obliczeń z pamięci operacyjnej, przeka- zywanie wyników z powrotem do pamięci oraz za właściwą kolejność przetwarza- nia. W rejestrach procesora przechowuje się adresy wybranych miejsc pamięci 36 operacyjnej oraz dane i wyniki obliczeń. W wyróżnionym rejestrze nazywanym licznikiem rozkazów jest umieszczany adres miejsca w pamięci wewnętrznej zawierającego bieżące zakodowane polecenie dla procesora. Procesor centralny w pełni nadzoruje pracę komputera, której najmniejszą jednostką jest cykl roz- kazowy. Przebieg jednego cyklu można opisać następująco: 1. Zawartość miejsca wskazywanego przez licznik rozkazów (słowa lub ciągu bajtów) zostaje przesłana do układów dekodera będącego częścią jednostk sterującej. 2. W dekoderze następuje rozdzielenie otrzymanej informacji na dwa pola pole operacji i pole argumentów; pole operacji zawiera adres rozkazi (czasami mówimy - instrukcji), który należy wykonać; pole argumentów może składać się z paru części (najczęściej dwóch) i zawiera adresy, po którymi są przechowywane argumenty rozkazu oraz adres przeznaczeni wyniku. 3. Na podstawie wyznaczonych w dekoderze adresów następuje odczytań z pamięci wartości argumentów oraz - na podstawie numeru rozkazu odwołanie do odpowiedniego układu w arytmometrze, gdzie odbywa s właściwe przetwarzanie informacji. 4. Wynik przetwarzania jest wysyłany do pamięci pod adres wskazany pr; jeden z argumentów. 5. Następuje zmiana wartości licznika rozkazów tak, aby wskazywał kole; rozkaz dla procesora. Wykonywanie obliczeń można przerwać. Po zmianie wartości licznika i kazów procesor sprawdza, czy nie było żądań przerwania obliczeń. Jeżeli t takie polecenia, co sygnalizuje stan odpowiedniego rejestru, to procesor zawk obliczenia, zapamiętuje stan licznika rozkazów i przechodzi do obsługi przerv Jeżeli nie było żądań przerwania obliczeń, to procesor rozpoczyna wykonyw; następnego cyklu rozkazowego. 2.3. Urządzenia zewnętrzne Przetwarzanie informacji w komputerze oraz korzystanie z efektów tego ; twarzania wymaga zapewnienia komunikacji środowiska zewnętrznego z puterem. Odbywa się to za pomocą urządzeń zewnętrznych, które n podzielić na kilka grup. Pamięć zewnętrzna zapewnia bezpieczne przecł wanie informacji, które aktualnie nie są przetwarzane. Pamięć ta - pod jak pamięć ROM - jest pamięcią trwałą, tzn. informacje raz w niej zaj mogą być wielokrotnie odczytywane. Dopuszczalny jest oczywiście ponowi pis. Wyłączenie komputera, a nawet odłączenie go od źródła prądu, nie duje utraty zawartości pamięci zewnętrznej. Obecnie najpopularniejszą pa 2.3. Urządzenia zewnętrzne 37 tego typu jest dysk stały, który składa się z płaskich talerzy pokrytych obu- stronnie materiałem magnetycznym. Dysk jest zamocowany w komputerze na osi i obraca się z dużą prędkością, a nad powierzchnią jego talerzy przesuwają się głowice zapisuj ąco-odczytujące przytwierdzone do ramion zawieszonych poza zasięgiem talerzy. Informacje na dysku są rozlokowane na ścieżkach, mających kształt koncentrycznych pierścieni o różnych promieniach. Podobnie są zbudo- wane dyski elastyczne, których napędy znajdują się na stałe w komputerze. Dyski elastyczne, nazywane dyskietkami, można wymieniać, co pozwala prze- nosić informacje między różnymi komputerami. W porównaniu z dyskami stałymi dyskietki mają znacznie mniejszą pojemność, obracają się dużo wolniej i są mniej trwałe. Bezpośrednią komunikację człowieka z komputerem zapewniają: monitor oraz klawiatura. Ekran monitora jest traktowany jako prostokąt i jest dzielony na punkty zwane pikslami, których stan określają takie cechy, nazywane atry- butami, jak: kolor, stopień jasności, migotanie, kolor tła. Ważnym parametrem technicznym monitorów jest rozdzielczość ekranu, czyli gęstość punktów na ekranie - im jest większa, tym dokładniejszy otrzymujemy obraz. Jeżeli pracu- jemy wyłącznie z informacją tekstową, to mówimy o pracy w trybie tekstowym i ekran monitora jest dzielony wówczas na znaki (np. 25 wierszy po 80 znaków -jak jest w komputerach IBM PC). W trybie tekstowym każdemu znakowi od- powiada prostokąt punktów, np. o wymiarach 9x16 piksli. Wzorce wszystkich znaków, które mogą być wyświetlane na ekranie monitora, są zapisane w ma- trycy znaków znajdującej się na karcie graficznej. Karta jest układem elek- tronicznym wyposażonym w pamięć i służy do komunikacji między komputerem a monitorem. Zwykle na ekranie jest widoczny znak w postaci prostokąta lub kreski, prawie zawsze migający dla łatwiejszego zauważenia. Znak ten nazywa się kursorem i wskazuje aktualne miejsce pisania lub wyświetlania. W trybie teksto- wym atrybuty dotyczą całych znaków, a nie punktów ekranu, jak ma to miejsce podczas pracy w trybie graficznym. W obu trybach pracy obraz wyświetlany na ekranie monitora jest odwzorowaniem informacji zapisanej w pamięci kompu- tera, nazywanej pamięcią obrazu. W pamięci tej jest dokładnie opisany stan każdego znaku albo punktu ekranu. Do wyprowadzania wyników na papier służą drukarki, wśród których naj- częściej spotyka się drukarki mozaikowe. Taka drukarka tworzy znaki z położonych blisko siebie, zlewających się na papierze pojedynczych kropek, które powstają w wyniku uderzania igieł, poprzez taśmę barwiącą, o papier. Igły znajdują się w głowicy, która w czasie drukowania przesuwa się w poprzek papieru. Szablony kropek dla wszystkich dopuszczalnych znaków znajdują się w pamięci drukarki. Istnieje ponadto możliwość zaprojektowania i wprowadzenia szablonów własnych znaków. 38 2. Jak działa komputer Większą dokładność druku, szybkość oraz komfort zapewniają drukarki la- serowe, w których druk jest wynikiem nanoszenia laserem na metalowy wałek odpowiedniego proszku, a następnie odbijania obrazu z wałka na papierze. Specyficznym elementem wyposażenia komputerów jest mysz - niewielkie, mieszczące się w dłoni urządzenie połączone kablem z komputerem i zaopatrzone w przyciski (od jednego do trzech) oraz ruchomą kulkę na spodzie. Ruch myszą pc gładkiej powierzchni powoduje zmianę położenia kursora na ekranie. Naciśnięcii przycisku wywołuje reakcję zgodną z funkcją aktualnie wykonywanego programu Myszy używa się zwykle do szybkiego wybierania funkcji lub informacji uwidocz nionej na ekranie albo do rysowania na ekranie. Komputery są ponadto wyposażane w dwa inne specyficzne urządzenia zew nętrzne: zegar i głośnik. Zegar z datownikiem jest używany przez programy d odnotowywania czasu wykonania operacji. Użytkownik ma oczywiście możliwoś ustawiania stanu zegara. Komputerowy głośnik pozwala na wydawanie tono1 o różnych wysokościach i czasie trwania. 2.4. Komputer w roli maszyny do pisania Maszyna do pisania, a ściślej mówiąc - jej znormalizowana klawiatura - znalaz uniwersalne zastosowanie jako jedno z podstawowych urządzeń zewnętrzny* komputera. Klawiatura jako urządzenie wejściowe (czyli do wprowadzania i formacji) jest częścią wyposażenia każdego współczesnego komputera osobisteg Za jej pomocą wywołuje się do pracy gotowe programy, steruje ich przebiegi© wprowadza dane do pamięci, pisze i uruchamia nowe programy. Chociaż od pn ciętnego użytkownika komputera nie wymaga się umiejętności zawodowej mas2 nistki, to dobrze jest przyswoić sobie od początku dwie wiadomości dotyczc maszynopisania: - rozmieszczenie liter na klawiaturach komputerów jest na ogół znormali: wane według układu QWERTY... (rys. 2.2); - do naciskania klawiszy podczas pisania na maszynie nadają się zupeł dobrze wszystkie palce obu rąk. Rozmieszczenie na klawiaturach znaków charakterystycznych dla poszczę^ nych języków, takich jak np. ą, ę, ć, ś w języku polskim, regulują wewnętr normy krajów - na ogół na zasadzie kompromisu ze standardem zaprezento1 nym na rys. 2.2. (Pomijamy języki, których alfabety są inne niż alfabet łacii - na przykład rosyjski, japoński). Występowanie w alfabetach języków ei pejskich dodatkowych liter poza łacińskimi nie jest cechą wyłącznie języka ] skiego. W języku niemieckim lub francuskim sprawa ta przedstawia się podob Współcześnie produkowane komputery i ich urządzenia zewnętrzne pokonują ] blem zróżnicowania alfabetów na drodze sprzętowej. Oznacza to, że te same b; 2.4. Komputer w roli maszyny do pisania 39 informacji raz mogą być interpretowane jako litery niemieckie, a innym razem jako francuskie itp. W mniejszym stopniu rozwiązania takie dotyczą liter specy- ficznych dla alfabetu polskiego, niemniej istnieją pewne propozycje normalizacji polskiej klawiatury, o czym wspominamy dalej (zob. p. 2.4.6). Tutaj ograniczymy się do uwagi, że w maszynach do pisania litery z polskimi znakami diakrytycznymi są umieszczane po prawej stronie klawiatury. Q q w w U u P P H h B b N n M m Rys. 2.2. Rozmieszczenie znaków na klawiaturze QWERTY - ASCII 2.4.1. Modularna budowa klawiatur W klawiaturach komputerów osobistych można zwykle wyodrębnić trzy grupy klawiszy (zob. rys. 2.3) zwane modułami: - moduł centralny (c), - jeden lub dwa moduły pomocnicze (p), występujące po prawej stronie kla- wiatury, - moduł klawiszy funkcyjnych lub zapasowych (/), umieszczony nad modułem centralnym lub po jego lewej stronie. / ?[ 3 l Z 1 1 | 1 i 1 | 1 II 1 1 _J II 1 nr nr i Rys. 2.3. Moduły klawiatury - schemat ideowy 2. Jak działa komputer 40 Dalej wyjaśnimy znaczenie klawiszy specjalnych, charakterystycznych dla kla- wiatur komputerów, ze szczególnym uwzględnieniem komputera IBM PC. 2.4.2. Moduł centralny klawiatury Moduł centralny klawiatury komputera dziedziczy cechy klawiatury maszyny dc pisania. Zawiera klawisze liter, cyfr, klawisz odstępu, czyli spacji (zazwycza podłużny), znaków interpunkcyjnych, innych znaków widocznych w tekście ora klawisze o specjalnym przeznaczeniu, które opiszemy później. Dla zmniejszeni liczby klawiszy każdemu z nich są przypisane dwa znaki. Klawisze literowe rm ją również podwójne działanie: mogą wytwarzać kody wielkich i małych lite Ze względu na sposób oznakowania (czcionki są umieszczane w dwu rzędach podobnie jak w maszynach do pisania) można mówić o dwu rejestrach klawisz Aby wybrać górny rejestr, należy nacisnąć klawisz oznaczony napisem ShiJ (rzadziej - strzałką skierowaną do góry). Przykładowo, aby napisać małą lite 1 wystarczy nacisnąć klawisz [lj. Dla napisania wielkiej litery L naciśnię< tego klawisza należy poprzedzić naciśnięciem i przytrzymaniem klawisza \ Shif 1 Podobnie za pomocą klawisza \ Shif 11 możemy, naciskając klawisz oznakował uzyskać znak wykrzyknienia (górny rejestr - klawisz ) Shif t) przyciśnięty) cyfrę 1 (dolny rejestr - bez udziału klawisza |Shift |). Oprócz niezbędnych klawiszy )Shift | (dla wygody występujących częste ?v i^„„.;„+„T.Q ma klawisz o nazwie Caps Lock , któi Oprócz niezbędnych klawiszy |sniii | ^uia ™J6~-,, ..„ obu stronach klawiatury) klawiatura ma klawisz o nazwie Caps Lock działanie polega na przełączaniu rejestrów klawiatury na stałe. Ten klawisz od się tylko do liter i jego naciśnięcie odwraca działanie klawiszy )Shift \. Po uż; -=-""«n+Qrir nwskuiesie bez naciskania klawis się tylko do liter i jego naciśnięcie odwraca uŁiaMmv iŁ____ klawisza I Caps Lock" wielkie litery uzyskuje się bez naciskania klawisza (shi •^_:_„;„ i,iow5QWS, I caDS Lock I przyw klawisza I Caps Lock i wwimcu.v,»j —.,-- a małe - z jego pomocą. Powtórne naciśnięcie klawisza Caps Lock przyw poprzednie działania klawisza \ Shif t \ (zob. zad. 2.6). Wprowadzanie informacji - zmiana wiersza W module centralnym klawiatury jest zawsze umieszczany klawisz wprowad: informacji albo zmiany wiersza. Klawisz taki jest oznaczany najczęściej naj Enter, Return lub CR albo piktogramem w kształcie następującej strzałki: 2.4. Komputer w roli maszyny do pisania 41 W modułach pomocniczych niektórych klawiatur, np. dla komputerów IBM PC, można znaleźć kopię klawisza | Enter |. W wielu zastosowaniach naciśnięcie klawisza | Enter | jest dla programów sygnałem o zakończeniu wprowadzania te- kstu polecenia i żądaniem wykonania tego polecenia lub znakiem kończącym wprowadzanie danych. Kiedy indziej za pomocą tych klawiszy uzyskuje się po prostu efekt zmiany wiersza na ekranie, równoważny powrotowi karetki i wysu- wowi papieru w maszynie do pisania. Powtarzanie znaków Zauważmy, że przytrzymywanie któregoś z klawiszy kasowania przez nieco dłuższą chwilę zwykle włącza automatyczne działania klawisza, powodując skutek równo- ważny jego wielokrotnemu naciskaniu. Automatyczna repetycja dotyczy na ogół wszystkich klawiszy (poza klawiszami zmiany rejestrów i specjalnymi). Usuwanie znaków Tekst wyświetlany na ekranie jest jednocześnie przechowywany w pamięci kompu- tera. Dzięki temu zmiana lub usunięcie (skasowanie) uprzednio napisanego znaku | BS |) jest czynnością łatwą. W tym celu używa się klawisza Backspace ozna- czonego czasami strzałką w lewo. Jest on umieszczony w prawym górnym rogu modułu centralnego. Po naciśnięciu klawisza Backspace następuje usunięcie znaku bezpośrednio poprzedzającego kursor. Do usuwania znaków służy również klawisz | Del | (zob. p. 2.4.3). Powrót z programu Obsługa wielu programów przypomina zagłębianie się w kolejne pomieszczenia gmachu. Zawsze istotną sprawą jest wtedy sposób wycofania się do któregoś z poprzednich, zewnętrznych poziomów lub środowisk, jak można nazywać kolejne zagnieżdżenia programu. Nicią Ariadny może okazać się tutaj klawisz Esc |. Wiele programów interpretuje jednolicie użycie tego klawisza jako żądanie wyjścia z aktualnie tworzonego przez nie środowiska. Zastosowanie tabulatora Przy wypełnianiu tabel, jak również przy pisaniu programów komputerowych, zachodzi potrzeba rozpoczynania pisania od określonych pozycji w wierszu, czyli kolumn. W celu szybkiego przemieszczania kursora do początków kolejnych ru- bryk stosuje się klawisz tabulatora, oznaczany skrótem JTab | lub strzałkami 42 wskazującymi w lewo i w prawo. Naciśnięcie klawisza tabulatora powoduje prze- sunięcie kursora na ekranie w przód do najbliższej kolumny określonej przez ta- bulator. Użycie klawisza tabulatora wspólnie z klawiszem |Shift \ powodujf cofnięcie kursora wstecz do poprzedniej kolumny tabulatora. Szerokość jedno razowego przemieszczenia uzyskiwanego za pomocą klawisza tabulacji wynos zwykle 2, 3 lub 8 znaków i może być zmieniana przez programy redagowani tekstów. Klawisz |Tab | służy też często do przemieszczania kursora w obrębi wyświetlanych wykazów, ofert itp. Inne klawisze sterujące Oprócz klawisza (Shift |w komputerach używa się jeszcze dwu klawiszy pow dujących zmianę interpretacji innych klawiszy, na przykład literowych. Ich n zwy to \ Ctrl | i \ Alt \. Sposób posługiwania się tymi klawiszami jest podob do sposobu używania klawisza \ Shift \. Operacje klawiszowe, polegające jednoczesnym użyciu któregoś z klawiszy )Ctrl \ lub | Alt | i innego klawis! rozszerzają funkcje podstawowych klawiszy dwukrotnie lub nawet trzykrotr Interpretacja wytwarzanych w ten sposób i przesyłanych do komputera kod zależy od oprogramowania (zob. zad. 2.8). 2.4.3. Moduł pomocniczy klawiatury Oprócz modułu centralnego klawiatury komputerów są zwykle wyposażone w datkową grupę klawiszy, umieszczaną z prawej strony. Ów moduł pom niczy klawiatury zawiera dodatkową klawiaturę numeryczną, tj. dzie klawiszy z cyframi arabskimi, ułożonych tak jak w podręcznych kalkulator Ułatwia ona wprowadzanie dużych wykazów liczb. Klawisze modułu por niczego mają zazwyczaj, tak jak klawisze literowe, podwójne funkcje. O< wiednikiem klawisza Caps Lockl dla pomocniczego modułu cyfr jest kla Num Lock , przełączający klawiaturę pomocniczą w numeryczny tryb prac; w tryb manewrowania kursorem. Klawisze z modułu pomocniczego klawiatury komputerów IBM PC wyki dodatkową właściwość we współpracy z klawiszem | Alt \. Przytrzymując wisz |Alt \, można uzyskiwać za pomocą klawiszy z tego modułu znaki o kc większych od 127 (rozszerzenie kodu ASCII), np. narożniki ramek, niektóre greckie itp. (zob. zad. 2.8). Wstawianie i usuwanie znaków 2.4. Komputer w roli maszyny do pisania 43 interpretowany przez programy redagowania tekstów (jak również przez system operacyjny) jako żądanie wstawiania lub - naprzemiennie - zastępowania znaków przy pisaniu. Jak już powiedziano przy omawianiu klawiszy modułu centralnego, znaki mo- żna usuwać z ekranu dwoma sposobami: za pomocą klawisza Backspace (kaso- wanie znaku występującego przed kursorem) lub przez naciśnięcie klawisza | Del |. W tym drugim przypadku usuwany jest znak w pozycji kursora. W modułach po- mocniczych klawiatur komputerów IBM PC znajdują się dwa klawisze kasowania: [Dell lub Delete . Ich działanie jest jednakowe. Klawisze sterowania kursorem Oznakowane strzałkami klawisze modułu pomocniczego powodują ruch kursora na ekranie. Kursor może być przemieszczany w prawo i w lewo, a w niektórych programach także do góry i na dół. Oprócz strzałek do manewrowania kursorem w klawiaturach występują także klawisze do przenoszenia kursora na sąsiednie partie tekstu, a także do początku tekstu i na jego koniec. Są to klawisze: Home I, |~Er PgUp | End [. Znajdują one zastosowanie zwłaszcza w edytorach tekstu (zob. rozdz. 8). Typowe klawiatury (od liczby klawiszy nazywane "K102") mają między mo- dułem centralnym a numerycznym dodatkowy moduł klawiszy ze strzałkami oraz klawiszami PgDn PgDn , PgUp Delete . Klawisze te spełniają identyczne funkcje jak odpowiednie klawisze z klawiatury numerycznej przełączonej w tryb manewrowania kursorem. 2.4.4. Moduł klawiszy funkcyjnych Moduł klawiszy funkcyjnych składa się z jednolicie oznaczonych klawiszy. Sta- nowią one zapas (w liczbie od kilku do kilkunastu) do indywidualnej interpretacji przez poszczególne programy. Klawiatury komputerów IBM PC mają 12 klawi- , | F12 [ (zob. zad. 2.9). Klawiatury starszego typu F2 szy funkcyjnych: |_FJ mają 10 klawiszy funkcyjnych zlokalizowanych po lewej stronie modułu central- nego. Naciśnięcie klawisza | Fl | jest w wielu programach traktowane jak wezwanie pomocy. Znaczenie innych klawiszy jest zwykle ściśle związane z przeznaczeniem programu. 2.4.5. Wskaźniki świetlne na klawiaturze W prawym górnym rogu klawiatury komputera IBM PC (nad modułem pomoc- niczym) znajdują się trzy wskaźniki świetlne (diody świecące), nazwane tak samo 44 2. Jak działa komputer Num Lock] i |Scroll Lock| (niektóre programy i ID jak klawisze terpretują ten ostatni klawisz jako zakaz przesuwania tekstu na ekranie w górę lu w dół). Świecenie któregoś z tych wskaźników oznacza przełączenie klawiatur w odpowiedni tryb pracy. Na przykład, bezpośrednio po standardowym un chomieniu komputera świeci dioda wskaźnika (Num Lock|, co oznacza, że mod pomocniczy pracuje w trybie numerycznym. Naciśnięcie klawisza |Num Lock| p woduje przełączenie tego modułu w tryb manewrowania kursorem (dioda gaśnii Kolejne naciśnięcie klawisza |Num Lock| spowoduje powrót modułu w tryb r meryczny i zapalenie diody. 2.4.6. Polskie litery na klawiaturach komputerów IBM PC Istnieje kilka konwencji otrzymywania polskich liter na klawiaturach komputer IBM PC. Dotyczą one zarówno uwzględnienia liter z polskimi znakami diakrytj nymi w układzie klawiszy na klawiaturze, jak i przyporządkowania tym litei wartości liczbowych w zbiorze kodów znaków. Do najpopularniejszych sposol kodowania polskich znaków należą standardy o nazwach: Mazovia i Latir Dodatek zamieszczony na końcu książki zawiera m.in. kody polskich liter w s dardzie Mazovia. Sposób uzyskiwania polskich liter na klawiaturze zależy od poszczegól: programów. Najczęściej jest stosowana konwencja polegająca na tym, i tery "ą", "ć", "ę" itd. otrzymuje się po naciśnięciu i przytrzymaniu kkv | Alt \ oraz naciśnięciu klawisza z odpowiednią literą łacińską (np. "a", "c", Wyjątkowo do napisania litery "ź" stosuje się kombinację klawiszy \ Alt X nieważ kombinacja klawiszy |_ATt__zJ służy do otrzymywania litery ż. Na życzenie użytkownika w monitorach i drukarkach komputerów ins się zwykle układ elektroniczny umożliwiający wyświetlanie i drukowanie zr w wybranym, ustalonym standardzie. Wiele systemów oprogramowania \r. wanych w szkołach używa standardu Mazovia. Między innymi w tym st; dzie może pracować upowszechniany w szkołach edytor tekstów TAG, omć w rozdziale 8. Poczynając od wersji 5.00 w systemie operacyjnym MS-DOS przewi możliwość posługiwania się klawiaturami ze znakami z alfabetów 20 krajó-v pejskich, w tym również klawiaturą z polskimi literami. Wzorzec takiej tury zawiera dokumentacja tego systemu. Litery polskie ze znakami diak nymi występują na tej klawiaturze w miejscu klawiszy z nawiasami kłam i kwadratowymi (por. rys. 2.2) oraz klawisza ze średnikiem i klawisza z a fem ('). Ponadto, na prawo od klawisza z literą L klawiatura w tym star zawiera klawisz z literą Ł. Te zmiany pociągają za sobą przemieszczeni* znaków na klawiaturze. 2.5. System operacyjny 45 ńdziano 5w euro- j klawia- ikrytycz- nrowymi apostro-j indardzii de innycl 2.5. System operacyjny Komputer jest bardzo prostym urządzeniem automatycznym: może jedynie wy- konywać instrukcje jakie zna, a które są zapisane w jego pamięci wewnętrznej. Ciągi odpowiednio zestawionych instrukcji tworzą programy (przyjmijmy na razie takie określenie pojęcia "program"). Powstają natychmiast pytania: jak umieścić program w pamięci, jak spowodować, aby został wykonany, jak przekazać dane do przetwarzania, a jak wyprowadzić wyniki? Na wszystkie te i wiele podobnych pytań jest jedna odpowiedź: należy przygotować odpowiednie programy, które będą wykonywały te czynności. Ponieważ z tych programów będzie korzystać praktycznie każdy użytkownik komputera, warto przygotować je tylko raz, ale za to bardzo starannie, i udostępnić wszystkim zainteresowanym. Warto przy tym zadbać, żeby ich obsługa była możliwie najprostsza, a dostęp jak najszybszy. Wszystkie te postulaty spełnia system operacyjny. Jest to program nadzo- rujący pracę komputera. Istnieją systemy operacyjne o różnym stopniu złożoności, od bardzo prostych przeznaczonych do obsługi komputerów osobistych, po wielce złożone, instalowane w dużych komputerach. Nas interesują te pierwsze, a szczególnie MS-DOS - najbardziej rozpowszechniony system operacyjny komputerów IBM PC. System operacyjny jest programem złożonym z wielu podprogramów, często niezależnych od siebie. Możemy odwoływać się do nich wydając odpowiednie zle- cenia (w użyciu jest także określenie komendy). Należy przy tym przestrzegać ustalonych zasad pisowni nazw zleceń oraz ich parametrów. Parametry zleceń są najczęściej związane z pewnymi zasobami informacji zgromadzonymi w postaci plików, o których piszemy w następnym punkcie. 2.5.1. Pliki Korzystanie z komputera polega zazwyczaj na przetwarzaniu informacji za po- mocą odpowiedniego programu, który jako wynik wytwarza inną informację. Użytkownik komputera może dysponować własnymi programami lub może ko- rzystać z programów przygotowanych przez innych. Wszystkie te informacje (program jest także pewnym rodzajem informacji, podającej jak należy przetwa- rzać inne informacje) muszą znajdować się w komputerze wtedy, gdy chcemy z nich korzystać. W dalszych rozdziałach poznamy rodzaje informacji, takie jak teksty czy bazy danych, które są gromadzone, przetwarzane i przechowy- wane w komputerach. Informacje są pamiętane w komputerach w oddzielnych zbiorach nazywanych plikami. System operacyjny umożliwia posługiwanie się plikami i rozróżnianie poszczególnych plików za pomocą ich nazw. Obowiązują przy tym pewne zasady. W systemie operacyjnym MS-DOS nazwa pliku składa jsię z nazwy podstawowej o długości co najwyżej ośmiu znaków, rozszerzę- 46 nia o długości do trzech znaków oraz kropki oddzielającej obie części. Nazwę podstawową oraz rozszerzenie mogą tworzyć następujące znaki: - litery małe i wielkie alfabetu łacińskiego, - cyfry dziesiętne, - znaki specjalne, spośród których najczęściej są używane minus (-), pod kreślenie (_), pojedynczy apostrof ('). W wielu programach - także tych podstawowych, takich jak system oper; cyjny - przyjęto, że pewne rozszerzenia nazw mają ustalone znaczenie i określa; rodzaj informacji zawartej w pliku. Warto polecić stosowanie proponowanych d danego typu plików rozszerzeń, gdyż - mimo iż często nie jest to obowiązkowe znakomicie ułatwia wyszukiwanie plików na dysku oraz rozumienie ich przezn czenia. Przykład 2.2. Przykładowe nazwy plików: PR0GRAM1.PAS rozszerzenie PAS jest zwykle stosowane w odniesieniu pliku zawierającego tekst programu w języku Pascal, ROK'93 DANE.P-1 dane.p-2 WYNIKI.P-l BACKUP.COM tpc.exe programl.exe autoexec.bat pliki z rozszerzeniem COM lub EXE są interpretowane pr system operacyjny jako zlecenia tego systemu lub progra do wykonania, rozszerzenie bat mają zwykle nazwy plików, których wartość stanowi ciąg zleceń dla systemu operacyjnego. Małe i wielkie litery w nazwach plików są utożsamiane, zatem nazwy dane oraz DANE.P-1 są dla systemu operacyjnego identyczne. W dalszych prz] dach nazw plików i zleceń systemu MS-DOS używamy wyłącznie wielkich (zob. Wyróżnienia w tekście omówione we Wstępie). W niektórych zleceniach jest dopuszczalne stosowanie nazw niejednozr nych mogących identyfikować jednocześnie wiele różnych plików. Znak ? \ w nazwie zastępuje dowolny inny znak na tej samej pozycji, różny od ki Znak * zastępuje w nazwie dowolny ciąg znaków nie zawierający kropki. Przykład 2.3. Jeżeli przyjmiemy, że mamy bezpośrednio dostępne pliki - i szej części tego rozdziału dowiemy się, co to oznacza - o takich nazwać! w przykładzie 2.2, to napis PR0GRAM1.* 2.5. System operacyjny 47 identyfikuje dwa pliki: PR0GRAM1.PAS oraz programl.exe, natomiast napis dane.p-? odnosi się do plików DANE.P-1 oraz dane.p-2. ? Dla istniejących plików - z wyjątkiem plików zawierających programy do wy- konania - dopuszcza się dwa typy operacji: zapis i odczyt, co oznacza, że do pliku można wpisywać nowe informacje (np. dane lub wyniki) lub odczytywać jego zawartość. Podobne funkcje pełnią urządzenia zewnętrzne: monitor, klawia- tura i drukarka. Przykładowo, monitor służy do wyświetlania różnych informacji, co uzyskuje się w wyniku wykonania operacji zapisu (wpisania) tych informacji na ekran monitora. Funkcjonalnie taka operacja zapisu niczym nie różni się od operacji zapisu do pliku na dysku, stąd monitor jest traktowany w programach jako plik. Podobnie są traktowane klawiatura i drukarka z tym, że w przypadku klawiatury można odczytywać z odpowiadającego jej pliku, a drukarka jest trak- towana jak plik, do którego można tylko zapisywać. Z uwagi na specyfikę tych urządzeń przyjęto stałe nazwy odpowiadających im plików, i tak: CDN - określa monitor lub klawiaturę (rozróżnienie jest uzależnione od funkcji urządzenia: zapis dotyczy monitora, a odczyt - klawiatury), PRK, LPT1 - określają drukarkę. 2.5.2. Podział logiczny pamięci zewnętrznej Dyski stałe, będące częścią pamięci zewnętrznej komputera, mogą być nieporęczne dla programów z uwagi na znaczną pojemność. Na przykład, wyszukiwanie pliku na całym dysku może powodować niepotrzebną stratę czasu. Dlatego istnieje możliwość - a najczęściej wręcz konieczność - logicznego podziału dysku na rozłączne części, które nazywamy partycjami lub tomami dyskowymi. Tym drugim terminem określa się także napędy dysków elastycznych. Podziału dysku na tomy dokonuje się jednorazowo w czasie przygotowywania dysku stałego do pracy, czyli formatowania - odpowiednie zlecenia poznamy w p. 2.6. Każdy tom ma swoją nazwę złożoną z jednej litery i dwukropka. Przykład 2.4. Przyjmijmy, że pamięć zewnętrzna zestawu komputerowego jest wyposażona w dwa różne napędy dysków elastycznych oraz jeden (fizycznie) dysk stały złożony z dwóch tomów. W tym przypadku o pamięci dyskowej komputera powiemy, że składa się z czterech tomów o nazwach: A:, B: - oznaczających napędy dysków elastycznych 2. Jak działa komputer 48 oraz C:, D: - oznaczających dwie logiczne części dysku stałego. Nazwy tomów można pisać oczywiście małą literą. W praktyce utrwaliło się utożsamianie tomów dyskowych z dyskami. Zamiast mówić np. "plik został skopiowany z tomu dyskowego C: na tom D:", mówi się "plik został skopiowany z dysku C: na dysk D:". Nie zawsze oznacza to jednak, że komputer jest wyposażony w dwa dyski fizyczne, a wyraża jedynie podział logiczny dysku fizycznego na dwie części. Każdy tom dyskowy użytkownik komputera może podzielić na logicznie roz- łączne części, które nazywamy kartotekami (p. 2.6 - zlecenie MD). W kartotece umieszcza się zwykle pliki związane ze sobą tematycznie lub funkcjonalnie. Każds kartotekę można także podzielić logicznie, tworząc w niej kartoteki podrzędne (podkartoteki). Powstaje w ten sposób drzewo kartotek - struktura podziału logicznego dysku lub tomu dyskowego (zob. rys. w przykładzie 2.5). Nazwy wszystkich plików zapisanych w kartotece są zawarte w katalogu two rzonym przez system operacyjny. Katalog jest plikiem zawierającym: nazw; wszystkich plików zawartych w kartotece, nazwy podkartotek, czas i datę utwc rżenia podkartoteki lub pliku oraz wielkość pliku wyrażoną w bajtach. Przykład 2.5. Użytkownik komputera zamierza umieścić na dysku C: systefi operacyjny MS-DOS, systemy programowania Turbo Pascal i Logo oraz edytor TAG i ChiWriter. W tym celu może zbudować drzewo kartotek przedstawione n rys. 2.4. System programowania Turbo Pascal wymaga założenia dodatkowyc podkartotek, których nazwy uwidoczniono w drzewie. W każdej z kartotek nalei umieścić właściwe pliki. Kartoteka główna, której odpowiada korzeń drzewa, je standardowo oznaczana znakiem \ . DOS JEŻYKI PASCAL BGI DOC DOCDEMOS - TVDEM0S - TYISION EDYTORY LOGO CHIWRIT TAG Rys. 2.4. Drzewo kartotek z przykładu 2.5. 2.6. Podstawowe zlecenia systemu MS-DOS 49 2.6. Podstawowe zlecenia systemu MS-DOS Zlecenia systemu operacyjnego piszemy podając ich nazwę oraz - o ile jest wyma- gany - parametr lub wykaz parametrów, których zadaniem jest uściślenie zlece- nia. Pierwszy parametr należy z reguły oddzielić od nazwy zlecenia co najmniej jednym odstępem, a pozostałe oddzielamy od siebie także odstępem lub - rzadko - innymi separatorami. Oprócz parametrów w niektórych zleceniach dopuszcza się używanie kluczy pozwalających - podobnie jak parametry - sprecyzować dokładniej wymagane działanie zlecenia. Klucze mają swoje nazwy poprzedzane znakiem /. W zleceniu można korzystać jedynie z zestawu dopuszczalnych dla tego zlecenia kluczy. W wersji 5.0 systemu MS-DOS we wszystkich zleceniach można używać klucza /?, który poleca wyświetlić na ekranie objaśnienie funkcji zlecenia, jego składni, dopuszczalnych parametrów i kluczy. Jest to pewien rodzaj pomocy. Zlecenia możemy wydawać tylko w stanie gotowości systemu operacyjnego do ich przyjmowania. Stan ten objawia się wyświetleniem zaproszenia do pisania zleceń (nazywanego czasem znakiem zachęty) - standardowo jest to znak > po- przedzony informacją wskazującą bieżącą kartotekę. Użytkownik może zmienić postać zaproszenia do pisania, wydając zlecenie PROMPT z odpowiednim parame- trem (por. zad. 2.12). System operacyjny może wykonywać swoje zlecenia lub uruchamiać programy znajdujące się na dysku. Zlecenia systemu dzielimy na zlecenia wewnętrzne oraz zlecenia zewnętrzne. Programy realizujące zlecenia wewnętrzne stanowią tę część systemu operacyjnego, która jest umieszczana bezpośrednio w pamięci operacyjnej podczas uruchamiania komputera i znajduje się tam przez cały czas pracy komputera. Dzięki temu zlecenia wewnętrzne są realizowane przez system operacyjny natychmiast po ich rozpoznaniu. Zlecenia zewnętrzne są traktowane tak jak pozostałe programy, których wykonanie wymaga najpierw odszukania odpowiedniego pliku z programem na dysku i załadowania go do pamięci opera- cyjnej, a następnie uruchomienia. System operacyjny w poszukiwaniu pliku z programem nie przegląda całego dysku lub dysków, a jedynie wskazane przez użytkownika kartoteki. Wyboru kartotek do przeszukiwania dokonujemy zleceniem PATH, które poznamy w dalszej części tego punktu. Omówimy teraz pokrótce wybrane, najczęściej używane zlecenia systemu ope- racyjnego MS-DOS. Pisząc dalej o tomach dyskowych, będziemy używali skróto- wego określenia "dysk" mając na uwadze dysk logiczny, co jak już wiemy, nie jest tożsame z dyskiem fizycznym. 14 — Elementy informatyki 50 2. Jak działa komputer 2.6.1. Wybór bieżącego miejsca pracy System operacyjny nadzoruje pracę wszystkich urządzeń zewnętrznych tworzą- cych zestaw komputera lub przyłączonych do komputera, ale w szczególny sposób traktuje dyski. Jeden z nich jest zawsze wyróżniony i jest to dysk bieżący. Po- minięcie nazwy dysku w tych zleceniach, które wymagają jej podania, jest in- terpretowane jako odwołanie się do dysku bieżącego. Po włączeniu komputera dyskiem bieżącym jest dysk, na którym znajduje się system operacyjny. W ze- stawach z dyskiem stałym jest to z reguły dysk C:, a w komputerach bez dysku stałego - dysk A:. W czasie pracy można zmieniać dysk bieżący. Wystarczy w tym celu podać nazwę odpowiedniego dysku (np. D:) w chwili, kiedy jest dopuszczalne pisanie zleceń. Nazwa bieżącego dysku jest standardowo podawana w zaproszeniu sy- stemu do pisania zleceń. Wiemy już, że każdy dysk jest podzielony na kartoteki (nawet jeżeli podziału nie dokonamy, to system operacyjny będzie traktował cały dysk jako jedną, główną kartotekę). Praca pod kontrolą systemu operacyjnego wymaga okreś- lenia jednej kartoteki jako bieżącej. Konsekwencją tego jest prostszy sposóli odwoływania się do plików zawartych w tej kartotece. Jeżeli na przykład pro- simy kogoś 'zamknij okno', to milcząco przyjmujemy, że chodzi o pomieszczeni; w którym się znajdujemy. Polecenie 'zamknij okno w sypialni' jest dokładniejsze ale ta precyzja ma znaczenie tylko wtedy, gdy jesteśmy w innym niż sypialni! pomieszczeniu. Podobnie jest z bieżącą kartoteką: odwołanie do pliku zawartego w niej wy maga jedynie podania nazwy pliku, natomiast odwołanie do pliku umieszczoneg w każdej innej kartotece zmusza nas dodatkowo do precyzyjnego wskazania kartc teki. Ponadto, jeżeli kartoteka znajduje się na innym dysku niż bieżący, to należ określić, o jaki dysk chodzi. Wskazanie kartoteki nie może ograniczać się do podi nia jej nazwy. Organizacja dysku w postaci drzewa dopuszcza bowiem stosowan identycznych nazw dla różnych kartotek pod warunkiem, że nie wywodzą się oi bezpośrednio z jednej kartoteki nadrzędnej. Dla każdego pliku jest konieczne z tem jednoznaczne wskazanie ścieżki dostępu do pliku, czyli drogi jaką nale: odbyć od kartoteki głównej albo bieżącej, poprzez kolejne kartoteki pośrednie, < właściwej kartoteki zawierającej dany plik. Droga ta odpowiada w drzewie kart tek drodze z korzenia (czyli z kartoteki głównej) lub wierzchołka odpowiadające bieżącej kartotece do wierzchołka odpowiadającego kartotece zawierającej da plik. Zapisując ścieżkę dostępu do pliku oddzielamy nazwy kartotek od siei znakiem \, co jest trochę niefortunne, gdyż identycznie jest nazwana kartote główna na każdym dysku. Zatem znak \ występuje - w zależności od konteks - jako nazwa kartoteki głównej bądź separator w ścieżce dostępu. Dwie kro] . . służą do oznaczania kartoteki nadrzędnej. 2.6. Podstawowe zlecenia systemu MS-DOS 51 Przykład 2.6. Załóżmy, że na dysku D: mamy drzewo kartotek przedstawione na rys. 2.5. \ USER ABC 1--- XYZ PROGRAMY LISTY GRY PROGRAMY LEKCJE PASCAL LOGO I Rys. 2.5. Drzewo kartotek z przykładu 2.6. Napis D:\USER\ABC\GRY\CHESS.EXE określa plik o nazwie CHESS.EXE znaj- dujący się na dysku D: w kartotece GRY, której nadrzędnymi kartotekami są (licząc od kartoteki głównej) USER i ABC. Pierwszy znak \ występuje w podwójnej roli: nazwy kartoteki głównej i se- paratora. Jeżeli bieżącą kartoteką jest kartoteka LOGO, a chcemy odwołać się do pliku PRÓG.PAS umieszczonego w sąsiedniej kartotece PASCAL, to ścieżkę dostępu możemy określić następująco ..\PASCAL\PROG.PAS gdzie - oznacza kartotekę PROGRAMY nadrzędną względem bieżącej (LOGO), \ - pełni rolę separatora: pierwszy znak \ oddziela nazwy dwóch kartotek, drugi - nazwę kartoteki i pliku. Można także wskazać pełną ścieżkę dostępu od korzenia w drzewie kartotek: \USER\XYZ\PROGRAMY\PASCAL\PROG.PAS ? W dalszej części tej książki pisząc o nazwie pliku będziemy mieli na myśli pełną nazwę pliku, a więc nazwę poprzedzoną - w razie konieczności - ścieżką dostępu do pliku. Zmiany bieżącej kartoteki dokonujemy zleceniem CD, podając w parametrze nazwę kartoteki wraz z ewentualną ścieżką dostępu do niej. Zlecenie CD bez parametru powoduje wyświetlenie na ekranie aktualnej ścieżki dostępu. Przykład 2.7. Dysponujemy drzewem kartotek przedstawionym na rysunku 2.5 i chcemy zmienić bieżącą kartotekę z kartoteki LOGO na LEKCJE. W tym celu piszemy zlecenie CD ..\..\LEKCJE lub CD \USER\XYZ\LEKCJE 52 2.6.2. Uruchamianie programów Uruchomienie programu komputerowego jest możliwe, jeżeli są spełnione nastę- pujące warunki: - plik zawierający program znajduje się w komputerze na dysku (plik ten musi mieć rozszerzenie EXE lub COM), - wydane zostało zlecenie uruchamiające ten program, - system operacyjny potrafi odnaleźć na dysku plik zawierający program, - w pamięci operacyjnej jest wystarczająco dużo miejsca na program i efekty] jego pracy. | Wydanie zlecenia uruchamiającego program polega na wprowadzeniu nazv pliku zawierającego program - można to robić w stanie gotowości systemu ope-ł racyjnego do przyjmowania zleceń - i naciśnięciu klawisza | Enter |. Jeżeli wypij sując nazwę programu podaliśmy ścieżkę dostępu do pliku zawierającego ten proj gram, to system operacyjny bez trudu odnajdzie ten plik. W przypadku plikom zawierających programy lub plików zawierających ciągi zleceń dla systemu ope racyjnego nie jest jednak konieczne wypisywanie każdorazowo ścieżki dostępu! W tym celu należy najpierw wskazać zleceniem PATH wszystkie kartoteki, jaki! system operacyjny powinien przejrzeć w poszukiwaniu właściwego pliku. 1 Zlecenie PATH ma postać PATH wykaz-nazw-kartotek-zakończonych-średnikiem lub PATH Wymienione kartoteki - a ściślej ich katalogi - będą przeszukiwane w kolejnoś' występowania w parametrze tego zlecenia. Zlecenie PATH bez parametru powi duje wyświetlenie aktualnie obowiązującego wykazu nazw kartotek, czyli wykaz- który został podany w ostatnim zleceniu PATH z parametrem. Przykład 2.8. Jeżeli mamy drzewo takie, jak na rys. 2.5 i wydamy zlecenie PATH C:\;C:\D0S;D:\USER\ABC\PROGRAMY;D:\USER\ABC\GRY; to przy każdym następnym zleceniu dla systemu operacyjnego, o ile nie jest zlecenie wewnętrzne systemu, będą przeglądane w kolejności katalogi: głów na dysku C:, \D0S także na dysku C:, \USER\ABC\PROGRAMY i \USER\ABC\G - oba na dysku D: . Jeśli w kartotece D:\USER\ABC\GRY znajduje się prograi CHESS. EXE grający w szachy, to można go uruchomić z dowolnej kartoteki zlecę niem CHESS. I Pisząc zlecenie uruchamiające program, z reguły nie podajemy rozszerzeni odpowiedniego pliku. W takim wypadku system operacyjny szuka pliku o podam i 2.6. Podstawowe zlecenia systemu MS-DOS 53 nazwie i rozszerzeniu EXE, COM lub BAT. Jak wspomniano w przykładzie 2.2, pliki z rozszerzeniem EXE lub COM zawierają programy do wykonania, natomiast pliki z rozszerzeniem BAT - ciągi zleceń systemu operacyjnego umożliwiające prze- twarzanie wsadowe. Polega ono na tym, że kolejne do wykonania zlecenia są czytane z tego pliku, a nie z klawiatury lub z ekranu (którym jak wiemy również odpowiada plik o nazwie CDN). Można uniknąć wydawania (złożonego) zlecenia PATH po każdorazowym włą- czaniu komputera. Wystarczy umieścić to zlecenie w pliku z rozszerzeniem BAT (ewentualnie razem z innymi zleceniami) i zadbać o to, aby system operacyjny wy- konał zawarty w pliku ciąg zleceń bezpośrednio po uruchomieniu komputera. Sy- stem MS-DOS przy każdym inicjowaniu (tj. po włączeniu komputera) sprawdza, czy w kartotece głównej na dysku, z którego jest inicjowany system, znajduje się plik o nazwie AUT0EXEC. BAT. Jeżeli tak, to system rozpoczyna przetwarzanie wsa- dowe, czyli wykonuje kolejne zlecenia zapisane w tym pliku. Widać, że m.in. zlece- nie PATH ustawiające ścieżki dostępu powinno znaleźć się w pliku AUTOEXEC.BAT, by stale obowiązywało bez konieczności wypisywania go po każdym włączeniu komputera. Programy można uruchamiać dla różnych zestawów danych, zgromadzonych zwykle w plikach; wyniki zapisuje się także w plikach. Najczęściej program czyta dane z jednego pliku, a wyniki zapisuje w innym pliku. Uruchamianie takich programów można parametryzować, określając w zleceniu inicjującym program strumień wejścia/wyjścia (we/wy) składający się z nazwy pliku z danymi (wejście) oraz nazwy pliku przeznaczonego na wyniki (wyjście). Ogólna postać zlecenia uruchamiającego program jest następująca: próg wyniki gdzie próg - jest nazwą pliku z programem, dane - oznacza nazwę pliku zawierającego dane dla programu, wyniki - jest nazwą pliku przeznaczonego na wyniki. Jeżeli program nie czyta żadnych danych, to wystarczy w strumieniu we/wy podać jedynie nazwę pliku na wyniki poprzedzoną znakiem >. Podobnie postę- pujemy w sytuacji odwrotnej, gdy np. wyniki są przesyłane wyłącznie na ekran, a potrzebny jest tylko plik z danymi. Odstępy między nazwą zlecenia a parametrem oraz między parametrami są nieistotne (można je pominąć) w przypadkach, gdy parametr rozpoczyna się od jednego ze znaków <,>,.., \, /. Podany tutaj sposób określania strumienia we/wy nie jest jedynym możliwym. Niekiedy (np. w programach w języku Pascal, zob. rozdz. 4 i 5) nazwy plików z danymi i przeznaczonych na wyniki są zapisane bezpośrednio w programie lub podaje się je dopiero na żądanie programu już w trakcie jego działania. 54 2.6.3. Wyświetlanie katalogu Wyświetlenie całego katalogu lub jego części określonej przez parametr powoduje zlecenie DIR, które ma postać DIR nazwa-kartoteki lub DIR nazwa-pliku Pominięcie parametru w zleceniu oznacza, że zostanie wyświetlony katalog bie- żącej kartoteki. Przykład 2.9. Następujące zlecenia powodują: DIR A:/P DIR *.PAS - DIR >PRN 1> CLO (J*^ Ł_7 ŁAJ ł_yi^-^ .-----------_ ^ wyświetlenie nazw wszystkich plików oraz podkartotek zapisa nych w kartotece głównej dyskietki umieszczonej w napędzie A: wyświetlenie nazw wszystkich plików mających rozszerzenie PAl i znajdujących się w bieżącej kartotece; katalog bieżącej kartoteki zostanie wydrukowany (a dokładnie wynik wykonania zlecenia zostanie skierowany do wskazaneg pliku PRN, czyli na drukarkę, zgodnie z podanym w poprzedni] punkcie sposobem określania strumienia we/wy). Klucz /P użyty w zleceniu DIR A: /P oznacza, że wyświetlanie katalogu będz zatrzymywane każdorazowo po zapełnieniu ekranu i wznawiane po naciśnięć dowolnego klawisza. Dzięki temu można obejrzeć nawet najdłuższy katalog b obawy, że część informacji zniknie z ekranu zbyt szybko. Należy dodać, że w rodzimej literaturze informatycznej często nie odróżr się pojęć kartoteki i katalogu. Dla obu pojęć używa się określenia katalog. 2.6.4. Zakładanie i usuwanie kartotek Do zakładania nowych kartotek na dysku służy zlecenie MD. Przybiera ono pos1 MD nazwa-kartoteki i zostanie zrealizowane przez system operacyjny, jeżeli w kartotece nadrzęd względem zakładanej nie ma kartoteki o takiej samej nazwie jak parametr zlecę oraz jest jeszcze miejsce na dysku. W nazwach kartotek dopuszcza się - podoi: jak dla plików - stosowanie rozszerzeń. Przykład 2.10. Załóżmy, że dysponujemy drzewem kartotek przedstawior na rys. 2.5 i chcemy w kartotece LEKCJE utworzyć trzy podkartoteki o nazw FIZYKA, POLSKI.KL2 oraz POLSKI.KL3. W tym celu najwygodniej jest najp: 2.6. Podstawowe zlecenia systemu MS-DOS 55 przejść z bieżącej kartoteki do kartoteki LEKCJE (o ile jesteśmy w innej kartotece) wydając znane nam już zlecenie CD z odpowiednim parametrem, a następnie napisać następujące zlecenia: MD FIZYKA MD POLSKI.KL2 MD POLSKI.KL3 Po wykonaniu tych zleceń drzewo kartotek będzie miało postać przedstawioną na rysunku 2.6. \ USER ABC XYZ PROGRAMY LISTY GRY PROGRAMY LEKCJE PASCAL LOGO FIZYKA POLSKI.KL2 POLSKI.KL3 Rys. 2.6. Drzewo kartotek z rys. 2.5 po rozszerzeniu Zlecenie MD można wydać z dowolnej innej kartoteki, pisząc w parametrze ścieżkę dostępu do zakładanej kartoteki, zatem w przykładzie powyższym założe- nie podkartoteki FIZYKA z kartoteki USER wymaga napisania zlecenia MD XYZ\LEKCJE\FIZYKA ? Istniejącą kartotekę można usunąć pod warunkiem, że jest ona pusta, tzn. nie zawiera żadnych podkartotek ani plików oraz nie jest kartoteką bieżącą ani główną. Do tego celu używamy zlecenia RD: RD nazwa-kartoteki Przykład 2.11. Z drzewa zamieszczonego na rys. 2.6 chcemy usunąć kartotekę GRY, a bieżącą kartoteką jest ABC. Powinniśmy najpierw upewnić się, że kartoteka GRY jest pusta, wyświetlając jej katalog zleceniem DIR GRY Jeżeli ta kartoteka nie jest pusta, to należy usunąć bądź skopiować potrzebne pliki (zob. zlecenie kopiowania plików, p. 2.6.5), a następnie wydać zlecenie RD GRY ? 56 Przy tworzeniu własnego drzewa kartotek na dysku należy dbać o to, aby nie przeciążać kartoteki nadmierną liczbą plików. Duża liczba plików w kartotece powoduje wydłużanie czasu dostępu do nich (gdyż zmusza system operacyjny do przeglądania każdorazowo dużego katalogu) i utrudnia naszą pracę (my także jesteśmy zmuszeni czasem przeglądać katalog). 2.6.5. Zakładanie i kopiowanie plików Tworzenie (mówimy także zakładanie) nowych plików jest domeną edytorów programów przeznaczonych do wprowadzania i redagowania tekstów, którym' jest poświęcony rozdział 8. Tutaj wspomnijmy jedynie, że użytkownik kompu^ tera ma do dyspozycji całą gamę edytorów o różnym przeznaczeniu: od edy-j torów służących do wprowadzania tekstów programów po edytory (a w ogólności, systemy składu drukarskiego takie, jak TęX) ułatwiające redagowanie książek, Nowe pliki mogą zostać utworzone także w wyniku wykonania programu. Systen operacyjny MS-DOS nie ma w swoim repertuarze odrębnego zlecenia zakładani! plików. Można jednak w prosty sposób tworzyć nowe pliki korzystając ze zleceni; kopiowania plików. Zlecenie to o nazwie COPY ma postać COPY plik-źródłowy plik-wynikowy [1 lub COPY plik-1+plik-2+... + plik-n plik-wynikowy (! gdzie plik-źródłowy, plik-wynikowy, plik-1, plik-2, ..., plik-n są nazwami plikó1 Nazwy plików mogą być niejednoznaczne (tj. mogą zawierać znaki * lub ?), cz; mogą określać grupę plików. Zlecenie w postaci (2) służy do skopiowania 2 wartości pliku plik-źródłowy do pliku plik-wynikowy, natomiast zlecenie w post; (3) łączy (mówimy także scala ) n plików o wskazanych nazwach w jeden p wynikowy w kolejności określonej parametrem zlecenia: plik-1 jest kopiowany pliku wynikowego, a następne pliki są dopisywane do pliku wynikowego (o innj metodach scalania plików jest mowa w rozdziałach 5 i 7). Nazwę pliku wyni wego można pominąć, wtedy system operacyjny przyjmie domyślnie w tej i nazwę pliku źródłowego lub pierwszego spośród scalanych plików {plik-1 w zk niu o postaci (3)), ale odniesie tę nazwę do pliku z bieżącej kartoteki. Zamiast pełnej nazwy pliku wynikowego można podać jedynie nazwę ka teki, co spowoduje, że system operacyjny przyjmie nazwę pliku wynikowego : dnie z zasadą podaną wyżej, ale plik ten znajdzie się oczywiście we wskaza a nie w bieżącej kartotece. Jak już wiemy monitor, drukarka oraz klawiatura są traktowane tak jak p Jeżeli zatem wydamy zlecenie COPY CON TEKST 2.6. Podstawowe zlecenia systemu MS-DOS 57 to wszystkie znaki wprowadzane z klawiatury i wyświetlane na ekranie zostaną skopiowane do pliku TEKST w bieżącej kartotece. Wprowadzanie zostanie za- kończone po przesłaniu specjalnego znaku oznaczającego koniec pliku. Znak ten uzyskujemy naciskając klawisze Ctrl Z | lub klawisz funkcyjny | F6 |, a następnie [Enter |. Wydane następnie zlecenie COPY TEKST CDN spowoduje wyświetlenie zawartości pliku TEKST na ekranie monitora. Przykład 2.12. Przykłady użycia zlecenia COPY: COPY ..\LIST.TXT - zlecenie spowoduje skopiowanie pliku o nazwie LIST.TXT z kartoteki nadrzędnej do kartoteki bieżącej; pominięcie drugiego parametru oznacza, że plik w bieżącej kartotece również będzie miał nazwę LIST.TXT; kopiowanie wszystkich plików z rozszerzeniem PAS z bieżącej kartoteki na dyskietkę umieszczoną w na- pędzie A: do kartoteki PASCAL z zachowaniem nazw plików; scalenie trzech plików o nazwach X, Y, Z w jeden plik o nazwie XYZ w bieżącej kartotece. ? COPY *.PAS A:\PASCAL - COPY X+Y+Z XYZ 2.6.6. Wyświetlanie i drukowanie zawartości plików Informacje zawarte w dowolnym pliku można odczytać. Sposób odczytywania zależy od rodzaju i postaci, w jakiej zapisano informacje. Najprostsze do od- czytania są teksty mające swoją naturalną znakową reprezentację w komputerze, w której każdy znak tekstu jest zapisany na jednym bajcie, np. w powszechnie stosowanym kodzie ASCII. Teksty mogą mieć jednak bardziej złożoną postać - przekonamy się o tym w rozdziale 8. Teraz ograniczymy się jedynie do przedsta- wienia kilku przykładowych krojów litery F dostępnych w systemie TęX: F F F F F . Stosowanie wielu krojów pisma oznacza, że jeden bajt nie wystarczy do za- pisania jednego znaku. Już z przykładu podanego wyżej wynika, że znak należy poprzedzić informacją wskazującą na wybrany krój. Niezbędne są także odpowie- dnie programy do wyświetlania i drukowania plików zawierających teksty przygo- towane za pomocą edytorów. System operacyjny pozwala co prawda wyświetlać , i drukować dowolny plik, ale każdy bajt zawartości pliku jest interpretowany jako [znak zapisany w kodzie ASCII. Do wyświetlania i/lub drukowania zawartości pliku służą zlecenia TYPE, MORĘ oraz PRINT. 58 Zlecenie TYPE nazwa-pliku powoduje wyświetlenie na ekranie zawartości pliku wskazanego przez parametr zlecenia. Jeżeli plik nie zawiera tekstu zapisanego w kodzie ASCII, to zlecenie zostanie wykonane, ale informacja wyświetlana na ekranie będzie nieczytelna. Można się o tym przekonać, próbując wyświetlić np. zawartość jakiegokolwiek pliku z programem, czyli pliku z rozszerzeniem EXE lub COM. Wyświetlanie odbywa się bardzo szybko, dlatego, jeżeli zawartość pliku nie mieści się na ekranie, te początkowe fragmenty pliku błyskawicznie znikną z ekranu, a widoczna będzk jedynie końcowa część pliku. Można próbować na przemian zatrzymywać i wzna wiać wyświetlanie naciskając klawisze Ctrl S |, ale wymaga to dużego renę ksu i opanowania. Dużo prostszym sposobem wyświetlania zawartości większycl plików jest stosowanie zlecenia MORĘ PRN które wywołuje ten sam skutek, tzn. poleca wydrukować zawartość wskazań* pliku, to w czasie drukowania system nie wykona żadnego innego zlecenia. Przykład 2.13. Podane niżej zlecenia polecają wyświetlić na ekranie, a następ wydrukować zawartość pliku ADRESY.TXT. MORĘ PRN narażamy się jedynie na wspomnianą wyżej niedogodność przy szybkim prs janiu ekranu. 2.7. Wokół komputera 59 2.6.7. Kasowanie pliku Pliki można usunąć z dysku zleceniem DEL nazwa-pliku Możliwość podawania nazw niejednoznacznych pozwala na jednoczesne kasowa- nie wielu plików. Zamiast DEL można pisać ERASE - skutek będzie ten sam. Przykład 2.14. Następujące zlecenia usuwają: DEL ABC\DANE.l DEL A:WYNIKI.* DEL *.* plik DANE. 1 z podkartoteki ABC; z dyskietki A: pliki o nazwie podstawowej WYNIKI i do- wolnym rozszerzeniu; wszystkie pliki z bieżącej kartoteki. Ponieważ jest to ope- racja drastyczna, przed jej wykonaniem system opera- cyjny upewnia się czy nie zaszła pomyłka, żądając podania odpowiedzi na pytanie Are you surę(Y/N)? Jeśli naciśniemy klawisz [Yj, to zlecenie zostanie wyko- nane, a w przeciwnym razie - zaniechane. ? 2.6.8. Zmiana nazwy pliku Zmianę nazwy pliku powoduje zlecenie REN w ogólnej postaci REN stara-nazwa nowa-nazwa Obie nazwy dotyczą tego samego pliku, zatem jest zrozumiałe, że nazwa kartoteki - o ile musi wystąpić w przypadku, gdy plik nie jest w bieżącej kartotece - pojawi się jedynie przy pierwszej nazwie. Przykład 2.15. Przykłady zastosowań zlecenia REN. REN DANE_B DANE1 - spowoduje zmianę nazwy pliku DANE_B w bieżącej kartotece na nazwę DANE1, REN A:\*.TXT *.LST - zmienia w nazwach wszystkich plików w kartotece głównej na dyskietce w napędzie A: rozszerzenie TXT na LST. ? ł.7. Wokół komputera i Przetwarzanie informacji jest zajęciem szczególnym z uwagi na materiał obróbki Li używane narzędzia. Przedmiotem obróbki nie są rzeczy materialne, ale in- 60 2. Jak działa komputer formacje, a podstawowym narzędziem jest obecnie komputer. Człowiek - na pierwszy rzut oka - ma bardzo ograniczoną rolę: podaje informacje, uruchamia program i odbiera gotowe wyniki na ekranie lub papierze. Jest to jednak po- zorne. Najważniejszym i często najtrudniejszym do wykonania ogniwem w tym łańcuchu jest program, którego skonstruowanie bez udziału człowieka jest wciąż jeszcze niemożliwe. Rozwiązując różne zadania staramy się znaleźć drogę prowadzącą niezawodnie do celu. Jeżeli jest ona na tyle uniwersalna, że daje się łatwo zastosować do roz- wiązywania zbliżonych zadań, to możemy mówić o metodzie postępowania. Jak pamiętamy z poprzedniego rozdziału, precyzyjny słowny opis metody roz- wiązywania nazywamy algorytmem. Jest on zrozumiały dla człowieka i może być przez niego wykonany, ale nie zostanie zaakceptowany w tej postaci przez kom puter. Komputer potrafi jedynie interpretować i wykonywać rozkazy, w któn jest wyposażony, a które są zawarte w jego pamięci wewnętrznej. Pozostaje za tem przekształcić algorytm opisany tradycyjnie w realizujący go ciąg rozkazów W wyniku otrzymujemy program rozwiązujący zadanie. Do wyrażania algorytm w postaci programu służą języki programowania. Każdy komputer potra wykonywać wyłącznie rozkazy swojego języka wewnętrznego. W praktyce ni pisze się programów bezpośrednio w języku wewnętrznym z uwagi na nieczytelii dla człowieka binarną postać rozkazów tego języka. W zamian stosuje się języ] symboliczne zwane także asemblerami, w których wszystkie rozkazy zamia binarnych kodów mają mnemoniczne oznaczenia, a adresy argumentów tych ro kazów - symboliczne nazwy. Języki symboliczne - dominujące w pierwszyi latach informatyki - zostały wyparte przez języki wyższe (algorytmiczne Rozkazy języków symbolicznych zastąpiono instrukcjami i wyrażeniami, kto pozwalają w czytelniejszej dla człowieka postaci opisać algorytmy realizowa później na komputerach. W następnych rozdziałach przedstawiamy bliżej dwa języki wyższe, a miai wicie Logo i Pascal. Języki programowania różnią się zdecydowanie od język etnicznych, którymi posługujemy się na co dzień. Za pomocą skończonego zbić reguł gramatycznych można bowiem zdefiniować wszystkie poprawne zdania w zyku programowania, a każde nawet najmniejsze złamanie tych zasad powód przykre konsekwencje. Praktyczne ćwiczenia przy komputerze powinny szył unaocznić, jak ważna jest znajomość gramatyki języka programowania. Współczesne języki programowania umożliwiają dość szybkie przejście od gorytmu do programu. Nie jest to jednak koniec drogi. Niezbędne jest jes2 przetłumaczenie programu na język, którego rozkazy może zinterpretować k< puter (czyli na jego język wewnętrzny) albo inny program. Tłumaczeniem : mują się przeznaczone do tego programy - translatory. Wyróżniamy dwa t translatorów: kompilatory oraz interpretatory. Kompilator tłumaczy i L 2.7. Wokół komputera 61 program na język wewnętrzny i gotowy przekład pozostawia do wykonania. In- terpretator natomiast tłumaczy program partiami (np. po jednej instrukcji) na pewien język abstrakcyjny (z reguły nie jest to język wewnętrzny) i ten częściowy przekład wykonuje, a właściwie interpretuje, po czym przystępuje do tłumaczenia następnego fragmentu. Cykl ten powtarza się. Translatory łączą tłumaczenie pro- gramów ze sprawdzaniem ich poprawności gramatycznej. Wykrycie jakiegokol- wiek błędu w programie uniemożliwia utworzenie jego przekładu i w konsekwencji zawiesza wykonywanie programu. Translatory są obok systemu operacyjnego najważniejszym elementem pod- stawowego oprogramowania komputera. Innym niezbędnym składnikiem są wspomniane już wcześniej edytory, które omawiamy w rozdz. 8. Są to pro- gramy przeznaczone do wprowadzania, poprawiania i redagowania tekstów. Za- pamiętajmy - komputer jest użytecznym narzędziem pracy, o ile jest wyposażony w oprogramowanie podstawowe: system operacyjny, translatory i edytory. Istotnym czynnikiem wpływającym na wygodę pracy z komputerem jest spo- sób obsługi programów. Coraz częściej z komputerów korzystają osoby nie zaj- mujące się zawodowo informatyką, stąd pojawia się konieczność budowania pro- gramów łatwych i czytelnych w użyciu. Dużą popularność zdobywa metoda komu- nikowania się użytkownika z programem za pomocą okien. W programach skon- struowanych tą metodą ekran jest dzielony najczęściej na trzy funkcjonalne części, stanowiące jak gdyby trzy okna wypełniające cały ekran. W pierwszym oknie (umieszczanym często u góry ekranu) jest przedstawiana oferta (ang. menu) programu, czyli wykaz wszystkich - lub tylko najważniejszych - operacji czy też usług oferowanych przez program. Każdej operacji odpowiada w oknie pole zawierające jej określenie. Konstrukcja okna umożliwia dokonanie wyboru jed- nej z operacji poprzez wskazanie odpowiedniego pola. Pole jest wyróżniane, np. podświetleniem, odmiennym kolorem lub migotaniem. Takie wyróżnienie . pola nazywa się kursorem wyboru, gdyż służy ono właśnie do określania wy- boru operacji. Zmianę wyróżnienia, czyli przesunięcie kursora wyboru z jednego pola na inne, uzyskujemy za pomocą klawiszy kierunkowych znajdujących się w module pomocniczym klawiatury. Wybór akceptujemy z reguły klawiszem [Enter [, po czym - zależnie od budowy programu - na ekranie może otworzyć się nowe okno z ofertą podrzędną związaną z wybraną operacją lub też zosta- nie wykonany właściwy dla wybranej funkcji fragment obliczeń. Okno z ofertą podrzędną może przykrywać na czas swojej aktywności dotychczasową zawartość fragmentu ekranu, która zostanie przywrócona po zamknięciu okna. Zasady wy- bierania w rozwijalnych oknach ofert podrzędnych są takie same jak dla oferty głównej programu. Niektóre funkcje z oferty można wybierać także za pomocą pojedynczych I klawiszy lub operacji klawiszowych, które nazywamy klawiszami wyboru. 62 2. Jak działa komputer Drugie okno funkcjonalne (umieszczane z reguły w dole ekranu) określa bie- żący stan programu i - z uwagi na swoją najczęściej spotykaną jednowierszową postać - jest nazywane wierszem stanu. W oknie tym pojawiają się niekiedy informacje o klawiszach wyboru, z jakich można korzystać w danym kontekście. Wiersz stanu występuje m.in. w oprogramowaniu, które poznamy w dalszych rozdziałach, a mianowicie w systemach programowania AC-Logo i Turbo Pascal, w edytorze TAG oraz w arkuszu kalkulacyjnym Quattro Pro. Ostatnie okno zajmujące centralną część ekranu jest oknem operacyjnym i służy do komunikowania się programu z użytkownikiem oraz wyświetlania wy- ników lub stanu realizacji programu. Wiele programów umożliwia ponadto korzystanie z podpowiedzi (ang. help), wyjaśniających dokładnie wybraną funkcję programu. Podpowiedzi pojawiają się w nowych oknach otwieranych kluczem, którym jest odpowiednia operacja klawiszowa, np. naciśnięcie klawisza funkcyjnego |F1 \ lub klawiszy |Alt H| W większych profesjonalnych programach, jak edytory czy kompilatory, wbu dowana w te programy pomoc stanowi często kompletny ekranowy podręczni! użytkownika. Przedstawiona tu ogólna postać programów okienkowych nie jest jedyną moi liwą - pokazuje tylko niektóre zasady budowy i obsługi programów tego typi Prostota i czytelność obsługi przesądzają o powodzeniu programów okienkowycl Rozwój tej metody komunikowania się użytkownika z programem doprowad: do zbudowania systemów operacyjnych (np. Windows), w których możliwe je równoczesne posługiwanie się na ekranie wieloma oknami o różnym przeznacz niu. Sterowanie oknami (otwieranie, zamykanie, przemieszczanie) oraz wyb funkcji odbywa się najczęściej za pomocą myszy. Zanim usiądziemy po raz pierwszy przed monitorem komputera spróbuji zobaczyć na czym będzie polegała praca z komputerem. Załóżmy, że mamy rozwiązania jakieś zadanie. Do jego rozwiązania chcemy użyć komputera, a od] wiedni program napisać w języku Pascal. Plan naszego działania może wygiąć następująco (podobnie będziemy postępować w przypadku korzystania z syste AC-Logo, w którym komunikacja z użytkownikiem odbywa się w języku polski: 1. Opracowujemy algorytm. 2. Zapisujemy algorytm w postaci programu, najlepiej najpierw na papier 3. Przygotowujemy dane (również na papierze), dla których chcemy wyko obliczenia. 4. Tekst programu oraz dane wprowadzamy do plików w pamięci zewnętrz System programowania Turbo Pascal (w skrócie TP), z którego będzi korzystali, jest wyposażony m.in. w kompilator języka Pascal oraz w tor. Edytorem posługujemy się przy wpisywaniu tekstu programu i dai oraz ich poprawianiu. W celu zainicjowania pracy systemu TP piszemy 2.8. Przy komputerze - pierwsze spotkanie 63 cenie TURBO. Od tej chwili nie komunikujemy się bezpośrednio z systemem operacyjnym - wszystkie dalsze czynności będą funkcjami Turbo Pascala. System TP jest programem okienkowym, wobec czego jego funkcje możemy wybierać w sposób charakterystyczny dla takich programów - za pomocą kursora wyboru lub klawiszy wyboru. Wprowadzając tekst programu i dane musimy podać nazwy odpowiadających im plików (w oknie rozwijanym po wyborze File z oferty głównej), które zostaną zapisane na dysk (Save). 5. Tłumaczymy program za pomocą kompilatora wybierając, odpowiednią funkcję z oferty (Compile). 6. Jeżeli kompilator sygnalizuje błędy, to musimy tekst programu poprawić. Ponownie korzystamy z usług edytora, a następnie wracamy do punktu 5. 7. Jeśli tłumaczenie programu kończy się sukcesem, to uzyskujemy gotowy do wykonania przekład programu, który możemy zapisać w pliku z rozszerze- niem EXE. 8. Uruchamiamy program, wybierając stosowne zlecenie (Run). Dane będą wczytywane z dyskietki, z wcześniej przygotowanego pliku lub bezpośrednio z klawiatury. 9. Analizujemy uzyskane wyniki -jeśli są złe, to staramy się poprawić program (lub także algorytm) i powtórzyć obliczenia. Wracamy do punktu 5. 10. Jeżeli wyniki są poprawne, to możemy zakończyć pracę powracając do pracy pod nadzorem systemu operacyjnego (klawisz wyboru | Alt X | lub odpo- wiednia funkcja w podofercie File). Pamiętajmy jeszcze o zrobieniu w kom- puterze porządków po sobie, czyli o usunięciu zbędnych plików powstałych w czasie pracy. 2.8. Przy komputerze — pierwsze spotkanie Po włączeniu komputera jest uruchamiany program inicjujący, który znajduje się w pamięci ROM. Zadaniem tego programu jest sprawdzenie stanu technicznego komputera oraz załadowanie do pamięci i uruchomienie systemu operacyjnego. W trakcie testowania komputera są wyświetlane wyniki testów oraz informacje o wyposażeniu komputera. Program inicjujący w pierwszej kolejności próbuje załadować system operacyjny z dyskietki. W przypadku niepowodzenia, wyni- kającego z braku dyskietki w napędzie, program usiłuje odnaleźć system opera- cyjny na dysku stałym, o ile komputer jest w taki dysk wyposażony. Praca z komputerem jest możliwa tylko pod kontrolą systemu operacyjnego, który powinien znajdować się na dysku stałym lub elastycznym. Z kolei umie- szczenie systemu na dysku jest możliwe, jeżeli dysk jest przygotowany do pracy, czyli zainicjowany. Inicjowanie dysku, zwane formatowaniem, polega na spraw- dzeniu stanu dysku i zapisaniu pewnych informacji technicznych na jego wy- branych ścieżkach. Formatowanie odbywa się jednorazowo za pomocą zlecenia 2. Jak działa komputer 64 FORMAT lub - w przypadku dysków twardych - za pomocą programów dostar- czanych przez producentów dysku. Osoby, które dopiero poznają komputery, nie powinny same inicjować dysków stałych, natomiast powinny umieć sformatować każdą nową lub uszkodzoną dyskietkę korzystając ze wspomnianego już zlecenia FORMAT o składni FORMAT A: lub FORMAT B: gdzie A:, B: oznaczają nazwy dostępnych napędów dysków elastycznych. Aby zlecenie formatowania zostało wykonane prawidłowo, należy znać ty napędu oraz inicjowanej dyskietki, tzn. jej średnicę wyrażoną w calach — 5.25 lu 3.5 cala, gęstość - normalną lub wysoką oraz liczbę stron zapisu - jedną lub dwi Formatowanie w przypadku niezgodności typów dyskietki i napędu jest niekiec możliwe, ale wymaga zastosowania odpowiednich kluczy w zleceniu, a czasai jest niebezpieczne i może prowadzić do późniejszych błędów przy próbie kórz stania z dyskietki. Przykład 2.16. Zlecenie FORMAT umożliwia zapisanie podstawowych plików s stemu operacyjnego na inicjowanej dyskietce. W tym celu, jeśli chcemy sforn tować dyskietkę zgodną z typem napędu A:, to należy wydać zlecenie FORMAT A:/S Napis /S określa jeden z dopuszczalnych dla tego zlecenia kluczy i oznacza, system operacyjny umieści na dyskietce trzy najważniejsze pliki niezbędne poprawnego uruchomienia systemu z dyskietki. Nie należy kopiować tych pli! znanym nam zleceniem COPY. Przykład 2.17. Dysponujemy napędem (A:) dyskietek o średnicy 5.25 cala i żej gęstości (co odpowiada pojemności dyskietki równej 1.2 megabajta (1\ czyli ponad 1.2 miliona bajtów). Chcemy w tym napędzie zainicjować dyski o normalnej gęstości, czyli o pojemności około 360 tys. bajtów (kB). W tym należy napisać zlecenie FORMAT A:/4 i umieścić dyskietkę w napędzie. Napis /4 jest kluczem nakazującym fort wanie dyskietki o normalnej gęstości, co zostanie poprawnie wykonane, mi: napęd jest przeznaczony dla dyskietek o dużej gęstości. Nie wymaga uzasadnienia potrzeba posiadania biurka, właściwego oświe czy też porządnych podręczników przy nauce w domu. Podobnie jest w Zadania 65 z komputerem - istotnym czynnikiem jest tu środowisko, jakie tworzymy w sa- mym komputerze. Najważniejszymi elementami komputerowego środowiska są: - drzewo kartotek, - zestaw własnych zleceń, - oprogramowanie wspomagające. Obecnie komputery IBM PC są na ogół wyposażone w dysk stały, który można dzielić na dyski logiczne (tomy). Wskazane jest przeznaczenie jednego z dysków na oprogramowanie podstawowe, czyli kompilatory, edytory i system operacyjny, oraz narzędziowe - wspomagające użytkownika. Drzewo kartotek takiego dysku, oznaczanego w typowych zestawach komputerowych jako C:, powinno zawierać osobne kartoteki przeznaczone na system operacyjny, poszczególne kompilatory lub systemy programowania (instalowane zawsze zgodnie z instrukcją produ- centa), edytory oraz arkusze kalkulacyjne. Mniejsze programy narzędziowe, takie jak programy antywirusowe czy kompresji plików, można umieścić w jednej kar- totece na tym samym dysku. Należy ponadto zadbać o swobodny dostęp do pro- gramów znajdujących się w tych kartotekach. Można to osiągnąć ustawiając od- powiednią ścieżkę dostępu do kartotek zleceniem PATH. Warto przy tym umieścić zlecenie PATH w pliku AUTOEXEC.BAT, którego zawartość, jeśli znajduje się on w kartotece głównej dysku systemowego, jest interpretowana jako ciąg zleceń wy- konywanych bezpośrednio po załadowaniu systemu operacyjnego do pamięci. Pliki znajdujące się na dysku systemowym należy zabezpieczyć przed przy- padkowym skasowaniem, co można osiągnąć za pomocą zlecenia ATTRIB (por. zad. 2.17). Inny z dysków można traktować jako dysk roboczy i wykorzystywać w trakcie bieżących obliczeń. Na dysku roboczym możemy zakładać kartoteki dla poszczególnych użytkowników komputera lub ważniejszych zadań. Zadania 2.1. Ile różnych liczb można zapisać na n bitach? Jaką wartość przyjmie najwięk- sza, a jaką najmniejsza z nich, jeśli założymy, że pierwszy bit jest bitem znaku? 2.2. Znajdź rozwinięcie dwójkowe liczby 75. Podaj dokładny algorytm wyzna- czania rozwinięcia dwójkowego dowolnej liczby naturalnej. Wskazówka: Podziel liczbę przez dwa i zanotuj resztę. Powtarzaj tę czynność i uzyskanego ilorazu. Co można powiedzieć o otrzymanym w ten sposób ciągu zt? 2.3. Znajdź rozwinięcie dwójkowe ułamka 0.37278. Podaj algorytm wyznaczania |rozwinięcia dwójkowego dowolnego ułamka właściwego. Wskazówka: Pomnóż liczbę przez dwa. Co można powiedzieć o części całko- f witej uzyskanego wyniku? Powtórz mnożenie dla części ułamkowej wyniku. 5 — Elementy informatyki 66 2. Jak działa komputer 2.4. Na część ułamkową liczby przeznaczono w pewnej reprezentacji dwójkowej k bitów, w tym jeden na bit znaku. Jaka jest maksymalna liczba różna od zera, która w tej reprezentacji równa się zeru? 2.5. Kod uzupełnieniowy liczby całkowitej jest zadany wzorem %uzup dla x > 0 |x| dla x < 0, gdzie |x| - oznacza moduł liczby x, 1- 1 ? - bitów przeznaczonych na reprezentację liczby (łączn: n - jest liczbą bitów z bitem znaku). Dla n = 8 liczba —75 w kodzie uzupełnieniowym przybiera postać 1011010 ponieważ - 75] = 01001011, 28 = 100000000, a zatem 28 - \ - 75| = 100000000 - 01001011 = 10110101. Znajdź kod uzupełnieniowy liczb 0.4375 oraz —0.372 wiedząc, że dla ułamt właściwych wyraża się on wzorem IX dla x > 0, dla x < 0. 2.6. Zbadaj działanie wszystkich klawiszy z klawiatury Twojego komput Zwróć uwagę na sposób uzyskiwania wielkich liter i cyfr. Jeśli klawiatura pomocniczy moduł numeryczny, użyj go do wprowadzenia kilkudziesięciu 1 dziesiętnych (np. zawartych na kilku rachunkach ze sklepu). Z której klawia jest wygodniej wprowadzać długie zestawy liczb: z centralnej czy z pomocni< Dlaczego? Jeśli dysponujesz programem-kalkulatorem, to uruchom go i pow doświadczenie z wprowadzaniem danych liczbowych. 2.7. Objaśnij różnicę w działaniu klawiszy kasowania Backspace 2.8. Wypróbuj klawiaturę Twojego komputera pod kątem uzyskiwania na ek znaków semigraficznych, tj. narożników ramek, różnego rodzaju wypełn pola znaku, znaków ikonicznych, czyli znaków-obrazków itp. Zastosuj kla [_Alt] lub (_CtrlJ (lub nawet oba na raz) w połączeniu z innymi klawiszam Wskazówka: Pamiętając, że znaki są zakodowane w komputerze w p liczb, spróbuj wpisywać kody znaków za pomocą modułu numerycznego k tury, przytrzymując wciśnięty klawisz | Alt j. Zadania 67 2.9. Wypróbuj na komputerze pod kontrolą systemu operacyjnego MS-DOS dzia- łanie klawiszy funkcyjnych | F3 | i | Fl | bezpośrednio po przesłaniu zlecenia. Wy- próbuj również, jak działają w tej sytuacji klawisze ze strzałkami poziomymi oraz klawisze Ins Backspace Wskazówka: Napisz na ekranie tekst zlecenia (innego od nazwy programu) z jakimś brakiem lub błędem, naciśnij klawisz [Enter |, a następnie naciśnij kla- wisz |F3 I lub klawisz | Fl |. 2.10. Sprawdź, posługując się systemem MS-DOS, jakie znaki poza literami i cy- frami mogą występować w nazwach plików. Utwórz za pomocą np. zlecenia COPY dowolny plik, a następnie spróbuj zmienić jego nazwę zleceniem REN. W jaki sposób system operacyjny reaguje na nielegalne znaki w nazwie? 2.11. W zleceniu DIR są dopuszczalne dwa klucze /P oraz /W. Sprawdź na kom- puterze ich znaczenie, wyświetlając katalogi różnych kartotek. 2.12. Zlecenie PROMPT służy do ustalenia postaci wzorca zaproszenia do pisa- nia, będącego sygnałem gotowości systemu operacyjnego do przyjmowania zleceń. Wzorzec - określany w parametrze zlecenia - jest dowolnym tekstem, w którym można umieszczać znaki sterujące w postaci $znak, np. PROMPT O.K. $P$G Sprawdź znaczenie podanych znaków sterujących: $B, $D, $E, $G, $H, $L, $N, $P, $Q, $T, $V, $$, $_, a następnie utwórz wzorzec gg:mm> gdzie gg:mm oznacza aktualny czas wyrażony w godzinach i minutach (odpowie- dnio gg i mm). 2.13. W pliku o nazwie LIST_D0_.EWY znajduje się tekst, który chcesz wysłać ośmiu zaprzyjaźnionym osobom. W jaki sposób można najprościej powielić w in- nym pliku jego treść ośmiokrotnie, korzystając przy tym jedynie z usług systemu operacyjnego, nie uciekając się do pomocy edytora? 2.14. Utwórz na sformatowanej, pustej dyskietce drzewo kartotek przedstawione na rys. 2.7. Podaj najkrótszy w zapisie sposób przejścia z jednej kartoteki na najniższym poziomie (np. 2B. 1) do innych kartotek na tym samym poziomie, znajdujących się w różnych gałęziach drzewa (np. 1A.2, 2A.1, 2B.2). 2.15. W systemie operacyjnym MS-DOS brak jest zlecenia zmiany nazwy karto- teki. W jaki sposób, korzystając z innych zleceń, można zmienić nazwę kartoteki zawierającej pliki, które mają znaleźć się w kartotece o zmienionej nazwie? 68 1A 1B 2A 2B 1A.1 1A.2 1B.1 1B.2 2A.1 2A.2 2B.1 2B.2 Rys. 2.7. Drzewo kartotek dla zadania 2.14 2.16. Jakie pliki znajdują się na dyskietce sformatowanej z kluczem /S? Jak jest przeznaczenie takiej dyskietki? Czy równoważny efekt uzyskamy formatuj dyskietkę bez klucza /S, a następnie kopiując takie same pliki zleceniem COP Wykonaj odpowiedni eksperyment. 2.17. Zlecenie ATTRIB służy do określania i sprawdzania atrybutów plików. Z cenie z dwoma parametrami ATTRIB +R nazwa-pliku nadaje plikowi o podanej nazwie atrybut pozwalający jedynie na czytanie z pli Zabroniony jest wtedy zapis do tego pliku oraz jego usuwanie. Zlecenie ATTRIB -R nazwa-pliku przywraca możliwość zapisywania i usuwania pliku, natomiast zlecenie ATTF w którym pominięto pierwszy parametr, powoduje wyświetlenie stanu atrybu wskazanego pliku. Sprawdź atrybuty wybranych plików, np. systemowych. 3. NAUKA I ZABAWA - GRAFIKA ZOŁWIA Grafika komputerowa jest gałęzią informatyki o szerokich możliwościach i per- spektywach zastosowań. Upowszechnianiu mikrokomputerów towarzyszy bardzo burzliwy rozwój tej dziedziny. Coraz częściej możemy oglądać zarówno na ekra- nach komputerów, jak i w telewizji nieruchome bądź ruchome kolorowe obrazy wykonywane za pomocą komputerów. Obrazy są nie tylko dwuwymiarowe, lecz i trójwymiarowe oraz tak dokładne, jeśli chodzi o światłocienie, że trudno je odróżnić od obrazów wykonywanych techniką fotogram. Często pierwsze zetknięcie z grafiką komputerową następuje poprzez gry kom- puterowe. Jednak przyglądanie się efektom wizualnym, nawet najbardziej pasjo- nującej gry z komputerem, po pewnym czasie już nie wystarcza. Chcielibyśmy się dowiedzieć, jak samemu zaprogramować - może nie od razu komputerową grę, ale przynajmniej pojawienie się na ekranie komputera nieruchomego rysunku. W profesjonalnej grafice komputerowej, szczególnie tej trójwymiarowej, wy- stępuje wiele problemów, na przykład związanych z obracaniem brył, znajdo- waniem ukrytych linii (aby ich nie uwidaczniać na rysunku), cieniowaniem i o- świetlaniem różnych części bryły w zależności od umiejscowienia źródła światła padającego na bryłę itp. Każdy z wymienionych problemów jest na tyle trudny, iż wymaga specjalistycznej wiedzy do jego rozwiązania. Nie jest naszym celem podejmowanie takich problemów w tej książce, ale programowanie dwuwymiaro- wych, nawet dość skomplikowanych rysunków, może stać się naszym udziałem. W tym rozdziale - jak i w następnych - interesuje nas w głównej mierze zdoby- wanie umiejętności konstruowania algorytmów, a na ich podstawie - programów komputerowych. Tu skupimy się na wybranych algorytmach graficznych i z ich pomocą przedstawimy sposoby postępowania począwszy od właściwego posta- wienia problemu, poprzez podanie sposobu jego rozwiązywania aż do zapisania algorytmu w określonym języku programowania, tj. w postaci programu kompu- terowego. Okazuje się, że i dla tych celów jeden rysunek może być wart stu słów. Dlatego równocześnie z komputerowym rysowaniem będziemy poznawać pojęcia i ogólne zagadnienia informatyczne. 70 3.1. Pierwszy rysunek Jak sporządzić komputerowy rysunek terminalu portu lotniczego, którego kształt oraz potrzebne wymiary pokazano na rys. 3.1? Najprościej byłoby wydać kom- puterowi polecenie "narysuj terminal" i oczekiwać na wynik w postaci żądanego rysunku. Rys. 3.1. Terminal Niestety, komputer - a właściwie język programowania, za pośrednictwei którego komunikujemy się z nim - nie zna takiego polecenia. Aby komputi mógł wykonać czynność zwaną rysowaniem terminalu, należy poinstruować \ bardzo precyzyjnie, jak - krok po kroku - ma to zrobić za pomocą znanych sot instrukcji. Te instrukcje, które będą szczegółowo opisane w tym rozdziale, p zwolą m.in. na rysowanie odcinka ustalonej długości, wybór punktu rozpoczęć i kierunku rysowania. Wykorzystując je potrafimy opisać zarówno rysowanie pi stokąta o danych bokach, jak i dorysowanie przylegającego do niego jednego bo sześciokąta (zob. rys. 3.1) oraz wybór punktu początkowego i kierunku rysov nia następnego prostokąta. Łatwo spostrzec, że aby otrzymać rysunek termina należy te czynności powtórzyć 6 razy. Zapiszmy to w postaci algorytmu. Algorytm 3.1. Ogólny schemat rysowania terminalu. 1. Powtórz 6 razy kroki 2 i 3, następnie zakończ algorytm. 2. Narysuj prostokąt o danych bokach. 3. Narysuj przylegający bok sześciokąta, ustal punkt początkowy i kieru rysowania następnego prostokąta. Do zapisywania komputerowych programów rysujących wybierzemy język gramowania Logo (a ściślej język AC-Logo w jego angielskojęzycznej wer umożliwiający tworzenie rysunków techniką zwaną grafiką żółwia. Nie zai szczamy jednak pełnego opisu systemu AC-Logo. Pomijamy całkowicie obs 3.2. Pierwotne instrukcje graficzne 71 systemu okienkowego i podajemy tylko niezbędne informacje o edytorze. Ko- lejne elementy języka Logo są wprowadzane, gdy okazują się przydatne z punktu widzenia prowadzonych rozważań. 3.2. Pierwotne instrukcje graficzne Po uruchomieniu systemu programowania AC-Logo (za pomocą odpowiedniego zlecenia wydanego dla systemu operacyjnego MS-DOS), napisaniu polecenia CS i naciśnięciu klawisza | ENTER |, na ekranie komputera pojawia się wskaźnik gra- ficzny w postaci przypominającej żółwia. Jest to właśnie żółw Logo. Żółw ma ustalone położenie, tzn. pozycję (czyli punkt, na którym jest usta- wiony) i kierunek. Ponadto przyjmuje się, że żółw jest wyposażony w pisak, który może być podnoszony bądź opuszczany. Instrukcje graficzne umożliwiają m.in. przemieszczanie żółwia po wydzielonej części ekranu monitora nazywanej oknem graficznym. Żółw poruszający się po ekranie z opuszczonym pisakiem zostawia ślad w postaci odcinka linii prostej. Sporządzanie rysunków w technice zwa- nej grafiką żółwia polega zatem na odpowiednim zmienianiu położenia żółwia oraz podnoszeniu lub opuszczaniu jego pisaka. Jednostką odległości podczas przemieszczania żółwia jest odległość między sąsiednimi punktami ekranu. Pierwotne instrukcje grafiki żółwia są zamieszczone i opisane w tablicy 3.1. Tablica 3.1. Pierwotne instrukcje graficzne Instrukcja Działanie instrukcji CS FD liczba BK liczba RT liczba LT liczba HT ST HOME PU PD Oczyszcza ekran; żółw pojawia się w środku ekranu i jest skierowany pionowo ku górze. Przesuwa żółwia do przodu o daną liczbę jednostek bez zmiany jego kierunku, np. FD 50. Cofa żółwia o podaną liczbę jednostek bez zmiany jego kierunku, np. BK 65. Obraca żółwia w prawo o kąt, którego miarą jest dana liczba stopni, np. RT 30. Obraca żółwia w lewo o kąt, którego miarą jest dana liczba stopni, np. LT 22. Czyni żółwia niewidocznym. Sprawia, że żółw jest widoczny. Przesuwa żółwia do środka ekranu i skierowuje go pionowo ku górze. Podnosi pisak żółwia. Opuszcza pisak żółwia. Okno graficzne ekranu monitora może być w systemie Logo interpretowane na trzy sposoby. Sposób interpretacji można zmieniać za pomocą instrukcji pier- wotnych wymienionych w tablicy 3.2. 72 3. Grafika żółwia Tablica 3.2. Zmiana interpretacji okna graficznego Instrukcja Okno graficzne jest interpretowane jako: WRAP Torus, tzn. tak, jakby górna krawędź okna była sklejona z dolną i prawa z lewą. WINDOW Prostokątny obszar na płaszczyźnie; żółw może poruszać się po płaszczyźnie również poza oknem. FENCE Prostokątny obszar, którego granic żółw nie może przekroczyć. Jak widać w tablicy 3.1, niektóre instrukcje, np.: CS, PU, PD, HOME, składają się wyłącznie z nazwy, inne, np.: FD 43, BK 10, RT 45, oprócz swojej nazwy zawierają dodatkowe informacje zwane parametrami. Pa- rametry są oddzielane co najmniej jednym odstępem od nazw instrukcji. Znając wymienione instrukcje, możemy zastanowić się, jak z ich pomocą nary- sować terminal z rys. 3.1. Rozpoczniemy od drugiego kroku algorytmu 3.1, czyli od narysowania prostokąta. Algorytm jest tak prosty, że od razu zapiszemy go w języku Logo. Sformułowanie tego i innych algorytmów graficznych jest treści? zadania 3.2. Instrukcje języka Logo można pisać każdą w osobnym wierszu lub grupować po kilka w jednym wierszu, oddzielając je wtedy od siebie odstępami. Po napisaniu jednej lub kilku instrukcji i naciśnięciu klawisza \ Enter | interpretator języka Logo powoduje natychmiastowe wykonywanie tych instrukcji w kolejności id występowania. Przykład 3.1. Program rysowania prostokąta. CS FD 35 RT 90 FD 10 RT 90 FD 35 RT 90 FD 10 RT 90 I Zanim przejdziemy do uściślenia i zaprogramowania pozostałych kroków al gorytmu 3.1, zwróćmy uwagę, że w ciągu instrukcji z przykładu 3.1 instruk cje występujące w drugim i trzecim wierszu powtarzają się. Można je zapisa prościej, wykorzystując instrukcję powtarzania. Ogólny schemat instrukcji po wtarzania w języku Logo, zwanej także instrukcją iteracyjną, jest następu jacy: REPEAT ile-razy-powtórzyć [ciąg-powtarzanych-instrukcji~\ Poleca ona powtórzyć instrukcje zapisane w nawiasach kwadratowych podał przed nawiasem liczbę razy. 3.3. Procedury 73 Tekst programu z przykładu 3.1, w którym skorzystano z instrukcji iteracyj- nej, przyjmuje bardziej zwartą postać: CS REPEAT 2 [FD 35 RT 90 FD 10 RT 90] Instrukcja REPEAT może się znaleźć wśród instrukcji powtarzanych. Zachę- camy do eksperymentowania (zad. 3.4) i proponujemy sprawdzić, jaki będzie efekt wykonania następujących instrukcji: CS REPEAT 10 [REPEAT 3 [FD 30 RT 120] RT 36] Niestety, powyższe programy nie są zachowywane w pamięci komputera (na- wet jeśli ich teksty są widoczne na ekranie monitora). Gdybyśmy - po oczyszcze- niu ekranu instrukcją CS - chcieli powtórnie narysować prostokąt, musielibyśmy jeszcze raz napisać odpowiedni program. Można jednak temu zaradzić. 3.3. Procedury Żeby zachować w pamięci komputera ciąg instrukcji, powodujących wykonanie określonych czynności, na przykład narysowanie terminalu, należy instrukcjom tym nadać postać definicji (opisu) procedury, czyli opatrzyć je nazwą. Roz- pocznijmy od definicji procedury rysowania prostokąta: TO NarysujProstokąt REPEAT 2 [FD 35 RT 90 FD 10 RT 90] END Pierwszy wiersz definicji procedury w języku Logo rozpoczyna się słowem TO, po którym następuje nazwa procedury. Ten wiersz jest określany mianem na- główka procedury. Pozostałe wiersze - wraz z kończącym opis słowem END - stanowią treść procedury. Nazwą w języku Logo, np. nazwą procedury, może być dowolny niepusty ciąg znaków zakończony separatorem. Separator nie wchodzi w skład nazwy. Separatorami w języku Logo są znaki spacji, przejścia do nowego wier- sza, nawiasy kwadratowe i okrągłe. Zarówno w polskojęzycznej, jak i w angiel- skojęzycznej wersji języka AC-Logo w nazwach można używać małych i wielkich liter alfabetu polskiego1. polską literę uzyskuje się przytrzymując klawisz j Alt | i naciskając klawisz z odpo- wiednią literą alfabetu łacińskiego, np. | Alt A | daje ą, a | Alt Z | - ż. Literę ź otrzymujemy za pomocą | Alt X |. Wielką polską literę otrzymuje się po naciśnięciu oprócz wymienionych klawiszy jeszcze klawisza Shif t . 74 3. Grafika żółwia Nazwy w języku Logo można wybierać dowolnie. Zachęcamy jednak do stoso- wania w programach nazw umożliwiających przynajmniej częściowe rozumienie programów bez dodatkowych komentarzy. W naszych przykładach nazwa będzie najczęściej ciągiem liter lub cyfr rozpoczynającym się od litery. •W trakcie pisania definicji procedury instrukcje z jej treści nie są natychmiast wykonywane nawet, jeśli kończymy je naciśnięciem klawisza |Enter |. Procedura jest tłumaczona dopiero po napisaniu końcowego END. Definicje procedur można przygotować w edytorze systemu AC-Logo i następnie je tłumaczyć2. Po zdefiniowaniu procedury o nazwie NarysujProstokąt, czyli podaniu de- finicji i przetłumaczeniu, czynność rysowania prostokąta jest komputerowi tak samo znana, jak pierwotne instrukcje języka Logo. Aby się o tym przekonać, wywołajmy opisaną procedurę, to znaczy napiszmy jej nazwę: NarysujProstokąt Nazwa zdefiniowanej procedury jest zarazem nazwą nowej instrukcji. Wy- konanie tej instrukcji polega na wykonaniu wszystkich instrukcji umieszczonych w treści wywołanej procedury, czyli w treści procedury NarysujProstokąt. J Usytuowanie prostokąta na ekranie zależy od położenia żółwia tuż przed wy- konaniem rysunku. Oto przykłady: CS LT 90 NarysujProstokąt PU RT 135 FD 25 PD NarysujProstokąt Zauważmy, że po narysowaniu prostokąta położenie żółwia - które ulega zmia nie w trakcie wykonywania procedury - jest takie samo jak przed rozpoczęciei rysowania. W oczywisty sposób dotyczy to wszystkich tych wielkości, które ni ulegają zmianie w procedurze, np. stanu żółwia (widoczny - ukryty) i stanu jeg pisaka (podniesiony - opuszczony). Te spośród wielkości zmienianych w procedurze, które po wykonaniu proc dury są takie same (tzn. mają takie same wartości lub są w takim samym stani jak przed jej wykonaniem, nazywają się niezmiennikami tej procedury. Poi żenię żółwia jest więc niezmiennikiem procedury o nazwie NarysujProstoka Przekonamy się, że stosowanie niezmienników w programach jest dużym ułatw: niem w projektowaniu algorytmów. Dotyczy to zwłaszcza sporządzania rysunki składających się z wielu elementów. Przejdźmy teraz do trzeciego kroku algorytmu 3.1, który brzmi: "naryi przylegający bok sześciokąta, ustal punkt początkowy i kierunek rysowania n tępnego prostokąta". Rozwiązanie tego podzadania przedstawimy również w ] 2Pracę w edytorze AC-Logo można rozpocząć naciskając klawisz | F3 |. Po naciśnięciu wiszy | Alt F9 | procedury znajdujące się w edytorze są tłumaczone. 3.3. Procedury — 75 staci procedury. Najpierw jednak - zgodnie z regułą postępowania przy projek- towaniu procedur rysujących - ustalmy: 1. położenie żółwia przed wywołaniem procedury, 2. sposób przemieszczania żółwia w trakcie działania procedury, 3. położenie żółwia po wykonaniu procedury. Przypuśćmy, że rysowanie terminalu rozpoczęto w punkcie A (zob. rys. 3.2) i został już narysowany prostokąt ABCDA. Chcemy teraz przesunąć żółwia do punktu E i obrócić w kierunku punktu F, by jako następny mógł być rysowany prostokąt EFGHE. B C Rys. 3.2. Terminal - kolejność rysowania Pamiętając o niezmienniku procedury Narysuj Prostokąt (którym jest poło- żenie żółwia), wiemy, że żółw znajduje się w punkcie A i jest ustawiony w kie- runku punktu B. Żółw znajdzie się w punkcie E po wykonaniu instrukcji RT 90 FD 30. Następnie należy wykonać obrót, np. za pomocą instrukcji LT 30, aby żółw został ustawiony w kierunku punktu F. Jest to jeden z możliwych sposobów rozwiązania rozważanego podzadania. Zapiszmy to w postaci procedury o nazwie i Narysuj Bok. TO NarysujBok RT 90 FD 30 LT 30 END Instrukcja Narysuj Bok ustawia żółwia w położeniu, od którego rozpoczyna się rysowanie następnego elementu terminalu. Po tych przygotowaniach możemy już opisać procedurę rysowania terminalu zgodnie z algorytmem 3.1. Nazwijmy ją NarysujTerminal. TO NarysujTerminal REPEAT 6 [NarysujProstokąt NarysujBok] END Program składa się z trzech procedur. procedurę główną NarysujTerminal. Sprawdź jego działanie, wywołując 76 3. Grafika żółwia Podsumujmy dotychczasowe rozważania. Naszym zadaniem było narysować terminal. Kolejne etapy pracy, prowadzące do napisania poprawnego programu można ująć w postaci następujących zasad postępowania: 1. Sprecyzuj zadanie, czyli ustal m.in. kształt oraz szczegółowe wymiary ry sunku. 2. Sformułuj ogólny schemat algorytmu i wyodrębnij w nim podzadania. 3. Opracuj algorytmy dla podzadań i zapisz je w postaci procedur. 4. Przygotuj opis procedury głównej, realizującej cały algorytm. 5. Wywołaj procedurę główną, by sprawdzić czy cały program (złożony z pn cedur) działa zgodnie z przyjętymi założeniami. Kolejność wykonywania kroków 3 i 4 można zmienić, a przy rozwiązywani podzadań również stosować zasady 1-5. Powyższe zasady postępowania zostały sformułowane na tyle ogólnie, że moj być przydatne podczas rozwiązywania innych zadań (zob. zad. 3.5). Do zestawu procedur (programu) rysowania terminalu dodajmy jeszcze jedi procedurę o nazwie Terminal. Przed rozpoczęciem rysowania spowoduje or wyczyszczenie ekranu, ukrycie żółwia (co przyśpiesza rysowanie) oraz ustawiei żółwia w początkowym położeniu. Będzie to nowa procedura główna naszego i stawu procedur: TO Terminal CS HT PU LT 90 FD 10 RT 90 FD 40 PD NarysujTerminal END I i j Uwaga: Zestaw procedur rysowania terminalu znajduje się na dyskietce w p TERMINAL.LOG umieszczonym w kartotece R0ZDZ3. 3.3.1. Procedura z parametrami Czy za pomocą jednego opisu procedury możemy rysować prostokąty o różr długościach boków? Odpowiedź brzmi - tak. Wystarczy rozszerzyć nieco procedury o nazwie NarysujProstokąt. Nową procedurę nazwiemy Prosto] TO Prostokąt :Bokl :Bok2 REPEAT 2 [FD :Bokl RT 90 FD :Bok2 RT 90] END W tej definicji wprowadzono możliwość wyboru długości boków rysowa prostokąta. ,W nagłówku po nazwie procedury następują dwa parametry dzielone odstępami. Te same parametry pojawiły się zamiast liczb 35 i 10 \ 3.3. Procedury 77 powiednich miejscach treści procedury Prostokąt. Parametry występujące w de- finicji procedury nazywają się parametrami formalnymi. W języku Logo taki parametr składa się z dwukropka i występującej bezpośrednio po nim nazwy. Po opisaniu i przetłumaczeniu procedury z parametrami możemy wywołać tę procedurę, pisząc jej nazwę z konkretnymi wartościami parametrów, czyli z pa- rametrami aktualnymi. Na przykład wykonanie następujących instrukcji: CS Prostokąt 50 50 Prostokąt 10 90 spowoduje pojawienie się na oczyszczonym ekranie dwóch prostokątów o bokach 50 na 50 i 10 na 90. Czynności związane z wywołaniem procedury z parametrami objaśnimy na przykładzie procedury rysującej wielokąt foremny (n-kąt) o danym boku: TO Wielokąt :n :Bok REPEAT :n [FD :Bok RT 360 / :n] END Parametrem aktualnym (n razy powtarzanej) instrukcji RT jest wynik dzielenia 360 przez liczbę kątów wielokąta, czyli przez n. Operatorem dzielenia w języku Logo jest znak /. Wykonanie instrukcji Wielokąt 6 50 jest równoważne wykonaniu wszystkich instrukcji z treści procedury Wielokąt, w których parametry formalne przybrały wartości odpowiednich parametrów ak- tualnych, tzn. instrukcja REPEAT :n [FD :Bok RT 360 / :n] jest wykonywana dla n = 6 i Bok = 50, czyli jako instrukcja REPEAT 6 [FD 50 RT 360 / 6]. Uwaga: Teksty procedur Prostokąt i Wielokąt znajdują się na dyskietce w pliku I i I FIGURY.LOG umieszczonym w kartotece R0ZDZ3. W języku Logo za pomocą parametrów można przekazywać informacje z oto- czenia procedury do jej treści. (W innych językach programowania, np. w języku Pascal, parametry umożliwiają również przekazywanie informacji z treści proce- dury do środowiska zewnętrznego.) Podkreślmy, że omówione w punkcie 3.2 instrukcje, np. FD, LT, mają podo- bną budowę, czyli składnię, jak wywołania procedur przez nas zdefiniowanych, 3. Grafika żółwia 78 nie trzeba jednak podawać ich definicji. Dlatego nazywa się je w języku Logo instrukcjami lub procedurami pierwotnymi. (W innych językach, np. w języku Pascal, w takim wypadku mówi się o procedurach standardowych.) 3.4. Wyrażenia Parametrami aktualnymi procedur w języku Logo nie muszą być wyłącznie liczby, Mogą nimi być wyrażenia. Wyrażeniem nazywamy taką konstrukcję języka pro- gramowania, która służy do wyznaczania pewnej wartości (wyniku) - na przykład wartości liczbowej. W treści procedury Wielokąt wystąpiło wyrażenie 360 / :n jako paramert aktualny procedury RT. Wyrażenie składa się z argumentów (np. 360, :n) i operatorów (np. /) Argumentami mogą być liczby, parametry procedur lub wywołania funkcji. Ti omówimy wyrażenia arytmetyczne, czyli wyrażenia, których wartościami s liczby. Operatory działań arytmetycznych są oznaczane następująco: + - dodawanie, - - odejmowanie i zmiana znaku, * - mnożenie, / - dzielenie. W języku AC-Logo znaki działań dwuargumentowych oddziela się od ar| mentów co najmniej jednym odstępem, np. 2 * :Bok + 15, a znaki działań ji noargumentowych zapisuje się bezpośrednio przed argumentem, np. -:Kąt. Podczas obliczania wartości wyrażenia mnożenie i dzielenie mają wyższy pi rytet niż dodawanie i odejmowanie. Zmianę kolejności wykonywanych dzia w wyrażeniu można uzyskać stosując nawiasy okrągłe. 3.4.1. Funkcje W wyrażeniu jako argumenty działań mogą występować wywołania procedur tylko takich procedur, które obliczają i przekazują pewną wartość (wynik), żywa się je w języku Logo procedurami z wartością lub - krócej - funkcji Podobnie jak w przypadku procedur rozróżnia się funkcje pierwotne i definiow Przykładami funkcji pierwotnych w języku Logo są: SQRT (pierwiastek kw? towy) i funkcje trygonometryczne SIN oraz COS. Argumenty funkcji zapisu; po nazwie funkcji bez ujmowania ich w nawiasy, np. SQRT 2, SIN 35. Przy obliczaniu wartości wyrażenia operatory będące nazwami funkcji najniższy priorytet w kolejności wykonywanych działań. Dlatego, na przj 3.4. Wyrażenia 79 napis SIN :x * 2 + 5 oznacza obliczenie wartości funkcji sinus dla argumentu :x * 2 + 5. Gdybyśmy do wartości funkcji SIN dla argumentu :x * 2 chcieli dodać 5, należałoby napisać 5 + SIN :x * 2 lub (SIN :x * 2) +5. W języku Logo można definiować własne funkcje. Na przykład, funkcję o na- zwie Potęga2, której wartością jest druga potęga jej argumentu, możemy zdefi- niować następująco: TO Potęga2 :Liczba OP :Liczba * :Liczba END Definicja funkcji w języku Logo ma postać definicji procedury, w której musi wystąpić instrukcja OP o składni: OP wyrażenie Wykonanie instrukcji OP w treści procedury o nazwie P powoduje (tak jak napo- tkanie słowa END) opuszczenie treści tej procedury (tj. P) i przekazanie wartości wyrażenia w miejsce wywołania procedury P. Procedurę z tak nadaną wartością nazywa się w języku Logo funkcją - o czym już wspominaliśmy - i można z niej korzystać w wyrażeniach tak samo, jak z funkcji pierwotnych języka Logo, np. z funkcji SIN. Pierwszy wiersz definicji funkcji nazywa się nagłówkiem funkcji, a pozostałe wiersze tworzą treść funkcji. Przypomnijmy na zakończenie tego punktu, że: - wywołanie procedury jest instrukcją; nazwa procedury jest nazwą instrukcji, parametr aktualny procedury może być wyrażeniem, np. FD 7 * 7, - wywołanie funkcji jest wyrażeniem, czyli może być użyte jako parametr aktualny procedury; nazwa funkcji jest operatorem, argument funkcji może być wyrażeniem, np. Potęga2 5 + SQRT 4. 3.4.2. Wyświetlanie tekstów i wartości wyrażeń Teksty w postaci pojedynczych słów lub całych zdań oraz wartości wyrażeń można wyświetlać na ekranie monitora. Miejsce, w którym rozpoczyna się wyświetlanie tekstu, jest wskazywane przez kursor tekstowy. Kursor ten można ustawić we wskazanym miejscu na ekranie za pomocą pierwotnej instrukcji SETCURSOR [nr-kolumny nr-wierszd\ Lewy górny róg ekranu ma pozycję [0 0]. Wyświetlanie odbywa się za pomocą pierwotnych instrukcji języka Logo. Wy- korzystamy instrukcje wymienione w tablicy 3.3. 80 3. Grafika żółwia Tablica 3.3. Instrukcje wyświetlania i wymazywania tekstów Instrukcja Wykonanie instrukcji PR wyrażenie TYPE wyrażenie CT TS Wyświetla wartość wyrażenia i ustawia kursor tekstowy na początku następnego wiersza, np. PR 3 + SQRT 2. Wyświetla wartość wyrażenia i pozostawia kursor tekstowy w tym samym wierszu, np. TYPE Potęga2 7. Wymazuje teksty znajdujące się na ekranie. Oczyszcza ekran i ustawia kursor tekstowy w lewym górnym rogu ekranu; cały ekran jest przeznaczony na tekst. Za pomocą instrukcji PR lub TYPE można wyświetlić pojedyncze słowo poprze dzając je znakiem cudzysłowu " zwanym w języku Logo jednoargumentowyi operatorem dosłowności, np. TYPE "Prostokąty. Jeśli chcemy wyświetli ciąg słów za pomocą jednej instrukcji, to należy ująć go w nawiasy kwadratowe, i przykład PR [Trzy prostokąty] . Pusty wiersz, czyli dodatkowy odstęp międi wierszami, można wstawić do wyświetlanego tekstu za pomocą PR [ ]. Jed< odstęp między słowami można wyświetlić za pomocą instrukcji TYPE CHAR 3 ponieważ wartością pierwotnej funkcji CHAR : kod jest znak o kodzie ASCII rói nym wartości parametru kod (zob. rozdz. 2). Zauważmy, że parametry niektórych instrukcji są umieszczane w nawiasa kwadratowych. Taki rodzaj danych w języku Logo nazywa się listą. Listy orr wiamy szerzej w punkcie 3.7. Składnia niektórych procedur pierwotnych języ Logo wymaga, aby ich parametr był listą, np. parametrem procedury SETCURS musi być lista złożona z dwóch liczb. 3.4.3. Rysunek i tekst Przykładem użycia wyrażeń, jako parametrów instrukcji, jest treść następi cej procedury TrzyProstokąty (zob. również zad. 3.6). Procedura ta, zgod ze swoją nazwą, powoduje narysowanie trzech prostokątów - których długi boków są wartościami odpowiednich wyrażeń arytmetycznych - i podpisanie sunku. Jeden prostokąt ma losowe długości boków. Do ich wyznaczenia wykoi stujemy funkcje pierwotne: RANDOM :11 oraz INT :12, których wartościam odpowiednio liczba losowa z przedziału [0,11) i część całkowita liczbowej wart parametru 12. TO TrzyProstokąty :Bokl :Bok2 WINDOW CS HT Prostokąt :Bokl :Bok2 RT 40 Prostokąt :Bokl / 2 (Potęga2 :Bok2 / 4) * 3 3.5. Zstępująca metoda projektowania algorytmów 81 LT 55 Prostokąt 30 + INT RANDOM 50 15 + INT RANDOM 70 SETCURSOR [30 13] PR [TRZY PROSTOKĄTY] WRAP END Zapisy instrukcji Prostokąt, których parametrami aktualnymi są dwa wyrażenia, są mało czytelne w powyższej procedurze. W takim wypadku dodanie nawiasów okrągłych zwykle poprawia czytelność zapisu: Prostokąt (:Bokl / 2) ((Potęga2 :Bok2 / 4) * 3) Prostokąt (30 + INT RANDOM 50) (15 + INT RANDOM 70) Uwaga: Teksty funkcji Potęga2 i procedury TrzyProstokąty znajdują się na dyskietce w pliku FIGURY.LOG umieszczonym w kartotece R0ZDZ3. Wywołanie procedury lub funkcji, której parametrami aktualnymi są wyraże- nia, polega na: - obliczeniu wartości wszystkich parametrów (wyrażeń), - przekazaniu tych wartości do treści procedury lub funkcji w miejsca odpo- wiednich parametrów formalnych, - wykonaniu tak zmodyfikowanej treści procedury lub funkcji. Na przykład, wykonanie instrukcji TrzyProstokąty 100 20 spowoduje na- rysowanie prostokątów o bokach odpowiednio 100 na 20, 50 na 75 i a na b jed- nostek, gdzie a jest liczbą z przedziału [30,80), a b z przedziału [15,85). 3.5. Zstępująca metoda projektowania algorytmów Umiemy już sporządzać komputerowe rysunki niektórych figur geometrycznych. Zastanówmy się, jak zaprogramować rysunek zbudowany z kilku różnych ele- mentów. Wybieramy niezbyt trudny do przygotowania rysunek, jednak na tyle skomplikowany, aby móc pokazać pewną systematyczną metodę programowania. Przypuśćmy zatem, że chcemy narysować taką wieżę, jak pokazano na rys. 3.3. Wielkość rysunku jest uzależniona od jednego parametru, dzięki któremu można tę wieżę skalować zachowując jej proporcje. Tym parametrem jest j (jak jednostka). I tak, ściana wieży ma 16 jednostek wysokości i 7 jednostek sze- rokości. W podobny sposób zostały oznaczone również inne odległości między elementami rysunku. Po szczegółowym określeniu wymiarów i wzajemnego położenia poszczegól- nych elementów wieży względem siebie możemy rozpocząć projektowanie sporzą- dzenia tego rysunku w systematyczny sposób. fi — Elementy informatyki 82 3. Grafika żółwia 2.5 1 Rys. 3.3. Wieża Nasza wieża składa się ze ściany, okien, dachu i chorągiewki. Wymienionej elementy wieży są podrzędne w stosunku do całości, co możemy zaznaczyć sche-j matycznie w następujący sposób: Wieża Ściana Okna Dach Chorągiewka Podobnie będziemy uściślać poszczególne składowe wieży, aż dojdziemy do pień wotnych instrukcji języka Logo. Wieża Ściana Okna I I Attyka Okno I Rama Dach Chorągiewka FD, BK, RT, LT,... Postać następującego programu wynika wprost z powyższego schematu. 3.5. Zstępująca metoda projektowania algorytmów 83 Przykład 3.2. Rysowanie wieży. TO RysujWieżę :j Ściana 16 * :j 7 * :j Okna :j Dach : j Chorągiewka :j END Zanim podamy opisy procedur, których nazwy występują w treści procedury RysujWieżę, pomyślmy o właściwym położeniu żółwia przed rozpoczęciem ryso- wania każdego z elementów rysunku. Założymy, że każdy element rozpoczynamy rysować od jego lewego dolnego rogu i że wówczas żółw jest skierowany pionowo ku górze. Ponadto, by po narysowaniu każdego elementu znać położenie żółwia, przyjmiemy zasadę, że jest ono niezmiennikiem procedur. Uzupełnijmy więc najpierw treść procedury RysujWieżę instrukcjami prze- mieszczającymi żółwia między kolejno rysowanymi elementami. Wykorzystamy w tym celu pomocniczą procedurę Hop. Procedura ta, której parametrami są dx idy, przenosi żółwia z podniesionym pisakiem z punktu (x,y), w którym on się znajduje, do punktu (x+dx,y+dy). Zakładamy, że przed wykonaniem procedury Hop żółw jest skierowany pionowo ku górze. TO Hop :dx :dy PU RT 90 FD :dx LT 90 FD :dy PD END Przerwijmy na moment tok rozumowania i wprowadźmy bardzo pożyteczny element programów. W dowolnym miejscu programu można umieścić komen- tarz. W języku AC-Logo komentarzem jest ciąg znaków, różnych od nawiasów klamrowych, wpisanych wewnątrz nawiasów { oraz }. W naszych programach komentarze objaśnią m.in. drogę żółwia między rysowanymi elementami. TO RysujWieżę :j Ściana 16 * :j 7 * :j {ruch od ściany do najniższego okna} Hop 3 * :j 3 * :j Okna :j {ruch od najniższego okna do dachu} Hop -2 * :j 13 * :j Dach :j {ruch od dachu do chorągiewki} Hop2.5*:j2.5*:j Chorągiewka :j {powrót na początek wieży} 84 Hop -3.5 * END (-18.5 * END Drugi parametr ostatniej instrukcji Hop, rozpoczynający się od liczby ujemnej,] został ujęty w nawiasy dla przejrzystości zapisu. ' Podamy teraz opisy poszczególnych procedur. TO Ściana -.Wysokość -.Szerokość FD :Wysokość RT 90 Attyka :Szerokość FD :Wysokość RT 90 FD -.Szerokość RT 90 END Procedurą podrzędną jest tutaj Attyka, której celem jest narysowanie linii łama- nej. Rysowanie następnego elementu ściany rozpoczyna się w końcowym punkcie tej linii, dlatego położenie żółwia przed i po wykonaniu instrukcji Attyka jest różne. TO Attyka -.Szerokość FD :j REPEAT (:Szerokość - :j [RT 90 FD :j LT 90 FD RT 90 END / (2 * :j) j LT 90 FD RT 90 FD END W treści procedury podrzędnej oprócz jej parametrów można używać pan metrów formalnych procedur nadrzędnych. Dla przykładu, w procedurze Attyl (z jednym parametrem Szerokość) jest używany parametr j z procedury na> rzędnej Rysuj Wieżę. A oto komplet procedur rysujących okna. TO Okna :j {rysowanie trzech okien} REPEAT 3 [Okno (2 * :j) :j (0.25 * :j) {powrót na początek okien} Hop 0 (-12 * :j) END TO Okno :Wysokość :Szerokość :Głębokość Rama :Wysokość :Szerokość {ruch do wewnętrznej ramy} Hop -.Głębokość 0 Rama :Wysokość - :Głębokość {powrót na początek okna} Hop -:Głębokość 0 END Hop 0 4 Szerokość - 2 * :Głębokość 3.5. Zstępująca metoda projektowania algorytmów 85 TO Rama :Wysokość :Szerokość FD :Wysokość - :Szerokość * 0.25 RT 45 FD 0.25 * :Szerokość * SQRT 2 RT 45 FD 0.5 * :Szerokość RT 45 FD 0.25 * :Szerokość * SQRT 2 RT 45 FD :Wysokość - :Szerokość * 0.25 {powrót na początek ramy} RT 90 FD :Szerokość RT 90 END Pozostało dorysowanie dachu i chorągiewki. TO Dach :j RT 45 FD 2.5 * :j * SQRT 2 RT 90 FD 2.5 * :j * SQRT 2 (powrót na początek dachu} RT 135 PU FD 5 * :j PD RT 90 END TO Chorągiewka :j FD 0.5 * :j REPEAT 3 [FD :j RT 120] {powrót na początek chorągiewki} BK 0.5 * :j END Powyższy program został zbudowany strukturalnie. Narzędziem struktu- ralizacji programu są procedury. Do kompletu dodajmy jeszcze procedurę o na- zwie Wieża, która spowoduje oczyszczenie ekranu, ukrycie żółwia, ustawienie go w początkowym położeniu i wywołanie procedury RysujWieżę. TO Wieża :Jednostka CS HT Hop -12.5 * :Jednostka RysujWieżę :Jednostka END (-10 * -.Jednostka) Aby sporządzić rysunek ustalonej wielkości, wystarczy wykonać instrukcję Wieża z odpowiednią wartością jednostki, czyli parametru Jednostka, na przy- kład Wieża 10. Uwaga: Teksty procedur użytych do rysowania wieży znajdują się na dyskietce w pliku HEZA.LOG umieszczonym w kartotece R0ZDZ3. _ Narysowana wieża może być częścią zamku - porównaj zadanie 3.7. 86 3. Grafika żółwia 3.5.1. Zamalowywanie obszaru Rysunki komputerowe możemy uatrakcyjnić, wykorzystując dwie pierwotne in- strukcje z języka AC-Logo (pomijamy tu możliwości użycia kolorów). Instrukcja FILL (bez parametrów) wypełnia dowolny zamknięty obszar na ekranie wzorem określonym za pomocą tzw. motywu wzoru, który jest ustalany przez instrukcję FILLPATTERN. Parametrem instrukcji FILLPATTERN jest osiem liczb całkowitych z zakresu od 0 do 255 ujętych w nawiasy kwadratowe, czyli lista liczb. Liczby te można zapisać w układzie dziesiętnym lub w układzie szesnastkowym - poprzedzając ciąg cyfr szesnastkowych3 znakiem #. Parametr instrukcji FILLPATTERN odpowiada polu 8x8 punktów ekranu. Każda z liczb reprezentuje zawartość jednego wiersza tego pola, co pokazuje tablica 3.4. Tablica 3.4. Przykład motywu wzoru z instrukcji FILLPATTERN [#40 #40 #ff 2 2 2 #ff #40] Numer Zawartość wiersza wiersza dwójkowa dziesiętna szesnastkowa 1 0 1 0 0 0 0 0 0 64 #40 2 0 1 0 0 0 0 0 0 64 #40 3 1 1 1 1 1 1 1 1 255 #ff 4 0 0 0 0 0 0 1 0 2 #2 5 0 0 0 0 0 0 1 0 2 #2 6 0 0 0 0 0 0 1 0 2 #2 7 1 1 1 1 1 1 1 1 255 #ff 8 0 1 0 0 0 0 0 0 64 #40 Motyw wzoru, powielany przez instrukcję FILL, począwszy od bieżącej pozycj żółwia, otrzymujemy interpretując zawartość dwójkową wierszy tak, że każd jedynka oznacza punkt zamalowany, a zero - niezamalowany. Jeśli natomia wzór nie został określony, to instrukcja FILL używa pierwotnego motywu wzorj złożonego z samych zamalowanych punktów i całkowicie zamalowuje wskaza obszar. Aby wypełnić wzorem wnętrze zamkniętego obszaru, należy ustawić żófo wewnątrz tego obszaru w dowolnym niezamalowanym punkcie, tzn. w punkc| w kolorze tła ekranu, określić motyw wzoru (jeśli wcześniej tego nie uczynion i użyć instrukcji FILL. W zamalowaniu elementów wieży, np. ściany, dachu i wnętrz okien (zo, rys. 3.4) pomoże nam procedura Zamaluj z parametrem ustalającym motj| 3Kolejnymi cyframi szesnastkowymi są cyfry od 0 do 9 i litery od a do f. 3.5. Zstępująca metoda projektowania algorytmów 87 Przeniesie ona żółwia do wnętrza obszaru, spowoduje zamalowanie ob- szaru, a następnie wycofa żółwia na poprzednią pozycję i przywróci mu poprzedni kierunek. Zakładamy, że przed zamalowaniem obszaru żółw znajduje się w lewym dolnym rogu tego obszaru i jest skierowany pionowo ku górze. Rys. 3.4. Zamalowana wieża Przykład 3.3. Procedura zamalowania obszaru dowolnym wzorem może mieć postać: TO Zamaluj -.Wzorek PU RT 75 FD 2 PD FILLPATTERN -.Wzorek FILL PU BK 2 LT 75 PD END ? Zwróćmy uwagę, że parametr formalny procedury Zamaluj, tj. Wzorek, w tre- ści tej procedury jest daną dla instrukcji FILLPATTERN, dlatego parametrem aktu- alnym musi być lista ośmiu liczb. Pokażemy to na przykładzie procedury, której celem jest zamalowanie ściany wzorem przypominającym cegły: TO ZamalujŚcianę Zamaluj [#40 #40 #ff 2 2 2 #ff #40] END W podobny sposób można opisać procedury zamalowania dachu i okien, na- stępnie użyć ich do zamalowania odpowiednich elementów wieży - zadanie 3.8. Uwaga: Teksty procedur Zamaluj i ZamalujŚcianę znajdują się na dyskietce w pliku HEZA.LOG umieszczonym w kartotece R0ZDZ3. i 3.6. Rysowanie za pomocą procedur rekurencyjnych Już wiemy, że w treści definiowanej procedury mogą wystąpić wywołania innych procedur. Sprawdźmy czy procedura może wywoływać samą siebie, a więc czy następująca definicja procedury jest poprawna. Przykład 3.4. Rysowanie spirali. TO Spirala :Bok FD :Bok RT 90 Spirala :Bok + 1 END I Uprzedzamy, że działanie instrukcji Spirala, na przykład w ciągu instrukcji; WINDOW CS Spirala 1 można przerwać jedynie za pomocą operacji klawiszowej | Ctrl Break |. Ciekawj efekt uzyskamy wykonując ciąg instrukcji: WRAP CS PX Spirala 1 Użycie pierwotnej instrukcji PX powoduje, że w trakcie rysowania są oczy szczane już zamalowane i zamalowywane czyste (tj. w kolorze tła) punkty ekranu po których porusza się żółw. Rozszerzenie możliwości procedury Spirala prc ponujemy w zadaniu 3.9. Procedura, która w swojej treści odwołuje się do siebie samej, nazywa s: procedurą rekurencyjną. Uzupełnijmy treść procedury Spirala tak, aby procedura ta miała skończ' ne działanie, tzn. zatrzymywała się, jeśli np. wartość parametru Bok przekroc: 100. W pierwszym wierszu po nagłówku procedury Spirala należy dopisać i strukcję: IF :Bok > 100 [STOP] Instrukcja IF nazywa się instrukcją warunkową i ma w języku Logo n; tępującą budowę: IF warunek iciąg-instrukcji-1'] ELSE [ciąg-instrukcji-2] Działanie tej instrukcji jest następujące: jeśli warunek jest spełniony, to jest \ konywany ciąg-instrukcji-1, w przeciwnym razie wykonuje się ciąg-instrukcji- Można również używać instrukcji warunkowej w uproszczonej postaci: IF warunek \_ciąg-instrukcji~\ Działa ona następująco: jeżeli warunek jest spełniony, to wykonuje się ciąg- trukcji, a w przeciwnym przypadku jest on pomijany. 3.6. Rysowanie za pomocą procedur rekurencyjnych 89 Zatem instrukcja warunkowa pozwala podejmować decyzje w zależności od spełnienia lub niespełnienia warunku. Warunkiem nazywamy wyrażenie logiczne, tj. takie wyrażenie, które może przyjmować wartości TRUE (prawda) albo FALSE (fałsz). W naszych przy- kładach warunki mają najczęściej postać relacji, np. Bok > 99, x = 0, n < 5. W języku AC-Logo operatory relacji oddziela się odstępami od ich argumentów. W treści procedury P można użyć instrukcji STOP na przykład tak, jak w treści procedury Spirala. Jej wykonanie powoduje na- tychmiastowy powrót w miejsce wywołania procedury P, a ściślej - przejście do instrukcji następującej po wywołaniu P. Teraz pokażemy jak można przekształcić algorytm iteracyjny w algorytm re- kurencyjny. Załóżmy, że chcemy narysować n jednakowych prostokątów. Algorytm ite- racyjny już znamy: powtórz n razy dwie instrukcje - narysuj jeden prostokąt i przesuń żółwia. Można jednak wykonać to zadanie inaczej. Jeśli mamy do na- rysowania n prostokątów, to - po sprawdzeniu, że n nie jest zerem - rysujemy jeden prostokąt i pozostaje do narysowania (tą samą metodą) jeszcze n - 1 pro- stokątów. Zapiszmy ten drugi sposób w postaci algorytmu i procedury. Algorytm 3.2. Algorytm rekurencyjny "Rysuj n prostokątów". 1. Jeśli n = 0, to zakończ algorytm. 2. Narysuj jeden prostokąt i przesuń żółwia. 3. Rysuj n - 1 prostokątów według niniejszego algorytmu. Przykład 3.5. Rysujemy prostokąty w sposób rekurencyjny. Przyjmiemy, że prostokąty mają boki o długościach 50 i 10 jednostek, leżą na linii prostej i jeden od drugiego jest oddalony o 5 jednostek. Łatwo zauważyć, że te założenia nie mają wpływu na działanie algorytmu 3.2. TO RysujProstokąty :n IF :n = 0 [STOP] Prostokąt 50 10 Hop 15 0 RysujProstokąty :n - 1 END ? Parametr n w procedurze Rysuj Prostokąty wyznacza tzw. stopień lub głę- bokość rekurencji. Uwaga: Procedury Spirala i Rysuj Prostokąty znajdują się na dyskietce w pliku ! ; | REKUREN.LOG umieszczonym w kartotece R0ZDZ3. 90 Instrukcje z treści procedury rekurencyjnej RysujProstokąty można pogru- pować następująco: 1. warunek-zakończenia-rekurencji, 2. instrukcje-bez-odwolań-rekurencyjnych, 3. wywołanie-rekurencyjne. Są możliwe również bardziej złożone schematy, np. takie, w których kroki 1-! przeplatają się. Jednak w każdym przypadku, jeśli procedura rekurencyjna m mieć skończone działanie, należy zadbać o to, aby warunek zakończenia rekurenc poprzedzał wywołanie rekurencyjne. Inne przykłady rysunków, które można sporządzić za pomocą iteracji lu rekurencji, są zasugerowane w zadaniu 3.10. W treści procedury może wystąpić więcej niż jedno wywołanie rekurencyjn Pokażemy to na przykładzie rysowania dywanu Sierpińskiego. 3.6.1. Dywan Sierpińskiego Definicja trójkątnego dywanu Sierpińskiego jest następująca: Dla n = jest nim trójkąt równoboczny o boku długości a jednostek - krócej - o bo a (rys. 3.5). Dla n = 1 dywanem jest poprzedni trójkąt, w który wpisano zan lowany trójkąt o wierzchołkach w środkach boków - rys. 3.6. Rys. 3.5. Dywan Sierpińskiego stopnia n = 0 Jeśli w każdy z trzech trójkątów leżących przy wierzchołkach dywanu z sunku 3.6, w podobny sposób jak poprzednio wpiszemy zamalowany trójkąi otrzymamy dywan Sierpińskiego następnego stopnia (por. rys* 3.7). Widać, że dywan Sierpińskiego stopnia 2 o boku a jest zbudowany z tr dywanów Sierpińskiego stopnia 1 o boku a / 2 i z zamalowanego trójkąta. dobnie możemy powiedzieć o dywanie stopnia 1. Uogólnieniem tych obsen jest następująca reguła: Dywan Sierpińskiego stopnia n (n > 0) o boku a jest zbudowany z trzeci powiednio ułożonych dywanów Sierpińskiego stopnia n - 1 o boku a / 2 i malowanego trójkąta o boku a / 2. 3.6. Rysowanie za pomocą procedur rekurencyjnych 91 Rys. 3.6. Dywan Sierpińskiego stopnia n = 1 Rys. 3.7. Dywan Sierpińskiego stopnia n = 2 Rekurencyjny algorytm rysowania trójkątnego dywanu Sierpińskiego wynika z definicji. W jego sformułowaniu pomoże nam rysunek 3.8. nu z ry- Rys. 3.8. Dywan Sierpińskiego - kolejność rysowania z trzech ? A.igorytm 3.3. Rysowanie dywanu Sierpińskiego stopnia n o boku a. ;ąta. rfr ? \ Rozpocznij w punkcie A. bserwacji | 2. Jeśli n = 0, to narysuj trójkąt równoboczny o boku a i zakończ algorytm. 3. Dla n > 0 postępuj następująco: (a) Narysuj dywan Sierpińskiego stopnia n - 1 o boku a / 2 (ABFA). (b) Przenieś żółwia do punktu B. (c) Narysuj dywan Sierpińskiego stopnia n - 1 o boku a / 2 (BCDB). 3. Grafika żółwia 92 (d) Przenieś żółwia do punktu F. . (e) Narysuj dywan Sierpińskiego stopnia n. - 1 o boku a / 2 {FDEF). \ (f) Zamaluj trójkąt FBDF. (g) Przenieś żółwia do punktu A i zakończ algorytm. Położenie żółwia, podobnie jak dotychczas, ma być niezmiennikiem proce- dur rysowania i zamalowywania. Napisanie kompletnego programu na podstawie algorytmu 3.3 pozostawiamy do samodzielnego wykonania - zad. 3.11. Tutaj natomiast napiszemy program rysujący dywan Sierpińskiego nieco inaczej. Sko- rzystamy mianowicie z następujących wskazówek upraszczających nasze zadanie - Po ustawieniu żółwia w wierzchołku dywanu obracamy żółwia w kierun ku następnego wierzchołka. Takie położenie przyjmujemy jako niezmienni! procedur. - Po narysowaniu dywanu ABFA przesuwamy żółwia do punktu C i obracani w kierunku punktu E. W dwóch pozostałych wierzchołkach (C i E) czynim podobnie. Oto zapowiedziany program. Przykład 3.6. Rysowanie dywanu Sierpińskiego. Procedura główna uwzględniająca czynności organizacyjne: TO DywanSierpińskiego :n :a CS HT {początkowe ustawienie żółwia} Hop -:a / 2 (-:a / 3) FILLPATTERN [#ff #ff #ff #ff #ff #ff #ff #ff] RT 30 RysujDywanSierpińskiego :n :a LT 30 END Procedura rekurencyjna: TO RysujDywanSierpińskiego :n :a IF -ii = 0 [Trójkąt :a STOP] REPEAT 3 [RysujDywanSierpińskiego ZamalujTrójkąt :a END Pozostałe procedury: TO Trójkąt :a REPEAT 3 [FD :a RT 120] END :n - :a / 2 FD :a RT 3.7. Struktury danych - listy 93 TO Zamaluj Trój kąt :a PU RT 30 FD :a / 2 PD FILL PU BK :a / 2 LT 30 PD END Uwaga: Zestaw procedur rysujących trójkątny dywan Sierpińskiego znajduje się na dys- [~T1 kietce w pliku DYWAN.LOG umieszczonym w kartotece R0ZDZ3. _ Przykłady innych rysunków definiowanych rekurencyjnie podano w zadaniach 3.12 - 3.14. 3.7. Struktury danych - listy Opisywane dotąd procedury, za pomocą których sporządzaliśmy rysunki, albo nie miały parametrów, albo jako dane najczęściej przyjmowały liczby (ogólniej - wartości wyrażeń arytmetycznych). Dane liczbowe określały na przykład długości boków prostokąta, wielkości kątów obrotu żółwia podczas rysowania spirali lub stopień rekurencyjnie definiowanego dywanu Sierpińskiego. W języku Logo mogą występować nie tylko dane proste, np. liczby, ale również dane złożone, czyli struktury danych, reprezentowane przez listy. Stosowaliśmy już procedury z parametrami zapisywanymi jako listy. Były to listy liczb, np. SETCURSOR [30 13], Zamaluj [#40 #40 #f f 2 2 2 #f f #40], lub listy słów, np. PR [TRZY PROSTOKĄTY] (zob. p. 3.4 i 3.5). W tym punkcie listy omówimy dokładniej. Rozpocznijmy od definicji. Lista w języku Logo jest ujętym w nawiasy kwadratowe ciągiem słów lub list; ciąg ten może być pusty. Jest to definicja rekurencyjna. Lista pusta, tj. [ ], ma zero elementów. Lista niepusta ma co najmniej jeden element. Może nim być słowo lub lista. Słowem w języku Logo określa się dowolny ciąg znaków zakończony separa- torem (zob. p. 3.3). Stąd wynika, że - poza tradycyjnymi słowami zaczerpniętymi z języka naturalnego - słowami w języku Logo są również pojedyncze znaki (np.: =, /), liczby (np.: 3, i20), a także ciągi liter i cyfr, np. Al, 2b itp. Oto przykłady list, które wcześniej występowały w instrukcjach REPEAT (zob. p. 3.2 i 3.3). [FD 35 RT 90 FD 10 RT 90] [REPEAT 3 [FD 30 RT 120] RT 36] [FD :Bok RT 360 / :n] 94 3. Grafika żółwia i 3.7.1. Przeglądanie listy danych Listy można przeglądać. Tablica 3.5 zawiera przykładowe wywołania najważniej- szych jednoargumentowych funkcji pierwotnych służących do tego celu. Wartoś- ciami tych funkcji są albo słowa, albo listy. Tablica i.5. Funkcje przeglądania listy Wywołanie funkcji Wynik Wartość funkcji FIRST [a b c] a Pierwszy element listy FIRST [[a] b c] [a] BF [a b c] [b c] Lista bez pierwszego elementu BF [a] [ ] LAST [a b c] c Ostatni element listy BL [a b c] [a b] Lista bez ostatniego elementu Wymienione funkcje wykorzystamy do rozwiązania następującego zadania: Napisać procedurę sterującą ruchem żółwia zgodnie z danymi z listy L. Liczby w liście danych L oznaczają ruchy żółwia zakodowane w następujący sposób: liczba 1 oznacza ruch do przodu o 50 jednostek, liczba 2 - ruch po okręgu o pro mieniu 30 jednostek, każda inna liczba - obrót w prawo o 10 stopni. Algorytm 3.4. Odtworzenie zakodowanych ruchów żółwia. 1. Jeśli L jest listą pustą, to zakończ algorytm. 2. Jeśli pierwszy element listy L jest równy 1, to wykonaj ruch żółwia do przodu o 50 jednostek i przejdź do kroku 5. 3. Jeśli pierwszy element listy L jest równy 2, to wykonaj ruch żółwia p: okręgu o promieniu 30 jednostek i przejdź do kroku 5. 4. Wykonaj obrót żółwia o 10 stopni w prawo. 5. Wykonaj ten algorytm od początku dla listy L bez pierwszego elementu. Procedurę realizującą algorytm 3.4 nazwiemy RuchŻółwia. Wykorzystam w niej sprawdzanie, za pomocą operatora = , czy lista danych jest pusta. TO RuchŻółwia :L IF :L = [ ] [STOP] ? IF (FIRST :L) = 1 [FD 50] ELSE [IF (FIRST :L) = 2 [Okrąg 30] ELSE [RT 10]] RuchŻółwia BF :L END Nawiasy w zapisach warunków ustalają kolejność działań (zob. p. 3.4.1) - iu pierw jest brany pierwszy element z listy L, a później porównywany z liczbą. 3.7. Struktury danych - listy 95 , Sposoby rysowania okręgów o zadanym promieniu są omówione w rozwiązaniu zad. 3.6 (zob. El-II). Procedura rysująca okrąg o promieniu r może mieć nastę- pującą postać: TO Okrąg :r RT 5 REPEAT 36 [FD 3.14 * :r / 18 RT 10] LT 5 END Działanie procedury RuchŻółwia można przetestować wywołując ją na przy- kład tak: CS ST RuchŻółwia [1213112323 1] Uwaga: Procedury RuchŻółwia i Okrąg znajdują się na dyskietce w pliku RUCH-Z.LOG umieszczonym w kartotece R0ZDZ3. Z powyższego zadania wynika ogólny schemat rekurencyjnego przegląda- nia list (podobny do schematu procedury rekurencyjnej - zob. p. 3.6): 1. Jeśli lista jest pusta, to zakończ algorytm. 2. Wykonaj jakieś czynności (bez rekurencji) dla pierwszego elementu listy. 3. Wykonaj ten sam algorytm (czyli rekurencja) dla listy danych bez pierw- szego elementu. W powyższym schemacie zwroty: pierwszego i bez pierwszego można zastąpić odpowiednio przez ostatniego i bez ostatniego. 3.7.2. Pamiętanie informacji Wprowadzimy teraz nową instrukcję, która pozwala upraszczać zapis niektórych algorytmów. W drugim i w trzecim kroku algorytmu 3.4 jest sprawdzany pierwszy element listy L otrzymywany za pomocą funkcji FIRST. Jeśli nie jest on równy 1, to po raz drugi jest liczona ta sama wartość funkcji FIRST. Możemy nieco zmodyfikować realizację algorytmu 3.4 - raz policzyć i zapamiętać pierwszy element listy L, następnie dwukrotnie z niego skorzystać. W językach programowania do pamiętania informacji używa się zmien- nych. Zmienna jest reprezentowana przez nazwę i wartość. W języku Logo zmienną tworzy się i nadaje jej wartość równą wartości wyra- żenia za pomocą instrukcji przypisania o następującej składni: MAKE " nazwa-zmiennej wyrażenie 96 3. Grafika żółwia m Wartość wyrażenia może być słowem lub listą. Działanie instrukcji MAKE objaśni- my na przykładach: MAKE "Zz 10 MAKE "Zz :Zz + 2 Wykonanie instrukcji MAKE "Zz 10 powoduje utworzenie nowej zmiennej Zz, je dotąd nie była użyta, i nadanie (przypisanie) jej wartości 10. Natomiast kolejna instrukcja przypisania MAKE "Zz :Zz + 2 oznacza dodanie do wartości zmiennej Zz, tj. do liczby 10, liczby 2 i przypisanie tej wartości, tj. 12, zmiennej Zz. Po wykonaniu instrukcji MAKE "L [1 2 1 3 1 1 2 3 2 3 1] wartością zmiennej o nazwie L jest lista [1213112323 1]. Dla tak określonej zmiennej L następujące dwie instrukcje są wykonane dla tych samych wartości parametru: RuchŻółwia [12 13 112 3 2 3 1] RuchŻółwia :L Procedurę RuchŻółwia wykorzystującą instrukcję MAKE i zmienną pomocnicza Pierwszy nazwiemy RuchŻółwial. | TO RuchŻółwial :L IF :L = [ ] [STOP] MAKE "Pierwszy FIRST :L IF :Pierwszy = 1 [FD 50] ELSE [IF :Pierwszy = 2 [Okrąg 30] ELSE [RT 10]] RuchŻółwial BF :L END Uwaga: Procedura RuchŻółwial znajduje się na dyskietce w pliku RUCH-Z.LOG umil szczonym w kartotece R0ZDZ3. 3.7.3. Tworzenie listy danych Za pomocą pierwotnych funkcji języka Logo, oprócz przeglądania zawartości i można utworzyć nową listę lub zmienić elementy w istniejącej liście. Jedną z funkcji jest RL, której wartością jest lista utworzona z elementó wpisywanych z klawiatury aż do naciśnięcia klawisza | Enter |. Na przykla jeśli w trakcie wykonywania instrukcji MAKE "L RL podamy następujący ciągel mentów: 1 5 3 2 i naciśniemy klawisz | ENTER |, to wartością zmiennej L będ lista [15 3 2]. 3.7. Struktury danych - listy 97 Elementy listy, którymi - jak wiemy - mogą być dowolne słowa, są trakto- wane dosłownie, tzn. zapis [1 + INT RANDOM 3] oznacza listę złożoną z pięciu stów: 1, +, INT, RANDOM i 3. Jeśli w liście chcemy umieścić wartość wyrażenia, np. 1 + INT RANDOM 3, to należy użyć funkcji pierwotnych. Dwuargumentowe funkcje pierwotne języka Logo, których wartościami są listy utworzone z wartości argumentów, podano w tablicy 3.6. Tablica 3.( i. Funkcje tworzenia listy Wywołanie funkcji Wynik Wartość funkcji LIST 5 2 [5 2] Lista argumentów. LIST [a b] 2 [[a b] 2] SE [a b] 2 [a b 2] Lista argumentów. Jeśli argument jest listą, to do wyniku są wpisywane elementy tej listy. SE [a b] [c] [a b c] SE 5 2 [5 2] FPUT 12 [a b] [12 a b] Lista, w której pierwszy argument został dopisany na początku listy będącej drugim argumentem. FPUT [a b] [c] [[a b] c] LPUT 12 [a b] [a b 12] Lista, w której pierwszy argument został dopisany na końcu listy będącej drugim argumentem. Pokażemy teraz jak można utworzyć listę złożoną z n (n > 0) liczb wybiera- nych losowo spośród trzech liczb 1, 2 i 3. W tym celu opiszemy rekurencyjną funkcję ListaLosowa, której wartością jest taka lista. TO ListaLosowa :n IF :n = 1 [0P FPUT (1 + INT RANDOM 3) [ ]] OP LPUT (1 + INT RANDOM 3) ListaLosowa :n - 1 END Uwaga: Definicja funkcji ListaLosowa znajduje się na dyskietce w pliku RUCH-Z.LOG umieszczonym w kartotece R0ZDZ3. Dla n = 1 wartością funkcji ListaLosowa jest jednoelementowa lista powstała po dopisaniu do listy pustej [ ] wartości wyrażenia 1 + INT RANDOM 3 za po- mocą wywołania funkcji FPUT. Ten sam rezultat można otrzymać stosując inne funkcje, np. LPUT (1 + INT RANDOM 3) [ ] lub SE [ ] (1 + INT RANDOM 3). Lista losowa złożona z n elementów dla n > 1 zostaje utworzona za pomocą funkcji LPUT przez dopisanie jednego elementu na koniec listy losowej n - 1 ele- mentowej . : — Elementy informatyki 3. Grafika żółwia Wartość funkcji ListaLosowa można zapamiętać za pomocą instrukcji MAKE. np. MAKE "Kody ListaLosowa 50, a następnie wykorzystać jako parametr pro- cedury RuchŻółwia, np. w wywołaniu RuchŻółwia :Kody. 3.7.4. Algorytmy i struktury danych Naszym zadaniem w tym punkcie będzie narysowanie n (n > 0) nieprzecina- jących się okręgów o losowo wybieranych środkach i promieniach. Dodatkowo zakładamy, że żaden okrąg nie może być narysowany wewnątrz innego okręgu. Dane o okręgach - w postaci trójek: współrzędne środka (x,y) i długość pro- mienia r - będziemy przechowywać w liście. Umożliwi to sprawdzanie, czy wy- losowane dane kolejnego okręgu (xl ,yl ,rl) można dołączyć do listy, czy trzeba powtórzyć losowanie trójki danych. Listę trójek można wykorzystać na co najmniej dwa sposoby. Pierwszy polega na wpisaniu n trójek do listy, a następnie przeglądaniu listy od początku i ryso- waniu odpowiednich okręgów (zob. zad. 3.15). Opiszemy drugi sposób, w którym kolejny okrąg jest rysowany przed dopisaniem jego danych do listy. Dane o jednym okręgu przedstawimy jako listę trzech liczb, zatem lista za- wierająca informacje o już narysowanych okręgach będzie listą list. Przyjmiemy, że jest ona wartością zmiennej o nazwie Trójki. Algorytm 3,5. Rysowanie n okręgów. 1. Utwórz pustą listę trójek. 2. Licznikowi okręgów do narysowania nadaj wartość n. 3. Oczyść ekran i ukryj żółwia. 4. Powtórz n razy krok 5, następnie przejdź do kroku 6. 5. Dorysuj jeden okrąg. 6. Wyświetl informację, że narysowano n okręgów i zakończ algorytm. Opiszmy procedurę Okręgi realizującą algorytm 3.5. TO Okręgi :n {czynności wstępne} MAKE "Trójki [ ] MAKE "Licznik :n CS HT {właściwy algorytm} REPEAT :n [Dorysuj Okrąg] {czynności końcowe} SETCURSOREO 18] TYPE [Liczba narysowanych okręgów:] TYPE :n PR [.] END 3.7. Struktury danych - listy 99 Podrzędna procedura Dorysuj Okrąg działa zgodnie z algorytmem 3.6. Algorytm 3.6. Dorysowanie kolejnego okręgu. 1. Wylosuj dane (xl,yl,rl) dla kolejnego okręgu do narysowania. 2. Ustaw żółwia w pozycji (xl-rl,yl). 3. Narysuj okrąg o promieniu rl. 4. Zmniejsz o 1 licznik okręgów do narysowania. 5. Wyświetl odpowiedni tekst i wartość licznika. 6. Dopisz na koniec listy trójek dane (xl ,yl ,rl). 7. Przenieś żółwia do środka ekranu i zakończ algorytm. Wyświetlana na ekranie (w kroku 5) wartość licznika okręgów umożliwia śledzenie działania programu, ponieważ losowanie dalszych trójek danych pod- czas rysowania wielu okręgów może trwać dość długo. Zakładamy, że przed i po narysowaniu okręgu żółw znajduje się w środku ekranu i jest skierowany pionowo do góry. Aby narysować kolejny okrąg o wyloso- wanych danych, żółwia ustawiamy w odpowiednim punkcie za pomocą procedury Hop. Oto procedura realizująca algorytm 3.6. TO DorysujOkrąg MAKE "Trzy LosujTrzy :Trójki MAKE "rl LAST :Trzy Hop (FIRST :Trzy) - :rl (FIRST BF :Trzy) Okrąg :rl MAKE "Licznik :Licznik - 1 CT SETCURSOR [0 17] TYPE [LOSOWE OKRĘGI.] IF :Licznik > 0 [TYPE "Jeszcze TYPE CHAR 32 TYPE :Licznik PR [.]] MAKE "Trójki LPUT :Trzy :Trójki PU HOME PD END Zdefiniujemy funkcję LosujTrzy z parametrem formalnym ListaTrójek. Od- powiadający mu parametr aktualny jest listą zawierającą dane o narysowanych już okręgach. Ta funkcja, zgodnie z krokiem 1 algorytmu 3.6, losuje trzy liczby (xl,yl,rl) tak długo, aż prawdą jest, że okrąg przez nie reprezentowany leży na zewnątrz każdego okręgu, którego dane znajdują się w liście reprezentowa- nej przez parametr ListaTrójek. Wylosowana i sprawdzona trójka liczb jest wartością funkcji LosujTrzy. Przyjmujemy, że losowane liczby są liczbami całkowitymi, spełniającymi nas- tępujące warunki: -170<=xl<170, -75<=yl<75, 3<=rl<50. TO LosujTrzy -.ListaTrójek MAKE "L3 SE (170 - INT RANDOM 340) (75 - INT RANDOM 150) MAKE "L3 SE :L3 (3 + INT RANDOM 47) IF Sprawdź :ListaTrójek :L3 [OP :L3] OP LosujTrzy :ListaTrójek END Funkcja logiczna Sprawdź ma dwa parametry formalne ListaTrójek i Trzy. Przyjmuje ona wartość TRUE, jeśli dla każdego elementu listy ListaTrójek okrąg reprezentowany przez ten element leży na zewnątrz okręgu, który ma być naryso- wany i jest reprezentowany przez wartość parametru Trzy. W przeciwnym razie funkcja Sprawdź ma wartość FALSE. Algorytm 3.7. Obliczanie wartości funkcji Sprawdź z dwoma parametrami ListaTrójek i Trzy. 1. Jeśli ListaTrójek jest listą pustą, to wartością jest TRUE. 2. Niech Tr będzie pierwszym elementem listy ListaTrójek. 3. Jeśli okręgi reprezentowane przez wartość zmiennej Tr i parametr Trzy nie przecinają się i żaden nie leży wewnątrz drugiego, to wynikiem jest wartość funkcji Sprawdź dla danej listy ListaTrójek bez pierwszego elementu. 4. W przeciwnym razie, tzn. jeśli nie jest spełniony warunek ani z kroku 1, ani z kroku 3, wartością jest FALSE. Warunek nałożony na okręgi można łatwo sprawdzić korzystając z następuj cej własności: dwa okręgi są rozłączne i żaden nie leży wewnątrz drugiego, je: odległość między ich środkami jest większa niż suma ich promieni. TO Sprawdź :ListaTrójek :Trzy IF :ListaTrójek = [ ] [OP TRUE] MAKE "Tr FIRST :ListaTrójek IF (Odległość BL :Tr BL :Trzy) > ((LAST :Tr) + (LAST :Trzy)) [OP Sprawdź BF :ListaTrójek :Trzy] ELSE [OP FALSE] END Wartością funkcji Odległość jest odległość między punktami Punktl i Punkt o współrzędnych danych w postaci listy [x y]. TO Odległość :Punktl :Punkt2 OP SORT (Potęga2 (FIRST :Punktl) - (FIRST :Punkt2)) + (Potęga2 (LAST :Punktl) - (LAST :Punkt2)) END Funkcja Potęga2 jest opisana w p. 3.4.1. Rysunek 3.9 pokazuje jeden z możliwych efektów wykonania instrukcji o i zwie Okręgi 57. 3.7. Struktury danych - listy 101 LOSOWE 0KKE6I. Liczba narysowanych okregóu: 57. Rys. 3.9. Okręgi Daną dla procedury Okręgi jest liczba n. Załóżmy, że liczba n należy do przedziału [1,70] i opiszmy funkcję o nazwie DanaN, której wartością jest n. Aby sprawdzić poprawność danych wprowadzanych z klawiatury, skorzystamy z funkcji pierwotnej NUMBERP :e. Wartością tej funkcji jest TRUE, jeśli jej para- metr e jest liczbą, lub FALSE - w przeciwnym razie. TO DanaN CS HT SETCURSOR [0 5] PR [RYSUJEMY LOSOWE OKRĘGI.] TYPE [Podaj liczbę okręgów z przedziału :] MAKE "Licznik FIRST RL IF NOT NUMBERP :Licznik [OP DanaN] IF OR :Licznik < 1 -.Licznik > 70 [OP DanaN] OP :Licznik END Zwróćmy uwagę, że w języku Logo NOT i OR są nazwami funkcji i stąd ich argumenty podaje się po tych nazwach. Wartością jednoargumentowej funkcji logicznej NOT jest TRUE, jeśli argument ma wartość FALSE, lub FALSE - w przeciwnym przypadku. Dwuargumentowa funkcja logiczna OR przyjmuje wartość TRUE, jeśli co najmniej jeden z jej argu- mentów ma wartość TRUE. Jeśli oba argumenty mają wartość FALSE, to wartością funkcji OR jest także FALSE. 102 3. Grafika żółwia Opiszemy procedurę LosoweOkręgi, w której daną dla procedury Okręgi jest wartość funkcji DanaN. TO LosoweOkręgi WINDOW Okręgi DanaN WRAP END Uwaga: Zestaw procedur rysujących losowe okręgi znajduje się na dyskietce w pliku 0KREGI.LOG umieszczonym w kartotece R0ZDZ3. Po wykonaniu procedury LosoweOkręgi są zachowane wartości zmiennych używanych w programie, w tym np. zmiennej Trójki przechowującej w liście dane o wszystkich narysowanych okręgach. Można wykorzystać tę zmienną i jej wartość w innych zadaniach i na przykład znaleźć dane największego z naryso- wanych okręgów (zob. zad. 3.16). Jeśli pominiemy problemy natury technicznej związane z zapisywaniem al gorytmów w wybranym języku programowania, to mogliśmy się przekonać, i największe trudności przy rozwiązywaniu problemów za pomocą komputera leżą w sferze projektowania algorytmów. Opracowanie metody rozwiązywania posta- wionego zadania bywa często żmudnym procesem. W kolejnych etapach postę- powania algorytm staje się coraz bardziej szczegółowy, aż wreszcie nadaje się do zapisania w jakimś języku programowania. Podane w tym rozdziale algorytmy graficzne mają na celu między innymi po- kazanie, jak w systematyczny sposób można dochodzić od sformułowania zadania, poprzez naszkicowanie algorytmu w języku naturalnym, uściślenie jego kroków, aż do przygotowania programu komputerowego realizującego ten algorytm. Za- prezentowane metody znajdują ogólne zastosowania w rozwiązywaniu problemów za pomocą komputera; nie ograniczają się tylko do programowania grafiki żółwia z wykorzystaniem języka Logo. Zadania 3.1. Sprawdź, jakie efekty uzyskasz po wykonaniu każdej z trzech grup instrukcji: a. WINDOW b. FENCE c. WRAP CS RT 30 FD 500 CS RT 30 FD 500 CS RT 30 FD 500 Jak jest interpretowany ekran graficzny po uruchomieniu systemu AC-Logo? 3.2. Podaj słowne opisy algorytmów rysowania następujących figur: kwadrat prostokąta, trójkąta równoramiennego, trójkąta prostokątnego i innych. Zadania 103 3.3. Napisz programy do algorytmów ułożonych w zadaniu 3.2. 3.4. Wykorzystując instrukcję REPEAT narysuj figury z zadania 3.2 oraz różnego rodzaju rozety, których elementami będą te figury obracane wokół punktu. 3.5. Zaprojektuj ul i napisz program rysujący go. Staraj się postępować zgodnie z poznanymi zasadami; pamiętaj o niezmiennikach procedur. 3.6. Opisz procedurę rysowania okręgu o promieniu r. Wykorzystaj ją do spo- rządzenia innych rysunków, na przykład kółek olimpijskich, bałwanka, korali itp. 1.7. Wykorzystaj procedury z przykładu 3.2 i opisz następne tak, aby móc nary- sować zamek takiego kształtu jak na rys. 3.10. Rys. 3.10. Zamek 3.8. Opisz procedury zamalowania elementów wieży (zamku) zgodnie ze swoimi upodobaniami i wstaw ich wywołania w odpowiednie miejsca programu z zadania 3.7. Pewną propozycję wzorów sugeruje rysunek 3.10. 3.9. Uzupełnij opis procedury Spirala z przykładu 3.4 o dwa dodatkowe para- metry Kąt (zamiast 90) i Dodatek (zamiast 1). Sprawdź jej działanie dla różnych wartości parametrów aktualnych, w tym także dla liczb ujemnych. 3.10. Wzorując się na przykładzie 3.5 opisz procedury rekurencyjne, które rysują: kwadrat, dowolny n-kąt foremny, rozetę. Uzupełnij definicję procedury o nazwie RysujProstokąty tak, aby położenie żółwia było niezmiennikiem tej procedury. 3.11. Napisz program realizujący algorytm 3.3. Porównaj go z programem poda- nym w przykładzie 3.6. 3.12. Na podstawie rysunku 3.11 ułóż algorytm i napisz program, który narysuje płatek Kocha stopnia n o boku długości a jednostek. 104 3. Grafika żółwia Płatek Kocha ma trzy boki. Bok jest definiowany rekurencyjnie. Jeden bok o stopniu n > 0 i długości a jednostek składa się z czterech odpowiednio ułożonych boków, z których każdy ma stopień n - 1 i długość a / 3 jednostek. stopień 0 stopień 1 Rys. 3.11. Płatki Kocha stopień 2 3.13. Na podstawie rysunku 3.12 ułóż algorytm i zapisz go w postaci procedury rekurencyjnej, która rysuje drzewo binarne stopnia n. stopień 0 stopień 1 stopień 2 Rys. 3.12. Drzewa binarne stopień 3 3.14. Podaj algorytm i napisz program rysujący drzewo Pitagorasa stopnia n. Drzewem Pitagorasa stopnia 0 jest zamalowany kwadrat. Drzewo PitaJ gorasa stopnia 1 otrzymujemy przyjmując bok tego kwadratu za przeciwprcl stokątną trójkąta prostokątnego (o odpowiednio wybranych kątach), któregtj przyprostokątne są bokami dwu nowych, zamalowanych kwadratów. Dalej po, stępujemy podobnie z dorysowanymi kwadratami. Na rysunku 3.13 pokazani] drzewa Pitagorasa stopnia 4. Pierwsze narysowano wybierając równoramienni trójkąt prostokątny, a drugie - trójkąt o kątach: 90, 60 i 30 stopni. Zadania 105 Wskazówka: W sformułowaniu algorytmu może pomóc prześledzenie rysowa- nia drzew binarnych (rys. 3.12). Rys. 3.13. Drzewa Pitagorasa 3.15. Napisz ciąg procedur, które losują i umieszczają w liście dane reprezen- tujące n nieprzecinających się okręgów, a następnie rysują te okręgi. 3.16. Po wykonaniu procedury LosoweOkręgi zmienna Trójki przechowuje da- ne o narysowanych okręgach. Opisz funkcję, której wartością dla takiej listy są dane największego narysowanego okręgu. Zamaluj ten okrąg wybranym wzorem i wyświetl jego dane. 4. OD PROBLEMU DO PROGRAMU - ELEMENTY PROGRAMOWANIA W JĘZYKU PASCAL Różnorodność zastosowań komputerów wynika z możliwości wykonywania prze nie programów o różnym przeznaczeniu. Sztuka konstruowania programów sta nowi klucz do pełnego wykorzystywania możliwości komputerów. Korzystanii z gotowych programów nie wymaga umiejętności programowania, niemniej zna jomość pewnych zasad programowania może być znacznym ułatwieniem w po sługiwaniu się gotowym oprogramowaniem. Ponadto w dalszej perspektywie za stosowań komputerów, rozumienie podstawowych zagadnień związanych z gramowaniem umożliwia ocenę celowości i opłacalności ich użycia w konkretnycl sytuacjach. Poznawanie zasad rządzących programowaniem rozpoczęliśmy w poprzednim rozdziale. Ten rozdział stanowi kontynuację i rozszerzenie wcześniejszych r żań. Z punktu widzenia użytkownika posługiwanie się programem odbywa się dług schematu: DANE DZIAŁANIE PROGRAMU informacje podawane programowi przez użytkownika przetwarzanie informacji WYNIKI rezultaty działania programu Programista, czyli osoba pisząca program, ma za zadanie: - szczegółowo opracować komunikację programu z użytkownikiem, - precyzyjnie sformułować metodę, zgodnie z którą działanie programu pn wadzi od danych do pożądanych wyników. Dokładne ustalenie tego, co ma stanowić dane dla programu, a co wynilj jego działania, oraz jaki związek zachodzi między danymi i wynikami, nazywa s 4. Elementy programowania w języku Pascal 107 f specyfikacją problemu. Następnie należy określić sposób otrzymania wyników ! na podstawie danych, czyli metodę rozwiązania problemu. Kolejnym etapem jest opisanie metody w konkretnym języku programowania, czyli napisanie programu. Ostatni etap to sprawdzenie, czy program działa poprawnie, czyli zgodnie ze j specyfikacją. W naszych rozważaniach przywiązujemy dużą wagę do metod rozwiązywa- nia, gdyż nie każde zadanie, które stawia sobie człowiek, nadaje się do wykonania przez komputer. Zadanie odpowiednie dla komputera to takie, które daje się rozłożyć na ciąg pewnych prostych czynności (np. operacji arytmetycznych), wy- konywanych w ściśle określonej kolejności, zależnej być może od wartości danych. Przypomnijmy, że uściślony sposób rozwiązywania zadania zawierający precy- zyjny opis zarówno czynności, jak też porządku ich wykonywania, nazywamy algorytmem. Dla wielu zadań sam algorytm jest prosty, ale liczba wykonań po- szczególnych operacji w nim zawartych może być bardzo duża. W takich właśnie sytuacjach komputer jest niezwykle użyteczny, uwalniając nas od żmudnego po- wtarzania prostych czynności. Język programowania Logo, którym posługiwaliśmy się w rozdziale 3, jest dogodnym narzędziem do tworzenia prostej grafiki komputerowej. Umożliwia on również proste zapisywanie algorytmów i przystępne wprowadzanie pewnych pojęć dotyczących programowania. W tym rozdziale do zapisu algorytmów po- służy nam język Pascal. W przypadku tego języka możemy mówić o języku standardowym i konkretnych jego realizacjach dla komputerów różnych typów. W tym podręczniku nie wykraczamy w zasadzie poza standardową wersję języka, ale przytaczane programy (zwłaszcza programy umieszczone na dyskietce) są przygotowane z myślą o konkretnej realizacji. Jest nią język Turbo Pascal (w wersji 6.0) dostępny na komputerach IBM PC. W związku z tym objaśniając fragmenty programów zawierające elementy tej wersji języka, używamy terminu: język Turbo Pascal (w skrócie TP). Poza tym całkowicie pomijamy opis zintegro- wanego systemu oprogramowania Turbo Pascal, który pozwala pisać i uruchamiać programy w tym języku. Informacje te można znaleźć w książkach poświęconych temu systemowi. Naszym celem w tym rozdziale jest przedstawienie podstawowych konstrukcji stosowanych do zapisywania algorytmów w postaci programów. Konstrukcje te mają swoje odpowiedniki w większości języków programowania. Należą do nich instrukcje przedstawione w następnym punkcie oraz procedury i funkcje. Niektóre z opisanych poniżej instrukcji pojawiły się już w poprzednim rozdziale. Oma- wiamy je tutaj powtórnie lub odsyłamy do wcześniejszych fragmentów tekstu. Sposób działania i stosowania tych instrukcji w programach jest niezmienny, bez względu na wybrany język programowania. Zmianie ulega tylko ich zapis, czyli składnia. 108 4. Elementy programowania w języku Pascal 4.1. Podstawowe instrukcje 4.1.1. Wyprowadzanie tekstów Rozpoczniemy od bardzo prostego zadania polegającego na wydrukowaniu wi-J zytówki według następującego projektu: ' ****************************** * Jan Kowalski * * ul. Piwna 31 m 5 * * 48-300 NYSA * I ****************************** Algorytm drukowania wizytówki sformułujemy jako ciąg pięciu poleceń druko- wania kolejnych wierszy składających się na jej tekst i ramkę. Dla naszej wygody, a także by zaoszczędzić na czasie i papierze, wyniki działania większości naszych programów w języku Pascal (w tym również informacje dla użytkownika) będą wyświetlane na ekranie monitora. O sposobach drukowania wyników powiemy dalej w tym punkcie. Ponieważ różnice między poleceniami wyświetlania i dru- kowania są niewielkie, będziemy używać tych określeń zamiennie wraz z ogólniej- szym poleceniem wyprowadzania wyników. Oto gotowy tekst programu w języku Pascal. Przykład 4.1. Drukowanie wizytówki. PROGRAM Wizytówka; BEGIN WRITELNC'*******************************'); WRITELNC* Jan Kowalski *'); WRITELNC* ul. Piwna 31 m 5 *'); WRITELNC* 48-300 NYSA *'); WRITELNC'*******************************') END. {Wizytówka} Uwaga: Tekst programu Wizytówka znajduje się na dyskietce w pliku WIZYT.PAS umie- szczonym w kartotece R0ZDZ4. Program Wizytówka został napisany zgodnie z następującymi zasadami: 1. Tekst programu rozpoczyna się nagłówkiem programu, w którym pij słowie PROGRAM występuje nazwa1 programu i średnik. 'Nazwą w języku Turbo Pascal jest ciąg znaków rozpoczynający się od litery. Znakami dopuszczalnymi w nazwie są: litery, cyfry i znak podkreślenia. Nazwy, w których pierwsze 63 znaki są takie same, są traktowane jako identyczne. 4.1. Podstawowe instrukcje 109 2. Na początku ciągu instrukcji programu znajduje się słowo BEGIN, a na końcu - słowo END, po którym bezpośrednio występuje kropka. 3. Dwie kolejne instrukcje programu są oddzielane między sobą średnikiem. Słowa takie jak PROGRAM, BEGIN, END są słowami kluczowymi języka Pascal. Słowa kluczowe w języku programowania mają z góry określone i niezmienne zna- czenie. Słowo WRITELN jest nazwą procedury standardowej. Procedury tej, podobnie jak procedur pierwotnych w języku Logo, nie trzeba definiować. Zmiana definicji procedury standardowej jest dopuszczalna, ale nie będziemy korzystać z tej możliwości. W języku Pascal parametry aktualne procedury (por. p. 3.3) są podawane w nawiasach okrągłych po nazwie procedury i oddzielone między sobą przecinkami. W naszym programie procedura WRITELN ma tylko jeden pa- rametr. Jest nim ciąg znaków ujęty w apostrofy i nazywany napisem. Procedura WRITELN działa w ten sposób, że po wyprowadzeniu napisu powoduje dopisanie do wyników zmiany wiersza. Jeśli nie chcemy wyprowadzać zmiany wiersza, to używamy procedury standardowej WRITE. Użycie procedury WRITELN bez para- metrów powoduje, w zależności od kontekstu, wyprowadzenie pustego wiersza w wynikach lub zmianę wiersza po wynikach uprzednio wyprowadzonych przez procedurę WRITE. Zgodnie z powyższymi uwagami wynik działania instrukcji: WRITELN(>Jan Kowalski') jest taki sam jak ciągu instrukcji: WRITEOJan'); WRITE (' '); WRITELN ('Kowalski O lub: WRITE('Jan',? WRITELN ,'Kowalski'); Zauważmy, że: - w jednym wierszu można umieszczać kilka instrukcji; - w jednej instrukcji WRITE lub WRITELN może wystąpić dowolna liczba para- metrów aktualnych; - odstęp, czyli spacja wewnątrz napisu jest traktowany tak, jak każdy inny znak; - wewnątrz napisu nie można umieszczać zmiany wiersza. W tym miejscu zwróćmy także uwagę na rolę spacji i zmiany wiersza, zwanych separatorami, w tekście programu: - separatora nie można użyć wewnątrz słowa kluczowego, nazwy lub liczby; - co najmniej jeden separator musi wystąpić między dwoma sąsiadującymi ze sobą słowami kluczowymi, nazwami lub liczbami; 110 4. Elementy programowania w języku Pascal - w każdym innym miejscu programu separator służy jedynie zwiększeniu czytelności tekstu programu. Poprawianiu czytelności służą także wcięcia w tekście programu i komenta- rze. Komentarze zawierają zwykle informacje pozwalające lepiej rozumieć tekst i działanie programu i mogą występować w programie jako separatory. Tekst komentarza ujmujemy w nawiasy klamrowe. Podczas tłumaczenia komentarze są ignorowane przez kompilator2. Przykładem komentarza jest informacja umie- szczana przez nas po słowie END i objaśniająca fragment programu, który to słowo zamyka. Przypomnijmy również nasze redakcyjne ustalenia (zob. Wstęp). Programy i ich fragmenty w tekście lub wydzielone z tekstu są wydrukowane pismem ma- szynowym. Słowa kluczowe i nazwy procedur standardowych piszemy wielkimi literami, zaś inne nazwy - z reguły małymi literami, wyróżniając jedynie wielką literą początek słowa w nazwie. Ponadto w nazwach pomijamy znaki diakry- tyczne liter używane w języku polskim, gdyż system Turbo Pascal nie akceptuje liter charakterystycznych dla polskiego alfabetu. Aby sprawdzić na komputerze działanie programu z przykładu 4.1 należy za- inicjować działanie systemu Turbo Pascal, a następnie wykonać poniższe czyn- ności: 1. Wczytać plik o nazwie WIZYT.PAS z kartoteki R.0ZDZ4 znajdującej się na dyskietce dołączonej do podręcznika (zlecenie Open) lub utworzyć nowy plik (zlecenie New) i wpisać z klawiatury tekst programu Wizytówka; 2. Przetłumaczyć program, czyli skompilować go (zlecenie Compile); 3. Wykonać przetłumaczony program (zlecenie Run). Czytelnik, który wykona opisane powyżej czynności, zauważy, że efekt dzia- łania tak napisanego programu jest trudny do uchwycenia, gdyż po wykonaniu programu system Turbo Pascal automatycznie wyświetla swoją ofertę. Wyniki wyprowadzone przez program pozostają natomiast na ekranie użytkownika który można obejrzeć naciskając klawisze Alt F5 . Proponujemy zatem umie szczanie na końcu programów ciągu instrukcji, które w efekcie pozwolą obsei wować wyniki działania programu dowolnie długo. Również na początku działam programu warto wykonać pewne czynności, które - na przykład - spowoduj oczyszczenie ekranu i wyprowadzenie informacji o tym, co robi program. Opis tych czynności wstępnych i końcowych dołączymy w postaci definicji procedu: odpowiednio Start i Koniec. Pojęcie procedury jest nam znane z rozdziału 3. W języku Pascal inna je tylko składnia opisu procedury i miejsce umieszczenia go w tekście programu. 2Wyjątek stanowią dyrektywy, które również umieszczamy między nawiasami klamrowyi: ale rozpoczynamy je zawsze znakiem $. Kompilator nie ignoruje dyrektyw, gdyż są to paramel określające sposób kompilacji lub wykonania programu. 4.1. Podstawowe instrukcje 111 Program napisany w języku Pascal ma następującą strukturę: PROGRAM nazwa-programu; {część opisowa} deklaracje-i-definicje BEGIN {program główny} ciąg-instrukcji END. Część opisowa może być pusta (tak, jak w przykładzie 4.1) lub zawierać, na przykład, definicje procedur. Ciąg instrukcji w programie głównym także może być pusty. Mówimy wówczas, że treścią programu jest instrukcja pusta, której działanie nie daje żadnego efektu. Definicja procedury ma postać podobną do postaci programu, co zoba- czymy na poniższym przykładzie. Przykład 4.2. Definicja procedury Start. PROCEDURĘ Start; BEGIN CLRSCR; WRITELN('Drukowanie wizytówki.'); WRITELN; WRITELN END; {Start} a Ogólna struktura definicji (opisu) procedury jest następująca: PROCEDURĘ nazwa-proceduryCwykaz-parametrów-formalnych); {część opisowa} deklaracje-i-definicje BEGIN {treść procedury} ciąg-instrukcji END; Pierwszy wiersz opisu procedury nazywamy nagłówkiem procedury. Na- główek procedury oprócz słowa kluczowego PROCEDURĘ zawiera nazwę procedury i informacje o jej parametrach. W naszym przypadku wykaz parametrów for- malnych został pominięty, gdyż definiujemy procedurę bez parametrów. Część opisowa jest także pusta. Standardowa procedura CLRSCR, występująca w treści procedury Start, po- woduje usunięcie z ekranu wszystkich, znajdujących się na nim informacji. Dzięki temu wizytówka zostanie wyświetlona na oczyszczonym ekranie. Przyjrzyjmy się jeszcze definicji procedury Koniec. 4. Elementy programowania w języku Pascal 112 Przykład 4.3. Definicja procedury Koniec. PROCEDURĘ Koniec; BEGIN WRITELN; WRITELN; WRITELNCNacisnij klawisz ENTER.'); READLN END; {Koniec} Standardowa procedura READLN służy do czytania danych. Jeśli użyjemy je tak, jak w procedurze Koniec, bez parametrów, to spowoduje ona oczekiwanii na wprowadzenie dowolnego (w szczególności pustego) ciągu znaków z klawiatur] zakończonego naciśnięciem klawisza |Enter |. Dzięki temu procedura Koniei spełni postawione jej zadanie - pozwoli obserwować ekran użytkownika dowolni długo. Opiszmy również drukowanie wizytówki w postaci procedury, by móc odwo- ływać się do niej w następnych przykładach. Przykład 4.4. Definicja procedury DrukujWizytowkel. PROCEDURĘ DrukujWizytowkel; BEGIN WRITELNC'*******************************'); WRITELNC5* Jan Kowalski *'); WRITELNC* ul. Piwna 31 m 5 *'); WRITELNC* 48-300 NYSA *'); WRITELNC'*******************************') END; {DrukujWizytowkel} Program z przykładu 4.1, którego część opisowa zawiera definicje procedur StaJ Koniec i DrukujWizytowkel, przybiera następującą postać. | PROGRAM Wizytowkal; USES CRT; {W tym miejscu należy umieścić definicje procedur z przykładów 4.2, 4.3, 4.4.} BEGIN Start; {wywołanie procedury odbywa sie tak, jak w Logo} DrukujWizytowkel; Koniec END. {Wizytowkal} I i 1 Uwaga: Tekst programu Wizytowkal znajduje się na dyskietce w pliku WIZYT1.I umieszczonym w kartotece R0ZDZ4. I 4.1. Podstawowe instrukcje 113 Po nagłówku, na początku części opisowej występuje w tym programie nowa informacja w postaci deklaracji pakietu USES CRT. Oznacza ona, że program będzie korzystał z pakietu procedur standardowych o nazwie CRT, wśród których jest procedura CLRSCR. Procedura CLRSCR byłaby niedostępna dla programu bez tej deklaracji. Wszystkie procedury standardowe w języku Turbo Pascal są po- grupowane w pakietach. Niektóre z nich, takie jak procedury WRITE, WRITELN i READLN, znajdują się w wyróżnionym pakiecie o nazwie SYSTEM, którego nie trzeba deklarować w żadnym programie. Inne pakiety muszą być deklarowane, jeśli program z nich korzysta. Deklaracja użycia pakietów może wystąpić tylko raz w tekście programu, bezpośrednio po nagłówku. Składa się ona ze słowa klu- czowego USES i ciągu nazw pakietów oddzielonych przecinkami i zakończonego średnikiem. Pakiet może zawierać także procedury niestandardowe, czyli zdefiniowane przez użytkownika. Ogólnie pakiet jest zbiorem wydzielonych definicji i deklaracji (w tym także opisów procedur i funkcji), z których można korzystać w różnych programach. Jeśli pakiet został zdefiniowany i chcemy skorzystać z jego procedur, to zamiast ich opisów w programie wystarczy po słowie USES umieścić nazwę tego pakietu. 4.1.2. Czytanie danych z klawiatury, zmienna, instrukcja warunkowa Załóżmy teraz, że projektujemy drugą wizytówkę, zawierającą informacje o miej- scu pracy i modyfikujemy nasz program tak, aby drukował jedną z dwóch, wy- braną przez nas wizytówkę. Projekt drugiego wzoru wizytówki może wyglądać następująco: ********************************* * Jan Kowalski * Biuro Turystyczne ODRA * ul. Wojska Polskiego 13 * 45-752 OPOLE * tel.345-64 w.23 * * * * * ********************************* Wyboru będziemy dokonywać naciskając klawisz oznaczony cyfrą 1 lub 2. Opi- szmy algorytm realizujący to zadanie. Algorytm 4.1. Drukowanie wizytówki. Dane: liczba 1 lub 2. Wyniki: wizytówka wyświetlona według pierwszego lub drugiego projektu. 1. Czytaj i zapamiętaj daną. 8 — Elementy informatyki 114 4. Elementy programowania w języku Pascal 2. Jeśli daną jest liczba 1, drukuj wizytówkę według pierwszego projektu, jeśli daną jest liczba 2, drukuj wizytówkę według drugiego projektu, a w prze- ciwnym przypadku zakończ działanie algorytmu. Zatrzymamy się przy pierwszym kroku algorytmu 4.1. Pojawia się tu pro- blem pamiętania informacji w programie. W rozdziale 3 pokazaliśmy, że do tego celu służą zmienne. Dodajmy w tym miejscu, że pojęcie zmiennej pojawiło się wcześniej w matematyce. W informatyce i w matematyce z każdą zmienną jest związany zbiór wartości, które może ona przyjmować. W informatyce zbiór ten nazywamy typem zmiennej. Różnica polega na tym, że w matematyce zmienna nie ma konkretnej wartości, a raczej jest symbolem całej klasy wartości, natomiast w informatyce (a dokładniej w programowaniu) zmienną zawsze kojarzymy z jej bieżącą wartością. Z tego względu interesują nas sposoby nadawania wartości zmiennej, zmieniania tej wartości i odwoływania się do niej. Bardzo ważne jest określenie rodzaju informacji przypisywanej zmiennej, któ- ry decyduje o jej typie. Język Pascal wymaga określenia typu wszystkich zmien- nych używanych w programie. Deklaracje zmiennych umieszczamy po dekla- racji użycia pakietów w części opisowej programu. Oto deklaracja zmiennej Numer, którą użyjemy do pamiętania jednej z dwóch liczb 1 lub 2. VAR Numer:INTEGER; Słowo INTEGER jest nazwą standardowego typu całkowitego i oznacza, w przy- padku języka Turbo Pascal, zbiór liczb całkowitych z przedziału [-32768,32767] Ogólnie deklaracja zmiennych ma postać - następującego po słowie kluczowym VAR - wyliczenia zmiennych wraz z opisem ich typów. Podajemy nazwę zmiennej, dwukropek i nazwę lub określenie jej typu. Jeśli występuje kilka zmiennych tego samego typu, ich nazwy rozdzielamy przecinkami, a tekst pojedynczej deklaracji kończymy średnikiem, na przykład: VAR a,b:INTEGER; Nadawanie (zwane także przypisywaniem) wartości zmiennej może odbywać się na kilka sposobów. Jeden z nich polega na skojarzeniu nazwy i wartości podczas czytania danych. Zobaczmy, jak to się odbywa w poniższym programie realizującym algorytm 4.1. PROGRAM Wizytowka2; USES CRT; VAR Numer:INTEGER; {W tym miejscu należy umieścić definicje procedur opisanych w przykładach 4.2, 4.3 i 4.4.} 4.1. Podstawowe instrukcje 115 PROCEDURĘ DrukujWizytowke2; BEGIN WRITELNC>*********************************'); WRITELNC* Jan Kowalski *'); WRITELNC* Biuro Turystyczne ODRA *'); WRITELNC* ul. Wojska Polskiego 13 *'); WRITELNC* 45-752 OPOLE *'); WRITELNC* tel.345-64 w.23 *'); WRITELNC>*********************************>) END; {DrukujWizytowke2> BEGIN Start; WRITECPodaj z klawiatury numer wizytówki, która '); WRITELNC chcesz drukować (1 lub 2).'); READLNCNumer); IF Numer=l THEN DrukujWizytowkel ELSE IF Numer=2 THEN DrukujWizytowke2; Koniec END. {Wizytowka2} Uwaga: Tekst programu Wizytowka2 znajduje się na dyskietce w pliku WIZYT2.PAS umieszczonym w kartotece R0ZDZ4. Program Wizytowka2 po oczyszczeniu ekranu powoduje wyświetlenie tekstu, zapraszającego do wprowadzenia danej. Informacje takie ułatwiają korzystanie z programów i warto pamiętać o nich pisząc własne programy. Stanowią one istotny element komunikacji programu z użytkownikiem. Dalej znajduje się reali- zacja kolejnych kroków algorytmu 4.1. Do czytania informacji z klawiatury służy procedura standardowa READLN. Parametrami tej procedury są nazwy zmiennych. Tym zmiennym są przypisywane kolejne wartości danych podawane z klawia- tury. W naszym przypadku zmiennej Numer zostaje przypisany numer wybra- nej wizytówki, a następnie pojawia się w programie instrukcja warunkowa (por. p. 3.6) w postaci: IF warunek THEN instrukcjal ELSE instrukcja2 gdzie warunek jest wyrażeniem logicznym (zob. p. 3.6), a instrukcjal i instruk- cja2 oznaczają dowolne instrukcje. Instrukcja warunkowa jest wykonywana zgo- dnie z zasadą znaną z rozdziału 3. Przypomnijmy: jeżeli warunek jest spełniony, to jest wykonywana instrukcjal, a jeżeli nie jest spełniony, to jest wykonywana instrukcja2. Instrukcja ta umożliwia wybór jednej z dwu dróg w działaniu pro- gramu, w zależności od spełnienia podanego warunku. 116 4. Elementy programowania w języku Pascal W języku Pascal istnieje również uproszczona wersja instrukcji warunkowej: IF warunek THEN instrukcja której działanie znamy także z poprzedniego rozdziału. 4.1.3. Instrukcje powtarzania, drukowanie wyników Ponieważ wizytówki są przydatne zazwyczaj w większej liczbie, kolejna mody- fikacja naszego zadania będzie polegała na wydrukowaniu na drukarce tylu wi- zytówek, ile będziemy potrzebować. Dla uproszczenia przyjmujemy ponownie, że mamy tylko jeden wzór wizytówki. Sformułujmy algorytm. Algorytm 4.2. Drukowanie dowolnej liczby wizytówek. Dane: liczba potrzebnych wizytówek. Wyniki: wydrukowane wizytówki. 1. Przeczytaj i zapamiętaj liczbę potrzebnych wizytówek. 2. Ustal wartość licznika drukowanych wizytówek równą jeden. 3. Dopóki licznik jest nie większy od liczby potrzebnych wizytówek, powtarzaj | kroki 4 i 5, a następnie zakończ działanie algorytmu. 4. Wydrukuj wizytówkę. 5. Zwiększ wartość licznika o 1. Zauważmy, że algorytm 4.2 polega na powtarzaniu pewnych czynności tą długo, dopóki jest spełniony określony warunek. Dla zapisania tego algorytmu posłużymy się instrukcją powtarzania WHILE: WHILE warunek DO instrukcja gdzie warunek i instrukcja mają takie samo znaczenie jak w opisanej wcześniej instrukcji warunkowej. Działanie tej instrukcji powtarzania jest następujące: - dopóki warunek jest spełniony, to powtarzane jest wykonanie instrukcji in- strukcja, - gdy warunek nie jest spełniony, to działanie instrukcji WHILE kończy się. W szczególności instrukcja może być instrukcją złożoną. Instrukcja złożona! składa się z ciągu instrukcji poprzedzonego słowem BEGIN i zakończonego słoweml END. Działanie tej instrukcji polega na wykonaniu kolejno wszystkich instrukcjij występujących w ciągu. Aby instrukcja WRITELN (lub WRITE) wyprowadzała wyniki programu na dr karkę, należy jako pierwszy jej parametr aktualny umieścić nazwę standardom LST, a po nagłówku programu zadeklarować standardowy pakiet PRINTER. 0 I nych sposobach drukowania dowiemy się w punkcie 5.1. Przyjmujemy, że komu] nikaty dla użytkownika są nadal wyświetlane na ekranie monitora. Oto tek programu realizującego algorytm 4.2. 4.1. Podstawowe instrukcje 117 PROGRAM Wizytowka3; USES CRT,PRINTER; VAR Ile,Licznik:INTEGER; ?[W tym miejscu należy umieścić definicje procedur Start i Koniec z przykładów 4.2 i 4.3.} PROCEDURĘ DrukujWizytowkel; {Jest to zmieniona wersja procedury z przykładu 4.4, umożliwiająca wyprowadzenie wizytówek na drukarkę.} BEGIN WRITELNCLST,'*******************************'); WRITELNCLST,'* Jan Kowalski *'); WRITELNCLST,'* ul. Piwna 31 m 5 *'); WRITELNCLST,'* 48-300 NYSA *'); WRITELNCLST,>*******************************') END; {DrukujWizytowkel} BEGIN Start; WRITELNC'Podaj liczbę potrzebnych Ci wizytówek.'); READLNCHe) ; IF Ile>0 THEN BEGIN WRITELNC'Włącz drukarkę i nacisnij ENTER.'); READLN END; Licznik:=1; WHILE Licznik<=Ile DO BEGIN DrukujWizytowkel; Licznik:=Licznik+l END; {WHILE} Koniec END. {Wizytowka3} Uwaga: Tekst programu Wizytowka3 znajduje się na dyskietce w pliku WIZYT3.PAS umieszczonym w kartotece R0ZDZ4. Nową instrukcją użytą w programie Wizytowka3 jest instrukcja przypisa- nia. Służy ona do nadawania wartości zmiennej. Jest to drugi obok czytania sposób powiązania wartości z nazwą zmiennej. Znaczenie instrukcji przypisania jest takie, jak instrukcji MAKE w języku Logo, tylko składnia jest inna. Do za- pisania tej instrukcji w języku Pascal używa się symbolu przypisania złożonego z dwóch znaków (dwukropka i znaku równości): nazwa-zmiennej := wyrażenie 118 4. Elementy programowania w jeżyku Pascal W trakcie wykonywania tej instrukcji zostaje obliczona wartość wyrażenia stoją- cego po prawej stronie symbolu przypisania :=, a następnie wartość ta zostaje I nadana zmiennej, której nazwa znajduje się po lewej stronie tego symbolu. Przyj-J mujemy, że wartość wyrażenia jest tego samego typu co zmienna3. Prześledźmy zmiany wartości zmiennej Licznik w czasie wykonywania ko-J lejnych instrukcji przypisania w powyższym programie. Na początku zostaje jej| przypisana wartość 1 za pomocą instrukcji: Licznik:=l W każdej iteracji instrukcji powtarzania jest wykonywana instrukcja: Licznik:=Licznik+l W przypadku drukowania trzech wizytówek zmienna Licznik przyjmuje wartości! Wartość zmiennej Warunek Działanie instrukcji Licznik powtarzania Licznik:=Licznik+l 1 1 <= 3 Licznik:=l+1 2 2 <= 3 Licznik:=2+1 3 3 <= 3 Licznik:=3+1 4 4<=3 warunek nie jest spełniony - zakończenie działania instrukcji Do konstruowania wyrażeń arytmetycznych (por. p. 3.4), których warto ciami są liczby całkowite, możemy używać następujących działań - obok poc jemy odpowiadające im operatory w języku Pascal: dodawanie + odejmowanie mnożenie * dzielenie całkowite DIV (np. 7 DIV 3 = 2) obliczanie reszty z dzielenia MOD (np. 10 MOD 3 = 1) Operatorami relacji występującymi w wyrażeniach logicznych są symbole: W matematyce W języku Pascal O <= >= 3Ogólnie wartość wyrażenia powinna być typu zgodnego z typem zmiennej. Zgodność typów jest omawiana w większości podręczników języka Pascal. t I 4.1. Podstawowe instrukcje 11!) Połączymy możliwości dwóch ostatnich programów tak, abyśmy mogli wy- brać zarówno wzór, jak i liczbę drukowanych wizytówek. Na tym przykładzie zademonstrujemy także działanie instrukcji powtarzania typu FOR. Instrukcje po- wtarzania w językach programowania służą realizacji pętli, czyli czynności wielo- krotnie powtarzanych. Organizacja pętli zależy od tego, czy znamy z góry liczbę powtórzeń czynności, czy też po każdym wykonaniu czynności należy sprawdzić warunek decydujący o zakończeniu powtarzania. Działanie poznanej instrukcji WHILE odpowiada drugiej sytuacji. W przypadku drukowania wizytówek liczba powtórzeń odpowiednich czynności jest jednak z góry określona, można więc za- stosować następującą instrukcję: FOR zmienna-sterująca:=wartość-początkowa TO wartość-końcowa DO instrukcja gdzie zmienna-sterująca jest nazwą pomocniczej zmiennej, a wariość-początkowa i wartość-końcowa są wyrażeniami, których wartości są obliczane przed wyko- naniem instrukcji FOR. Zmienna sterująca przyjmuje kolejne wartości całkowite począwszy od wartości początkowej aż do osiągnięcia wartości końcowej. Dla każdej wartości tej zmiennej jest wykonywana instrukcja, która może być po- jedynczą instrukcją lub instrukcją złożoną. Jeśli wartość początkowa zmiennej sterującej jest większa od wartości końcowej, to instrukcja nie zostanie wykonana ani razu. Nieraz jednak potrzeba, aby wartości zmiennej sterującej malały, a nie rosły. Wówczas można użyć instrukcji FOR, w której zamiast słowa kluczowego TO należy wpisać słowo DOWNTO i zamienić miejscami (czyli także rolami) wartość-początkową z wartością-końcową. W naszym przypadku zmienną sterującą będzie zmienna Licznik i możemy zilustrować użycie obu rodzajów instrukcji FOR, gdyż przy drukowaniu ustalonej liczby wizytówek jest istotna tylko liczba powtórzeń, a nie wartości zmiennej sterującej. PROGRAM Wizytowka4; USES CRT.PRINTER; VAR Licznik,Numer,Ile:INTEGER; {W tym miejscu należy umieścić definicje procedur: Start z przykładu 4.2, Koniec z przykładu 4.3, DrukujWizytowkel z programu Wizytowka3.} PROCEDURĘ DrukujWizytowke2; {Jest to zmieniona wersja procedury z programu Wizytowka2 umożliwiająca wyprowadzenie wizytówek na drukarkę.} 120 4. Elementy programowania w jeżyku Pascal BEGIN WRITELNCLST,>*********************************>); I Jan Kowalski Biuro Turystyczne ODRA ul. Wojska Polskiego 13 45-752 OPOLE tel.345-64 w.23 *'); *'); *'); *'); WRITELNCLST,'* WRITELNCLST,'* WRITELNCLST,'* WRITELNCLST,'* WRITELNCLST,'* WRITELNCLST, END; {DrukujWizytowke2> BEGIN Start; WRITECPodaj numer wizytówki, która chcesz '); WRITELNC'wydrukować Cl lub 2).'); READLNCNumer); WRITELNC'Podaj liczbę potrzebnych Ci wizytówek.'); READLNCHe); IF Ile>0 THEN BEGIN WRITELNC'Wlacz drukarkę i nacisnij ENTER.'); READLN END; IF Numer=l THEN FOR Licznik:=1 TO Ile DO DrukujWizytowkel ELSE IF Numer=2 THEN FOR Licznik:=Ile DOWNTO 1 DO DrukujWizytowke2; Koniec END. {Wizytowka4> I i j Uwaga: Tekst programu Wizytowka4 znajduje się na dyskietce w pliku WIŻYT4.PAS umieszczonym w kartotece R0ZDZ4. Jeśli chcielibyśmy skorzystać z powyższego programu, by po wydrukowaniu wizytówek według jednego wzoru wydrukować następne według drugiego wzoru, to musimy uruchomić program powtórnie. Podamy teraz sposób zorganizowania pętli tak, aby czynność była powtarzana przez program, dopóki użytkownik nie zadecyduje o zakończeniu działania programu. W tym celu wykorzystamy trzecią,, stosowaną w języku Pascal instrukcję powtarzania, która ma postać: REPEAT ciąg-instrukcji UNTIL warunek Jej działanie jest następujące: — ciąg-instrukcji jest powtarzany, dopóki warunek nie jest spełniony, - gdy warunek jest spełniony, to działanie instrukcji kończy się. 4. Elementy programowania w języku Pascal 121 Zwróćmy uwagę na to, że warunek jest sprawdzany po raz pierwszy po wyko- naniu instrukcji tworzących dąg-instrukcji. Jest to jedna z cech odróżniających instrukcję REPEAT od instukcji WHILE. Instrukcja REPEAT w powyższej postaci jest równoważna ciągowi instrukcji: dąg-instrukcji; WHILE NOT warunek DO BEGIN ciąg-instrukcji END Przyjmijmy w naszym zadaniu, że warunek w instrukcji REPEAT ma być speł- niony, gdy użytkownik chce zakończyć pracę programu. Aby skonstruować taki warunek program musi zadać odpowiednie pytanie użytkownikowi, wczytać jego odpowiedź i ustalić wartość logiczną wyrażenia. Wartości przyjmowane przez wyrażenia logiczne, czyli TRUE (prawda) i FALSE (fałsz), tworzą standardowy typ logiczny o nazwie BOOLEAN. Wyrażenia logiczne mogą składać się z wartości logicznych, relacji, zmiennych typu BOOLEAN, wywołań funkcji logicznych oraz operatorów AND (koniunkcji), OR (alternatywy) i NOT (negacji). W naszym przy- padku zdefiniujemy funkcję logiczną JuzKoniec, której wartość będzie zależała od decyzji użytkownika (kontynuować czy zakończyć pracę). Do wczytania odpowiedzi użytkownika posłuży nam zmienna typu znako- wego. Standardowy typ znakowy o nazwie CHAR tworzą znaki dostępne z kla- wiatury, które zapisujemy w pojedynczych apostrofach. Należy rozróżnić dwie sytuacje: Liczba:=1 Znak:='l> Wartością zmiennej Liczba jest liczba 1, a wartością zmiennej Znak jest znak 1. W programie są to dwie różne wielkości, dwóch różnych typów. A oto definicja potrzebnej nam funkcji. Przykład 4.5. Definicja funkcji logicznej JuzKoniec. FUNCTION JuzKoniec:BOOLEAN; VAR Odp:CHAR; BEGIN WRITELN; WRITELN; WRITECCzy chcesz kontynuować prace z programem? (t/n)'); READLN(Odp); IF (Odp='t') OR (Odp='T') THEN JuzKoniec:=FALSE ELSE JuzKoniec:=TRUE END; {JuzKoniec} B Ogólna struktura definicji (opisu) funkcji jest bardzo podobna do struk- tury opisu procedury (zob. p. 4.1.1) i ma następującą postać. 122 4. Elementy programowania w języku Pascal FUNCTION nazwa-funkcji(wykaz-parametrów-formalnych): nazwa-typu-wartości-funkcji; {część opisowa} deklaracje-i-definicje BEGIN {treść funkcji} ciąg-instrukcji END; Opis funkcji odróżnia się od opisu procedury postacią nagłówka (zmiana słowaj kluczowego i wystąpienie określenia typu wartości funkcji), ale najważniejszą różnica polega na tym, że w treści funkcji musi wystąpić instrukcja przypU sania wartości funkcji jej nazwie. Jest to odpowiednik instrukcji OP w języ ku Logo. Dzięki temu wywołanie funkcji, czyli użycie jej nazwy w wyrażeni! oznacza odwołanie się do obliczonej wartości tej funkcji. W naszym przykładzi| wystąpienie nazwy JuzKoniec w zamieszczonym poniżej programie Wizytowka5] jest równoważne odwołaniu się do konkretnej wartości logicznej. W definicji z przykładu 4.5 brak jest wykazu parametrów formalnych, bo jest to funkcja bez parametrów. Natomiast w części opisowej pojawiła się deklaracja zmiennej Odp. Zmienne deklarowane w definicji procedury lub funkcji nazywamy zmiennymi lokalnymi tej procedury lub funkcji. Wartości zmiennych lokalnych są dostępne tylko w treści procedury, w której zostały zadeklarowane. Zmienne deklarowane w części opisowej programu, po deklaracji użycia pakietów nazy- wamy zmiennymi globalnymi, gdyż ich wartości są dostępne w każdym miej- scu programu. Wyjątek stanowi sytuacja, gdy w definicji procedury lub funkcji została zadeklarowana zmienna lokalna o tej samej nazwie co zmienna globalna, Wówczas w treści procedury jest dostępna tylko zmienna lokalna. Poniżej zamieszczamy ostatnią już modyfikację programu drukującego wizy- tówki. PROGRAM Wizytowka5; USES CRT,PRINTER; VAR Licznik,Numer,Ile:INTEGER; {W tym miejscu należy umieścić definicje procedur: Start z przykładu 4.2, DrukujWizytowkel z programu Wizytowka3, DrukujWizytowke2 z programu Wizytowka4, JuzKoniec z przykładu 4.5.} BEGIN REPEAT Start; WRITE('Podaj numer wizytówki, która chcesz '); WRITELNCwydrukować (1 lub 2).'); 4.1. Podstawowe instrukcje 123 READLN(Numer); WRITELNCPodaj liczbę potrzebnych Ci wizytówek.'); READLN(Ile); IF Ile>0 THEN BEGIN WRITELNCWlacz drukarkę i nacisnij ENTER.'); READLN END; IF Numer=1 THEN FOR Licznik:=1 TO Ile DO DrukujWizytowkel ELSE IF Numer=2 THEN FOR Licznik:=Ile DOWNTO 1 DO DrukujWizytowke2; UNTIL JuzKoniec END. {Wizytowka5} Uwaga: Tekst programu Wizytowka5 znajduje się na dyskietce w pliku WIZYT5.PAS umieszczonym w kartotece R0ZDZ4. Instrukcje powtarzania mogą spowodować powstanie w programie pętli nie- skończonej, gdy wyrażenie logiczne opisujące warunek zakończenia działania instrukcji WHILE lub REPEAT stale przyjmuje wartość umożliwiającą powtarzanie instrukcji (ciągu instrukcji) lub gdy w instrukcji FOR zaburzeniu uległy zmiany wartości zmiennej sterującej. Taka sytuacja, jeśli nie panujemy nad nią, jest trak- towana jako błąd programisty. Program, którego działania nie można świadomie zakończyć, nie jest interesujący z praktycznego punktu widzenia. Ogromnie waż- ną sprawą jest zatem uzyskanie pewności, że napisany przez nas program jest pozbawiony tego rodzaju błędów. Na zakończenie tego punktu wymieńmy podstawowe instrukcje omówione do- tychczas w tym rozdziale, służące do zapisywania algorytmów w postaci progra- mów w języku Pascal: - instrukcja procedury, czyli wywołanie procedury, - instrukcja przypisania, - instrukcje warunkowe, - instrukcja złożona, - instrukcje powtarzania, - instrukcja pusta. Używaliśmy również procedur standardowych służących do wyprowadzania wyników i wprowadzania danych oraz procedur i funkcji przez nas zdefiniowa- nych, które ułatwiły opisanie często wykonywanych czynności i uczyniły teksty programów bardziej przejrzyste. Więcej informacji o procedurach i funkcjach znajduje się w następnych punktach. 124 4. Elementy programowania w języku Pascal 4.2. Od problemu do programu Poznaliśmy podstawowe instrukcje użyteczne przy formułowaniu algorytmów. Spróbujmy teraz prześledzić na wybranym przykładzie drogę od postawienia pro- blemu do napisania gotowego do wykonania programu. Naszym przykładowym problemem będzie znajdowanie największego wspólnego dzielnika dwóch niezero wych liczb naturalnych. Oznaczmy te liczby przez a i b, a ich największy wspólny dzielnik przez NWD(a,&). Pierwszy i najprostszy pomysł to postępowanie w myśl reguły: Sprawdzaj podzielność liczb a i b przez kolejne liczby naturalne począwszy od 1 aż do uzyskania największej, jednocześnie dzielącej je obie. Zakończ sprawdzanie po osiągnięciu mniejszej z liczb a i b. Uściślijmy podany opis tak, by umożliwiał napisanie programu. Zastanówmyj się, jakie informacje musimy pamiętać w programie. Na pewno są to liczby a i i dla których szukamy największego wspólnego dzielnika, ponadto bieżąca w danej chwili liczba (oznaczmy ją przez d), dla której sprawdzamy podzielność, i bieżą największy wspólny dzielnik (oznaczmy go przez wsp). Sprawdzanie podzielnoś| polega na badaniu reszty z dzielenia - jeśli reszta jest zerem, to odpowiedź je pozytywna. Zapiszmy teraz algorytm oparty na powyższych spostrzeżeniach. Algorytm 4.3. Szukanie największego wspólnego dzielnika dwóch liczb. Dane: niezerowe liczby naturalne a i b. Wynik: NWD(a,6). 1. Czytaj liczby a i b. 2. Ustal wartość zmiennych d i wsp na 1. 3. Dopóki wartość d nie jest większa od wartości a lub 6, powtarzaj czynnoś(j opisane w krokach 4 i 5, następnie przejdź do kroku 6. 4. Jeżeli reszty z dzielenia a oraz b przez d są równe zero, to nadaj zmiennej wsp wartość zmiennej d. 5. Zwiększ wartość zmiennej d o jeden. 6. Drukuj wartość wsp. Ponieważ program komputerowy jest jedynie formą zapisu algorytmu, ktÓ! jest głównym ogniwem na drodze od problemu do programu, proponujemy zapis* nie powyższego algorytmu w języku Pascal jako samodzielne ćwiczenie (zad. 4.1), Dla nas bardziej interesującym zagadnieniem jest projektowanie, odkryw; nie nowych algorytmów oraz ulepszanie już znanych. Kontynuując rozważani nad algorytmem znajdowania największego wspólnego dzielnika dwóch liczb, za-' uważmy, że w pewnych przypadkach algorytm 4.3 jest bardzo pracochłonny. Na przykład dla liczb 12346 i 12348 zostanie wykonanych 2 • 12346 operacji obli- czenia reszty z dzielenia. Pomimo dużej szybkości działania komputera zajmie 4.2. Od problemu do programu 125 to dłuższą chwilę. W praktyce, zwłaszcza w przypadku programów wielokrot- nie uruchamianych, jest ważne, aby umożliwiały one wykonanie obliczeń w jak najkrótszym czasie. Przedstawimy inny o wiele szybszy algorytm znajdowania największego wspólnego dzielnika dwóch liczb. Jest to współczesna wersja zna- nego już w starożytności algorytmu, który został opisany przez Euklidesa w jego fundamentalnym dziele Elementy. Algorytm 4.4. Algorytm Euklidesa znajdowania największego wspólnego dziel- nika dwóch liczb. Dane: niezerowe liczby naturalne a i b. Wynik: NWD(o,6). 1. Czytaj liczby a i b. 2. Dopóki a i b są większe od zera, powtarzaj krok 3, a następnie przejdź do kroku 4. 3. Jeśli a jest większe od b, to weź za a resztę z dzielenia a przez b, w prze- ciwnym razie weź za b resztę z dzielenia b przez a. 4. Przyjmij jako największy wspólny dzielnik tę z liczb a i b, która pozostała większa od zera. 5. Drukuj NWD(a,6). W przypadku algorytmu 4.3, sposób jego działania jest dość naturalny. Tym razem nie jest tak oczywiste, że dla dowolnych liczb naturalnych a i b wynik będzie poprawną wartością NWD(a, 6). A jaką mamy pewność, że algorytm 4.4 w ogóle zakończy swoje działanie? Poprawność i skończoność działania algorytmu Euklidesa wynikają z nastę- pujących dwóch faktów: 1. Prawdziwe jest twierdzenie mówiące, że dla liczb naturalnych a i b spełniających warunek a > b > 0, największe wspólne dzielniki liczb a i b oraz reszty z dzielenia a przez b i liczby b są sobie równe. Stosując przyjęte oznaczenia, fakt ten możemy zapisać w następującej postaci NWD(a, b) =NWD(a mod b, b) dla a > b > 0, gdzie wartość operacji a mod b jest resztą z dzielenia a przez b. Wynika stąd, że w każdym kroku algorytmu 4.4, największy wspólny dzielnik bieżących wartości a i b jest taki sam jak dla ich wartości początkowych. 2. Ciąg kolejnych liczb, które stają się wartościami a i b, jest malejący. Wynika to stąd, że reszta z dzielenia jest zawsze mniejsza od dzielnika. Ponadto wszystkie działania są wykonywane na liczbach naturalnych. Ponieważ nie można w nieskończoność wypisywać coraz to mniejszych liczb naturalnych, musimy kiedyś otrzymać zero. A to oznacza koniec działania algorytmu. 126 4. Elementy programowania w jeżyku Pascal Po tych rozważaniach podamy algorytm Euklidesa w postaci programu o na- zwie Euklides. Na początku zauważmy, że obliczanie największego wspólnego! dzielnika dwóch liczb możemy potraktować jako liczenie wartości funkcji, któral parze liczb naturalnych a i b przyporządkowuje ich największy wspólny dzielnik,! Zdefiniujmy więc odpowiednią funkcję o nazwie nwd, realizującą kroki od 2 do 4| algorytmu 4.4. Przykład 4.6. Definicja funkcji nwd. FUNCTION nwd(a,b:INTEGER):INTEGER; BEGIN WHILE (a>0) AND (b>0) DO IF a>b THEN a:=a MOD b ELSE b:=b MOD a; nwd:=a+b END; {nwd} W realizacji kroku 4 skorzystaliśmy ze spostrzeżenia, że jeśli tylko jedna z liczbl naturalnych a i b jest większa od zera, to jej wartość jest dokładnie równa a + b\ Po raz pierwszy zdefiniowaliśmy funkcję z parametrami. Przypomnijmy, zarówno opis funkcji jak i opis procedury może zawierać wykaz parametrów formalnych, który jest ujęty w nawiasy okrągłe i umieszczony w nagłówku nazwie funkcji lub procedury (zob. p. 4.1.1 i p. 4.1.3). W nawiasach podajemyl nazwy i typy parametrów, stosując te same zasady, które obowiązują przy dekla-| rowaniu zmiennych. W programie Euklides wprowadzimy ogólniejszą definicję procedury Start,| Przykład 4.7. Definicja procedury Start - wersja z parametrem. PROCEDURĘ Start(Tytuł:STRING); BEGIN CLRSCR; WRITELN(Tytuł); WRITELN; WRITELN END; {Start} Opis procedury rozszerzyliśmy o parametr, w miejsce którego będziemy umie- szczać tytuł programu. Pozwoli to na stosowanie tej procedury w dowolnym pro| gramie. Tytuł programu jest tekstem lub inaczej - napisem. W języku Turb Pascal do pamiętania napisów służą zmienne standardowego typu napisoweg o nazwie STRING. Po słowie STRING w nawiasach kwadratowych możemy poda liczbę określającą maksymalną liczbę znaków w napisie. Jeśli jej nie podamy, jest przyjmowane, że napis może mieć co najwyżej 256 znaków. Oto tekst programu realizującego algorytm 4.4. 4.2. Od problemu do programu 127 PROGRAM Euklides; USES CRT; VAR a,b:INTEGER; {W tym miejscu należy umieścić definicje procedury i funkcji: Start z przykładu 4.7, nwd z przykładu 4.6, JuzKoniec z przykładu 4.5.} BEGIN REPEAT StartC******* NAJWIĘKSZY WSPÓLNY DZIELNIK *******>); WRITELN ('---------------------Czytanie danych--------------------'); WRITELN('Podaj dwie niezerowe liczby naturalne: '); WRITE('a= '); READLN(a); WRITE('b= '); READLN(b); IF NOT ((a>0) AND (b>0)) THEN WRITELN('ZLE DANE') ELSE BEGIN WRITELN; WRITELN ('---------------------------Wyniki----------------------------') ; WRITELN('Największym wspólnym dzielnikiem liczb '); WRITELNCa,' i ',b,' jest liczba ',nwd(a,b),'.') END {ELSE} UNTIL JuzKoniec END. {Euklides} Uwaga: Tekst programu Euklides znajduje się na dyskietce w pliku EUKLIDES.PAS umieszczonym w kartotece R0ZDZ4. W tym programie zawarliśmy po raz pierwszy badanie poprawności wczy- tywanych danych. Liczby a i b muszą być nie mniejsze od zera, gdyż tylko dla takich liczb jest określone działanie algorytmu 4.4. Liczby te powinny być także nie większe od liczby 32767, która jest ograniczeniem górnym dla wartości liczb typu INTEGER reprezentowanych w języku Turbo Pascal. Nie sprawdzamy ? jednak, czy zostało przekroczone to ograniczenie, gdyż program zawiesi swoje działanie bez naszej ingerencji, jeśli liczba czytana przez procedurę READLN jest ; spoza tego zakresu. Zwróćmy uwagę, że czytanie danych i sprawdzenie ich po- prawności oraz drukowanie wyniku zostały umieszczone poza treścią funkcji nwd, gdyż czynności te nie są istotne dla obliczeń realizujących algorytm Euklidesa. Zauważmy jeszcze, że za pomocą procedury standardowej WRITELN możemy dru- I kować nie tylko ciągi znaków, ale także wartości zmiennych, funkcji i wyrażeń, np. instrukcja WRITELN (nwd (a, b)) drukuje liczbę, która jest wartością funkcji inwd obliczoną dla danych liczb a i b. 128 4. Elementy programowania w języku Pascal Jednym z zastosowań programu obliczania największego wspólnego dzielni jest wykonywanie działań arytmetycznych na ułamkach, np. skracanie, które oma wiamy w następnym punkcie. 4.3. Funkcje i procedury WTykorzystamy teraz obliczanie największego wspólnego dzielnika do skracani; ułamka. Dla ułatwienia zajmiemy się tylko ułamkiem dodatnim. Danymi są dwif liczby naturalne reprezentujące licznik i mianownik ułamka, a wynikiem mi być licznik i mianownik nieskracalnego ułamka. Metoda postępowania jest bar dzo prosta: licznik i mianownik należy podzielić przez ich największy wspóln] dzielnik. Zapiszmy odpowiedni algorytm. Algorytm 4.5. Skracanie ułamka. Dane: dwie niezerowe liczby naturalne reprezentujące licznik i mianownik ułamka. Wyniki: licznik i mianownik nieskracalnego ułamka. 1. Czytaj licznik i mianownik ułamka. 2. Oblicz największy wspólny dzielnik liczb licznik i mianownik (oznaczn go przez dzielnik). 3. Podziel licznik i mianownik przez dzielnik. 4. WTydrukuj licznik i mianownik skróconego ułamka. Tak sformułowany algorytm pozwala potraktować każdy z jego kroków jakol osobny podproblem (podzadanie). Z podziałem rozwiązywanego zadania na pro-l stsze podzadania spotkaliśmy się już w rozdziale 3. W punkcie 3.3 zostały opi-J sane zasady postępowania w pracy nad programem. Zasady te prowadzą naj do stosowania zstępującej metody projektowania algorytmów przedstawione! w punkcie 3.5, a w konsekwencji do programowania strukturalnego, które możemy uprawiać bez względu na wybrany język programowania. W językjj Pascal (podobnie, jak w języku Logo) znajdujemy środki ułatwiające struktura! lizację programu: procedury i funkcje, które wprowadziliśmy w p. 4.1.1 i p. 4.1,3 Przedstawimy teraz poszczególne kroki algorytmu 4.5 w postaci definicji pro cedur. Dla każdej z procedur należy określić, co stanowi dane, a co wyniki. NależjJ także ustalić, jakie informacje mają być przekazywane między procedurami. Kroi 2 algorytmu 4.5 został już opisany w punkcie 4.2. Krok 3 algorytmu 4.5 ujmiemy w ramy procedury. Przypomnijmy, że nymi są dwie liczby: licznik i mianownik, a wynikiem skracania jest także pari liczb. W języku Pascal, odmiennie niż w języku Logo, wartością funkcji nie możl być para liczb. (W języku Logo wartością funkcji może być lista, zawierając! w szczególności parę liczb). Istnieje natomiast inny sposób pozwalający prze kazywać obliczone, nowe wartości licznika i mianownika na zewnątrz procedur) 4.3. Funkcje i procedury 129 jako jej wyniki. Przyjrzyjmy się definicji procedury Skracaj realizującej operację .skracania ułamków. [Przykład 4.8. Definicja procedury Skracaj. PROCEDURĘ Skracaj(VAR l,m:INTEGER); VAR Dzielnik:INTEGER; BEGIN Dzielnik:=nwd(l,m); 1:=1 DIV Dzielnik; m:=m DIV Dzielnik END; {Skracaj} B Wywołanie funkcji może wystąpić tylko w wyrażeniach, np. w instrukcji przy- pisania w treści procedury Skracaj: Dzielnik: =nwd (1, m) gdzie po prawej stronie symbolu przypisania znajduje się nazwa funkcji wraz z jej parametrami aktualnymi, czyli argumentami, dla których ma być obliczona wartość funkcji. Działanie tej instrukcji spowoduje najpierw wykonanie instrukcji z treści funkcji nwd, czego konsekwencją będzie obliczenie wartości tej funkcji dla podanych parametrów aktualnych, a następnie przypisanie zmiennej Dzielnik obliczonej wartości. Zmienna Dzielnik jest zmienną lokalną, użytą w treści procedury Skracaj do oznaczenia wartości pomocniczej. Procedura Skracaj ilustruje nowe możliwości posługiwania się parametrami. Wiemy już, że parametry procedury-(lub funkcji) mogą służyć do wprowadzania danych do treści procedury. W szczególnym przypadku parametry aktualne mają postać wyrażeń i w chwili wywołania procedury następuje obliczenie ich wartości i przypisanie tych wartości odpowiednim parametrom formalnym. Wartości pa- rametrów aktualnych muszą być tego samego typu, co parametry formalne za- deklarowane w definicji procedury. W ten sposób parametry formalne uzyskują wartości początkowe, od których zależy przebieg działania procedury. Parametry takie nazywamy parametrami przekazywanymi przez wartość. Parametry formalne występujące w opisie procedury Skracaj zostały po- przedzone w nagłówku słowem kluczowym VAR. Oznacza to, że są one para- metrami przekazywanymi przez zmienną. W tym przypadku parametry aktualne muszą być nazwami zmiennych odpowiedniego typu. Parametry prze- kazywane przez zmienną mogą również służyć do wprowadzania danych do treści procedury, ale głównym ich zadaniem jest przekazywanie wyników działania pro- cedury na zewnątrz. Podobnie jak w treści funkcji musimy zadbać o przypisa- nie wartości nazwie funkcji, tak w tym przypadku musimy nadać parametrom przekazywanym przez zmienną wartości będące wynikami działania procedury. i 9 — Elementy informatyki 130 4. Elementy programowania w języku Pascal Podczas wykonywania instrukcji z treści procedury wszystkie operacje dotyczące parametrów przekazywanych przez zmienną są w rzeczywistości wykonywane na zmiennych, których nazwy wystąpiły jako parametry aktualne. W ten sposób następuje zmiana wartości zmiennych spoza procedury, czyli — innymi słowy - przekazanie informacji na zewnątrz procedury. Przeanalizujmy program, w którym umieściliśmy definicje funkcji nwd, proce- dury Skracaj oraz dwóch innych procedur realizujących pierwszy i ostatni krok algorytmu 4.5: PROGRAM SkracanieUlamka; USES CRT; VAR Licznik,Mianownik:INTEGER; {W tym miejscu należy umieścić definicje: funkcji nwd z przykładu 4.6, procedury Skracaj z przykładu 4.8, procedury Start z przykładu 4.7 procedury Koniec z przykładu 4.3.} PROCEDURĘ CzytajUłamek(VAR l.m:INTEGER); BEGIN WRITELN ('---------------------Czytanie danych---------------------'); WRITE('Podaj licznik i mianownik ułamka jako dodatnie'); WRITELN(' liczby naturalne: '); WRITE('licznik = '); READLN(l); WRITE('mianownik = '); READLN(m); IF NOT ((l>0) AND (m>0)) THEN BEGIN WRITELN('ZLE DANE'); WRITELN; CzytajUlamekd.m) END {IF} END; {CzytajUłamek} PROCEDURĘ DrukujUłamek(l,m:INTEGER); BEGIN WRITELN; WRITELN ('-----------------------------Wyniki-----------------------------'); WRITELN(' ',1); WRITELN(' ------------'); WRITELN(' ',m) END; {DrukujUłamek} BEGIN {Program główny} StartC************* SKRACANIE UŁAMKA *************>); CzytajUlamek(Licznik,Mianownik); Skracaj(Licznik,Mianownik); i 4.3. Funkcje i procedury 131 DrukujUlamek(Licznik,Mianownik); Koniec END. {SkracanieUlamka} Uwaga: Tekst programu SkracanieUlamka znajduje się na dyskietce w pliku I ; | SKRACAJ. PAS umieszczonym w kartotece R0ZDZ4. W powyższym programie funkcja nwd jest wywoływana w procedurze Skracaj i dlatego jej definicja powinna zostać umieszczona przed definicją procedury Skracaj. W języku Pascal obowiązuje ogólna zasada, że najpierw definiujemy pewne wielkości, a później z nich korzystamy. W programie SkracanieUlamka opisaliśmy dodatkowo dwie procedury czyta- nia i drukowania ułamka. Zwróćmy uwagę, że w treści procedury CzytajUlamek występuje wywołanie tej samej procedury. Jest to przykład znanej z poprze- dniego rozdziału procedury rekurencyjnej. Dzięki takiej definicji procedury CzytajUlamek, po otrzymaniu komunikatu ZLE DANE możemy ponownie podać dane bez konieczności powtórnego uruchamiania programu od początku. Działanie programu SkracanieUlamka dla ułamka 4/12 i przepływ informacji między jego procedurami są zilustrowane na rysunku 4.1. dane podawane z klawiatury: 4,12 I CzytajUlamek(Licznik,Mianownik) \ Licznik=4 Mianownik=12 i Skracaj(4,12) nwd(4,12) ! Dzielnik=4 r Licznik=l Mianownik=3 \ DrukujUlamekd ,3) Wyniki wyświetlone na ekranie: —r o Rys. 4.1. Przepływ informacji pomiędzy procedurami w programie SkracanieUlamka dla przykładowych danych 132 4. Elementy programowania w języku Pascal Innym algorytmom wykonywania działań na ułamkach są poświęcone za- dania 4.2 i 4.3. Na zakończenie rozważań o funkcjach, procedurach i ich parametrach wróćmy jeszcze raz do algorytmu Euklidesa. Zauważmy najpierw, że obliczanie najwięk- szego wspólnego dzielnika dwóch liczb nie powinno zależeć od tego, w jakiej ko- lejności podajemy te liczby. Opis algorytmu 4.4 moglibyśmy uprościć, gdybyśmy byli pewni, że w każdym powtórzeniu kroku 3, b jest mniejszą z liczb. Wtedy, gdy b staje się zerem, to a jest wartością największego wspólnego dzielnika danych wartości a i b. Uwagi te prowadzą nas do następującej modyfikacji algorytmu Euklidesa: Obliczanie NWD(a, b) zastępujemy obliczeniem NWD(6, a), gdy b > a oraz uznajemy za zakończone, gdy b = 0. W przeciwnym razie oblicza- nie NWD(a, b) sprowadza się do obliczenia NWD(6, a mod b). W języku Pascal poza procedurami rekurencyjnymi można definiować także funkcje rekurencyjne. Jako przykład posłuży nam właśnie funkcja obliczająca największy wspólny dzielnik. Oto jej rekurencyjna definicja stanowiąca realizację powyższej modyfikacji algorytmu Euklidesa. Przykład 4.9. Rekurencyjna realizacja modyfikacji algorytmu Euklidesa. FUNCTION nwdRek(a,b:INTEGER):INTEGER; BEGIN IF ak) THEN BEGIN WRITELN('Zle dane: podaj liczbę z przedziału [', p>',',k,']'); WRITELN; CzytajLiczbę(l,p,k) END {IF} END; {CzytajLiczbe} Procedura czyta liczbę 1, która powinna być nie mniejsza od p (w naszym przypadku od zera, gdyż długość ciągu może być równa zero) i nie większa niż k - maksymalna liczba elementów w tablicy (wartość stałej MaxIloscLiczb). Dla uzyskania ogólności zakładamy, że końce przedziału określającego poprawny za- kres wartości czytanej liczby są parametrami tej procedury. Parametrem jest także zmienna służącą do zapamiętania wczytywanej liczby. Zauważmy podo- 4.4. Strukturalne typy danych - tablice 135 bieństwo procedury Czytaj Liczbę do procedury Czyta jUlamek wykorzystywanej w programie SkracanieUlamka z poprzedniego punktu. Krok 2 algorytmu 4.6 jest opisany w procedurze CzytajDane, dla której da- nymi są: tablica przeznaczona do zapamiętania ciągu liczb i długość tego ciągu. Przykład 4.11. Czytanie ciągu liczb. PROCEDURĘ CzytajDane(VAR Tab:CiagLiczb;Dlugosc:INTEGER); VAR i:INTEGER; BEGIN WRITELN; WRITELN ('-------------Czytanie danych-------------') ; WRITECPodawaj liczby naciskając klawisz ENTER po '); WRITELN('każdej z nich.'); FOR i:=l TO Dlugosc DO BEGIN WRITECi,' '); READLN(Tab[i]) EMD {FOR} END; {CzytajDane} B Tak zdefiniowana procedura może być stosowana do czytania ciągów liczb różnej długości w zależności od definicji typu CiagLiczb i wartości parametru Dlugosc. Tablice umożliwiają powtarzanie tej samej operacji dla każdego z jej ele- mentów, np. czytanie liczby z klawiatury. Stosujemy wówczas instrukcję FOR, w której zmienną sterującą wykorzystujemy do określenia indeksu elementu. Na przykład w procedurze CzytajDane powtarzamy dwie instrukcje; WRITECi,' '); READLNCTab[i]) Pierwsza z nich drukuje wartość indeksu i wskazującego, która z kolei liczba jest czytana, a druga czyta element tablicy Tab o tym indeksie. Do elementu tablicy odwołujemy się podając jego indeks w nawiasach kwadratowych. Poniżej ilustrujemy działanie procedury CzytajDane dla ciągu danych liczb 34, 56, 25, 46, 12 i parametru Dlugosc równego 5: Element, któremu zostaje Wartość zmiennej i Czytana liczba przypisana czytana liczba 1 34 Tab[l] 2 56 Tab[2] 3 25 Tab [3] 4 46 Tab[4] 5 12 Tab [5] 136 4. Elementy programowania w języku Pascal Pierwszy parametr procedury Czytaj Dane jest przekazywany przez zmienną, więc czytane liczby są przypisywane elementom tablicy, której nazwa wystąpi jako parametr aktualny. Kolejna procedura zgodnie z trzecim krokiem algorytmu 4.6 ma obliczać średnią arytmetyczną. Zauważmy, że obliczanie średniej arytmetycznej można potraktować jako obliczanie wartości pewnej funkcji. Zdefiniujemy więc funkcję o nazwie ObliczSrednia, realizującą poniższy algorytm. Algorytm 4.7. Obliczanie średniej arytmetycznej. Dane: ciąg liczb i jego długość. Wynik: średnia arytmetyczna ciągu liczb. 1. Przypisz zmiennej pomocniczej Suma początkową wartość zero. 2. Każdą kolejną liczbę ciągu dodaj do wartości zmiennej Suma. 3. Podziel wartość zmiennej Suma przez ilość liczb w ciągu, czyli jego długość. Parametrami funkcji ObliczSrednia są: tablica zawierająca ciąg liczb i dłu- gość tego ciągu. Wartością tej funkcji jest liczba typu REAL równa średniej aryt- metycznej ciągu liczb. Operatorem dzielenia dla liczb typu rzeczywistego jest znak /. Przykład 4.12. Obliczanie średniej arytmetycznej. FUNCTION ObliczSrednia(Tab:CiagLiczb; Dlugosc:INTEGER):REAL; VAR Suma:REAL; i :INTEGER; BEGIN Suma:=0; FOR i:=l TO Dlugosc DO Suma:=Suma+Tab[i]; ObliczSrednia:=Suma/Dlugosc END; {ObliczSrednia} Danymi dla następnej procedury obliczającej odchylenia od wartości średniej są: tablica zawierająca ciąg liczb, obliczona wartość średniej arytmetycznej oraz długość ciągu danych. Wynikiem działania procedury jest tablica odchyleń. Obli- czanie odchyleń polega na obliczaniu bezwzględnej wartości różnicy między liczbą z ciągu a obliczoną wartością średniej. Przykład 4.13. Obliczanie odchyleń od wartości średniej. PROCEDURĘ ObliczRoznice(Tab:CiagLiczb;Średnia:REAL; Dlugosc:INTEGER;VAR Różnice:CiagLiczb); VAR i:INTEGER; BEGIN 4.4. Strukturalne typy danych - tablice 137 FOR i:=l TO Dlugosc DO Różnice[i]:=ABS(Tab[i]-Średnia) END; -(ObliczRoznice} W tekście procedury ObliczRoznice użyliśmy standardowej funkcji języka Pascal o nazwie ABS, obliczającej wartość bezwzględną swojego argumentu. Ostatni krok algorytmu 4.6 dotyczy drukowania wyników. W procedurze re- alizującej ten krok jako dane występują: tablica zawierającą ciąg liczb, tablica odchyleń, długość ciągu oraz obliczona wartość średniej arytmetycznej. Przykład 4.14. Drukowanie wyników. PROCEDURĘ DrukujWyniki(Tab,Różnice:CiagLiczb; Dlugosc:INTEGER;Średnia:REAL); VAR i:INTEGER; BEGIN WRITELN; WRITELNC------------------Wyniki------------------'); WRITELN; WRITELN('Średnia arytmetyczna = '.Średnia:11:3); WRITELN; WRITELNC'Ciąg liczb Ciąg odchyleń'); FOR i:=l TO Dlugosc DO WRITELN(Tab[i]:11:3,' ',Różnice[i]:11:3) END; {DrukujWyniki} W przypadku drukowania liczb, zwłaszcza typu rzeczywistego, należy zadbać o ich postać zwaną formatem. Zaproponowany przez nas format Średnia: 11:3 oznacza, że wartość parametru Średnia zostanie wydrukowana z 11 cyframi dzie- siętnymi, z czego 3 przypadną na część ułamkową po kropce. W przytoczonym poniżej tekście programu ObliczanieSredniej w części opi- sowej pojawiają się wcześniej omówione definicje stałych i typów. Podkreślmy, że definicje i deklaracje mogą występować w dowolnej kolejności, ale z zachowa- niem zasady, że deklaracja lub definicja poprzedza wykorzystanie definiowanej wielkości. Na przykład definicja stałej MaxIloscLiczb poprzedza definicję typu CiagLiczb, gdyż jest w niej wykorzystywana. PROGRAM ObliczanieSredniej; USES CRT; CONST MaxIloscLiczb=100; TYPE CiagLiczb=ARRAY[l..MaxIloscLiczb] OF REAL; VAR Dane,Odchylenia:CiagLiczb; 138 __ 4. Elementy programowania w jeżyku Pascal r SrAryt :EEAL; IloscLiczb :INTEGER; {W tym miejscu należy umieścić definicje procedur i funkcji z przykładów 4.3, 4.7, 4.10, 4.11, 4.12, 4.13, 4.14.} BEGIM {Program glowny} Start('ŚREDNIA ARYTMETYCZNA CIĄGU LICZB'); WRITECObliczanie średniej arytmetycznej maksymalnie '); WRITELN(MaxIloscLiczb,' liczb podanych przez Ciebie'); WRITEC'oraz ich odchyleń od obliczonej '); WRITELN ('wartości średniej.'); WRITELN; WRITELN('Podaj ilosc liczb w ciągu:'); CzytajLiczbe(IloscLiczb,0,MaxIloscLiczb); IF IloscLiczb>0 THEN BEGIN CzytajDane(Dane,IloscLiczb); SrAryt:=ObliczSrednia(Dane,IloscLiczb); ObliczRoznice(Dane,SrAryt,IloscLiczb,Odchylenia); DrukujWyniki(Dane,Odchylenia,IloscLiczb,SrAryt); END; {IF} Koniec END. {ObliczanieSredniej} Uwaga: Tekst programu ObliczanieSredniej znajduje się na dyskietce w pliku ŚREDNIA.PAS umieszczonym w kartotece R0ZDZ4. Elementami tablicy mogą być również tablice. Wykorzystamy tę możliwość, definiując nowy typ tablicowy dla naszego zadania. Zamiast dwóch tablic tego samego typu, w których są pamiętane dane liczby i ich odchylenia od średniej, użyjemy jednej tablicy dwuwymiarowej. Odpowiednia definicja typu i dekla- racja zmiennej mają postać: TYPE CiagLiczb =ARRAY[1..MaxIloscLiczb] 0F REAL; DwaCiagiLiczb=ARRAY[l..2] 0F CiagLiczb; VAR DaneOdchyl:DwaCiagiLiczb Jeśli wprowadzimy powyższą deklarację do tekstu programu, to zamiast zmiennej tablicowej Dane musimy użyć zmiennej DaneOdchyl [1], a odwołanie do i-tego elementu ciągu danych będzie miało postać DaneOdchyl [1, i]. Proponujemy samodzielnie wprowadzić dalsze zmiany w opisach procedur i w treści programu ObliczanieSredniej. Z obliczaniem średniej arytmetycznej spotykamy się, np. przy obliczaniu śred- nich ocen uczniów. W przypadku tego zadania algorytm obliczania średniej po- zostaje bez zmian, natomiast wygodniej byłoby odwoływać się do ocen (pamię- 4.4. Strukturalne typy danych - tablice 139 tanych w tablicy) poprzez nazwę przedmiotu, a nie jego numer. Spróbujmy więc zaprojektować odpowiednią strukturę danych. Liczba przedmiotów, ich nazwy oraz kolejność w dzienniku są zazwyczaj ustalone. W języku Pascal indeksami tablicy mogą być nie tylko liczby całkowite, ale również nazwy. Pozwala to zde- finiować tablicę, której elementami są oceny, a indeksami - nazwy przedmiotów. Warunkiem koniecznym jest uporządkowanie tych nazw. Osiągamy to definiując typ wyliczeniowy. Definicja typu wyliczeniowego ma postać wyliczenia w na- wiasach okrągłych nazw (różnych od słów kluczowych) elementów, które stanowią wartości zmiennych tego typu. W ten sposób ustalamy również kolejność ele- mentów, co okaże się istotne w dalszej części naszych rozważań. Proponujemy następującą definicję typu wyliczeniowego o nazwie Przedmioty: TYPE Przedmioty=(polski.angielski,matematyka,fizyka,chemia, biologia,geografia,wf); Podana lista przedmiotów została przykładowo ustalona dla potrzeb naszego za- dania. Wartość elementu tablicy o ustalonym indeksie, który jest nazwą przed- miotu, stanowi ocena z tego przedmiotu. Przyjmujemy, że ocenami mogą być liczby naturalne z przedziału od 1 do 6 (wykluczamy oceny w rodzaju: plus dostateczna). Oto definicja typu tablicowego Oceny: TYPE Oceny=ARRAY[Przedmioty] OF INTEGER; Dla podanej struktury danych definiujemy nową funkcję obliczającą średnią aryt- metyczną. Przykład 4.15. Obliczanie średniej ocen ucznia. FUNCTION SredniaCTab:Oceny):REAL; VAR Suma:REAL; i :INTEGER; p :Przedmioty; BEGIN Suma:=0; i:=0; FOR p:=polski TO wf DO BEGIN Suma:=Suma+Tab[p]; EMD; Średnia:=Suma/i END; {Średnia} 140 4. Elementy programowania w języku Pascal Zauważmy, że w funkcji tej jest wyznaczana liczba przedmiotów i, gdyż nią jest ona znana. Zwróćmy także uwagę, że zmienna sterująca w instrukcji FOlj może przyjmować nie tylko wartości typu całkowitego, ale również typu wylicz& niowego. Kolejne jej wartości są jednoznacznie określone, gdyż elementy typi| wyliczeniowego są uporządkowane w jego definicji. Przed obliczeniem średniej ocen należy wczytać oceny z poszczególnych prze miotów. Do czytania pojedynczej oceny użyjemy nieznacznie zmodyfikowani procedury Czytaj Liczbę z przykładu 4.10. Przykład 4.16. Ogólniejsza wersja procedury CzytajLiczbe. PROCEDURĘ CzytajLiczbe(VAR 1:INTEGER;p,k:INTEGER; Tekst:STRING); BEGIN WRITE(Tekst); READLN(l); WRITELN; IF (Kp) 0R (l>k) THEN BEGIN WRITELN('Zle dane: podaj liczbę z przedziału [\p,',\k,']')J WRITELN; CzytajLiczbę(l,p,k,Tekst) END {IF} END; {CzytajLiczbe} Uogólnienie polega na wprowadzeniu dodatkowego parametru, który umożli' wybór treści napisu wyświetlanego jako zaproszenie do podania liczby. W naszyn przypadku chcielibyśmy, aby tym napisem była nazwa przedmiotu. W języku Pascal brak jest możliwości bezpośredniego czytania i drukowania wartości typu wyliczeniowego (nie można na przykład napisać WRITE(p), gdzie] jest zmienną typu wyliczeniowego). Dlatego do drukowania nazw przedmiotów posłużymy się funkcją Nazwa, która wartościom typu wyliczeniowego Przedmiot; przyporządkowuje nazwy przedmiotów w postaci napisów. Przykład 4.17. Definicja funkcji Nazwa. FUNCTION Nazwa(p:Przedmioty):STRING; BEGIN CASE p 0F polski :Nazwa:='polski '; angielski :Nazwa:='angielski '; matematyka:Nazwa:='matematyka '; fizyka :Nazwa:='fizyka '; chemia :Nazwa:='chemia '; biologia :Nazwa:='biologia '; geografia :Nazwa:='geografia '; 4.4. Strukturalne typy danych - tablice 141 wf END {CASE} END; {Nazwa} :Nazwa:='wf ' W funkcji tej użyliśmy po raz pierwszy instrukcji wyboru CASE. Umożliwia ona wybór jednej z wielu możliwych dróg w programie, a jej działanie polega na wykonaniu tej instrukcji umieszczonej po dwukropku, dla której tekst przed dwukropkiem jest wartością wyrażenia znajdującego się między słowami CASE i OF. Jeśli wartości wymienione przed dwukropkami nie wyczerpują wszystkich możliwych wartości zmiennej p (w naszym przypadku), to dla wartości nie u- względnionych w wykazie po lewej stronie dwukropka, nie jest wykonywana żadna instrukcja. W innej wersji instrukcji CASE dla tych wartości jest wykonywana in- strukcja występująca po słowie kluczowym ELSE, które umieszczamy na końcu po wyliczeniu wszystkich wartości stojących przed dwukropkami. Przykład użycia instrukcji CASE w tej postaci znajduje się w treści zadania 4.11. Pozostała nam do opisania procedura czytania ocen wykorzystująca procedurę CzytajLiczbe i funkcję Nazwa. Przykład 4.18. Czytanie ocen ze wszystkich przedmiotów. PROCEDURĘ Czytaj Oceny(VAR Tab:Oceny); VAR p:Przedmioty; BEGIN WRITE('Podawaj kolejne oceny jako liczby '); WRITELNCz przedziału <1,6>:'); FOR p:=polski TO wf DO CzytajLiczbe(Tab[p],1,6,Nazwa(p)) END; {CzytajOceny} Na koniec przedstawimy kompletny program obliczania średniej ocen. PROGRAM SredniaOcen; USES CRT; TYPE Przedmioty=(polski,angielski,matematyka,fizyka,chemia, biologia,geografia,wf); Oceny =ARRAY[Przedmioty] OF INTEGER; VAR Swiad:Oceny; {W tym miejscu należy umieścić definicje procedur i funkcji z przykładów: 4.5, 4.7, 4.15, 4.16, 4.17, 4.18.} BEGIN REPEAT Start('ŚREDNIA OCEN UCZNIA'); 142 4. Elementy programowania w języku Pascal Czytaj Oceny(Swiad); WRITELN; WRITELN; WRITELN('Twój a średnia ocen wynosi:',Srednia(Swiad):11:3) UNTIL JuzKoniec END. {SredniaOcen} Uwaga: Tekst programu SredniaOcen znajduje się na dyskietce w pliku OCENY.PAS umieszczonym w kartotece ROZDZ4. 4.4.2. Rekordy Obliczone średnie ocen uczniów są potrzebne nauczycielom do przygotowywania różnych sprawozdań i statystyk obrazujących wyniki nauczania. Szczególnie in- teresujące są informacje, którzy uczniowie uzyskali najwyższe, a którzy najniższe średnie oceny. Zaprojektujemy teraz prosty program, który będzie drukował na- zwiska uczniów ze średnią ocen powyżej 4.5. Sformułowanie algorytmu rozwią- zywania tego zadania, nie sprawi nam kłopotu. Większą trudność stanowi : projektowanie odpowiednich struktur danych umożliwiających reprezentowanie w programie wszystkich potrzebnych informacji. Jakie informacje należy pamiętać? Trzeba znać listę imion i nazwisk uczniów, a z każdym nazwiskiem powiązać obliczoną średnią ocen uzyskanych z poszcze- gólnych przedmiotów. Liczba uczniów w klasie jest określona. Przyjmijmy, że in- formacje o uczniu tworzą element tablicy wszystkich uczniów o nazwie Dziennik, Zmienna Dziennik będzie zmienną typu DziennikLekcyjny. TYPE DziennikLekcyjny=ARRAY[l..MaxLiczbaUczniow] OF Uczeń; W tej definicji MaxLiczbaUczniow jest nazwą stałej, której wartość określimy na początku programu, a Uczeń - nazwą typu służącego do zgromadzenia infor- macji o uczniu. Informacje o uczniu są dość złożone. Składają się na nie imię i nazwisko oraz średnia ocen. Tak złożony i niejednorodny zbiór danych o uczniu możemy pamiętać za pomocą struktury zwanej rekordem. Rekord, podobnie jak tablica, grupuje elementy, ale mogą to być elementy różnych typów. Oto definicja przy- datnego nam w tym zadaniu typu rekordowego: TYPE Uczen=RECORD Imię,Nazw:STRING[15]; Sr :REAL END; Rekord tego typu zawiera trzy elementy zwane polami. Pola o nazwach Imię oraz Nazw służą do pamiętania imienia i nazwiska ucznia, które są napisami zło- żonymi z co najwyżej 15 znaków. Trzecie pole rekordu o nazwie Sr jest typu REAL 4.4. Strukturalne typy danych - tablice 143 i służy do pamiętania średniej ocen z poszczególnych przedmiotów na świadectwie szkolnym. Skoro zaprojektowaliśmy już struktury danych, sformułujmy algorytm. Algorytm 4.8. Wyszukanie uczniów o średniej ocen powyżej 4.5. Dane: imiona i nazwiska uczniów wraz ze średnią ocen uzyskanych z przedmio- tów szkolnych. Wyniki: lista imion i nazwisk uczniów, którzy uzyskali średnią ocen powyżej 4.5. 1. Czytaj imiona i nazwiska uczniów oraz średnie ich ocen. 2. Dla każdego z uczniów wykonaj krok 3, a następnie przejdź do kroku 4. 3. Jeśli średnia ocen ucznia jest większa od 4.5, to zapamiętaj jego numer porządkowy, czyli indeks w tablicy. 4. Wydrukuj listę imion i nazwisk uczniów, których numery porządkowe zo- stały zapamiętane. Zdefiniujemy procedury realizujące kroki 1, 2 i 3 oraz 4. Oto definicja pierw- szej z nich. Przykład 4.19. Czytanie danych o uczniach. PROCEDURĘ CzytajŚrednie(VAR dz:DziennikLekcyjny; IluUczniow:INTEGER); {Dla każdego z uczniów procedura czyta z klawiatury imię i nazwisko oraz średnia ocen i wypełnia nimi pola rekordu odpowiadające temu uczniowi.} VAR i:INTEGER; PROCEDURĘ Czytaj(VAR 1:REAL;p,k:INTEGER; Tekst:STRING); BEGIN WRITE(Tekst); READLN(l); WRITELN; IF (Kp) OR (l>k) THEN BEGIN WRITELN('Zle dane: podaj liczbę z przedziału [',p,',',k,']'); WRITELN; Czytaj(l,p,k,Tekst) END {IF} END; {Czytaj} BEGIN WRITELN('Podawaj informacje o kolejnych uczniach:'); FOR i:=l TO IluUczniow DO BEGIN WRITELN; WRITE(i:2,'imie: ':12); READLN(dz[i].Imię); 144 4. Elementy programowania w języku Pascal WRITE('nazwisko: ':14); READLN(dz[i].Nazw); Czytaj(dz[i].Sr,1,6,'średnia ocen: ') END {FOR} END; {Czytaj Średnie} W powyższej procedurze korzystamy z możliwości ustalenia formatu wypro- wadzanych napisów i liczb całkowitych. Jeśli w wywołaniu procedury WRITE lub WRITELN w nawiasach po napisie, liczbie całkowitej, zmiennej typu napisowego lub całkowitego umieścimy dwukropek i liczbę naturalną m, to napis lub liczba zostanie wydrukowany na m pozycjach znakowych w ten sposób, że ewentualne dodatkowe spacje znajdą się na lewo od napisu (liczby), a on sam zostanie do- sunięty do prawego marginesu. Służy to do poprawienia czytelności i estetyki wyprowadzanych wyników. W części opisowej procedury Czytaj Średnie umieściliśmy definicję procedury Czytaj, która jest odpowiednikiem procedury CzytajLiczbe z przykładu 4.1 dla liczb rzeczywistych i służy do wczytania liczby reprezentującej średnią ocen. Opis jednej procedury może być umieszczony wewnątrz opisu innej procedury. Konsekwencją takiego układu opisów jest ograniczenie, że procedura wewnętrzna nie może być wywołana poza treścią procedury, w której została opisana. Podobne ograniczenie obowiązuje dla zmiennych lokalnych. Procedurę CzytajLiczbe wykorzystamy na początku programu do wczytania liczby uczniów. W przykładzie 4.19 po raz pierwszy spotykamy się z odwołaniami do wartości zmiennych typu rekordowego. Przyjrzyjmy się znaczeniom poszczególnych za- pisów: dz - odwołanie do całej tablicy rekordów, czyli do całego dziennika; dz [i] - odwołanie do rekordu z indeksem i, czyli do informacji o jed- nym uczniu; dz[i] .Imię - po dołączeniu do powyższego napisu kropki i nazwy pola re- kordu po kropce otrzymujemy odwołanie do tego pola. Kroki 2 i 3 algorytmu 4.8 opiszemy w procedurze Szukaj Najlepszych. Prze- glądamy w niej tablicę Dziennik i w tablicy pomocniczej zapisujemy numery porządkowe (czyli indeksy odpowiednich elementów tablicy) uczniów o średniej ocen powyżej 4.5. Zatem elementami tablicy pomocniczej będą liczby całkowite, a jej indeks będzie miał taki sam zakres, jak w tablicy Dziennik, gdyż w najlep- szym przypadku wszyscy uczniowie mogą mieć średnią powyżej 4.5. W zadaniu 4.10 sugerujemy uogólnienie procedury Szukaj Najlepszych tak, aby umożliwiała I wyszukanie uczniów ze średnią ocen z dowolnego przedziału. Wynikiem działania tej procedury jest tablica zawierająca numery porządkowe i liczba uczniów spel-j 4.4. Strukturalne typy danych - tablice 145 niąjących warunek. Oto definicja omawianej procedury, poprzedzona definicją odpowiedniego typu tablicowego. Przykład 4.20. Wyszukiwanie uczniów o średniej ocen powyżej 4.5. TYPE Pomocniczy=ARRAY[l..MaxLiczbaUczniow] OF INTEGER; PROCEDURĘ Szukaj Najlepszych(dz:DziennikLekcyj ny; IluUczniow:INTEGER; VAR Tpom:Pomocniczy; VAR Ilu:INTEGER); VAR i:INTEGER; BEGIN Ilu:=0; FOR i:=l TO IluUczniow DO IF dz[i].Sr>4.5 THEN BEGIN Tpom[Ilu] :=i END {IF> END; {SzukajNajlepszych} Opis procedury drukującej listę nazwisk wybranych uczniów, czyli realizującej ostatni krok algorytmu, umieścimy w treści programu. PROGRAM Najlepsi; USES CRT; CONST MaxLiczbaUczniow=40; TYPE Uczeń =RECORD Imie,Nazw:STRING[15] ; Sr :REAL END; DziennikLekcyjny=ARRAY[1..MaxLiczbaUczniow] OF Uczeń; Pomocniczy =ARRAY[1..MaxLiczbaUczniow] OF INTEGER; VAR Dziennik -.DziennikLekcyjny; LiczbaUczniow,LiczbaDobrych:INTEGER; TabPom :Pomocniczy; PROCEDURĘ DrukujNajlepszych(dz:DziennikLekcyjny; Tpom:Pomocniczy;Ilu:INTEGER); VAR i:INTEGER; BEGIN WRITELN ('NAJLEPSI:'); WRITELN; 10 — Elementy informatyki 146 4. Elementy programowania w języku Pascal WRITELNCimie i nazwisko':30,'średnia ocen':21); FOR i:=l TO Ilu DO WITH dz[Tpom[i]] DO WRITELN(i:2,Imie:15,Nazw:15,Sr:15:l) END; {DrukujNajlepszych} {W tym miejscu należy umieścić definicje procedur i funkcji z przykładów: 4.3, 4.7, 4.16, 4.19, 4.20.} BEGIN Start('UCZNIOWIE 0 NAJLEPSZEJ ŚREDNIEJ OCEN'); WRITECPodaj liczbę uczniów w klasie (max. ', MaxLiczbaUczniow,'): '); CzytajLiczbę(LiczbaUczniow,0,MaxLiczbaUczniow,''); IF LiczbaUczniow>0 THEN BEGIN Czytaj Średnie(Dziennik,LiczbaUczniow); Szukaj Najlepszych(Dziennik,LiczbaUczniow,TabPom, LiczbaDobrych); IF LiczbaDobrych>0 THEN DrukujNajlepszych(Dziennik,TabPom,LiczbaDobrych) ELSE WRITELN('Nie ma uczniów o średniej ocen powyżej 4.5.') END; {IF} Koniec END. {Najlepsi} Uwaga: Tekst programu Najlepsi znajduje się na dyskietce w pliku NAJLEPSI.PAS umieszczonym w kartotece R0ZDZ4. W procedurze Drukuj Najlepszych użyliśmy instrukcji wiążącej, która ma ogólną postać: WITH nazwa-rekordu DO instrukcja Instrukcja ta umożliwia prostszy zapis operacji wykonywanych na polach tego samego rekordu. W naszym przypadku zamiast instrukcji WRITELN(i:2,dz[Tpom[i]].Imię:15,dz[Tpom[i]].Nazw:15, dz[Tpom[i]].Sr:15:l) mogliśmy napisać WITH dz[Tpom[i]] DO WRITELN(i:2,Imię:15,Nazw:15,Sr:15:1) Podobnie można uprościć zapis ciągu instrukcji umieszczonych w instrukcji FOR { w procedurze Czytaj Średnie. i 4.5. Dynamiczne struktury danych 147 4.5. Dynamiczne struktury danych W poprzednim punkcie ujawniła się podstawowa wada tablic jako struktur da- nych polegająca na tym, że przed uruchomieniem programu musimy z góry prze- widzieć, jaka będzie maksymalna liczba elementów przechowywanych w tablicy. Informację tę należy umieścić w tekście programu, gdyż rozmiaru tablicy nie można zmieniać podczas działania programu. Powyższa wada tablic jest poważnym utrudnieniem, gdy w obliczeniach nie można z góry określić liczby przetwarzanych elementów. W rozdziale 3 poświęco- nym językowi Logo została wprowadzona struktura danych zwana listą, która jest pozbawiona tej wady. W języku Pascal nie ma typu danych odpowiadającego li- stom, można natomiast konstruować podobne struktury. Służą temu odpowiednio zdefiniowane typy wskaźnikowe. Wartościami zmiennych typu wskaźnikowego są adresy w pamięci zwane wskaźnikami. Wskaźniki te nie są liczbami, ale określają obszary pamięci, w których można przechowywać wartości typu wska- zywanego. Definicja typu wskaźnikowego ma następującą postać: nazwa-typu-wskaźnikowego=~nazwa-typu-wskazywanego Dla przykładu zdefiniujmy typ wskaźnikowy WskCalk, którego wartościami będą wskaźniki na zmienne typu całkowitego: TYPE WskCalk=-INTEGER; a następnie zadeklarujmy zmienne tego typu: VAR w,v:WskCalk; Wtedy w programie zmienna w lub v może otrzymać wartość w jeden z następu- jących sposobów: - przypisanie jej wartości NIL, czyli adresu pustego, np. w:=NIL; - przypisanie jej wartości innej zmiennej tego samego typu wskaźnikowego, np. v:=w; - wywołanie procedury standardowej NEW ze zmienną w lub v jako parametrem aktualnym, np. NEW (w). W dwóch pierwszych przypadkach instrukcje przypisania nie wymagają ko- mentarza. Wykonanie instrukcji NEW (w) powoduje zarezerwowanie pamięci na zapamiętanie wartości typu całkowitego i nadanie zmiennej w wartości, która jest wskaźnikiem do tego obszaru. Obszar ten należy do zmiennej dynamicznej, która jest dostępna przez identyfikator w" i traktowana jak każda inna zmienna typu INTEGER. Po wykonaniu instrukcji NEW (w) wartość zmiennej w" jest nieo- kreślona. Można nadać jej wartość, na przykład wykonując instrukcję: w":=25; 148 4. Elementy programowania w języku Pascal Wzajemne powiązania między opisanymi powyżej pojęciami są zilustrowanej na rysunku 4.2. NEW(w) w*:=25 w-------- 25 Rys. 4.2. Wskaźnik i zmienna dynamiczna Zauważmy, że ponowne wykonanie instrukcji NEW (w) powołuje nową zmien- ną dynamiczną w", a zatem tracimy przez to dostęp do wartości poprzednio wskazywanej przez wskaźnik w. Oszczędne gospodarowanie pamięcią zajmowaną przez zmienne dynamiczne jest możliwe dzięki istnieniu procedury standardo- wej DISPOSE. Wykonanie instrukcji DISPOSE(w) powoduje, że wartość zmiennej w staje się nieokreślona, a obszar pamięci zajmowany przez zmienną w" zostaje zwolniony i może być wykorzystany w innym celu. Praktyczny sens stosowania typów wskaźnikowych uwidacznia się w sytuacji, gdy typ wskazywany jest złożonym typem strukturalnym (np. tablicą lub rekor- dem) i zadeklarowanie zmiennej tego typu pociąga za sobą rezerwację znacznego obszaru pamięci, a istnieją przesłanki, że pamięć ta nie będzie w pełni wykorzy- stywana podczas działania programu. Na przykład, zdefiniujmy typy danych: TYPE DuzaTablica=ARRAY [1..5000] OF REAL; Wskazuj =~DuzaTablica; Wówczas zadeklarowanie zmiennej Tablica: VAR Tablica:Wskazuj; oznacza, że pamięć potrzebna do zapamiętania tablicy złożonej z 5000 liczb typu REAL zostanie przydzielona dopiero wtedy, gdy zmienna ta wystąpi jako parametr aktualny w procedurze NEW. Jeśli nie możemy przewidzieć, jak duże będą nasze dane, to musimy zagwa- rantować, że przydział pamięci dla kolejnego elementu będzie następował wraz z jego pojawieniem się. Tworzenie zmiennych dynamicznych jest właśnie takim postępowaniem. Zmienne dynamiczne wykorzystuje się do tworzenia list. Elementami listy są I rekordy połączone ze sobą za pomocą wskaźników. Uzyskujemy to definiując typ i 4.5. Dynamiczne struktury danych 149 wskaźnikowy, który wskazuje rekordy. Rekordy te mają pole typu wskaźnikowego i w tym polu umieszczamy wskaźnik do następnego rekordu lub wartość NIL, gdy brak jest następnego elementu. Zaproponujemy teraz definicje typów dla przykładu omówionego w poprze- dnim punkcie, które pozwolą utworzyć dziennik jako listę uczniów, w miejsce tablicy. W dalszych rozważaniach zachowamy takie same nazwy dla typów oraz zmiennych oznaczających te same wielkości. Dla ułatwienia uprościmy budowę rekordu gromadzącego informacje o uczniu i pozostawimy tylko pola Imię i Nazw. Przykład 4.21. Definicje typów danych dla listy uczniów. TYPE DziennikLekcyjny=~Uczen; Uczeń =REC0RD Imię,NazwrSTRING[15] ; Wsk :DziennikLekcyjny END; m Powyższa definicja zawiera wyjątek w języku Pascal, gdyż nazwa typu rekor- dowego Uczeń jest użyta w tekście programu wcześniej, niż została opisana. Taka sytuacja jest dopuszczalna tylko w definicji typu wskaźnikowego. Dla tak zdefiniowanego typu wskaźnikowego lista uczniów jest reprezentowana przez zmienną Dziennik VAR Dziennik:DziennikLekcyjny; w następujący sposób: - jeśli lista jest pusta, to zmiennej Dziennik nadajemy wartość NIL; - jeśli lista jest niepusta, to wartością zmiennej Dziennik jest wskaźnik do pierwszego elementu listy. Wskaźniki do następnych elementów są umieszczane w polach Wsk kolejnych rekordów. W ostatnim elemencie listy polu Wsk nadajemy wartość NIL, aby u- łatwić rozpoznanie końca listy. Struktura listy jest zilustrowana na rysunku 4.3. Dziennik - Imię Nazw Wsk NIL Rys. 4.3. Struktura listy zbudowanej za pomocą wskaźników 150 4. Elementy programowania w języku Pascal Napiszemy teraz program, który korzystając z nowych typów danych zdefinio- wanych w przykładzie 4.21, będzie czytał imiona i nazwiska uczniów z klawiatury. a następnie je drukował. Do czytania danych użyjemy procedury podobnej do procedury Czytaj Średnie z przykładu 4.19. Zrealizujemy w niej następujący algorytm: Algorytm 4.9. Tworzenie listy uczniów. Dane: informacje o uczniach wprowadzane z klawiatury. Wynik: wskaźnik do początku listy uczniów (dz). 1. Na początku lista jest pusta, więc wskaźnikowi dz przypisz wartość NIL. 2. Czytaj imię i nazwisko ucznia. Jeśli przeczytany napis jest pusty, to zakończ działanie algorytmu, w przeciwnym razie przejdź do następnego kroku. 3. Zarezerwuj obszar pamięci dla nowego elementu używając pomocniczego wskaźnika Nowy. 4. Umieść dane o uczniu w odpowiednich polach rekordu Nowy" (polu Wsk nadaj wartość NIL, gdyż nowy element jest umieszczany na końcu listy). 5. Dopisz nowy element do końca listy. 6. Powtarzaj kroki od 2 do 6. Objaśnić należy sposób wykonania kroku 5. Jeśli dopisujemy nowy element do końca pustej listy, to wskaźnikowi dz przypisujemy wartość wskaźnika Nowy. Jeśli lista nie jest pusta, to musimy znać wskaźnik dz do początku listy i dodatkowo wskaźnik Bieżący do ostatniego elementu listy, po którym należy dołączyć nowy element. Wówczas wykonujemy dwie operacje: - w polu Wsk ostatniego elementu umieszczamy wskaźnik do nowego elementu (tj. wykonujemy Bieżący" .Wsk:=Nowy); - zmieniamy wartość wskaźnika Bieżący tak, aby wskazywał na aktualnie ostatni element listy (tj. Bieżący :=Nowy). Powyższy algorytm realizujemy w procedurze Czytaj ImNazw. Przykład 4.22. Wczytywanie danych o uczniach. PROCEDURĘ CzytajImNazw(VAR dz:DziennikLekcyjny); {Dla każdego z uczniów procedura czyta z klawiatury jego imię i nazwisko i wypełnia pola odpowiadającego mu rekordu.} VAR i :INTEGER; n :STRING[15]; Nowy,Bieżący:DziennikLekcyjny; BEGIN WRITELN('Podawaj informacje o kolejnych uczniach'); WRITE('(na końcu danych nacisnij ENTER zamiast'); WRITELNC podawać imię):'); 4.5. Dynamiczne struktury danych 151 dz:=NIL; {na początku lista uczniów jest pusta} i:=l; {licznik uczniów, o których wprowadzamy informacje} REPEAT WRITELN; WRITE(i:2,'imie: ':10); READLN(n); IF n<>'' THEN BEGIN NEW(Nowy); {rezerwacja pamięci dla nowego rekordu} Nowy".Imię:=n; {wypełnianie poi nowego rekordu} WRITE('nazwisko: ' :12); READLN(Nowy".Nazw); Nowy".Wsk:=NIL; IF dz=NIL THEN BEGIN dz:=Nowy; {tworzenie pierwszego elerfitentu listy} Bieżący:=dz END ELSE BEGIN Bieżący".Wsk:=Nowy; {dołączanie kolejnego elementu do listy} Bieżący:=Nowy END; END {koniec wprowadzania danych o uczniu} UNTIL n=>> {koniec wczytywania danych} END; {CzytajImNazw} Na rysunku 4.4 są przedstawione zmiany wartości wskaźników i postaci listy zachodzące w czasie wczytywania danych o trzech uczniach: uczen-1, uczen-2 oraz uczeń-3. W procedurze drukowania listy uczniów można odnaleźć cechy rekurencyjnego schematu przeglądania listy w języku Logo (por. p. 3.7). W naszym przypadku stosujemy następujący algorytm, zrealizowany w procedurze Drukuj Listę, opi- sanej w przykładzie 4.23. Algorytm 4.10. Przeglądanie listy uczniów. Dane: wskaźnik do początku listy uczniów (Dziennik). 1. Wskaźnikowi dz przypisz wartość wskaźnika do początku listy. 2. Dopóki lista nie jest pusta (tj. dzONIL), wykonuj kroki 3 i 4. 3. Wykonaj operacje związane z elementem wskazywanym przez wskaźnik dz. 4. Przesuń wskaźnik dz do następnego elementu (tj. wykonaj dz:=dz~ .Wsk). 152 Dziennik=NIL 4. Elementy programowania w języku Pascal Dziennik - Nowy Bieżący - uczeń-1 NIL LV.Jf uczeń-1 uczeń-2 NIL Dziennik i_________ uczeń-1 Nowy,E iezacy - uczeń-2 uczeń-3 NIL Rys. 4.4. Zmiany wartości wskaźników i postaci listy podczas wczytywania danych Przykład 4.23. Drukowanie listy uczniów. PROCEDURĘ DrukujListe(dz:DziennikLekcyjny); VAR i:INTEGER; BEGIN WRITELN; WRITELN; WRITELN('LISTA UCZNIÓW:20); WRITELN; WHILE dzONIL DO BEGIN WITH dz~ DO WRITELNCi:2,Imię:15,Nazw:15); dz:=dz~.Wsk; i: 4.5. Dynamiczne struktury danych 153 END -CWHILE} END; {DrukujListę} Zwróćmy jeszcze raz uwagę na sposób tworzenia i drukowania listy uczniów. Nowy element jest dopisywany zawsze do końca listy, a przeglądając listę, wy- prowadzamy elementy w kolejności ich dołączania, tzn. element dopisany do listy jako ostatni zostanie wydrukowany również jako ostatni. Tak zorganizowaną listę nazywamy kolejką - zasady posługiwania się nią przypominają reguły rządzące kolejką znaną z życia. Kompletny tekst programu, który wykorzystuje procedury z. przykładów 4.22 i 4.23 zamieszczamy poniżej. PROGRAM ListaUczniow; USES CRT; TYPE DziennikLekcyjny="Uczen; Uczeń =REC0RD Imię,Nazw:STRING[15] ; Wsk -.DziennikLekcyjny END; VAR Dziennik:DziennikLekcyjny; {W tym miejscu należy umieścić definicje procedur z przykładów: 4.3, 4.7, 4.22, 4.23.} BEGIN Start('TWORZENIE I DRUKOWANIE LISTY UCZNIÓW'); CzytajImNazw(Dziennik); DrukuJListe(Dziennik); Koniec . . END. {ListaUczniow} Uwaga: Tekst programu ListaUczniow znajduje się na dyskietce w pliku LISTA.PAS I ; I umieszczonym w kartotece R0ZDZ4. Proponujemy zmodyfikować program Najlepsi z p. 4.4.2 oraz rozwiązać zada- nia 4.10 i 4.11 zamieszczone na końcu rozdziału, uwzględniając zmianę struktury danych, a następnie sięgnąć do trudniejszych zadań (4.13 i 4.14). Na tym kończymy nasze rozważania dotyczące drogi, jaką trzeba przebyć od podania specyfikacji problemu do otrzymania tekstu kompletnego programu, za- pisanego w języku programowania (w naszym przypadku w języku Pascal). Nie staraliśmy się przedstawić pełnego opisu języka Pascal. Nie wszystkie elementy języka zostały omówione, a te które wystąpiły w programach objaśniliśmy tylko w stopniu umożliwiającym zrozumienie toku rozważań. Naszym celem było na- świetlenie tych zagadnień, które wiążą się z programowaniem w dowolnym języku, 154 4. Elementy programowania w języku Pascal I a często okazują się przydatne również tym osobom, które nie zamierzają progra- mować. Na zakończenie wymieńmy najważniejsze z nich: 1. Specyfikacja problemu - szczegółowe określenie danych i wyników oraz wiążącej je zależności. 2. Opracowanie algorytmu i wyodrębnienie podproblemów (podzadań). Spre- cyzowanie algorytmów realizujących poszczególne podzadania. 3. Projektowanie struktur danych. 4. Zaprojektowanie komunikacji między procedurami za pomocą parametrów. 5. Wykorzystanie podstawowych konstrukcji języka programowania do napi- sania programu. Zadania 4.1. Napisz program realizujący algorytm 4.3. 4.2. Do wykonywania działań na ułamkach jest przydatna funkcja obliczająca najmniejszą wspólną wielokrotność dwóch liczb naturalnych. Oznaczymy j ą przez NWW(a, b). Przeanalizuj naszkicowane poniżej algorytmy obliczania NWW(a, b). Dla ostatniego z nich wykaż, że otrzymana wartość jest rzeczywiście najmniejszą wspólną wielokrotnością, a algorytm zawsze kończy swoje działanie. Wybierz je- den z algorytmów, uściślij jego opis i zapisz w postaci definicji funkcji w języku Pascal o nazwie nww: 1. Począwszy od większej z liczb a i b dla kolejnej liczby naturalnej, nie większej niż a • b, sprawdź, czy a i b są jej dzielnikami. Pierwsza taka liczba napotkana jest najmniejszą wspólną wielokrotnością liczb a i b. 2. Skorzystaj z następującej zależności: NWD(o, 6)-NWW(o, b) = a-b oraz funkcji nwd z przykładu 4.6 (zob. p. 4.3). 3. Przyjmij za początkowe wartości zmiennych pomocniczych a' i b' odpowie- dnio a i b. Dopóki wartości zmiennych a' i b' są różne, powtarzaj: jeśli wartość zmiennej a' jest większa od wartości zmiennej b', zwiększ wartość b' o b, w przeciwnym razie zwiększ wartość a' o a. Końcowa wartość zmiennej a' jest najmniejszą wspólną wielokrotnością liczb a i b. 4.3. Korzystając z funkcji nwd (zob. p. 4.3), nww (zob. zad. 4.2) i procedury Skracaj (zob. p. 4.4) sformułuj algorytm i napisz program wykonujący dodawa- nie i odejmowanie ułamków. Zwróć uwagę na czytanie danych (ułamki ujemne, operatory działań) oraz na postać wyników (długość kreski ułamkowej). Przy wyprowadzaniu wyników skorzystaj z opisanej poniżej procedury standardowej języka Pascal G0T0XY zawartej w pakiecie CRT. Zadania 155 Uwaga: Procedura G0T0XY służy do wyświetlania wyników w dowolnym miej- scu na ekranie. Parametrami tej procedury są numery kolumny i wiersza, w któ- rych ma się rozpocząć wyprowadzanie tekstu. Na przykład wykonanie poniższych instrukcji spowoduje wyświetlenie słowa KONIEC w lewym górnym rogu ekranu: G0T0XY(l,l); WRITEC KONIEC) 4.4. Podaj w języku Pascal rekurencyjną definicję funkcji o nazwie Fib, której wartości są elementami ciągu zdefiniowanego następująco: ao = 1, a\ = 1, an+2 — on+i + an dla n > 2 zwanego ciągiem Fibonacciego. Jego elementami są liczby 1, 1, 2, 3, 5, 8, ... 4.5. Niektóre algorytmy dają się prosto formułować i programować w postaci rekurencyjnej, która może prowadzić do bardzo nieefektywnych obliczeń. Zo- baczmy, jak przebiega obliczanie wartości funkcji Fib zdefiniowanej w zad. 4.4. Dla parametru aktualnego o wartości 5 otrzymamy ciąg wywołań funkcji Fib po- kazany na rys. 4.5. Zauważmy, że ta sama wartość Fib (3) będzie obliczana dwa Fib(5) Fib(4) Fib(3) Fib(3) Fib(2) Fib(2) Fib(l) Fib(2) Fib(l) Fib(l) Fib(O) Fib(l) Fib(O) Fib(l) Fib(O) Rys. 4.5. Schemat rekurencyjnych wywołań funkcji Fib razy (niezależnie jedna od drugiej), a Fib(2) - trzy razy. W takich przypadkach rezygnuje się z opisu rekurencyjnego na korzyść iteracyjnego. Algorytm itera- cyjny, wykorzystując instrukcję powtarzania, liczy wartość wielkości zdefiniowa- nej rekurencyjnie począwszy od warunku początkowego. Zaproponuj iteracyjny algorytm obliczania elementu ciągu Fibonacciego i zapisz go w języku Pascal. 4.6. Sformułuj algorytm drukowania wczytanej liczby naturalnej w odwróconym porządku cyfr (np. 1234 dla wczytanej liczby 4321) i zapisz go w języku Pascal. 4.7. Opracuj algorytm sprawdzania czy dana liczba naturalna jest liczbą do- skonałą, tzn. czy jest sumą swoich dzielników mniejszych od niej samej. Napisz odpowiedni program w języku Pascal. 156 4. Elementy programowania w języku Pascal 4.8. Zaprojektuj algorytm i napisz program sprawdzający, czy w ciągu liczb występują dwie takie same. Wykorzystaj strukturę danych i procedurę czyta- nia danych z przykładu 4.11. 4.9. Zrealizuj w języku Pascal następujący algorytm zamiany zapisu liczby natu- ralnej danej w systemie dziesiętnym na zapis w systemie pozycyjnym o podstawie p(2 0 powtarzaj krok 3. 3. Wykonaj dzielenie całkowite liczby / przez p, resztę z dzielenia zapamiętaj jako kolejną cyfrę przedstawienia liczby Z w nowym systemie pozycyjnym, 4. Drukuj cyfry przedstawienia liczby I w nowym systemie pozycyjnym w od- wrotnej kolejności niż były zapamiętywane. Wskazówka: Cyfry przedstawienia liczby w nowym systemie pozycyjnym umie- szczaj w tablicy. Wystarczy użyć tablicy o rozmiarze 16, gdyż z tylu cyfr składa się zapis w systemie dwójkowym największej liczby całkowitej typu INTEGER (32767). 4.10. Połącz możliwości programów SredniaOcen z p. 4.4.1 i Najlepsi z p. 4.4.2 tak, aby średnia ocen nie była wczytywana z klawiatury, ale obliczana w progra- mie. Wymaga to oczywiście wprowadzenia ocen z poszczególnych przedmiotów dla każdego ucznia. Zmień ponadto opis procedury Szukaj Najlepszych (z przy- kładu 4.20) tak, aby można było wyszukiwać uczniów ze średnią ocen należącą do przedziału podanego przez użytkownika (np. poniżej 3.5, między 4.0 a 4.5). 4.11. Rozbuduj rekord typu Uczeń z p. 4.4.2, dopisując pole służące do pamię- tania ocen z poszczególnych przedmiotów. Dla tak zmienionej struktury danych napisz procedury: - Drukuj Średnie, która drukuje nazwiska uczniów i średnie ich ocen zgodnie z życzeniem użytkownika (wszystkie średnie lub tylko z wybranego prze- działu); - Drukuj Świadectwo, która drukuje świadectwo, czyli wykaz wszystkich ocen danego ucznia; - ObliczZestawienie, która oblicza zestawienie ocen dla każdego z przed- , miotów, tzn. liczy ile ocen celujących, bardzo dobrych, dobrych, dostatecz-l nych, miernych i niedostatecznych uzyskali uczniowie z danego przedmiotu. Umieść w odpowiednim miejscu w programie definicję i wywołanie poniższej | procedury Oferta umożliwiającej wybór jednej z dostępnych możliwości. Zadania 157 PROCEDURĘ Oferta; VAR OdprINTEGER; BEGIN WRITELN('l. Drukowanie nazwisk i średnich ocen uczniów.'); WRITELNC2. Drukowanie świadectwa wybranego ucznia.'); WRITEC3. Drukowanie zestawienia ocen z poszczególnych '); WRITELN('przedmiotów.'); WRITELN('4. Zakończenie pracy.'); WRITELN; WRITE('Wybierz numer opcji: '); READLN(Odp); CASE Odp OF 1:DrukujŚrednie; 2:DrukujŚwiadectwo; 3:ObliczZestawienie; 4:; ELSE Oferta END; -CCASE} Koniec; IF Odp<>4 THEN Oferta END; {Oferta} Uwaga: Tekst procedury Oferta znajduje się na dyskietce w pliku OFERTA.PAS umie- szczonym w kartotece ROZDZ4. W procedurze Oferta, jeśli wartość zmiennej Odp jest różna od wartości wymienionych przed dwukropkami, to jest wykonywana instrukcja umieszczona po słowie kluczowym ELSE, czyli następuje rekurencyjne wywołanie procedury Oferta. Jeśli 0dp=4, to jest wykonywana instrukcja pusta, a instrukcje następu- jące po instrukcji CASE spowodują albo zakończenie pracy programu, albo powrót do oferty programu w przypadku wybrania opcji o numerze od 1 do 3. 4.12. Zaproponuj definicję typu wskaźnikowego dla listy reprezentującej ciąg liczb rzeczywistych dowolnej długości. 4.13. Zmodyfikuj procedurę Czytaj ImNazw z p. 4.5 tak, aby tworzona lista ucz- niów była uporządkowana alfabetycznie według nazwisk. 4.14. Napisz procedurę, która usuwa z listy rekord z danymi ucznia o podanym nazwisku. Wskazówka: Procedura powinna działać poprawnie także wtedy, gdy lista jest pusta lub, gdy jest usuwany ostatni uczeń z listy lub, gdy na liście nie ma ucznia o podanym nazwisku. i i 5. ZAKŁADAMY WŁASNY KATALOG - BAZY DANYCH 5.1. Zakładamy bazę danych. Pliki Komputery umożliwiają przetwarzanie dużych ilości informacji przechowywanych w postaci zbiorów danych w pamięci zewnętrznej. Zbiór zawierający dane o ok- reślonej strukturze nazywa się bazą danych. Wiele zbiorów informacji z naszego otoczenia odpowiada ogólnemu pojęciu bazy danych, na przykład: dziennik lek- cyjny (zob. rozdz. 4), książka adresowa, zbiór rachunków za światło, katalog bi- blioteczny, wykaz części zamiennych, spis pracowników w przedsiębiorstwie itd. (por. zad. 5.1). Celem, dla którego tworzy się bazy danych w pamięci kompu- terów, jest chęć uzyskania szybkiego dostępu do informacji w nich zapamiętanych. Wykonywanie operacji na bazach danych ułatwia odpowiednia organizacja zawar- tych w nich informacji. Najmniejszym elementem, który wchodzi w skład bazy danych, jest rekord, czyli zbiór danych tworzących logiczną całość. Każda dana zajmuje w rekordzie j określone miejsce zwane polem. W języku Pascal takiemu elementowi odpowiada j zmienna typu rekordowego. Końcowy efekt przetwarzania bazy danych można wyrazić jako złożenie wszy- j stkich lub niektórych z następujących operacji: - wyszukiwanie i odczytywanie rekordów, - aktualizacja (modyfikacja) zawartości istniejących rekordów, - dołączanie (zapisywanie) nowych rekordów do bazy danych, - usuwanie rekordów z bazy danych. Zajmiemy się utworzeniem własnej bazy danych w komputerze. Będzie to I katalog książek znajdujących się w naszym księgozbiorze. Przyjmijmy, że pod-1 stawowa informacja dotycząca pojedynczej książki składa się z nazwiska i imienia| autora oraz tytułu książki. Dodatkowo chcemy również wiedzieć, czy wypoży- czyliśmy tę książkę komuś, czy też znajduje się ona na naszej półce. Informację! 5.1. Pliki 159 dotyczącą książki zapiszemy w postaci rekordu złożonego z trzech pól. Oto jego definicja w języku Pascal. Przykład 5.1. Księgozbiór opisano jako plik elementów typu Książka: TYPE Napis30 =STRING [30]; Napis50 =STRING[50]; Książka =REC0RD Autor:Napis30; Tytuł:Napis50; Jest :B00LEAN END; Ksiegozbior=FILE 0F Książka; VAR Katalog:Księgozbiór; -[zmienna odpowiadająca naszemu księgozbiorowi} Egz :Ksiazka; {reprezentacja pojedynczej książki} Uwaga: Tekst powyższych definicji typów i deklaracji zmiennych znajduje się na dys- kietce w pliku TYPY.PAS umieszczonym w kartotece R0ZDZ5. Plik w języku Pascal jest strukturą danych, która podobnie jak tablica, składa się z elementów tego samego typu (w przykładzie 5.1 są to elementy typu Książka). W przeciwieństwie do tablicy, w której liczba elementów jest z góry określona w odpowiedniej deklaracji, w przypadku pliku nie ma ograniczenia na liczbę jego elementów. Wynika stąd, że plik jest znacznie wygodniejszy od ta- blicy w sytuacjach, gdy nie potrafimy z góry przewidzieć, z jaką liczbą elementów będziemy mieli do czynienia. W zasadzie plik jest strukturą danych o dostępie sekwencyjnym1. Oznacza to, że elementy w niepustym pliku są dostępne po kolei, w danej chwili co najwyżej jeden element. W programach w języku Pascal możemy korzystać ze standardowego typu plikowego TEXT, zwanego tekstowym. Niepuste pliki tekstowe składają się z se- kwencji wierszy, a wiersze są podzielone na znaki. W tym rozdziale termin plik oznacza zmienną plikową w systemie Turbo Pa- scal, czyli zmienną typu plikowego. Natomiast plik w znaczeniu podanym w roz- dziale 2 (por. p. 2.5) nazywamy tutaj plikiem fizycznym. Plik na ogół reprezen- tuje dane przechowywane na dysku. W przeciwieństwie do danych pamiętanych np. w tablicach czy w listach, dane zapamiętane w pliku fizycznym na dysku są dostępne nie tylko w czasie działania programu, ale np. przy powtórnym jego uruchomieniu i mogą z nich korzystać również inne programy. Napisaliśmy "w zasadzie", gdyż w standardowej wersji języka Pascal pliki są właśnie tak traktowane. Można jednak spotkać pewne odstępstwa od tej zasady, np. w systemie Turbo Pascal do elementów pliku można się odwoływać poprzez numery miejsc jakie zajmują. W przykładach przedstawionych w tym rozdziale nie ma jednak potrzeby korzystania z tej możliwości. 160 5. Bazy danych Przed pierwszym użyciem pliku w programie musi być wywołana procedura ASSIGN, na przykład ASSIGN(Katalog,NazwaPliku) w której pierwszy parametr jest zmienną plikową, a drugi - jest wyrażeniem napisowym. W wyniku wykonania powyższej instrukcji zmienna Katalog zo- stanie skojarzona z fizycznym plikiem o nazwie określonej wartością parame- tru NazwaPliku. Od tej chwili każda operacja wykonana w programie na pliku Katalog odnosi się do fizycznego pliku NazwaPliku. Jeśli przenosimy informacje do (lub z) pliku, to nazwę tego pliku umie- szczamy jako pierwszy parametr procedury WRITE (lub READ), a następnymi pa- rametrami są nazwy zmiennych takiego samego typu jak elementy pliku, np. WRITE (Katalog, Egz). Z podobnym użyciem procedury WRITE spotkaliśmy się już w p. 4.1, gdzie pierwszy parametr procedury oznaczał plik związany z dru- karką (zob. także p. 2.5). Przetwarzanie plików w programie odbywa się według jednolitego schematu opisanego w następującym algorytmie. Algorytm 5.1. Przetwarzanie pliku w programie. 1. Zwiąż plik w programie z plikiem fizycznym za pomocą procedury ASSIGN, np. ASSIGN(Katalog,NazwaPliku). 2. Otwórz plik do odczytu lub zapisu. Odpowiednie czynności wykonuje proce- dura RESET lub REWRITE, np. REWRITE(Katalog) - procedury te są opisane w punkcie 5.2. 3. Następnie są wykonywane operacje odczytu lub zapisu elementów pliku za pomocą procedur READ i WRITE (a także READLN i WRITELN w przypadku plików tekstowych; por. p. 4.2), np. WRITE(Katalog,Egz). 4. Zamknij plik za pomocą procedury CLOSE, np. CLOSE(Katalog). Na końcu każdego pliku definiowanego w tym rozdziale umieszczamy ele- ment zawierający w wyróżnionym polu specjalną wartość różną od wartości znaj- dujących się w tym polu we wszystkich pozostałych elementach pliku. Taki element nazywamy powszechnie wartownikiem (dalej, tego terminu używamy również dla oznaczenia tej specjalnej wartości). Wartownik ułatwia na ogół roz- poznawanie końca danych - korzystamy z tego w procedurze PrzetwPliki. Dla zachowania jednolitości opisów algorytmów w kolejnych przykładach, związanych z tworzeniem i modyfikowaniem księgozbioru, stosujemy wartownika już od sa- mego początku zakładania bazy. Przykład 5.2. Napiszemy teraz program, który zapisuje informacje o naszym księgozbiorze w pliku Katalog. Dane będziemy wprowadzać z klawiatury, a ko- munikaty o wykonywanych operacjach będą wyświetlane na ekranie monitora. 5.1. Pliki 161 Program2 TworzeniePliku zakłada plik opisów książek. Ponieważ w kodzie ASCII najpierw występują wszystkie wielkie, a później wszystkie małe litery al- fabetu łacińskiego, dlatego za wartownika przyjmujemy napis 'zz'. Zakładamy ponadto, że nazwiska autorów i tytuły książek będą pisane tylko wielkimi albo tylko małymi literami alfabetu łacińskiego. Dzięki temu można łatwo sprawdzać alfabetyczną kolejność ciągu znaków (napisu) stosując relację np. <. Gdybyśmy chcieli używać jednocześnie małych i wielkich liter, to należałoby zmodyfikować ten i następne programy wprowadzając porównywanie napisów znak po znaku. W programach zamieszczonych w tym rozdziale korzystamy z procedur Start i KojarzeniePliku. Procedura Start wyświetla informacje o programie, które podajemy w jej wywołaniu jako parametr aktualny. Oto opis tej procedury: PROCEDURĘ Start(Nagłówek:STRING); BEGIN CLRSCR; WRITE(Nagłówek); WRITELN; WRITELN END; {Start} Procedura KojarzeniePliku kojarzy plik z plikiem fizycznym. Przyjmujemy, że nazwę pliku fizycznego będzie podawał użytkownik po wyświetleniu przez pro- gram odpowiedniego komunikatu. PROCEDURĘ KojarzeniePliku(VAR Plik:Księgozbiór; OpisPliku:STRING); -[Procedura kojarzy zmienna Plik z plikiem fizycznym (NazwaPliku) w pamięci zewnętrznej. Nazwa pliku fizycznego jest podawana przez użytkownika.} VAR NazwaPliku:STRING; BEGIN {Wartością napisu 'Podaj ... reprezentującego '+ OpisPliku jest ciąg znaków: Podaj ... reprezentującego , po którym występuje ciąg znaków będących wartością zmiennej OpisPliku. Znak dodawania + oznacza tutaj konkatenacje (czyli łączenie) dwóch napisów, polegająca na dopisaniu drugiego bezpośrednio po pierwszym.} WRITELN('Podaj nazwę pliku fizycznego reprezentującego ' + OpisPliku +'.'); W programach nie umieszczono, występującego w profesjonalnych systemach baz danych, badania poprawności danych wprowadzanych przez użytkownika. Dodanie takiej kontroli wy- magałoby znacznego rozbudowania programów, co utrudniałoby śledzenie istotnych czynności związanych z tworzeniem baz danych, które chcemy zilustrować w tym rozdziale. i — Elementy informatyki 162 5. Bazy danych READLN(NazwaPliku); ASSIGN(Plik,NazwaPliku) END; {KojarzeniePliku} Uwaga: Teksty procedur Start i KojarzeniePliku są umieszczone na dyskietce w pro- gramie TworzeniePliku, który znajduje się w pliku TWÓRZ.PAS w kartotece R0ZDZ5. Przykładowo, po wywołaniu procedury KojarzeniePliku(Katalog,'książki') jest wyświetlany napis: Podaj nazwę pliku fizycznego reprezentującego książki. i program oczekuje na podanie przez użytkownika nazwy odpowiedniego pliku fi- zycznego. Wprowadzona nazwa staje się wartością zmiennej NazwaPliku i zostaje wykorzystana w instrukcji ASSIGN(Plik.NazwaPliku). Zapamiętajmy, że w systemie Turbo Pascal parametry typu plikowego mogą być przekazywane tylko przez zmienną, dlatego w nagłówku procedury muszą być poprzedzone słowem kluczowym VAR. Poniższy program tworzy plik z infor- macjami o książkach. PROGRAM TworzeniePliku; USES CRT; CONST Wartownik='zz';{ostatni element w porządku alfabetycznym} TYPE Napis30 =STRING [30]; Napis50 =STRING[50]; Książka =REC0RD Autor:Napis30; Tytuł:Napis50; Jest :B0DLEAN END; Ksiegozbior=FILE 0F Książka; VAR Katalog:Księgozbiór; {zmienna odpowiadająca naszemu księgozbiorowi} Egz :Książka; {reprezentacja pojedynczej książki} {Tutaj należy umieścić opisy procedur Start i KojarzeniePliku omówionych w tym punkcie oraz opis procedury Koniec z przykładu 4.3.} BEGIN {Program glowny} Start('Program tworzy plik opisów książek.'); KojarzeniePliku(Katalog,'Katalog'); 5.1. Pliki 163 {otwarcie pustego pliku do zapisu} REWRITE(Katalog); {dołączanie informacji katalogowych} WRITEOAUTOR: '); READLN(Egz.Autor); WHILE Egz.AutorZmKlucz} BKlucz:=ZmKlucz; PSk.Autor:=Wartownik END; {nadano wartość zmiennej BKlucz} 174 5. Bazy danych WHILE ZmKlucz=BKlucz DO BEGIN IF PSk.Autor READ(Poprawki, Zm); ZmKlucz:=Zm.Autor+Zm.Tytuł END; {WHILE} {Wartość klucza kolejnego elementu z pliku Poprawki i pliku StaryKatalog jest większa niz BKlucz.} IF PSk.Autor |). Z kolei naciśnięcie | Enter | zamiast wpisania pierwszego znaku w pierwszym polu kolejnego rekordu bazy jest sygnałem końca wprowadzania informacji do bazy. Opiszemy teraz pokrótce sposoby korzystania z systemu dBASE na przykła- dach zadań przedstawionych w poprzednich punktach tego rozdziału. 5.5.2. Tworzenie bazy danych Tworzymy własną bazę danych - katalog książek znajdujących się w naszym księgozbiorze. Przyjmiemy, podobnie jak w programach zrealizowanych w języku Pascal, że podstawowa informacja dotycząca pojedynczej książki składa się z na- ? 180 5. Bazy danych zwiska i imienia jej autora oraz jej tytułu (por. p. 5.1). Dodatkowo będzie podana również informacja o tym czy wypożyczyliśmy komuś tę książkę, czy też znaj- duje się ona na naszej półce. Informację o książce zapiszemy w postaci rekordu złożonego z pól AUTOR i TYTUŁ typu napisowego i pola JEST typu logicznego. Definiowanie struktury nowego pliku bazy danych4 rozpoczynamy od wyda- nia polecenia CREATE nazwa-pliku Naszą bazę nazwiemy Katalog, zatem poleceniem inicjującym tworzenie no- wego pliku bazy danych jest w tym przypadku CREATE Katalog. System rozpocznie pracę od umieszczenia kursora w pierwszym polu. Możemy przystąpić do definiowania struktury rekordów bazy podając nazwy, typy i roz- miary poszczególnych pól. Typ pola, czyli typ wartości umieszczanych w tym polu, określamy podając jedną z liter: C - pole znakowe, tj. przeznaczone na napisy; N - pole liczbowe, czyli zawierające liczby; L - pole logiczne, przechowujące wartości logiczne prawdę lub fałsz; D - pole daty; M - pole notatnikowe zawierające uwagi. W naszych przykładach nie korzystamy z dwóch ostatnich typów pól. Rozmiar pola rekordu w systemie dBASE jest mierzony liczbą znaków, które mogą być umieszczone w tym polu. Rozmiar pola znakowego jest całkowitą liczbą znaków, które mogą być w nim zapisane i wynosi co najwyżej 254. Pole liczbowe może mieć rozmiar co najwyżej 19 znaków, przy czym znakami w tym przypadku są cyfry, znak liczby (+ lub —) oraz kropka dziesiętna. Liczba może mieć co najwyżej 15 cyfr po kropce. Jeśli nie podamy liczby cyfr po kropce lub jest ona równa 0, to w takim polu liczbowym można umieszczać tylko liczby całkowite. Pole logiczne ma rozmiar jednego znaku przeznaczonego na literę T (od TRUE - prawda) lub F (od FALSE - fałsz). Wprowadzimy teraz zgodne z przykładem 5.1 informacje dotyczące struktury rekordów w definiowanym przez nas pliku danych. Rekord składa się z trzech pól: AUTOR typu C i rozmiaru 30, TYTUŁ typu C i rozmiaru 50 oraz JEST typu L. Definiowanie struktury rekordu w pliku bazy danych kończymy naciśnięciem klawisza | Enter [ zamiast wprowadzenia pierwszego znaku nazwy kolejnego pola. 4System dBASE korzysta z wielu rodzajów plików, które są rozróżniane za pomocą rozszerzeń ich nazw. W tym punkcie wykorzystujemy jedynie pliki, które mają standardowe rozszerzenie DBF. Nazywamy je tutaj plikami bazy danych lub plikami danych. Ich nazwy podajemy bez rozszerzenia. 5.5. Wprowadzenie do systemu dBASE 181 System wymaga potwierdzenia tej decyzji - wyświetlając u dołu ekranu komu- nikat: Press Enter to confirm. Any other key to resume. Naciśnięcie kla- wisza |Enter| oznacza potwierdzenie, a każdego innego klawisza - powoduje powrót do dalszego definiowania struktury rekordu. Po zakończeniu definiowania struktury rekordu pojawia się pytanie: Input data records now? (Y/N) Odpowiadamy na nie twierdząco (tj. Y), jeśli chcemy zacząć wprowadzać kon- kretne dane do tworzonej bazy, czyli naśladować czynności wykonywane przez program z przykładu 5.3. Wtedy pojawia się wzorzec pól rekordu z zaznaczonym obszarem na konkretne dane. Możemy rozpocząć wprowadzanie informacji o kolejnych książkach z naszej biblioteki wypełniając pola zgodnie z wyświetlanym wzorcem. Wprowadzanie wartości do poszczególnych pól kończymy naciśnięciem klawisza | Enter |. Podob- nie kończymy tworzenie pliku bazy w momencie, gdy pojawia się nowy rekord do wypełnienia. Dane możemy podawać w porządku alfabetycznym nazwisk i imion autorów oraz tytułów książek. Zauważmy już teraz, że w systemie baz danych takim jak dBASE, w przeci- wieństwie do języka Pascal, nie musimy definiować specjalnych procedur służą- cych do tworzenia struktury rekordów bazy, wypełniania ich konkretnymi war- tościami, a także wykonywania na nich operacji. Za pomocą polecenia CREATE definiujemy strukturę rekordów pliku bazy danych oraz możemy wprowadzać do ich pól konkretne wartości. Plik utworzony za pomocą polecenia CREATE staje się aktywny. Wszystkie omawiane w tym punkcie polecenia dotyczą aktywnego pliku danych. Aby uaktywnić plik danych o nazwie nazwa-pliku, wydajemy polecenie USE nazwa-pliku zamykające jednocześnie plik danych, który był dotąd aktywny. Wydanie pole- cenia USE bez parametru zamyka otwarty (aktywny) plik danych. W aktywnym pliku danych rekord aktualnie dostępny dla poleceń nazywa się rekordem bieżącym. Można jednak określić w poleceniu, że dotyczy ono innego rekordu niż rekord bieżący. Zmiana bieżącego rekordu może być wynikiem wykonania polecenia lub efektem ubocznym innego polecenia. Na przykład: - po uaktywnieniu (otwarciu) pliku bazy danych poleceniem USE lub CREATE rekordem bieżącym jest pierwszy rekord, - po wykonaniu polecenia dotyczącego wszystkich rekordów (np. LIST) re- kordem bieżącym jest pusty rekord po ostatnim rekordzie bazy, - po wykonaniu polecenia dotyczącego grupy rekordów bieżącym jest rekord, dla którego polecenie zostało wykonane ostatnio. 182 5.5.3. Wyświetlanie zawartości bazy danych Zawartość pliku bazy danych utworzonego przez system dBASE możemy wyświet- lić, aby na przykład sprawdzić czy nie popełniliśmy błędów przy wprowadzaniu danych (podobne jest działanie procedury DrukEcho z przykładu 5.3). W tym celu wystarczy skorzystać z polecenia DISPLAY lub LIST. Jeśli nie zrobiliśmy tego dotychczas, to musimy najpierw uaktywnić plik da- nych, którym w naszym przypadku jest Katalog. Wydajemy więc polecenie USE Katalog. Struktura rekordu w aktywnym pliku danych jest wyświetlana po wydaniu polecenia lub DISPLAY STRUCTURE LIST STRUCTURE Z kolei zawartości pól rekordów w pliku danych wyświetlamy używając pole- cenia DISPLAY zakres gdzie zakres może mieć jedną z następujących postaci: ALL - oznacza wszystkie rekordy pliku danych, NEXT n - oznacza n kolejnych rekordów począwszy od bieżącego, RECORD n - oznacza rekord o numerze n, REST - oznacza wszystkie rekordy począwszy od bieżącego aż do końca. W opisanych i używanych dalej poleceniach DISPLAY, DELETE, RECALL i EDIT brak zakresu wśród parametrów oznacza przyjęcie zakresu domyślnego, którym w przypadku tych poleceń jest bieżący rekord, a w przypadku polecenia LIST - cały aktywny plik bazy danych. Możemy sprawdzić (na przykład na naszym pliku Katalog), że wydanie po- lecenia DISPLAY ALL powoduje wyświetlanie zawartości całego pliku bazy da- nych partiami po 15 rekordów (wyświetlanie jest kontynuowane po naciśnięciu dowolnego klawisza). Polecenie DISPLAY NEXT 2 powoduje wyświetlenie dwóch rekordów, tj. bieżącego i następującego po nim, a po wydaniu polecenia DISPLAY RECORD 2 jest wyświetlana zawartość tylko drugiego rekordu z pliku danych. 1 Domyślny zakres polecenia może zostać zmieniony na ALL, gdy jednym z pa-j rametrów polecenia jest fraza FOR wyrażenie. Fraza ta umożliwia wybieranie do \ przetwarzania tylko tych rekordów z danego zakresu, które spełniają warunek j określony przez wyrażenie i można ją umieścić na końcu poleceń LIST i DISPLAY, jak również w poleceniach DELETE, RECALL, EDIT, które omawiamy w dalszej 5.5. Wprowadzenie do systemu dBASE 183 części. W szczególności polecenie DISPLAY FOR wyrażenie powoduje wyświetlenie wszystkich tych rekordów z całej bazy danych, które spełniają warunek określony przez wyrażenie. Jeśli na przykład chcemy wyświetlić dane o wszystkich książkach z naszego księgozbioru Katalog napisanych przez Sienkiewicza, to wydajemy po- lecenia USE Katalog DISPLAY FOR AUT0R='Sienkiewicz' Działanie poleceń LIST i DISPLAY jest bardzo podobne. Różnica polega na tym, że - jeśli nie jest podany zakres polecenia LIST, to zakresem domyślnym są wszystkie rekordy aktywnego pliku bazy danych, a w przypadku polece- nia DISPLAY - bieżący rekord; - polecenie LIST powoduje ciągłe wyświetlanie rekordów bazy, a polecenie DISPLAY - wyświetlanie rekordów partiami. 5.5.4. Aktualizowanie bazy danych Przejdźmy teraz do uaktualniania bazy danych. Omówimy wybrane polecenia związane z włączaniem i usuwaniem danych, zmianą zawartości rekordów bazy i ich porządkowaniem (sortowaniem). Dołączanie rekordów Przypuśćmy, że aktywnym plikiem danych jest plik Katalog i chcemy dołączyć do niego informacje o nowo nabytych książkach. Uzupełnianie bazy o nowe re- kordy można zorganizować na dwa sposoby: 1. Dołączać do niej natychmiast każdy nowy rekord, gdy tylko się pojawi pełna informacja o nim. 2. Gromadzić informacje o nowych rekordach w osobnym pliku (ale o takiej samej strukturze rekordów), a następnie okresowo uaktualniać główną bazę danych informacjami z tego pomocniczego pliku. Omówimy oba sposoby w odniesieniu do naszego pliku Katalog. Plik danych, w którym będziemy gromadzić dane o nowych książkach, nazwijmy Nabytki. Plik ten można utworzyć w podobny sposób jak plik Katalog za pomocą polecenia CREATE. Istnieje jednak prostszy sposób polegający na utworzeniu pliku Nabytki i jednocześnie skopiowaniu do niego struktury rekordów z pliku Katalog. W tym celu należy wydać polecenie COPY STRUCTURE TO Nabytki gdy aktywny jest plik Katalog. 184 5. Bazy danych Dołączanie nowych książek do jednego z tych plików odbywa się podobnie. Najpierw ustalamy poleceniem USE, który plik ma być aktywny, a następnie wy- dajemy polecenie APPEND bez parametrów, które powoduje, że system będzie oczekiwał na wprowadzanie nowych danych z klawiatury. Nowe dane są dołączane do aktywnego pliku bazy danych. Jeśli zdecydowaliśmy się okresowo uaktualniać plik Katalog, to sposobem opisanym powyżej gromadzimy dane o nowych książkach w pliku Nabytki. Wy- dajemy polecenia: USE Nabytki APPEND a następnie wprowadzamy dane o książkach, które otrzymaliśmy. Wprowadza- nie kończymy naciśnięciem | Enter | zamiast wpisania informacji do kolejnego rekordu. Zawartość pliku Nabytki dołączamy co jakiś czas do pliku Katalog wy- dając polecenia USE Katalog APPEND FROM Nabytki Jeśli zawartość pliku bazy danych jest uzupełniana poleceniem APPEND, to ko- lejne rekordy są dopisywane do końca pliku. Zatem w naszym przypadku, jeśli plik danych Katalog był uporządkowany, np. względem nazwisk (i imion) au- torów oraz tytułów książek, to po dopisaniu do niego nowych rekordów porządek ten może zostać zaburzony. Pliki baz danych można jednak porządkować stosując polecenie SORT, które ustawia rekordy w porządku wyznaczonym przez zawartoś- ci wyróżnionych pól. Polecenie to ma postać SORT TO plik ON lista-pól ASCENDING lub SORT TO plik ON lista-pól DESCENDING gdzie plik jest nazwą pliku danych, do którego zostaną przepisane rekordy ak- tywnego pliku bazy w niemałej ącej (w pierwszym przypadku) lub nierosnącej (w drugim przypadku) kolejności wartości klucza w polach rekordów o nazwach wymienionych w wykazie lista-pól5. Podobny efekt, jak w pierwszym przypadku otrzymujemy wydając polecenie SORT bez określenia porządku (zobacz ciąg poleceń na następnej stronie.) 5Innym sposobem porządkowania rekordów w bazie danych, o którym nie piszemy tutaj, jest indeksowanie. 5.5. Wprowadzenie do systemu dBASE 185 Jeżeli mamy uporządkować rekordy według zawartości kilku pól, tak jak w pliku Katalog (według nazwiska i imienia autora oraz tytułu książki), to w wy- kazie pól umieszczamy nazwy tych pól w kolejności ich ważności dla przyjętego porządku. Zatem ciąg poleceń porządkujących plik Katalog będzie miał postać: USE Katalog SORT ON AUTOR,TYTUŁ TO Chwilowy USE Chwilowy COPY TO Katalog Po wydaniu ostatniego polecenia u dołu ekranu ukazuje się informacja, że baza Katalog istnieje, i pytanie czy można ją zniszczyć zapisaniem w niej nowej postaci katalogu. Decydujemy, że tak (pisząc Y). Zawartość posortowanej bazy możemy sprawdzić wydając polecenia USE Katalog i DISPLAY ALL. Plik Katalog zawiera te same rekordy co uprzednio, ale teraz są one uporządkowane alfabetycz- nie względem nazwisk (i imion) autorów oraz tytułów książek. Podobny wynik otrzymaliśmy w p. 5.3 stosując procedurę Lacz (por. przykład 5.5), która scala dwa uporządkowane pliki w jeden plik uporządkowany. Kolejnym poleceniem w systemie dBASE, które dołącza rekordy do bazy, jest INSERT. Wywołanie tego polecenia bez frazy BEFORE powoduje wstawienie dodat- kowego rekordu po bieżącym rekordzie, a w postaci INSERT BEFORE - przed bieżącym rekordem. Samo wpisywanie wartości pól w kolejnych rekordach przebiega podobnie jak w przypadku poleceń CREATE i APPEND. Rekord wstawiony staje się rekordem bieżącym. I I Usuwanie rekordów Omówimy teraz działanie poleceń, które pozwalają usuwać rekordy z pliku bazy danych. Ponieważ pliki bazy danych są zwykle traktowane jako bardzo istotne zbiory danych i źródła uporządkowanych oraz dobrze zorganizowanych informacji, to operacje zmieniające ich zawartość są obwarowane wieloma ograniczeniami i ich wykonanie wymaga pewnych przygotowań. Chodzi zwłaszcza o zabezpieczenie bazy przed przypadkowym usunięciem rekordu. Z tego powodu (jak i z powodu dużej czasochłonności przebudowywania bazy danych) operacja usuwania składa się z dwóch etapów: najpierw oznaczamy rekordy, które chcemy usunąć i do- piero po upewnieniu się, że zostały zaznaczone tylko właściwe rekordy, możemy je usunąć. Rekordy do usunięcia oznaczamy za pomocą polecenia DELETE o postaci: DELETE zakres FOR wyrażenie 186 5. Bazy danych Jeżeli w tym poleceniu nie jest podany ani zakres, ani warunek (fraza FOR), to odnosi się ono do bieżącego rekordu. Przyjmijmy teraz, że dalsze polecenia będą się odnosić do pliku Nabytki. Wydajemy więc polecenie USE Nabytki. Jeśli chcemy usunąć np. trzy rekordy począwszy od rekordu o numerze 2, to przyjmujemy go najpierw jako rekord bieżący (podając numer rekordu) a następnie zaznaczamy rekordy do usunięcia poleceniem DELETE NEXT 3 Rekordy zaznaczone do usunięcia mają gwiazdkę umieszczoną pomiędzy nu- merem rekordu a nazwą. Można to sprawdzić wykonując polecenie DISPLAY ALL. Po upewnieniu się, że oznaczone zostały tylko te rekordy, które chcemy usunąć, możemy wykonać polecenie PACK które wykonuje właściwą operację usuwania wszystkich rekordów oznaczonych do usunięcia za pomocą polecenia DELETE. Wyniki użycia polecenia DELETE (czyli oznaczenie rekordów do usunięcia) można anulować za pomocą polecenia RECALL, którego postać ogólna jest taka sama jak polecenia DELETE (z dokładnością do nazwy polecenia). Zmiany w bazie danych Wartości pól w wybranych rekordach pliku danych można zmieniać posługując się poleceniem EDIT6. Ma ono ogólną postać EDIT zakres FIELD lista FOR wyrażenie Jak już wiemy, jeśli brak jest parametru określającego zakres, to zmieniane będą zawartości pól w bieżącym rekordzie. Ponadto, jeśli w poleceniu występuje fraza FOR, to zmieniane są tylko te rekordy, dla których jest spełniony warunek określony przez podane wyrażenie. Na przykład, jeśli chcemy zmienić wartości pól AUTOR i TYTUŁ w dwóch pierwszych rekordach naszej bazy Katalog, to wpro- wadzamy następujący ciąg poleceń EDIT NEXT 2 FIELD AUTOR,TYTUŁ a następnie odpowiednio wypełniamy (lub pozostawiamy bez zmian) pola wyś- wietlane przez system. Identyczną postać ma polecenie CHANGE. Zadania 187 Pracę z systemem dBASE kończymy pisząc polecenie QUIT. Polecenie to za- myka wszystkie otwarte pliki i po jego wykonaniu sterowanie komputerem prze- nosi się na poziom, z którego przeszliśmy do korzystania z systemu dBASE. Użytkownik, który nie ma wprawy w programowaniu, może za pomocą tej nie- wielkiej liczby poznanych dotąd poleceń nie tylko uzyskiwać informacje dostępne w istniejącej bazie danych (LIST, DISPLAY) ale także założyć własną bazę danych (CREATE), usunąć z niej niepotrzebne już rekordy (DELETE, PACK), dołączyć nowe informacje (APPEND) oraz modyfikować zawartość rekordów w bazie (EDIT). Bardziej zaawansowane działania na bazach danych wymagają uprzedniego ich zaprogramowania. ;, Bazy danych, które założono, mogą być obsługiwane przez osoby nie znające programowania, jeśli tylko zostały udostępnione odpowiednio zaprogramowane systemy ich obsługi (przykładem może być obsługa kont w banku). Naszym celem w tym rozdziale było jednak opisanie w języku Pascal realizacji podstawowych operacji wykonywanych przy tworzeniu i korzystaniu z baz danych. Dysponując tymi wiadomościami osoba znająca elementy programowania w języ- ku Pascal powinna umieć samodzielnie utworzyć bazę, a korzystając z istniejącej bazy - będzie świadoma mechanizmów rządzących przetwarzaniem baz. Zadania 5.1. Podaj opis pojedynczego elementu bazy danych, która zawiera informacje dotyczące: - danych osobowych, - wyników nauczania uczniów w wybranej szkole (por. np. program SredniaOcen w p. 4.4.1), - abonentów telefonicznych, - zużycia gazu i prądu przez pojedynczych użytkowników. Jaką postać będzie miał opis bazy danych, reprezentującej dziennik lekcyjny lub jego fragment? 5.2. Omawiając aktualizację i wyszukiwanie informacji w bazie danych, zakła- damy, że jej elementy są uporządkowane według klucza. Wykorzystaj procedurę Lacz do utworzenia uporządkowanej bazy danych. 5.3. Nanieś poprawki do istniejącej bazy danych (np. abonentowi zmieniono nu- mer telefonu i należy to uwzględnić w bazie danych reprezentującej książkę telefo- niczną). Napisz procedurę aktualizującą elementy bazy danych. W tym zadaniu oraz w zadaniach 5.4 i 5.5 nie korzystaj z przykładu 5.6, lecz napisz procedurę wykonującą ten jeden określony rodzaj zmian. 188 5. Bazy danych 5.4. Podaj szczegółowy opis algorytmu przeszukiwania księgozbioru (niekoniecz- nie uporządkowanego). Interesują nas np. książki napisane przez wybranego au- tora. Napisz program, który dostarczy takich informacji. 5.5. Zdecydowaliśmy się podarować część książek z naszego księgozbioru szkolnej bibliotece. Napisz procedurę, która tylko usuwa elementy z pliku. 5.6. Utwórz, za pomocą programu TworzeniePliku z przykładu 5.2, plik za- wierający katalog książek oraz plik zawierający nowo nabyte książki. Następnie uzupełnij program o wykorzystanie procedury DrukEcłio z przykładu 5.3. 5.7. Korzystając z procedury Lacz (przykład 5.5), napisz program, który łączy pliki utworzone w zadaniu 5.6, a następnie drukuje otrzymany plik za pomocą procedury DrukEcłio. 5.8. Wykorzystując program TworzeniePliku (przykład 5.2) napisz program, który robi to samo ale dla plików, których elementy są typu Zmiana (por. przyk- ład 5.6). Uwaga: Pamiętaj o tym, że wartości typu wyliczeniowego Op=(Us,Wst,Akt) nie mogą być czytane. Można natomiast czytać pojedyncze litery (np. u, w, a) i w zależności od wprowadzonej litery nadawać zmiennej typu Op jedną z trzech | możliwych wartości: Us, Wst lub Akt. 5.9. Napisz procedurę DrukEcłio dla pliku, którego elementy są typu Zmiana | (przykład 5.6). Rozwiąż zadanie 5.6 dla plików tego rodzaju. 5.10. Napisz program, który wykorzystuje procedurę PrzetwPliki zdefiniowaną j w przykładzie 5.6. 5.11. Sprawdź, że algorytm 5.1 będzie działał poprawnie także wówczas, gdy dopuścimy możliwość występowania kilku egzemplarzy tej samej książki w pliku j Katalog lub w pliku Nabytki. 5.12. Napisz program, który przetworzy plik NowyKatalog (utworzony przez pro- gram Polacz w przykładzie 5.4) na plik, który będzie można wydrukować za po-J mocą zlecenia PRINT (systemu MS-DOS). 5.13. Zaprojektuj w systemie dBASE strukturę rekordów pliku bazy danych,j które zawierają informacje opisane w zadaniu 5.1. 5.14. W systemie dBASE, wprowadź konkretne dane do bazy (np. zawierającej informacje o abonentach telefonicznych), której struktura została określona w mą wiązaniu poprzedniego zadania. cz- m- 1 6. OBLICZENIA W MATEMATYCE - METODY NUMERYCZNE 6.1. Zadania numeryczne W pracach naukowców, konstruktorów oraz technologów często jest konieczne obliczanie wielkości określonych za pomocą skomplikowanych zależności matema- tycznych. Doskonałymi narzędziami ułatwiającymi wykonywanie takich obliczeń są współczesne komputery, które charakteryzują się tym, że - liczą bardzo szybko wykonując setki tysięcy działań arytmetycznych na se- kundę, - umożliwiają pełną automatyzację procesu obliczeniowego. W tym rozdziale zajmujemy się rozwiązywaniem za pomocą komputerów tak zwanych zadań numerycznych, które polegają na obliczaniu wielkości zdefi- niowanych za pomocą zależności matematycznych. Przystępując do rozwiązywania zadania numerycznego, na przykład rozwią- zywania równania kwadratowego ax 2 + bx + c = 0 lub obliczania wartości całki oznaczonej ,6 = / Ja I dx (1) (2) musimy najpierw opracować odpowiedni algorytm. Przyjęliśmy w poprzednich rozdziałach (por. p. 1.2), że algorytmem jest uporządkowany ciąg podstawowych operacji (lub instrukcji), które należy wykonać, by otrzymać rozwiązanie posta- wionego zadania. Pamiętać przy tym należy, zwłaszcza w przypadku zadań nu- merycznych, że komputer potrafi wykonywać tylko cztery podstawowe działania arytmetyczne: dodawanie, odejmowanie, mnożenie i dzielenie oraz kilka operacji logicznych (np. sprawdzanie czy liczba jest zerem lub czy jest większa od zera). 190 6. Metody numeryczne Algorytmy będziemy zapisywać w języku Pascal. W języku tym znajdują się niezbędne dla naszych celów funkcje standardowe, które liczą wartości ele- mentarnych funkcji matematycznych, takich jak: pierwiastek kwadratowy SQRT, funkcje trygonometryczne SIN i COS, logarytm LN i funkcja wykładnicza EXP. Stan- dardowe oznacza tutaj, że nie musimy podawać komputerowi w jaki sposób (tzn. za pomocą jakiego algorytmu) ma wyznaczać wartości tych funkcji. Kompilator języka Pascal zawiera podprogramy, które obliczają wartości funkcji standardo-j wych za pomocą tylko podstawowych działań arytmetycznych komputera. To, co dotychczas powiedzieliśmy o możliwościach komputerów, oznacza, że I opracowując algorytmy rozwiązywania zadań numerycznych możemy korzystać tylko z bardzo ubogiego zestawu możliwych działań podstawowych, nawet jeśli zapisujemy algorytmy w języku wysokiego rzędu. W przypadku równania kwa-1 dratowego (1) podanie algorytmu znajdowania jego pierwiastków jest dość proste, gdyż możemy skorzystać ze znanych wzorów zawierających wykonalne w języku! Pascal operacje arytmetyczne (algorytm ten jednak może mieć dla niektórych współczynników a, b i c złe własności numeryczne - piszemy o tym w p. 6.4). Gorzej jest z obliczaniem wartości całki (2), gdyż operacji całkowania nie znaj ani komputer, ani język Pascal. Nie znamy także żadnego sposobu wyrażenia! całki za pomocą operacji i funkcji elementarnych, z wyjątkiem tych całek, dlal których możemy wprost wyznaczyć postać funkcji pierwotnej. W wielu jednaki przypadkach nie potrafimy znaleźć tej funkcji - wtedy musimy skorzystać z me-l tody przybliżonego całkowania, która prowadzi do bardzo prostego algorytmu| obliczeń. Ale o tym powiemy dopiero pod koniec tego rozdziału. Zadania numeryczne można zwykle rozwiązywać wieloma różnymi metodami.! Nas interesować będą takie, które działają możliwie szybko, liczą z dużą dokła&l nością i zajmują mało miejsca w pamięci komputera. O takich metodach mówimyj że mają dobre własności numeryczne. W następnych punktach przeprawa dzimy analizę wybranych zadań numerycznych i ich algorytmów właśnie takim kątem. Istnieją jednak zadania, dla których każda metoda daje wyniki obarczoij dużymi błędami - są to zadania źle uwarunkowane. Przykładami takich: dań są niektóre układy równań liniowych (zob. układ równań liniowych w p. 6.4 6.2. Błędy zaokrągleń Dla uproszczenia naszych rozważań przyjmijmy, że każda liczba w komputerze je zapisana w dziesiętnym układzie pozycyjnym z s cyframi. Istnieją dwa podst| wowe sposoby pamiętania liczb w komputerze, które nazywamy reprezentacja liczb: stałopozycyjna i zmiennopozycyjna (zob. także p. 2.1). 6.2. Błędy zaokrągleń 191 Reprezentacja stałopozycyjna W tej reprezentacji liczby mają t cyfr po kropce dziesiętnej, s — t cyfr przed kropką oraz kropkę i znak. W szczególnym przypadku, gdy t = 0, reprezentacja stałopozycyjna służy do pamiętania liczb całkowitych, a dokładniej liczb, które w języku Pascal są określane mianem typu całkowitego (INTEGER). Największa liczba w tej reprezentacji składa się z s dziewiątek i ma wartość 10s — 1, a naj- mniejsza jest do niej przeciwna. Najważniejszą własnością liczb typu całkowitego i wartości wykonywanych na nich działań jest to, że jeśli mieszczą się między tymi granicznymi wartościami, to są dokładne. Reprezentacja zmiennopozycyjna Niedogodnością reprezentacji stałopozycyjnej jest niewielki zakres wartości, jakie mogą być przy jej pomocy zapamiętane. Znacznie większe liczby można pamiętać w komputerze korzystając z tak zwanej znormalizowanej postaci, w której min. są pamiętane liczby typu rzeczywistego (REAL) w języku Pascal. Re- prezentacja ta jest także stosowana na przykład przy zapisie stałych fizycznych, które są najczęściej albo bardzo małe, albo bardzo duże. Liczbę w postaci znor- malizowanej zapisujemy jako a = m • 10c (3) gdzie m jest liczbą rzeczywistą zwaną mantysą, a c jest liczbą całkowitą i nazywa się cechą liczby a. Zakłada się, że dla o^O mantysa m spełnia nierówności: 0.1 <\m < 1. (4) Dla a = 0 przyjmuje się m = 0 i c = 0. Z dwóch liczb 0.0032300678 • 104 oraz 0.3212345678-102 druga jest w postaci znormalizowanej, gdyż jej mantysa spełnia warunek (4). Mantysa i cecha są pamiętane w komputerze w reprezentacji stałopozycyjnej. Mantysa ma zero cyfr przed kropką dziesiętną, a cecha jest liczbą całkowitą. Przyjmijmy, że dla każdej liczby w reprezentacji (3) przeznacza się t cyfr na zapisanie mantysy, s — t cyfr na zapisanie cechy, ponadto zarówno przed mantysą, jak i cechą znajduje się miejsce na znak + lub — (znak + jest zwykle opuszczany). Zatem w pamięci komputera zamiast dokładnej wartości liczby a zostanie wpisana jej wartość przybliżona równa fl(a) = m • 10c (5) gdzie m jest obciętą (a dokładniej mówiąc zaokrągloną) do t cyfr mantysą m. Liczba fl(a) jest reprezentacją zmiennopozycyjna liczby a w komputerze. Do- wolne przybliżenie liczby a oznaczamy dalej symbolem a. i 192 6. Metody numeryczne Przykład 6.1. Przyjmijmy, że na mantysę przeznaczono 5 cyfr, a na cechę- jedną cyfrę. Oto trzy przykładowe liczby i ich komputerowe przybliżenia: ai = 2/3 = 0.66666(6) • 10°, fl(oi) = 0.66667 • 10°, a2 = 38.762135, fl(o2) = 0.38762 • 102, a3 = 0.124456 • 10-3, fl(a3) = 0.12446 • 10"3. ? Ponieważ liczby w reprezentacji zmiennopozycyjnej są zapisywane w kompu- terze za pomocą s cyfr, zbiór tych liczb jest skończony. Dlatego istnieje w nim liczba o największym module K. Z drugiej strony, wśród liczb różnych od zera ist- nieje również liczba o najmniejszym module k, k > 0. Oznacza to, że każda różna od zera liczba zmiennopozycyjna fl(a) reprezentowalna w komputerze, spełnia nierówności 0 < k <| fl(a) |< K. Jeśli wynik wykonania operacji arytmetycznej na liczbach zmiennopozycyjnych jest liczbą fł(o) taką, że I fl(a) !> K, to mówimy, że powstał nadmiar zmiennopozycyjny. Pojawienie się nadmiaru jest sygnalizowane przez komputer i powoduje zatrzymanie działania programu. Jeśli natomiast w obliczeniach pojawi się liczba fł(a) taka, że I n(a) |< k, to mówimy, że wystąpił niedomiar zmiennopozycyjny. W tym przypadku dzia- łanie programu nie zostaje przerwane, a wartość fł(a) jest równa zeru. Wynika stąd, że w zbiorze liczb zmiennopozycyjnych zero nie jest jednoznacznie repre- zentowane. Liczba fl(a) jest obarczona błędem powstałym przez zaokrąglenie mantysy m do i cyfr. Określimy teraz ten błąd. Najczęściej są rozważane dwa rodzaje błędów: bezwzględny i względny. Błąd bezwzględny Błąd bezwzględny ea wartości przybliżonej a jest określony wzorem ea =| a — a | . Ponieważ m jest zaokrągleniem dokładnej wartości m do t cyfr znaczących, więc m-fh |< 0.5-10"*. Stąd otrzymujemy następującą nierówność dla błędu bezwzględnego przybliżenia fl(a): e[fl(a)] =| a - rl(a) |=| m ? 10c - rh ? 10c |< 0.5 • 10"* • 10c. 6.2. Błędy zaokrągleń 193 Błąd względny Błąd względny Sa wartości przybliżonej a jest określony wzorem óa = a — a ea Korzystając z oszacowania błędu bezwzględnego i pierwszej nierówności w (4), otrzymujemy następujące oszacowanie błędu względnego przybliżenia fl(a): 6[&(a)] = a - fl(o) 0.5 • 10- m-10c 10c 0.5 • 10-* • 10c t < -----——-------= 5-10 \ 0.1 • 10c Oznaczmy u = 5 • 10 *. Wielkość ta określa względną dokładność kom- putera. Dokładność obliczeń zależy przede wszystkim od liczby t cyfr mantysy w liczbie zmiennopozycyjnej. Mówimy wówczas, że obliczenia komputerowe są wykonywane w arytmetyce i-cyfrowej. Z ostatniego oszacowania błędu wynika istnienie liczby p takiej, że | p |< u i spełniającej następującą równość: fl(a) = a(l+ /?)). Zatem można powiedzieć, że przybliżona wartość fł(a) jest równa nieco znie- kształconej (w wyniku pomnożenia jej przez liczbę bliską jedynce) wartości do- kładnej liczby a. Błąd względny daje ważną informację o liczbie przybliżonej. Wyjaśnia to następujący przykład. Przykład 6.2. Przyjmijmy za a liczbę 3.526437 i policzmy błędy względne dla kilku przybliżonych wartości a : a 5a 3 526430 2 .0 • io-6 3 .526400 1 .0 •10~5 3 526000 1 2 • io-4 3 520000 1 8 • 10-3 3 500000 0 8 ?IO-2 3 000000 1 5 • io-1 Z tego przykładu wynika, że jeśli błąd względny ba liczby przybliżonej a jest w przybliżeniu równy 10~n, to liczby a i a mają takie same n pierwszych cyfr I znaczących w mantysie. I na odwrót, jeśli liczba a i jej przybliżenie o mają takie same n pierwszych cyfr znaczących w mantysie, to błąd da jest w przybliżeniu równy lQ-n. 13 — Elementy informatyki 194 6. Metody numeryczne Jak już wspomnieliśmy, wyniki działań na liczbach w reprezentacji zmiennopo- zycyjnej, a więc w języku Pascal na liczbach typu REAL, są obarczone błędami za- okrągleń. Zakłada się, że wyniki podstawowych działań arytmetycznych spełniają następujące równości: fl(a • 6) = fl(o/6) = fl(a + 6) = b(l P2)/b, 6(1 gdzie | pi \< u, i = 1,2,3,4. Powyższe zależności należy rozumieć następu- jąco: zmiennopozycyjny iloczyn jest równy dokładnemu iloczynowi nieco znie- kształconych czynników a i 6(1 + pi). Podobnie iloraz jest równy dokładnemu ilorazowi nieco zniekształconej dzielnej a(\ + p2) i b. Zmiennopozycyjna suma jest równa dokładnej sumie nieco zniekształconych składników a(l + P3) i 6(1 + pi). Wyniki podstawowych działań arytmetycznych w większości mikrokompu- terów spełniają zależności (6). Z nich można łatwo wyprowadzić wzory na błędy względne dla poszczególnych działań. Dla mnożenia i dzielenia mamy: ab - fl(a6) ab a/b - fl(a/6) a/b Natomiast dla dodawania otrzymujemy = 1 P\ \ 4- 10"2. Stąd wynika, że przy odejmowaniu liczb mało różniących się między sobą występuje znaczny wzrost błędu względnego. Należy ten fakt mieć na uwadze przy projektowaniu algorytmów numerycznych. 6.3. Schemat Hornera. Wzory rekurencyjne Jednym z często rozwiązywanych zadań numerycznych jest obliczanie wartości wielomianu. Wynika to z ważnego faktu matematycznego, zgodnie z którym każdą funkcję ciągłą, nawet o najbardziej skomplikowanej postaci, można lo- kalnie zastąpić wielomianem, którego postać zależy od tego, jaką chcemy uzy- skać dokładność obliczeń i oczywiście od samej funkcji. Dla przykładu, wartości niektórych standardowych funkcji w języku Pascal są obliczane jako wartości od- powiednio dobranych wielomianów lub ilorazów wielomianów. Przedstawimy teraz schemat Hornera, jeden z fundamentalnych algorytmów numerycznych, który służy do obliczania wartości wielomianów. Można go także znaleźć w metodach rozwiązywania wielu innych zadań numerycznych. Za jego pomocą zilustrujemy ważną klasę zależności matematycznych zwanych wzorami rekurencyjnymi, które znajdują wiele zastosowań w informatyce. Naszym zadaniem jest obliczenie wartości wielomianu wn(x) = a\x n-1 dla ustalonej wartości argumentu x = z. Wyznaczmy najpierw liczbę dodawań (7) mnożeń potrzebnych do obliczenia wn(z) ze wzoru (7). Dla obliczenia kolejnych potęg z , z ,..., zn należy wykonać n—l mnożeń. Następnie potrzeba n mnożeń, by obliczyć wartości jednomianów a{Zn~l dla i = 0,1,..., n — 1, i n dodawań, aby je zsumować. Zatem obliczenie wartości wielomianu ze wzoru (7) wymaga wykonania In — 1 mnożeń i n dodawań. Wielomian (7) można przedstawić w innej postaci sugerującej odmienny spo- sób liczenia jego wartości. Pokażemy to najpierw na przykładzie wielomianu stopnia 3, który można zapisać następująco: = ((clqx + ai)x + a2)x + a3. 196 6. Metody numeryczne Postać ta podpowiada następujący sposób obliczania wartości wz(z): bo = ao, b\ = boz + ai, 62 = b\z + a-i, h = b2Z + a3. Szukaną wartością wielomianu jest 63. Zauważmy, że z wyjątkiem pierwszego kroku w każdym następnym są wykonywane te same działania: mnożenie po- przedniej wartości b przez z i dodanie do tego iloczynu kolejnego współczynnika wielomianu. Możemy uogólnić tę obserwację i zastosować do wielomianu dowol- nego stopnia. Otrzymamy wtedy następującą postać wielomianu: wn(x) = (? • ? a\)x + a2)x an-i)x + an (8). i odpowiadający jej sposób obliczania wartości dla argumentu z, zwany schema-J tem Homera 60 = a0, bi = bi—\z + aj, i = 1,2,... ,71, Liczba działań arytmetycznych potrzebnych do obliczenia wartości wielomianu za pomocą schematu Homera wynosi n mnożeń i n dodawań, a więc jest on-1 mnożeń mniejsza niż w przypadku stosowania metody bezpośredniej, wynikającej j z postaci (7). Wzory (9) są przykładem zależności rekurencyjnej, którą tworzą współczyn-' niki b: kolejny współczynnik bi oblicza się korzystając z wartości poprzedniegoj współczynnika 6j_i, a współczynnik bo jest równy ac. Przy okazji omawiania schematu Homera podkreślmy, że jednym z ważniej-"' szych elementów w projektowaniu wielu algorytmów jest rekurencyjny opis rozwa-' żanego zadania, oczywiście, jeśli taki opis jest możliwy. Nieraz długie obliczenia można przedstawić w zwarty sposób za pomocą krótkich wzorów rekurencyjnychj przyjmujących postać yn+i = F{Vn)- W czasie obliczeń, będących realizacją takiej zależności każda wielkość yn występuje najpierw po lewej stronie, gdy jest obliczana jej wartość, a następnie po prawej stronie, gdy służy do obliczenia wartości yn+x- Schemat Homera jest nie tylko bardzo efektywną metodą numeryczną pod względem liczby wykonywanych działań arytmetycznych, ale także ma bardzo prosty opis w języku Pascal. Zapiszemy go w postaci funkcji niestandardowej Homer, której wartością jest wn(z). Dodatkowym wynikiem działania tej funkcji jest tablica współczynników b. 6.3. Schemat Hornera. Wzory rekurencyjne 197 Na użytek funkcji i procedur występujących w tym rozdziale zdefiniujmy naj- pierw następującą stałą i typ danych: CONST NMax=50; TYPE TablicaOn=ARRAY[O. .Max] OF REAL; FUNCTION Horner(n:INTEGER;a:TablicaOn;z:REAL; VAR b:TablicaOn):REAL; {Wartością funkcji jest wartość wielomianu w postaci (7) dla argumentu z obliczona za pomocą schematu Hornera (9).} VAR i:INTEGER; BEGIN b[0]:=a[0]; FOR i:=l TO n DO Horner:=b[n] END; {Homer} Uwaga: Tekst funkcji Horner znajduje się na dyskietce w pliku HDRNER.PAS umieszczo- nym w kartotece R0ZDZ6. Wielkości 6j występujące we wzorach (9) mają bardzo ciekawą interpretację. Pozostawiamy do sprawdzenia, że prawdziwa jest następująca równość X — Z (10) Wn{x) n_1 n_2 x — z Wynika z niej, że wyrazy 6, są współczynnikami ilorazu 1JJ __-| I ^ J ^zz Qf\X i O~\ X ~T" ~T~ w 1 otrzymanego z dzielenia wielomianu wn(x) przez dwumian (x — z), &bn jest resztą z tego dzielenia. Kolejną zależność, jaką spełniają współczynniki 6j, otrzymujemy mnożąc obie strony równości (10) przez (x — z), różniczkując obustronnie i podstawiając z w miejsce x. Po lewej stronie dostajemy w'n(z), a po prawej pozostaje tylko wn-i(z). Zatem jest spełniona równość w'n(z) = wn-i(z). (U) Wynika stąd prosty sposób obliczania wartości wielomianu i jego pochodnej dla tego samego argumentu z. Należy wykonać następujące czynności: 1. Obliczyć wartość wielomianu wn(z) stosując schemat Hornera. Jako dodat- kowy wynik otrzymujemy ciąg liczb bo, b\,..., bn-\. 2. Stosując ponownie schemat Hornera, obliczyć wartość wielomianu o współ- czynnikach 6q> fri> ? • •) bn-\, która jest równa w'n(z). 198 6. Metody numeryczne 6.4. Stabilność algorytmów Wiemy już, że każda operacja arytmetyczna na liczbach typu REAL może wprowa- dzić błędy spowodowane zaokrągleniami argumentów i wyników działań. Zada- nia numeryczne wymagają na ogół wykonania setek tysięcy działań. Jeśli każde z nich lub przynajmniej znaczna ich część wprowadza błędy zaokrągleń, to mogą się one kumulować (tzn. sumować) i powodować powstawanie zauważalnych znie- kształceń wyników. W takim przypadku mówimy, że algorytm jest niestabilny. Natomiast algorytm jest stabilny, jeśli w trakcie jego wykonywania nie dochodzi do niekontrolowanej kumulacji błędów zaokrągleń. Obliczenia numeryczne mają sens jedynie w przypadku stosowania algorytmów stabilnych. 6.4.1. Pierwiastki równania kwadratowego Zakładając, że a ^ 0 możemy sprowadzić równanie (1), tj. ax2 + bx + c = 0 do ~2 postaci px + q = 0 (12) wygodniejszej w dalszych rozważaniach. Jeśli równanie (12) ma dwa różne pier- wiastki, to oblicza się je ze znanych wzorów (13) Przyjmijmy, że obliczenia są wykonywane w arytmetyce 4-cyfrowej (tzn. z 4- cyfrową mantysą), a współczynniki równania są równe p = —6.433 i q = 0.009474. Obliczanie pierwiastka x\ może przebiegać następująco: 1. a = fl[(6.433)2] = 41.38, 2. (3 = fl[4 • (0.009474)] = 0.03790, 3. 7 = fl(a -P) = 41.34, 4. a = fl(/y) = 6.430, 5.

0, to pierwiastek x\ jest liczony z większą dokładnością niż X2, natomiast dla p < 0 dokładniej będzie obliczony X2- Otrzy- mujemy stąd stabilny algorytm znajdowania pierwiastków równania kwadrato- wego, który zapiszemy poniżej w postaci procedury w języku Pascal. W pro- cedurze tej uwzględniamy także przypadek, gdy równanie nie ma pierwiastków rzeczywistych. PROCEDURĘ Rownanie2(p,q:REAL;VAR Del:B00LEAN;VAR xl,x2:REAL); {Procedura oblicza z jednakowa dokładnością pierwiastki rzeczywiste równania kwadratowego (12). Zmienna Del przyjmuje wartość TRUE, jeśli równanie ma pierwiastki rzeczywiste, i FALSE - w przeciwnym przypadku.} VAR Delta:REAL; BEGIN Delta:=p*p-4*q; Del:=Delta>=0; IF NOT Del THEN EXIT; Delta:=SQRT(Delta); IF p<0 THEN BEGIN x2:=(-p+Delta)/2; xl:=q/x2 END ELSE BEGIN 200 6. Metody numeryczne xl:=(-p-Delta)/2; x2:=q/xl END END; {Rownanie2} Uwaga: Tekst procedury Rownanie2 znajduje się na dyskietce w pliku RÓWNANIE.PAS umieszczonym w kartotece R0ZDZ6. Procedura EXIT działa podobnie jak procedura STOP w języku Logo. W zadaniu 6.6 zachęcamy do napisania procedury będącej bezpośrednią rea- lizacją wzorów (13) i porównania wartości pierwiastków otrzymanych obydwoma sposobami rozwiązywania równania kwadratowego. 6.4.2. Układ dwóch równań liniowych Omówimy teraz inne zadanie, by pokazać, że mimo użycia algorytmu stabil- nego można otrzymać rozwiązanie dość poważnie zniekształcone błędami. Źródło błędów leży teraz nie w użytej metodzie rozwiązywania a w samym zadaniu. Należy znaleźć rozwiązanie układu = a2ja\ i odejmijmy od - b2y = c2. W tym celu pomnóżmy pierwsze równanie przez di drugiego równania. Otrzymamy wówczas (14) Dla współczynników a\ = 3.000, bx = 4.127, ci = 15.41, a2 = 1.000, b2 = 1.374, c2 = 5.147 dokładnym rozwiązaniem są liczby x = 13.6658 i y = —6.2. Podobnie jak w poprzednim przykładzie wartość y wyznaczymy wykonując obliczenia w arytmetyce 4-cyfrowej: 1. a = fl(15.41/3) = 5.137, 2. /? = fl(5.147-ev) = 0.010, 3. 7 = fl(4.127/3) = 1.376, 4. a = fl(1.374 - 7) = -0.002, y = fl(/?/ 0. 202 6. Metody numeryczne Zatem ciąg liczbowy {yn} jest ciągiem malejącym o wyrazach dodatnich. Łatwo sprawdzić, że prawdziwy jest następujący wzór rekurencyjny (por. zad. 6.3) yn = l/n - 5yn-i. Z tego wzoru wynika następujący algorytm obliczania wartości yn: 1. Obliczyć 2/0 korzystając ze wzoru (15): (16) dx 2 + 5 \l= 0.182. 2. Obliczyć kolejno 2/1,2/2, • • •, 2/8 z wzoru rekurencyjnego (16). Wyniki obliczeń tym algorytmem w arytmetyce 3-cyfrowej są następujące: 3/1 = 1 — 5y0 = 0.090, 2/2 = 0.050, V3 = 0.083, 2/4 = -0.165,... Zauważmy, że wartości już pierwszych wyrazów ciągu są błędne: 2/3 jest] większe od 2/2, a 2/4 jest ujemne. Wyjaśnijmy przyczynę tak złego działania algo-J rytmu. Każde zaokrąglenie liczby do trzech cyfr znaczących powoduje powstani^ bezwzględnego błędu zaokrąglenia równego około 0.5 • 10~3. Zatem 2/0 jest obar-1 czone błędem e takim, że | e |< 0.5-10~~3, to znaczy 2/0 = 0.182 + e. Ze wzoru (16) dlań = 1 obliczamy wartość 2/1 = 1 —5yo = 1 —5(0.182+e) = 0.090+5e, która jest! już obarczona błędem 5e, czyli pięć razy większym. Licząc dalej, otrzymujemy g/2} z błędem 25e i 2/4 z błędem 625e, równym w przybliżeniu 0.3125. Zatem algorytm I będący realizacją wzoru (16) powoduje w każdym kroku zwielokrotnienie błędu j wytworzonego w poprzednim kroku. Odwróćmy teraz zależność rekurencyjną (16) tak, byśmy mogli liczyć wyrazy ] yn od końca: -yn/h. (17)1 Moglibyśmy skorzystać z tego wzoru, gdyby znane były wartości 2/8 lub Aby temu jakoś zaradzić, skorzystajmy z faktu, że {yn} jest ciągiem malejącymi o wyrazach dodatnich. Ciąg taki jest zbieżny, a zatem dostatecznie dalekie jego wyrazy są sobie bliskie. Możemy więc założyć, że z pewną dokładnością zachodzi I równość 2/9 = 2/io- Następnie użyjmy wzoru (16) do obliczenia 2/9 i skorzystajmy' z zależności (17), by policzyć interesujące nas wyrazy. Otrzymujemy wówczas 2/9 = 0.017, 2/6 = 0.025, j/3 = 0.043, yQ = 0.182, 2/8 = 0.019, j/5 = 0.028, y2 = 0.058, 2/7 = 0.021, 2/4 = 0.034, yx = 0.088, 6.5. Interpolacja 203 Zauważmy, że w ten sposób otrzymaliśmy poprawną (z dokładnością do 3 cyfr) wartość j/o- Sukces ten można wytłumaczyć tym, że w obliczeniach prowadzonych zgodnie z wzorem (17), błędy zaokrągleń w każdej iteracji są dzielone przez 5. Mamy zatem do czynienia w tym przypadku ze zjawiskiem tłumienia błędów zaokrągleń. Dzięki temu algorytm ten jest stabilny. Przykład ten pokazuje, że niektóre zależności, chociaż matematycznie równo- ważne, mogą mieć przeciwstawne własności numeryczne. 6.5. Interpolacja Wiele zjawisk w przyrodzie daje się opisać za pomocą zależności funkcyjnych. Dobrze są znane takie zależności w fizyce. Jest bardzo dobrze, jeśli zależność taka jest opisana za pomocą konkretnej funkcji danej wzorem analitycznym. Wówczas opisane zjawisko można dokładnie i wszechstronnie analizować, badając funkcję z nim związaną. Istnieją jednakże takie zjawiska, które nie dają się opisać dokładnymi zależnościami funkcyjnymi. Wówczas informacje o nich uzyskuje się z pomiarów. Przypuśćmy, że interesuje nas stężenie zanieczyszczeń jako funkcja odległości od ich źródła, którym jest dymiący komin fabryczny. W tej sytuacji możemy jedynie pomierzyć stężenie zanieczyszczeń w różnych odległościach od źródła i otrzymać następującą tablicę opisującą tę nieznaną funkcję: X Xq Xl Xl .. xn f /o h h ? gdzie Xi jest odległością od źródła zanieczyszczeń mierzoną w metrach, a fi jest stężeniem zanieczyszczającej substancji mierzonym w g/m2. Wygodniej byłoby mieć jawną zależność funkcyjną f(x), ale z kilkunastu czy nawet z kilkudziesięciu pomiarów zależności tej nie da się odtworzyć. Można natomiast zbudować inną funkcję, która niedużo będzie różniła się od poszukiwanej. Takich funkcji jest wiele. My ograniczymy swoją uwagę tylko do wielomianów n-tego stopnia wn(x) jako funkcji przybliżających, które powinny spełniać warunki wn(xi) = fi, i = 0, l,...,n, (18) zwane warunkami interpolacji. Liczby Xi nazywamy węzłami interpolacji i zakładamy, że są parami różne oraz uporządkowane rosnąco lub malejąco (jeśli ten drugi warunek nie jest spełniony, to podany dalej algorytm może być niestabilny). Wielomian wn nazywamy wielomianem interpolacyjnym. Znanych jest wiele sposobów konstruowania wielomianów interpolacyjnych. Tutaj zajmiemy się zbudowaniem wielomianu interpolacyjnego Newtona w postaci 204 6. Metody numeryczne wn(x) = -xi)... (x-xn-\) Współczynniki c« w tym wzorze można wyznaczyć korzystając z warunków (18). Obliczymy kilka początkowych z nich. Dla x = xo otrzymujemy natych- miast co = /o- Dla x = x\ otrzymujemy h = -x0), skąd ci = fi-fo xi -x0 Oznaczmy tę ostatnią wielkość przez /oi. Obliczmy jeszcze c2- W tym celu pod- stawmy X2 w miejsce x w wielomianie interpolacyjnym Newtona i skorzystajmy z warunków (18). Otrzymamy /2 = /o + (X2 - XO)foi + C2(x2 - X0)(X2 - Xl). Po podzieleniu obu stron przez (x2 — Xo)(x2 — xi) mamy /2-/0 (X2 - ___1_ 1 X2 — i -foi; — fi fi — fo --------------1------------------ /12 + /( X2 — Xo X2 - Xi Ol X2 — Xl -/or X2 - Xi /oi x2 - = /012- Wielkości /o, /oi, /oi2i • • ? jakie pojawiają się we wzorach na kolejne współ- czynniki Ci nazywają się ilorazami różnicowymi odpowiednio zerowego, pierw- szego, drugiego itd. rzędu. Można je łatwo obliczyć za pomocą następującego) wzoru rekurencyjnego Xk-Xi który umożliwia obliczanie ilorazów różnicowych dowolnego rzędu p + 1 za po mocą dwóch ilorazów różnicowych rzędu p. Jest to proces, który można łato zautomatyzować korzystając z następującej tablicy 6.5.Interpolacja 205 /o h /oi "0123 Każdy element tej tablicy, poczynając od trzeciej kolumny, jest obliczany ze wzoru (19) według schematu zaznaczonego strzałkami. Można wykazać indukcyjnie, że Ci = /oi2...i, i = 0,1,2,..., n, a zatem wielomian interpolacyjny Newtona przyjmuje ostatecznie postać n{x) = /o (x - Xj_l (20) Przykład 6.4. Korzystając z powyższych wzorów, zbudujemy wielomian interpo- lacyjny Newtona trzeciego stopnia spełniający warunki: W3(—2) = 2, 7i>3(0) = 2, U)3(l) = —4, ws(2) = —6. Tworzymy najpierw tablicę ilorazów różnicowych 2 2 0 2 0 1 -4 -6 -2 2 -6 -2 2 1 ej odczytujemy: co = /o = 2, c\ = /oi = = 0, ci = /012 : = -2, C3 = /oi23 = 1. Z wzoru (20) otrzymujemy w3(x) = 2 + 0(a; + 2) - 2(a; 4- 2)x + l(x + 2)x{x - 1). Po przekształceniu wielomian można zapisać w postaci w3(x) = x3 - x2 - 6x + 2. Wielomian interpolacyjny zbudowany dla funkcji danej w postaci tablicy jej wartości można uznać za przybliżoną postać analityczną tej funkcji. ? 206 6. Metody numeryczne Poniższa procedura InterNewton umożliwia skonstruowanie wielomianu in- terpolacyjnego Newtona (20) dla n+1 wartości funkcji i węzłów danych odpowie- dnio w tablicach c i x. Węzły interpolacji mogą należeć do ustalonego przedziału i być w nim równo rozmieszczone - nie są to jednak warunki konieczne dla po- prawnego działania tej procedury. Obliczone współczynniki wielomianu interpo- lacyjnego zostają umieszczone w tablicy c. PROCEDURĘ InterNewton(n:INTEGER;x:TablicaOn;VAR c:TablicaOn); {Procedura oblicza współczynniki c[i] wielomianu interpola- cyjnego Newtona (20), spełniającego warunki (18) dla war- tości funkcji f i wezlow interpolacji umieszczonych odpo- wiednio w tablicach c i x.} VAR i,k:INTEGER; BEGIN FOR k:=i TO n DO FOR i:=n DOWNTO k DO [ END; {InterNewton} I ; | Uwaga: Tekst procedury InterNewton znajduje się na dyskietce w pliku INTERNEW.PAS umieszczonym w kartotece R0ZDZ6. Podana niżej funkcja oblicza wartość wielomianu interpolacyjnego Newtona (20) za pomocą odpowiednio dostosowanego schematu Homera. FUNCTION InterHorner(n:INTEGER;x,c:TablicaOn;z:REAL):REAL; {Wartością funkcji jest wartość wielomianu interpolacyjnego Newtona (20), o współczynnikach i węzłach umieszczonych odpowiednio w tablicach c i x.} VAR i:INTEGER; v:REAL; BEGIN v:=c[n] ; FOR i:=n-l DOWNTO 0 DO v:=v*(z-x[i])+c[i]; InterHorner:=v END; {InterHorner} , Uwaga: Tekst procedury InterHorner znajduje się na dyskietce w pliku INTERHOR.PAS umieszczonym w kartotece R0ZDZ6. Najważniejszym zagadnieniem rozważanym w przypadku stosowania interpo- lacji jest skuteczność (mówimy także, dobroć) przybliżania nieznanej funkcji przez wielomian interpolacyjny, zbudowany na podstawie pewnej liczby wartości 6.5. Interpolacja 207 funkcji otrzymanych w określonych punktach. Jeśli interpolowana funkcja jest rzeczywiście nieznana, to trudno jest ocenić tę dobroć. Można natomiast przepro- wadzić testy i oceniać dobroć wielomianu interpolacyjnego na podstawie obliczeń wykonanych dla znanych funkcji. Poświęcimy temu resztę uwagi w tym punkcie. Zaobserwujmy najpierw na przykładzie, jakie może być wzajemne położenie wy- kresów funkcji i jej wielomianu interpolacyjnego wn (zob. rys. 6.1). Funkcją jest j[x) = 0.5 sin a: + 2, a wielomian wn ma stopień 5 i otrzymano go w przedziale [a,b] = [0.3,9.9] (porównaj wyniki zamieszczone w przykładzie 6.5). xi = 2.2 x2 = 4.1 x3 = 6.1 x4 = 8.0 Rys. 6.1. Funkcja i jej wielomian interpolacyjny = 9.9 x Z rysunku 6.1 możemy odczytać, że w węzłach interpolacji xq, x\, ..., xn są spełnione równości f(xi) = wn(xi), a w pozostałych punktach przedziału [a, b] wartości funkcji i wielomianu mogą się różnić dość znacznie. Natomiast poza przedziałem [a, b] te różnice mogą być dowolnie duże. Moduł (czyli wartość bezwzględna) największej różnicy wartości funkcji i wie- lomianu w przedziale [a, b] możemy uznać za miarę odległości między funkcją / a wielomianem wn, i oznaczamy przez p(f,w) : p(f,w) = max \f{x) - wn(x)\. xe[a,b] Wielkość ta charakteryzuje skuteczność przybliżania danej funkcji / wielo- mianem interpolacyjnym wn w przedziale [a,b]. Przybliżoną wartość odległości p wyznaczoną na podstawie 128 punktów w przedziale [a, b] oblicza następująca funkcja: 208 6. Metody numeryczne FUNCTION RoFW(n:INTEGER;a,b:REAL;x,c:TablicaOn):REAL; {Wartością funkcji jest przybliżona wartość odległości Ro(f,w) pomiędzy nielokalna funkcja f i jej wielomianem interpolacyjnym Newtona (20) w przedziale [a,b]. Węzły interpolacji i współczynniki wielomianu sa umieszczone odpowiednio w tablicach x i c. Funkcja RoFW korzysta z funkcji InterHorner.} CONST m=128; VAR t,h,Max,r:REAL; BEGIN h:=(b-a)/m; t:=a; Max:=ABS(InterHorner(n,x,c,t)-f (t)); REPEAT t:=t+h; r:=ABS(InterHorner(n,x,c,t)-f(t)); IF Max=b; RoFW:=Max END; {RoFW} I '. J Uwaga: Tekst funkcji RoFW znajduje się na dyskietce w pliku ROFW.PAS Umieszczonym w kartotece R0ZDZ6. Rozważmy teraz następujące zadanie obliczeniowe. Dla danej funkcji / zbu- dować wielomian interpolacyjny wn w przedziale [a, b] na n + 1 równoodległych węzłach i obliczyć odległość p(f, w). Na ekran wyprowadzić następujące wyniki: j stopień wielomianu n, węzły Zj, współczynniki Cj oraz odległość p(f,w). Sformułowane wyżej zadanie realizuje program Testlnterpolacji1. {$N-} PROGRAM Testlnterpolacji; USES CRT; CONST NMax=50; TYPE Tablica0n=ARRAY[0..NMax] 0F REAL; VAR a,b:REAL; n :INTEGER; x,c:TablicaOn; *Na początku tego programu pojawia się po raz pierwszy w naszych programach w języj Turbo Pascal dyrektywa (tutaj N-), która odgrywa rolę wskazówki uwzględnianej przez syst( TP w czasie tłumaczenia lub działania programu. Dyrektywa W- jest żądaniem wykonania otj czeń na wartościach typu REAL bez użycia procesora numerycznego, nawet jeśli jest zainstakra w komputerze. Dokładniejsze omówienie znaczenia dyrektyw można znaleźć w podręczn dotyczących systemu TP. 6.5. Interpolacja 209 FUNCTION f(x:REAL):REAL; BEGIN f :=0.5*SIN(x)+2 END; {W tym miejscu należy umieścić opisy procedury InterNewton i funkcji InterHorner oraz RoFW zdefiniowane powyżej.} PROCEDURĘ CzytajDane(VAR n:INTEGER; VAR a,b:REAL); VAR Error:B00LEAN; BEGIN WRITELN; WRITELNCDane:'); WRITELN(' 0 0. (Liczba e nie może być dowolnie mała, ponieważ ze względu na ograniczoną dokładność obliczeń, w tym także błędy zaokrągleń, powyższa nierówność mogłaby nie być nigdy spełniona.) sprawdzenie, czy dwa kolejne przybliżenia Xi, Xi+\ pierwiastka leżą dosta- tecznie daleko Xi — Xi+\ |> MaxErr; sprawdzenie, czy liczba iteracji przekracza zadaną maksymalną liczbę ite- racji Maxlter. 6.7. Wyznaczanie pierwiastków równania 217 Spełnienie pierwszego kryterium oznacza zbieżność metody Newtona, nato- miast przerwanie obliczeń na skutek spełnienia jednego z dwóch ostatnich wa- runków sugeruje, że metoda jest rozbieżna lub jej zbieżność jest zbyt wolna. Przykład 6.8. Zastosujemy metodę Newtona do obliczenia pierwiastka n-tego stopnia z liczby a. Zatem interesuje nas rozwiązanie następującego równania x n - a = 0. W tym przypadku f(x) = xn — a i f'(x) = nxn 1. otrzymujemy 1 Podstawiając do wzoru (24) = — \(n i = 0,1,2,... (25) gdzie xq > 0. Wzór (25) określa bardzo dobrze zachowującą się numerycznie metodę znajdowania pierwiastka n-tego stopnia z liczby a (pamiętajmy, że dla n parzystych a musi być liczbą dodatnią). Przybliżenie początkowe w tym przy- padku może być dowolną liczbą dodatnią. Za jedno z lepszych przybliżeń przyj- muje się xq = 1 + (a — l)/n. Zachęcamy do wykonania samodzielnego zadania rachunkowego (por. zad. 6.4 i p. 9.11). ? Omówimy teraz najważniejsze fragmenty programu ZeraFunkcji, który za pomocą metody Newtona (24) znajduje pierwiastki równania (23) dla dowolnej funkcji / w przedziale [a,b]. Uwaga: Tekst kompletnego programu ZeraFunkcji znajduje się na dyskietce w pliku I ; | ZERAFUNK.PAS umieszczonym w kartotece R0ZDZ6. Przebieg obliczeń w programie ZeraFunkcji wynika z rozważań przeprowa- dzonych powyżej i można wyróżnić w nim dwa etapy: - lokalizację pierwiastków metodą tablicowania (zob. przykład 6.7); - obliczanie pierwiastków metodą Newtona. Przedstawiamy poniżej teksty dwóch podprogramów wchodzących w skład programu ZeraFunkcji, które realizują obliczenia wymienionych etapów - pro- cedury Tab i funkcji Newton. Pozostałe podprogramy, to funkcje obliczające wartości funkcji / i jej pochodnej oraz procedury czytania danych i wyprowa- dzania wyników. Teksty tych ostatnich procedur są podobne do tekstów odpo- wiednich procedur w programie Testlnterpolacji (zob. p. 6.5). PROCEDURĘ Tab(a,b,h:REAL;VAR xp,xk:TablicaOn; VAR lz:INTEGER); {Procedura wyznacza w przedziale [a,b] podprzedzialy [xp[i],xk[i]], i=l,2,...,lz o długości h zawierające 218 6. Metody numeryczne zera rzeczywiste nielokalnej funkcji f, gdzie Iz jest liczba znalezionych podprzedzialow.} VAR hl,x,y,yl:REAL; BEGIN x:=a; lz:=0; WHILE x0.0} END {WHILE} END; {Tab} FUNCTION Newton(xO,Eps,MaxErr:REAL;VAR RozbrBOOLEAN; VAR MaxIter:INTEGER):REAL; {Funkcja oblicza w otoczeniu punktu xO z dokładnością Eps zero funkcji f o pochodnej pf za pomocą metody Newtona (24). Jeśli proces iteracyjny jest rozbieżny, to parametr Rozb przyjmuje wartość TRUE. Funkcje f i pf sa nielokalne. War- tością parametru Maxlter jest liczba wykonanych iteracji.} VAR xl,x2,eb:REAL; Iter :INTEGER; BEGIN eb:=1.0; Iter:=0; Rozb:=FALSE; REPEAT Iter:=Iter+l; xl:=f(xO); x2:=pf(xO); IF x2=0.0 THEN Rozb:=TRUE ELSE BEGIN 6.7. Wyznaczanie pierwiastków równania 219 xl:=x0-xl/x2; eb:=ABS(xl-xO); IF (eb>MaxErr) OR (Iter=MaxIter) THEN Rozb:=TRUE END; xO:=xl UNTIL (eb 0 i a^ jest pierwszym ujem- nym współczynnikiem wielomianu (7), a B jest największym z modułów ujemnych współczynników tego wielomianu. Wówczas jest liczbą większą od wszystkich dodatnich pierwiastków wielomianu (7). Z drugiej strony, aby wyznaczyć wartość a (lewego końca przedziału zawie-l rającego pierwiastki), możemy zastosować to samo twierdzenie do wielomianu! vn(x) = wn(-x). Na zakończenie naszych rozważań poświęconych metodom numerycznym oma-J wiamy program ZeraWielomianow wyznaczający pierwiastki równania algebra icznego wyżej opisaną metodą. I ; j Uwaga: Tekst kompletnego programu ZeraWielomianow znajduje się na dyskietce wj pliku ZERAWIEL.PAS umieszczonym w kartotece RDZDZ6. Obliczenia programem ZeraWielomianow przebiegają podobnie jak progra-1 mem ZeraFunkcji. Zasadnicze różnice są następujące: 1. Wykorzystując twierdzenie Lagrange'a można wyznaczyć przedział zawie-l rający wszystkie zera rzeczywiste wielomianu. Wykonuje to procedura] Przedział, której tekst zamieszczamy poniżej. 2. Odpowiednikami procedury Tab i funkcji Newton z programu ZeraFunkcji 1 są w programie ZeraWielomianow procedura TabWiel i funkcja NewtonWiel, w których wartości wielomianu (czyli funkcji, której zer szukamy) są obli- czane za pomocą funkcji Homer zdefiniowanej w punkcie 6.3. 6.7. Wyznaczanie pierwiastków równania 221 PROCEDURĘ Przedzial(n:INTEGER;a:TablicaOn; VAR ax,bx:REAL); {Dla wielomianu stopnia n o współczynnikach a [i], i=0,...,n, procedura wyznacza przedział [ax,bx] zawierający wszystkie jego zera rzeczywiste.} VAR i:INTEGER; b:TablicaOn; FUNCTION LimSup(n:INTEGER;a:TablicaDn):REAL; VAR i,k :INTEGER; g,r,ri,r2:REAL; BEGIN r:=a[0]; i:=0; k:=0; REPEAT i:=i+l; rl:=a[i]; IF r*rl<0 THEN k:=i UNTIL (k>0) OR (i=n); IF k=0 THEN LimSup:=0 ELSE BEGIN g:=0; FOR i:=l TO n DO BEGIN rl:=a[i]; r2:=ABS(rl); IF (r*rl<0) AND (g} END; {LimSup} BEGIN bx:=LimSup(n,a); b:=a; IF ODD(n) THEN FOR i:=0 TO (n+1) DIV 2 DO b[2*i] :=-a[2*i] ELSE FOR i:=l TO n DIV 2 DO b[2*i-l]:=-a[2*i-l]; ax:=-LiraSup(n,b) END; {Przedział} Uwaga: Tekst procedury Przedział jest fragmentem programu ZeraWielomianow, który znajduje się na dyskietce w pliku ZERAWIEL.PAS umieszczonym w kartotece R0ZDZ6. 222 6. Metody numeryczne Przykład 6.10. Programu ZeraWielomianow użyto do znalezienia miejsc zero- wych następującego wielomianu x7 - 3x6 - 12x4 - x3 + 3x2 - 12. Przyjęto krok tablicowania h=0.15, dokładność obliczania zer Eps=lE-8 oraz MaxIter=10 i MaxErr=l. Niżej prezentujemy otrzymane wyniki. Przedział zawierający zera wielomianu: [-4.46410E+00, 1.30000E+01] Wielomian ma co najmniej Iz zer rzeczywistych, gdzie lz=5. Przedział Pierwiastek Iteracje [-2.064102 ,-1.914102] -2.000000000 4 [-1.014102 ,-0.864102] -1.000000000 4 [ 0.935898 , 1.085898] 1.000000000 3 [ 1.985898 , 2.135898] 2.000000000 4 [ 2.885898 , 3.035898] 3.000000000 4 Zadania 6.1. Działania arytmetyczne na liczbach o i-cyfrowej mantysie są wykonywane we współczesnych komputerach z dokładnością do 2t cyfr, a otrzymywany wy- nik zaokrągla się do t cyfr. Na przykład dodanie liczb a = 0.1007 ? 105 oraz b = -0.9232 • 103 dla t = 4 przebiega następująco: - sprowadzanie liczb do postaci o jednakowych cechach i wykonanie dodawa- nia: r = 0.1007 • 105 + (-0.009232) • 105 = 0.091468 • 105; - normalizacja mantysy, czyli sprowadzanie mantysy do przedziału (4) oraz zaokrąglenie jej do 4 cyfr r = 0.91468 • 105, fi(a + b) = 0.9147 • 105. a. Sprawdź, że dla dodawania zmiennopozycyjnego nie zachodzi na ogół prawo łączności. W tym celu oblicz wielkości 5i = fl(a + fl(6 + c)) i S2 = fł(fł(a + b) + c) i I Zadania 223 w arytmetyce 7-cyfrowej dla liczb a = 0.1234567 • 10°, b = 0.4711325 • 104 oraz c=-b. b. Przy obliczaniu H(a + b) w części a zadania, ze względu na konieczność denormalizacji mantysy liczby a (w czasie sprowadzania liczb do jednakowych cech), wystąpiła utrata cyfr po zaokrągleniu. Stracone cyfry można odzyskać obliczając P = fl(fl(6-fi(a + 6)) + a). Oblicz P w arytmetyce 7-cyfrowej dla a i b z części a zadania. c. Poprawkę P można wykorzystać. Oblicz S = fl(P + S2) z dokładnością do siedmiu cyfr i porównaj wynik z wartością S\, gdzie S\ i S2 są wielkościami obliczonymi w części a. 6.2. Sprawdź prawdziwość równości (10) i (11). 6.3. Wykaż prawdziwość zależności rekurencyjnej (16). 6.4. Napisz program, który jest realizacją algorytmu iteracyjnego zapisanego wzo- rem (25) i nie korzysta z funkcji Newton, opisanej w p. 6.7. Umieść w programie liczenie liczby iteracji metody. Wykonaj obliczenia dla różnych liczb podpier- wiastkowych, różnych przybliżeń początkowych i różnych dokładności. Porównaj liczby wykonanych iteracji. 6.5. Bardzo ważną rolę w wielu działach metod numerycznych odgrywają wie- lomiany Czebyszewa, które najczęściej są definiowane rekurencyjnie w nastę- pujący sposób: T0(x) = 1, Ti(x) = x, Tn(x) = 2zTn_i(z) - Tn^2(x), n = 2, 3,... a. Sporządź opis niestandardowej funkcji rekurencyjnej o nagłówku FUNCTION WielCzebRek(n:INTEGER;x:REAL):REAL której wartością jest Tn(x). b. Nie korzystając z pomocy komputera oblicz wartość wielomianu Czeby- szewa Tq(1.5), stosując powyższe wzory rekurencyjne. Zauważ przy tym, że nie- które wartości wielomianów niższych stopni są liczone wielokrotnie. c. Nieefektywność z części b zadania można usunąć zamieniając rekurencyjny sposób obliczania wartości wielomianów Czebyszewa na iteracyjny. Sporządź opis niestandardowej funkcji o nagłówku FUNCTION WielCzebIter(n:INTEGER;x:REAL):REAL której wartością jest Tn(x) liczona iteracyjnie (por. zad. 4.4 i 4.5). 224 6.6. Opracuj program obliczania pierwiastków równania kwadratowego według wzorów (13). Wykonaj obliczenia i porównaj otrzymane rozwiązania z wynikami procedury Rownanie2. Przyjmij dla przykładu p = —1000.00001 i q = 0.01. 6.7. Rozwiąż w arytmetyce 3-cyfrowej następujący układ równań 0.300s + 0.212?/ = 0.890 O.lOOa; - 0.100y = -0.130 Wyznacz błędy względne obliczonych wartości niewiadomych, jeśli dokładne war- tości są równe a; = 1.2 i y = 2.5. Czy powyższy układ jest zadaniem dobrze uwarunkowanym? Odpowiedź uzasadnij. 6.8. Wzorując się na programie Testlnterpolacji, opracuj program wyzna- czający dla funkcji f(x) w przedziale [a, b] wielomiany interpolacyjne wn(x) stopni n= 1,2,... oraz obliczający dla każdego n odległość p(f,wn). Za kryterium zakończenia obliczeń przyjmij spełnienie jednego z warunków: p(f, wn) < e lub n > Maxn, gdzie e jest rzędem dokładności przybliżenia funkcji / przez wn, a Maxn jest górnym ograniczeniem na stopień wielomianu interpolacyj- nego. Wykonaj obliczenia dla następujących danych: f(x) = exp(—x2), [a,b] = [-0.25,0.25], Maxn = 10 i Eps = 1E-9. 6.9. Opracuj program porównujący skuteczność złożonych kwadratur trapezów i Simpsona. Program powinien powtarzać obliczenia całki obiema metodami, dzieląc przedział całkowania na m = 2l części, dla i = 1, 2,..., n. 6.10. Oblicz pole elipsy x'2/4 + y2/9 = 1 jako wartość odpowiedniej całki. 6.11. Dla dowolnej liczby a > 1 prawdziwy jest wzór 1 f \ F dx ln(a) = / —. J\ x Stosując wzór Simpsona dla różnych liczb podziałów przedziału całkowania, oblicz wartości ln(2), ln(2.5), In(3). Porównaj otrzymane przybliżenia z wartościami lo- garytmów wziętymi z tablic lub otrzymanymi przez odwołanie się do standardowej funkcji LN. 6.12. Oblicz pole ograniczone krzywą y = x3 + 3x — 14, osią Ox i prostą 5x + Ay = 20. Wskazówka: Wyznacz punkty przecięcia się krzywych i skorzystaj z całkowa- nia. 6.13. Za pomocą programu ZeraWielomianow znajdź wszystkie pierwiastki rze- czywiste następującego wielomianu: w5(x) = x5 - 4x - 20. 7. LICZYĆ SZYBCIEJ ALGORYTMÓW EFEKTYWNOŚĆ 7.1. Złożoność obliczeniowa Opisywane przez nas algorytmy zapewniają poprawne rozwiązywanie postawio- nych zadań. Staramy się także by były one jak najprostsze, a realizujące je programy działały jak najefektywniej, czyli także jak najszybciej. W rozdziale 4 rozważaliśmy zadanie polegające na wyznaczeniu dla dwóch danych liczb naturalnych a i b trzeciej liczby naturalnej z, oznaczonej przez NWD(a, b), będącej największym wspólnym dzielnikiem liczb a i b. Omówiliśmy tam naiwny algorytm wyznaczania liczby z oraz algorytm pochodzący od Eukli- desa i przedstawiliśmy realizację tego drugiego w języku Pascal. Uzasadniliśmy, że oba algorytmy działają poprawnie, tzn. dla każdych dwóch liczb naturalnych a i b zatrzymują się po skończonej liczbie kroków, a końcowa wartość zmiennej z jest równa NWD(a, b). Postawiliśmy sobie także pytanie, jaka jest zależność między liczbą kroków a wartościami danych a i 6 w tych algorytmach. Algorytm naiwny może w pewnych przypadkach wykonywać tyle kroków, ile wynosi mniejsza z liczb a i b, dla algorytmu Euklidesa zaś nie podaliśmy żadnej zależności, gdyż nie jest to takie łatwe. Proponujemy sprawdzić samodzielnie, dla jakich danych algorytm Euklidesa wykonuje dużą liczbę kroków a dla jakich małą (por. zad. 7.1). W następnych punktach przeanalizujemy kilka dalszych prostych zadań, al- gorytmów i programów, by zilustrować podstawowe pojęcia związane ze sposo- bami oceny efektywności algorytmów i programów. Za miarę dobroci algorytmu przyjmujemy liczbę wykonywanych w nim elementarnych operacji takich, jak do- dawanie czy porównywanie (tj. sprawdzanie prawdziwości relacji <). W przy- padku programu komputerowego efektywność jego działania można także oce- niać na podstawie czasu pracy. Obie wielkości, liczbę elementarnych operacji algorytmu i czas działania programu nazywamy miarą złożoności lub po pro- stu złożonością obliczeniową algorytmu (lub programu). Bardziej potocznie złożoność jest nazywana pracochłonnością. Złożonością algorytmu posługujemy 15 — Elementy informatyki 226 7. Efektywność algorytmów się porównując różne metody rozwiązywania tego samego zadania i często jest to najważniejsze kryterium wyboru algorytmu. Za uzasadnienie ważności naszych rozważań w tym rozdziale można przyjąć następujące dwa fakty: - spośród wielu algorytmów rozwiązujących dany problem powinniśmy umieć wybrać ten najlepszy, czyli na przykład najszybszy, - posiadanie nawet wyszukanego algorytmu rozwiązywania nie powinno wy- kluczać poszukiwań jeszcze lepszych metod rozwiązywania. Chociaż są budowane coraz szybsze komputery, to jednak istnieją problemy (np. należące do klasy problemów NP-zupełnych), których dla dużych roz- miarów danych nie można rozwiązać za pomocą żadnego z istniejących kompu- terów i są małe szansę, że sytuacja ta szybko ulegnie zmianie (por. zad. 7.4). Cała więc nadzieja w coraz efektywniejszych algorytmach. ? 7.2. Złożoność algorytmu a czas działania programu Zajmiemy się tutaj analizą złożoności obliczeń wykonywanych za pomocą pro- gramu CzasSumowania, którego główną składową jest opisana w nim funkcja Suma. Wartością tej funkcji jest YL'iLixi' ^zn- suma rn kolejnych elementów ciągu x poczynając od x\. Głównym zadaniem tego programu jest wyznaczanie czasu obliczania wartości funkcji Suma dla różnych długości sumowanego ciągu. W tym celu stosujemy procedurę standardową GETTIME oraz napisaną przez nas funkcję niestandardową PrintTime. Pierwsza z nich ma cztery parametry: g, m, s i r typu WORD (oznaczające odpowiednio godziny, minuty, sekundy i setne części sekund) i podaje aktualny czas, a wartością funkcji PrintTime jest różnica między dwoma punktami w czasie (gl,ml,sl,rl) i (g2,m2,s2,r2), wyrażona w sekundach. Zdefiniowanie funkcji PrintTime pozostawiamy do samodzielnego wykonania (zob. rozwiązanie zad. 7.3 w EI-II). {$N-> PROGRAM CzasSumowania; USES CRT.DOS; COWST MaxM=1000; TYPE TablicaR=ARRAY[l..MaxM] OF REAL; VAR j,m :INTEGER; gl.ml.sl.rl, g2,m2,s2,r2 :W0RD; r :REAL; a :TablicaR; FUNCTION Suma(m:INTEGER;x:TablicaR):REAL; 7.2. Złożoność a czas działania 227 VAR i:INTEGER; s:REAL; BEGIN {1.} s:=x[l]; FOR i:=2 TO m DO {2.} s:=s+x[i] ; {3.} Suma:=s EMD; {Suma} {Pominięty został opis funkcji niestandardowej PrintTime, zob. rozw. zad. 7.3.} BEGIN CLRSCR; REPEAT WRITE('Podaj liczbę sumowanych elementów m (m=<',MaxM,') = '); READLN(m); IF m>MaxM THEN WRITELN('Musi byc m<',MaxM) UNTIL m<=MaxM; FOR j:=l TO m DO a[j]:=RAND0M; GETTIME(gl5ml,sl,rl); r:=Suma(m,a); GETTIME(g2,m2,s2,r2); WRITELNCsuma ' ,m,' liczb =' ,r,';'); WRITELNCczas sumowania = '.PrintTime,' sek'); READLN; WRITECNacisnij dowolny klawisz'); REPEAT UNTIL KEYPRESSED END. -[CzasSumowania} Uwaga: Tekst kompletnego programu CzasSumowania znajduje się na dyskietce w pliku CZASSUMA.PAS umieszczonym w kartotece R0ZDZ7. Ten sam program może być użyty do obliczenia wartości sumy zarówno dwóch jak i tysiąca liczb, które są generowane losowo za pomocą funkcji standardowej RANDOM. Zatem długość programu, jakbyśmy jej nie mierzyli (np. liczbą wierszy), nie może reprezentować złożoności wykonywanych za jego pomocą obliczeń, gdyż dodanie dwóch liczb będzie trwało oczywiście krócej niż dodanie tysiąca liczb. Określenie złożoności algorytmu zrealizowanego w powyższym programie jest dość proste. Liczba elementarnych operacji wykonywanych w funkcji Suma zależy wprost proporcjonalnie od liczby składników sumy, tzn. im więcej liczb mamy do dodania, tym dłużej to potrwa. Możemy nawet wyznaczyć dokładną liczbę wyko- nywanych działań. W przypadku liczenia sumy najistotniejszym działaniem jest dodawanie. Funkcja Suma wykonuje m—l dodawań w pętli FOR, a więc dokładnie 228 7. Efektywność algorytmów tyle, ile znaków dodawania jest w sumie x\ + 22 + ? • ? + xm. Ponadto w trakcie obliczania wartości funkcji Suma powyższym programem, poza dodawaniem kom- puter wykonuje wiele innych operacji o różnych jednostkowych czasach działania. Wszystkie operacje można jednak podzielić na dwie zasadnicze grupy: - operacje, których liczba zależy od m (jak np. przypisania w instrukcji FOR w wierszu nr 2, - operacje, których liczba nie zależy od liczby dodawanych elementów (jak np. przypisania w wierszach nr 1 i 3). Czas działania funkcji Suma możemy więc wyrazić w postaci zależności: t(m) = Am + B, (1) gdzie we współczynniku A zostały uwzględnione czasy wykonania wszystkich ope- racji z pierwszej grupy, a we współczynniku B - operacji z drugiej grupy. Wartości tych współczynników można wyznaczyć na podstawie kilku przykładowych wy- konań programu CzasSumowania dla różnych wartości m. W tym celu, w układzie XT(12 MHz) 3000 5000 10000 15000 20000 30000 Rys. 7.1. Wykresy funkcji t{m) otrzymane dla komputerów: IBM PC/XT i AT współrzędnych o osiach odpowiadających m i t(m), nanosimy czasy obliczeń t(m) dla kilku wartości m i rysujemy prostą przechodzącą możliwie blisko tych punk- tów. Zauważmy, że to, iż sumowane liczby są generowane losowo, nie ma wpływu na wartości współczynników A i B , gdyż czas dodawania w komputerze dwóch liczb ustalonego typu (INTEGER lub REAL) jest stały i nie zależy od wartości 7.3. Dwa algorytmy optymalne 229 składników. Wartości współczynników we wzorze (1) zależą więc jedynie od ro- dzaju komputera, na którym są wykonywane obliczenia. Ilustrują to wykresy przedstawione na rys. 7.1. Zachęcamy także do wykonania własnych ekspery- mentów (por. zad. 7.5). Znajomość złożoności programu w postaci zależności czasu działania od dłu- gości danych (czyli od ich liczby) jest bardzo pożyteczna. Po pierwsze, we współ- czynnikach są uwzględnione nie tylko liczby poszczególnych operacji, ale także ich rzeczywiste czasy wykonywania. Po drugie, wzór (1) może być użyty do wyznaczenia przybliżonego czasu obliczania wartości funkcji Suma dla dowolnej liczby składników m. Na przykład, czas dodania 15 tys. liczb na komputerze IBM PC/XT odczytany z wykresu na rys. 7.1 wynosi 12.56 s, a w rzeczywistości wyniósł 12.63 s1. 7.3. Dwa algorytmy optymalne Scalanie ciągów Powróćmy do zadania, które pojawiło się w rozdz. 5 przy łączeniu dwóch plików. Procedura Lacz (por. przykład 5.5) scala ze sobą dwa pliki rekordów, w których są zapamiętane dane o książkach. Ponadto założyliśmy tam, że rekordy w pli- kach danych i w tworzonym pliku są uporządkowane alfabetycznie ze względu na nazwisko i imię autora oraz na tytuły jego książek. Uprościmy tutaj to zada- nie i zajmiemy się łączeniem dwóch ciągów złożonych z liczb i uporządkowanych zgodnie z relacją < w jeden ciąg uporządkowany tą samą relacją. Algorytm zaprogramowany w procedurze Lacz polega na przeglądaniu obu plików od początku i przenoszeniu do tworzonego pliku mniejszego z dwóch bieżących elementów. Podamy teraz ten algorytm jeszcze raz (w procedurze Scal) w wersji dostosowanej do dalszych zastosowań omawianych w p. 7.5. Róż- nica polega na tym, że rezygnujemy tutaj z użycia wartownika w ciągu liczb dla zaznaczenia końca danych. Algorytmy stają się przez to bardziej efektywne, cho- ciaż ich opis jest mniej jednorodny. Zakładamy, że uporządkowane podciągi, które mają być scalone, są umieszczone w jednej tablicy x, na miejscach od Początek do Granica—1 i od Granica do Koniec, i po scaleniu w jeden ciąg mają być umieszczone na tym samym miejscu, czyli w tablicy x na miejscach od Początek do Koniec. Zauważmy, że ciąg powstający w trakcie scalania dwóch ciągów nie może być bezpośrednio umieszczany na miejscu któregokolwiek ze scalanych ciągów, nawet jeśli oba ciągi są dane w jednej tablicy tak, jak w procedurze Scal. (Podobna 1 Zaproponuj modyfikację programu CzasSumowania tak, aby można było wyznaczać nim czas sumowania 100 tys. liczb typu REAL. 230 7. Efektywność algorytmów uwaga odnosi się także do scalania plików.) Dlatego wynik scalania musi być zapisywany w dodatkowej tablicy. W naszym przypadku jest nią tablica z. Po scaleniu ciągów, otrzymany ciąg jest z powrotem kopiowany do tablicy x, w której dane były ciągi do scalenia. PROCEDURĘ Scal(Poczatek,Granica,Koniec:INTEGER; VAR x:TablicaR); VAR i,j,l:INTEGER; z :TablicaR; BEGIN i:=Poczatek; j:=Granica; l:=Poczatek; WHILE (KGranica) AND (j<=Koniec) DO BEGIN IF x[i]<=x[j] THEN BEGIN z[l] :=x[i] ; i:=i+l END ELSE BEGIN z [1]:=x[j]; j:=j + l END; END; {dołączanie końcówki pierwszego podciągu} WHILE i 4^3. Po drugie, za miarę złożoności algorytmu przyjmujemy tylko liczbę wykonywanych porównań między elementami ciągu danych. Uściślijmy więc jeszcze nasz problem algorytmiczny. Danymi są: długość ciągu elementów m oraz liczby tworzące ten ciąg xi, X2, ? ? ?, xm. Należy znaleźć najmniejszy co do wartości element tego ciągu. Na początku, jeszcze przed wykonaniem jakichkolwiek obliczeń, każda z m danych liczb X{ może potencjalnie być najmniejszą w tym ciągu, a jako wynik powinniśmy otrzymać dokładnie jedną liczbę będącą najmniejszą w tym ciągu. Zatem nasze zadanie polega na przeprowadzeniu zbioru m elementowego X = 7.3. Dwa algorytmy optymalne 233 {xi, x%,..., xm\ w zbiór jednoelementowy utworzony z min tego zbioru. Dopu- szczamy, że X może być zbiorem z powtórzeniami, jeśli ciąg x zawiera elementy o takich samych wartościach. Ponadto przyjmujemy, że jeśli X zawiera wiele ele- mentów minimalnych, to min jest dowolnym z nich. Korzystając z tych uściśleń możemy teraz zapisać nasz problem w następującej postaci: przeprowadzić parę zbiorów (X, 0) w parę (min, X — {min}). Tej transformacji pary zbiorów odpowiada następująca zmiana ich liczebności: Możemy teraz już dość dokładnie określić możliwe kroki jakiegokolwiek al- gorytmu znajdującego min, który realizuje powyższą transformację. Algorytm taki powinien przeprowadzać parę zbiorów (X, Y) o początkowych liczebnościach (m, 0) w parę o liczebnościach (l,m — 1) stosując jedynie porównania między elementami tych zbiorów. Określmy więc, jaki wpływ na parę zbiorów (X,Y) o liczebnościach (k,l), gdzie k + I = m, ma wykonanie jednego porównania dwóch elementów należących do sumy zbiorów X i Y. Możliwe są cztery ro- dzaje porównań: a < Ca' dla a, a1 E a < C b dla a € X i 6 E b< ' a dla a e X ib E y, b< :b' dla b. b' E Y. W pierwszym przypadku, jeśli nierówność jest prawdziwa, to możemy prze- nieść a1 z X do Y, a jeśli nie (tzn. a > a'), to możemy przenieść a z X do Y. Zatem po wykonaniu porównania pierwszego rodzaju, zmniejsza się o jeden liczba elementów w zbiorze X, a zwiększa w zbiorze Y. Możemy więc scharakteryzować to porównanie przejściem (k,l) => (k — 1,1 + 1). W drugim przypadku, jeśli zachodzi a < b, to element a musi nadal pozostać w zbiorze X. W przeciwnym zaś razie, tzn. gdy a > b, rozumujemy w zależności od tego czy jest to nierówność słaba, czy ostra. Jeśli a > 6, to możemy przenieść a z X do Y, gdyż dla elementu b istnieje element a" w X spełniający a" < b, a zatem mamy a" < b < a, czyli także a" < a. Jeśli natomiast a = b, to nie mamy dość informacji, by zadecydować o tym, co zrobić z o bez porównania go z innymi elementami w zbiorze X (dokładniej, jeśli a jest jedynym najmniejszym elementem w X, to musi tam pozostać, a w przeciwnym razie można przenieść a do Y). Zatem porównania drugiego rodzaju można scharakteryzowaćprzejściem (k,ł) =>(k,l) lub (k-1,1 + 1). Podobnie można opisać trzeci rodzaj porównania. W ostatnim zaś przypadku wynik porównania nie ma żadnego wpływu na parę zbiorów (X, Y). Analizę wszy- stkich rodzajów porównań możemy więc podsumować następującym wykazem odpowiadających im przejść: 234 7. Efektywność algorytmów a < a': (k, l) = ^(Jfe- l.Z + 1), a < b: (k, 1) = >{k,l) b < a : (k, Z) = >(k,l) lub (jfe- 1,/ 1), Wynika stąd, że największe zmiany liczebności zbiorów X i Y w jednym kroku zachodzą podczas wykonywania porównań pierwszego rodzaju i - by przejść od stanu (m,0) do stanu (l,m — 1) - takich kroków należy wykonać m — 1. Wyka- zaliśmy więc prawdziwość następującego twierdzenia: Twierdzenie 7.1. Wyznaczenie najmniejszej spośród m liczb wymaga wykona- J nia co najmniej m — 1 porównań między tymi liczbami. Ponieważ w funkcji Min jest wykonywanych dokładnie m — l porównań między elementami ciągu x, zatem jest ona realizacją optymalnego algorytmu wyznacza- nia min. 7.4. Porządkowanie ciągów Porządkowanie, zwane także sortowaniem, jest jednym z najczęściej wy- konywanych zadań przez komputery. Uporządkowanie zbioru danych ułatwia korzystanie z niego, na przykład łatwiej można znaleźć w nim określony ele- ment lub wstawić nowy element z zachowaniem porządku. W komputerach porządkowane są liczby i słowa (a ogólniej napisy, czyli ciągi znaków). W pierw- szym przypadku porządkowanie polega na znalezieniu kolejności liczb zgodnej na przykład z relacją <, a w przypadku porządkowania nazw - na ustawianiu ich w porządku słownikowym (lub alfabetycznym) zwanym także leksy- kograficznym. Dla przykładu, uporządkowaniem ciągu liczb (2',—1,2",10,3,0) jest ciąg (-1,0,2',2",3,10) a także ciąg (-1,0,2",2',3,10) (primem oznaczyliśmy pierwsze pojawienie się w ciągu liczby 2, a bisem - drugie; dopuszczamy, że porządkowane ciągi mogą zawierać elementy o tych samych wartościach). Na- tomiast nazwy (kotara,tara,kotka,ara,kotek) występują w słowniku w kolejności (ara, kotara, kotek, kotka, tara). Różnica między sposobami porządkowania nazw, a porządkowaniem liczb wy- nika przede wszystkim z różnic w sposobach pamiętania porządkowanych elemen- tów. Pojedyncze znaki nazw mogą być (i najczęściej są) pamiętane w oddzielnych bajtach - mamy wtedy do nich bezpośredni dostęp i możemy z nich korzystać. Na- tomiast kolejne cyfry dziesiętne liczb (zwłaszcza typu REAL) są trudniej dostępne, gdyż w komputerze liczby są najczęściej reprezentowane przez swoje wartości, często przybliżone, a nie jako ciągi osobno pamiętanych cyfr. Porównywanie nazw może być sprowadzone do porównywania ich liczbowych kodów. Korzystaliśmy z tego w rozdz. 5 porównując jako liczby klucze rekordów 7.4. Porządkowanie ciągów 235 utworzone ze zlepienia nazwiska i imienia autora oraz tytułu książki. Dalej główną uwagę skupimy przede wszystkim na porządkowaniu liczb, a metoda koszykowa stosowana do porządkowania nazw znak po znaku w swojej najprostszej postaci jest opisana w zadaniu 7.13. Aby uściślić zadanie porządkowania liczb, wprowadźmy następujące oznacze- nia, ułatwiające także zapis algorytmów. Dany jest ciąg niekoniecznie różnych m liczb x = (xi,X2, ? ? ? ,xm) i należy znaleźć ich kolejność od najmniejszej do największej. Na przykład, dla ciągu , ?2, X3, X4, = (2',-----1,2", 10, 3, 0), jedno z szukanych uporządkowań ma postać (x2, x$, xi,x3, z5, x4) = (-1, 0, 2', 2", 3,10). W ogólnym przypadku uporządkowany ciąg jest permutacja ciągu danych, tzn. jest pewnym przestawieniem elementów ciągu z, zatem ciąg wskaźników (i\,i2, • ? •, im) jest permutacja ciągu (1,2,..., m). W naszym przykładzie mamy (*1,*2,«3,*4,«5,*6) = (2,6,1,3,5,4). Zauważmy, że rozwiązanie zadania porządkowania (tzn. kolejność elementów zgodna z relacją <) może być jednoznacznie wyznaczone przez podanie permu- tacji wskaźników określającej ten porządek. Przedstawione dalej algorytmy porządkujące wyznaczają jako rozwiązanie właściwą permutację ciągu danych. Dla wielu zastosowań jest to duże uproszcze- nie rzeczywistego problemu. Najczęściej bowiem pojawia się zadanie uporządko- wania pewnych elementów według jednej z ich cech, zwanej kluczem (por. p. 5.3). Elementy mogą mieć bardzo rozbudowaną strukturę i stanowić tylko niewielką część dużej bazy danych. Dla przykładu, na podstawie bazy danych osobowych przedsiębiorstwa możemy chcieć wydrukować listę pracownic w kolejności długości ich stażu pracy, od najkrócej pracujących. W takich przypadkach przestawianie całych elementów (czyli całego rekordu danych o pracowniku) jest bardzo cza- sochłonne lub wręcz niemożliwe. Rozwiązaniem zadania porządkowania w tym przypadku powinna więc być permutacja wskaźników elementów porządkowa- nych. Ponieważ w tym rozdziale zajmujemy się przede wszystkim złożonością algorytmów, poprzestajemy na ich najprostszych realizacjach. Algorytm porząd- kujący, który wyznacza permutację wskaźników elementów w miejsce permutacji samych elementów, jest opisany w zadaniu 7.18. 236 7. Efektywność algorytmów 1 Algorytm naiwny Podanie naiwnego algorytmu porządkowania nie powinno nikomu sprawić więk- szego kłopotu. Pamiętamy, jak się wyznacza najmniejszy lub największy element w ciągu liczb. Wystarczy więc najpierw znaleźć najmniejszy element w ciągu danych x i przenieść go z a; na początek szukanego ciągu, a w każdym następnym kroku wyznaczyć najmniejszy element wśród tych, które jeszcze pozostały w x, usunąć go z a; i dopisać na końcu tworzonego ciągu. Szczegółową realizację tej metody w języku Pascal polecamy napisać samodzielnie, por. zad. 7.14. Tutaj wyznaczymy jedynie pracochłonność tego algorytmu, czyli liczbę sprawdzanych porównań. Nasz naiwny algorytm wykonuje: m — 1 m-2 2 1 0 porównań w pierwszym kroku, porównania w drugim kroku, porównania w kroku (m — 2), porównanie w przedostatnim kroku, porównań w ostatnim kroku. Zatem całkowita liczba porównań w naiwnym algorytmie wynosi: (m - 1) + (m - 2) + ... + 2 + 1 = ((m - 1) + l)(m - l)/2 = m(m - l)/2. Ten prosty algorytm porządkowania może być ulepszony na wiele różnych sposobów. Za jedną z takich modyfikacji algorytmu naiwnego można uznać algorytm bąbelkowy. Każdy krok w tym algorytmie, nazywany przez nas przebiegiem, polega na przeglądaniu porządkowanego ciągu (a najczęściej tylko jego fragmentu) i zamianie miejscami każdych dwóch kolejnych elementów, które nie spełniają nierówności <. Ciągi porządkowane algorytmem bąbelkowym są najczęściej zapisywane w kolumnie i przeglądane od dołu do góry. Jeśli napo- tkana liczba jest mniejsza od liczby znajdującej się bezpośrednio nad nią, to liczby zamieniane są miejscami. Działanie algorytmu bąbelkowego ilustrujemy na przykładzie zamieszczonym na rys. 7.2, a jego szczegółową realizację ponownie pozostawiamy do samodziel- nego wykonania (zad. 7.15). Na rysunku zaznaczyliśmy zamiany między ele- mentami i oznaczyliśmy liniami poziomymi te miejsca w ciągu, powyżej których wszystkie liczby są już we właściwym porządku i nie ma potrzeby tego sprawdzać. W porównaniu z naiwnym algorytmem, który zgodnie z wyznaczoną złożo- nością wykonałby w tym przypadku 15 porównań, algorytm bąbelkowy wykonał jedynie 12 porównań (5, 4 i 3 odpowiednio w pierwszym, drugim i trzecim prze- biegu). Są jednak takie ciągi liczb, dla których algorytm bąbelkowy wykonuje! taką samą liczbę porównań co naiwny algorytm (por. zad. 7.16). Zauważmy, że 7.5. Porządkowanie przez scalanie pierwszy przebieg drugi przebieg trzeci przebieg 2' 2' 2' -1 -1 -1 -1 -1 -1 -1 -1 J 0 0 2" 2" 0 o o-l 2 2' 10 10-, o—l 2" 2" 2" 2 " 2" 0 J 10 10 10-, 3 3 3 3 3 3 3 J 10 10 10 237 Rys. 7.2. Ilustracja algorytmu bąbelkowego po każdym przebiegu algorytmu bąbelkowego przynajmniej jeden nowy element w porządkowanym ciągu znajduje się na właściwym miejscu. Takich elementów może być więcej i to jest właśnie źródłem większej efektywności tego algorytmu (w sensie liczby wykonanych porównań) w porównaniu z naiwnym algorytmem. Zwróćmy jednak uwagę w tym miejscu na to, że przeciwstawiamy sobie dwie metody tylko na podstawie liczby sprawdzonych porównań. Z kolei, czasy obli- czeń wykonanych tymi metodami (por. rozw. zad. 7.21 w EI-II) wskazują na odmienny charakter ich rzeczywistej pracochłonności. Spowodowane to jest tym, że w metodzie bąbelkowej, jeśli wynik porównania jest pozytywny, to porównywa- ne elementy są natychmiast zamieniane miejscami. Ponadto ta ostatnia operacja jest bardziej czasochłonna niż porównanie i jej liczba w całym algorytmie może być niewiele mniejsza od liczby porównań. Zauważmy jeszcze, że algorytm bąbelkowy porządkuje dany ciąg na miejscu (po łacinie, in situ), tzn. ciąg danych, częściowo uporządkowane ciągi pośrednie oraz ostatecznie uporządkowany ciąg mogą być pamiętane w jednej i tej samej tablicy. Tej własności nie ma na przykład operacja scalania (zob. p. 7.3) oraz wykorzystująca ją metoda sortowania przez scalanie (zob. p. 7.5). 7.5. Porządkowanie przez scalanie Poznaliśmy już dwa algorytmy porządkowania, które dla wielu ciągów wyko- nują podobną liczbę porównań. Powstaje zatem pytanie, czy wszystkie metody porządkowania mają taką samą złożoność. A może istnieją bardziej efektywne algorytmy? W tym punkcie odpowiemy twierdząco na tę ostatnią wątpliwość, a na zakończenie rozważań o porządkowaniu wykażemy w p. 7.6, że w pewnym sensie tego zadania nie można rozwiązywać szybciej. I 238 7. Efektywność algorytmów Algorytm, który chcemy teraz opisać, korzysta z algorytmu scalania dwóch uporządkowanych ciągów opisanego w p. 7.3. Wiemy już, że procedura Scal jest realizacją optymalnego algorytmu. By móc ją jednak zastosować do porządko- wania dowolnego ciągu x, musimy określić, które ciągi (uporządkowane) mają być scalane. Kwestię tę rozstrzygamy dzieląc porządkowany ciąg na dwie nie- mal równe części, które z kolei są porządkowane ... tym samym algorytmem. Postępujemy tak aż do momentu otrzymania podciągów jednoelementowych, które oczywiście są ciągami uporządkowanymi. Wtedy następuje ich scalanie niejako na drodze powrotnej. Zastosujemy więc rekurencję, o której mówiliśmy już w p. 3.6 i 4.3. Działanie algorytmu porządkowania przez scalanie jest zilu- strowane na naszym przykładzie na rysunku 7.3. (2',-l,2",10,3,0) dziel Rys. 7.3. Przykład porządkowania przez scalanie Zapiszemy teraz ten algorytm w postaci procedury ScalSort i policzymy jego złożoność. Ponieważ procedura ta ma być wywoływana rekurencyjnie dla 7.5. Porządkowanie przez scalanie 239 podciągów o różnej długości i zaczynających się w różnych miejscach ciągu x, jej paramatrami są Lewy i Prawy, odpowiednio lewy i prawy koniec porządkowane- go podciągu. By uporządkować ciąg zapisany w tablicy x[l. .m], należy zatem wywołać ScalSort (l,in,x). PROCEDURĘ ScalSort(Lewy,Prawy:INTEGER;VAR x:TablicaR); VAR Środek:INTEGER; {Tutaj należy umieścić opis procedury Scal z p. 7.3.} BEGIN IF Lewy 2, to w algorytmie można wydzielić trzy kroki: dwa z nich polegają na uporządkowaniu tą samą metodą ciągów o połowę krótszych (odpowiadają im wywołania procedury ScalSort), a trzeci - to scalanie uporządkowanych podciągów (za pomocą procedury Scal). Każdy z dwóch pierwszych kroków ma złożoność r(m/2), a w trzecim jest wykonywanych m/2 4- m/2 — 1 czyli m — l porównań. W konsekwencji otrzymujemy następującą zależność: r(m) = 2r(m/2) + m - 1 dla m > 2, (2) r(2) = 1 i r(l) = 0. W powyższym wzorze r{rń) jest wyrażone przez tę samą funkcję, lecz dla mniejszego argumentu. Jest to więc zależność rekurencyjna. Wzór ten ilustruje 240 7. Efektywność algorytmów dość częstą sytuację w analizie algorytmów, gdy złożoność algorytmu rekurencyj- nego jest wyrażona zależnością rekurencyjną. Jawną postać funkcji r(m) można otrzymać korzystając z tego samego wzoru na policzenie wartości funkcji r dla coraz mniejszych argumentów. W końcu dochodzimy do wartości m, dla której jest znana wartość liczbowa funkcji r. Prześledźmy ten sposób wyznaczania r(m). Wstawmy m/2 w miejsce m we wzorze (2) na r{m) - otrzymamy r(m/2) = 2r(m/4) + m/2 - 1, a zatem, po zastąpieniu r(m/2) w wzorze (2) prawą stroną powyższej równości dostajemy r(m) = 2(2r(m/4) + m/2 - 1) + m - 1 = 4r(m/4) + 2m - 3. Jeśli m/4 > 2, to ponownie wykonujemy operacje takie jak powyżej, ale dla argumentu m/4 we wzorze (2) zamiast m i otrzymujemy r(m) = 4(2r(m/8) + m/4 - 1) + 2m - 3 = 8r(m/8) + 3m - 7 = 23r(m/23) + 3m - (23 - 1). Postępujemy tak aż do chwili, gdy argumentem funkcji r po prawej stronie staje się 2. Wtedy możemy skorzystać z jawnej postaci r(2) = 1. Zauważmy, że argument funkcji r staje się 2 po k — 1 iteracjach (tj. po k — 1 wywołaniach rekurencyjnych). W naszym przypadku, tj. dla m = 2k, otrzymujemy więc Dzięki szczególnej postaci m mamy 2k~1 = m/2 oraz k = log2 m. A zatem r(m) = m/2 + (log2 m — l)m — m/2 + 1, i ostatecznie, po redukcji wyrazów podobnych, otrzymujemy r{m) = m log2 m — m + 1. (3) Przypomnijmy, wzór (3) został wyprowadzony przy założeniu, że liczba po- rządkowanych elementów jest potęgą liczby 2. Jeśli m nie spełnia tego warunku, to możemy przyjąć, że wartość funkcji złożoności r(m) jest ograniczona przez 7.6. Złożoność algorytmów porządkowania 241 I i r(m'), gdzie m' jest najmniejszą potęgą liczby 2 spełniającą nierówność m < m'. Wynika to z dość oczywistego faktu, że funkcja r(m) jest monotonicznie rosnąca. Złożoność algorytmu porządkowania przez scalanie jest więc mniejsza niż złożoność algorytmu naiwnego (nie uwzględniając stałych współczynników i skład- ników liniowych względem m), gdyż funkcja logarytmiczna spełnia nierówność log2 m < m. Podobnie wypada porównanie z algorytmem bąbelkowym. O tym jak duża jest to różnica, świadczą trzy pierwsze kolumny w tablicy 7.1. (Czwarta kolumna tej tablicy zostanie wykorzystana w dalszych rozważaniach.) Tablica 7.1. Wartości trzecr i funkcji złożoności m m(m- l)/2 r(m) Iog2(m!) 23 8 28 17 16 24 16 120 49 45 25 32 496 129 118 26 64 2016 321 296 100 4950 566 525 27 = 128 8128 769 717 200 19900 1330 1246 28 = 256 32640 1793 1684 7.6. Niezbędna liczba porównań w algorytmach porządkowania Uzasadnimy teraz, że algorytm porządkowania przez scalanie jest w pewnym sensie optymalny. A dokładniej, wykażemy, że funkcja złożoności obliczeniowej każdej innej metody porządkowania zawiera składnik, który ze wzrostem m rośnie co najmniej tak szybko, jak funkcja mlog2 m występująca we wzorze (3). Przypomnijmy, że zadanie uporządkowania ciągu x = (xi, X2, • • •, xm) polega na znalezieniu takiej permutacji (i\,i2, ? ? ? ,im) ciągu wskaźników (l,2,...,m), dla której mamy x^ < Xi2 < ... < Xim. Łatwo się przekonać, że rozwiązaniem problemu porządkowania może być dowolna permutacja, której postać zależy od wartości porządkowanych elementów. Na przykład, dla m = 6, jeśli rozwiązaniem ma być permutacja (3,5,1,4,6,2), to za porządkowany ciąg wystarczy przyjąć (3, 6,1,4, 2, 5). Zależność między tymi dwoma ciągami ilustruje diagram: (xh,xi2,...,Xim) =361425 (ii,i2,-.-,im) =351462 16 — Elementy informatyki 242 7. Efektywność algorytmów Zatem dla ustalonej długości m porządkowanego ciągu x liczba możliwych rozwiązań problemu porządkowania jest równa liczbie wszystkich permutacji cią- gu (1,2,..., m). Ta liczba zaś jest równa m! (czytaj m silnia) i wynosi m! = 1 • 2- ... • (m- 1) -m. Tablica 7.2. ilustruje szybkość wzrostu funkcji m! ze wzrostem m. Ponadto, w trzeciej kolumnie są podane czasy wykonania m! operacji przez komputer działający z szybkością 1 miliarda (tj. 109) operacji na sekundę. Zbudowano już takie komputery - nazywamy je superkomputerami - jest nim na przykład Cray 4, który wykonuje 100 miliardów operacji na sekundę. Tablica 7.2. Wartości silni m m! Czas obliczeń 10 15 20 25 3628800 1.3E+12 2.4E+18 1.55E+25 0.0036 s 21.8 min 77 lat 496E+6 lat Funkcja m! jest rzeczywiście bardzo szybko rosnąca. W związku z tym po- winniśmy unikać obliczeń, w których liczba działań, w zależności na przykład od długości danych m, jest proporcjonalnie związana z m\. Zauważmy, że w przy- padku porządkowania, chociaż liczba możliwych rozwiązań wynosi ml, to jednak potrafimy znaleźć właściwe uporządkowanie znacznie szybciej, na przykład me- todą bąbelkową o złożoności co najwyżej m2. Przejdźmy teraz do wyprowadzenia zapowiedzianego wniosku. Na początku zilustrujmy wszystkie możliwe drogi działania algorytmu porządkującego trzy liczby a, b i c. W tym celu posłużmy się drzewem obliczeń, w którym zawrzemy wykonywane operacje (w naszym przypadku są nimi porównania) i możliwe wy- niki działania algorytmu (por. rys. 7.4). Każde inne drzewo porządkujące ciąg liczb o ustalonej długości ma z tym drzewem przynajmniej dwie cechy wspólne: - z wierzchołka pośredniego wychodzą na dół dokładnie dwie krawędzie, - wierzchołki końcowe zawierają wszystkie możliwe permutacje porządko- wanego ciągu. Ta pierwsza własność wynika stąd, że wierzchołki pośrednie w drzewie za- wierają porównania, a rezultatem wykonania tej operacji jest jedna z dwóch możliwych odpowiedzi: Tak (T) lub Nie (N). Operacje takie nazywają się bi- narnymi, a drzewo obliczeń złożonych z operacji binarnych nazywa się drze- wem binarnym. Druga zaś własność jest związana z tym, że każdy algorytm 7.6. Złożoność algorytmów porządkowania 243 korzeń — — — — — —?- a < b Tak wierzchołki pośrednie (c,a,b) wierzchołki-------?? (a, b, c) (a, c, b) (b, c, a) (b, a, c) końcowe Rys. 7.4. Drzewo algorytmu porządkującego trzy liczby porządkujący musi uwzględniać wśród swoich wyników wszystkie możliwe ko- lejności porządkowanych elementów. Możemy więc przyjąć, że z dowolnym al- gorytmem porządkowania m liczb jest związane drzewo binarne, które ma co najmniej m! wierzchołków końcowych. Zastanówmy się teraz, co odpowiada złożoności algorytmu w tym modelu porządkowania. Powróćmy do ilustracji z rys. 7.4. Algorytm tam przedstawiony wykonuje dwa porównania, gdy wynikami są uporządkowania (c,a,b) i (c,b,a), a trzy porównania w pozostałych przypadkach. Liczba porównań sprawdzonych, by otrzymać wynik w ustalonym wierzchołku końcowym, jest więc równa liczbie wierzchołków pośrednich na drodze z korzenia do tego wierzchołka. Uzasadnia to przyjęcie za złożoność algorytmu przedstawionego w postaci drzewa liczby wierz- chołków w najdłuższej drodze z korzenia do wierzchołka końcowego - wielkość tę nazywamy w drzewie jego wysokością. Zatem złożoność algorytmu, któremu odpowiada drzewo z rys. 7.4 jest równa wysokości tego drzewa i wynosi 3. Za- uważmy, że w niektórych przypadkach obliczeń, algorytm może wykonywać mniej operacji niż wynosi jego złożoność, ale nigdy więcej. Przyjęte przez nas określenie złożoności algorytmu nazywa się pesymistyczną złożonością, gdyż jest ona największą liczbą wykonywanych operacji, wziętą po wszystkich możliwych wy- nikach działania algorytmu przy ustalonej długości danych. Z podobną sytuacją spotkaliśmy się już przy scalaniu ciągów. Podsumujmy dotychczasowe rozważania. Dowolny algorytm porządkujący m liczb, którego podstawową operacją jest porównanie dwóch liczb, można przed- 244 7. Efektywność algorytmów stawić w postaci drzewa binarnego z przynajmniej m\ wierzchołkami końcowymi, a za jego złożoność przyjmujemy wysokość tego drzewa. Zatem drzewo o mniej- szej wysokości odpowiada lepszemu (tj. szybszemu) algorytmowi. Pokażemy, że takie drzewo nie może mieć mniejszej wysokości niż log2m!. Prześledźmy najpierw na kilku przykładach (por. rys. 7.5.), jak wyglądają najniższe drzewa binarne o liczbie wierzchołków końcowych 2, 3,4, 5 i 6. Drzewa te konstruujemy w taki sposób, że do następnego poziomu przechodzimy dopiero po wypełnieniu poprzedniego. Za poziom w drzewie binarnym przyjmujemy zbiór tych wierzchołków, dla których droga do korzenia ma taką samą liczbę wierz- chołków pośrednich. Zauważmy, że każdy poziom może mieć co najwyżej dwa razy więcej wierzchołków niż poprzedni, a zatem kolejne poziomy w najniższych drzewach binarnych zawierają 1, 2, 22, 23, 24,... wierzchołków. Rys. 7.5. Najniższe drzewa binarne Aby policzyć, ile poziomów musi mieć drzewo zawierające m! wierzchołków końcowych, skorzystamy z prostego faktu, że każde drzewo binarne o n wierz- chołkach końcowych ma n — 1 wierzchołków pośrednich. Przykłady drzew bi- narnych z rys. 7.4 i 7.5. potwierdzają ten fakt, a indukcyjny dowód ogólnej własności pozostawiamy do samodzielnego wykonania (por. zad. 7.20). Zatem drzewo binarne o przynajmniej m! wierzchołkach końcowych ma co najmniej 2ml — 1 wszystkich wierzchołków. Ponieważ drzewo o k poziomach ma co najwyżej 1 + 2 + 2 + ... + 2 wszystkich wierzchołków, zatem musimy znaleźć najmniejsze k spełniające nierówność: 2m! - 1 < 1 + 2 + 22 Zadania 245 Zsumujmy prawą stronę jako szereg geometryczny o ilorazie 2, wykonajmy zaznaczone działania i zlogarytmujmy obie strony: 2m! - 2m! - 2fc+1 - m! log2 ml < k Zatem drzewo binarne o przynajmniej m! wierzchołkach końcowych ma wy- sokość co najmniej log2 ml. Ten sam wniosek w języku algorytmów porządkowa- nia sformułujemy jako twierdzenie. Twierdzenie 7.2. Jakikolwiek algorytm porządkowania m liczb wykonuje co naj- mniej log2 m\ porównań między elementami porządkowanego ciągu. Wyrażenie log2 ml jest w przybliżeniu równe mlog2m (wynika to ze wzoru Stirlinga na przybliżoną wartość ml, którego tutaj nie podajemy), a jego wartości dla kilku m są podane w tablicy 7.1. Przy okazji porównajmy wartości w czwartej kolumnie tablicy 7.1 z odpowiednimi wartościami w kolumnach drugiej i trzeciej - te pierwsze rzeczywiście ograniczają od dołu złożoności algorytmów naiwnego i przez scalanie, którym odpowiadają dwie środkowe kolumny, Powróćmy na zakończenie do procedury ScalSort. Z jednej strony wy- kazaliśmy, że jej złożoność wynosi mlog2m — m + 1. Z drugiej zaś, wartość tego wyrażenia w porównaniu z wartością log2 m! różni się jedynie składnikiem rosnącym wolniej. Mamy więc podstawy stwierdzić, że algorytm porządkowania przez scalanie jest optymalny z dokładnością do stałego współczynnika. Uzupełnieniem rozważań o złożoności algorytmów porządkujących i potwier- dzeniem postaci otrzymanych dla nich funkcji złożoności mogą być obliczenia te- stowe przeprowadzone z komputerowymi realizacjami algorytmów (por. zad. 7.21). Zadania 7.1. Dobierz takie wartości liczb naturalnych a i b, aby algorytm Euklidesa wyko- nywał możliwie dużą i możliwie małą liczbę kroków. Wszystkie obliczenia prze- prowadź bez użycia komputera. 7.2. Zmodyfikuj opis funkcji Suma w programie CzasSumowania tak, by ta nowa funkcja działała poprawnie nawet wtedy, gdy m=0. Jaka jest złożoność zmodyfi- kowanej funkcji? 7.3. Zmodyfikuj program CzasSumowania tak, aby obliczał sumę liczb umieszczo- nych w pliku. 246 7. Efektywność algorytmów 7.4. Przyjmij, że dysponujesz sześcioma algorytmami Ai,A%,... ,Aq, które wy- I konują odpowiednio lOOOre, 100nlog2n, lOn n , n i 2n podstawowych operacji, by wyznaczyć rozwiązanie problemu określonego za pomocą n danych. a. Policz, ile czasu zajmie wykonanie obliczeń tymi algorytmami dla n = 10, 20, 50, 100, 500,1000 danych za pomocą komputera, który liczy z szybkością 100 min operacji na sekundę. b. Przyjmij, że Sj jest największym rozmiarem (tj. liczbą danych) zadania, jakie możesz rozwiązać na swoim komputerze używając algorytmu Ai i określ, 0 ile wzrośnie rozmiar zadań rozwiązywalnych tym algorytmem, gdy wymienisz komputer na dziesięć razy szybszy. Uwaga: Zadanie to ma Cię przekonać, że większe korzyści można mieć z polep- szania (czyli przyspieszania pracy) algorytmów niż z przyspieszania pracy kom- puterów, co staje się bardzo kosztowne i trudno oczekiwać, by szybkość pracy komputerów dawało się tak często polepszać i to aż o tak wiele jak rząd wielkości. 7.5. Wykonaj obliczenia programem CzasSumowania na swoim komputerze (naj- lepiej innym niż IBM PC/XT lub AT). Czasy działania otrzymane dla różnych m nanieś na wykres z rys. 7.1 i dopasuj do nich prostą określoną wzorem (1). Policz jej współczynniki i porównaj ze współczynnikami prostych z rysunku 7.1. 7.6. Zrealizowany w funkcji Suma algorytm obliczania sumy m liczb nazywa się metodą od-lewej-do-prawej, gdyż liczy sumy częściowe począwszy od x\ i po- suwa się na prawo ku xm. Rozważ metodę obliczania wartości sumy, w której na każdym kroku są dodawane do siebie dwie sąsiednie liczby. Zatem po pierwszym kroku sumowany ciąg składa się z [m/2] liczb i powtarzamy to postępowanie aż pozostanie jeden element. (Wyrażenie [m/2] jest równe najmniejszej liczbie całkowitej, równej lub większej niż m/2). Przekonaj się, że jest nim wartość sumy dodawanych elementów. Na przykład, z ciągu (3, 7,4, 5, 9) po pierwszym kroku tej metody pozostaje ciąg (3 + 7,4+5,9) = (10, 9, 9), po drugim - (10+9,9) = (19,9) 1 ostatecznie otrzymujemy 28. Określ, ile dodawań w zależności od m wykonuje ten algorytm i zapisz go jako procedurę w języku Pascal. 7.7. Dowolny algorytm sumowania można przedstawić w postaci drzewa obli- czeń, które składa się z wierzchołków i krawędzi między nimi. W wierz- chołkach zwanych końcowymi znajdują się argumenty działań, a w wierzchołkach pośrednich - działania. Krawędzie zaś odzwierciedlają kierunek przebiegu in- formacji w algorytmie. Na rysunku 7.6 jest zilustrowany algorytm dodawania sześciu liczb metodą od-lewej-do-prawej. Narysuj drzewa obliczeń dla algorytmu z zadania 7.6 dla m = 5, 6, 7, 8. 7.8. W jakich przypadkach procedura Scal wykonuje najmniej porównań, a kiedy najwięcej? Postaraj się przekonująco uzasadnić swoją odpowiedź. Zadania 247 Xl X2 Rys. 7.6. Drzewo dodawania od-lewej-do-prawej 7.9. Wartość jakiego wyrażenia liczy następujący ciąg instrukcji? s:=0.0; FOR i:=l TO m DO s:=s+3.0*x[i]*y*SIN(3.0*3.1415926/2.0) Zmodyfikuj ten fragment tak, by działał szybciej. Sprawdź na swoim komputerze, jaki osiągnąłeś zysk na czasie dla różnych wartości m. Sformułuj ogólny wniosek. 7.10. Uzupełnij opis funkcji Min o dodatkowe instrukcje wyznaczające jedno- cześnie wskaźnik minimalnego elementu w tablicy x. 7.11. Funkcja Min przez prostą zmianę zwrotu nierówności w instrukcji warun- kowej, może być użyta do wyznaczania maksimum, czyli elementu o największej wartości w ciągu x. Zatem obie wielkości - minimum i maksimum spośród m liczb - można znaleźć za pomocą 2(m — 1) porównań. Zauważ, że w tym przypadku wielkości te są wyznaczane niezależnie jedna od drugiej. Zaproponuj natomiast algorytm jednoczesnego znajdowania min oraz max, który wykonuje ["3m/2~| — 2 porównań i zapisz go w języku Pascal. Wskazówka: Skorzystaj z następującego spostrzeżenia, które najpierw uzasa- dnij: porównując dwa elementy ze sobą, można zawsze jeden z nich wyeliminować ze zbioru kandydatów na minimum, a drugi - spośród kandydatów na maksimum. 7.12. Wykaż indukcyjnie, że liczba wszystkich permutacji rn elementowego ciągu jest równa m\ = 1 ? 2 • ... ? m. Wskazówka: Skorzystaj z metody generującej permutacje m-elementowe z per- mutacji (m — l)-elementowych. 248 7. Efektywność algorytmów i 7.13. Algorytm koszykowy jest stosowany do porządkowania elementów, którym można przyporządkować wartości będące liczbami naturalnymi z przedziału od 1 do n, gdzie n jest małą liczbą w porównaniu z długością ciągu rn. Algorytm ten ma następującą postać: 1. Zainicjuj n koszyków po jednym dla każdej liczby z przedziału od 1 do n. 2. Przeglądaj elementy ciągu danych i wkładaj je do odpowiednich koszyków, element o wartości i włóż do i-tego koszyka. 3. Ustaw elementy z kolejnych koszyków w jeden ciąg, biorąc najpierw ele- menty z koszyka o numerze 1, po nich element z koszyka o numerze 2, następnie elementy z koszyka o numerze 3 itd. Otrzymany tym algorytmem ciąg jest oczywiście uporządkowany niemalejąco względem wartości elementów. Napisz procedurę w języku Pascal realizującą ten algorytm, w której koszyki są reprezentowane przez listy utworzone za pomocą typu wskaźnikowego. Przyjmij, że podstawowym działaniem w algorytmie jest przeniesienie elementu z miejsca w miejsce (w języku Pascal przeniesieniu odpo- wiada przypisanie). Określ złożoność podanej procedury (czasową i pamięciową) jako funkcję zmiennych m i n. Jaka byłaby złożoność realizacji algorytmu koszy- kowego, gdyby koszyki były pamiętane w tablicach, a nie w listach. 7.14. Napisz procedurę w języku Pascal realizującą naiwny algorytm porząd- kowania. W jej treści skorzystaj ze zmodyfikowanej funkcji Min, która zamiast elementu najmniejszego w ciągu znajduje jego wskaźnik. Postaraj się by Twoja procedura porządkowała in situ. 7.15. Napisz procedurę BabelSort realizującą algorytm bąbelkowy. Jako jeszcze jedno usprawnienie przyjmij, że w kolejnym przebiegu algorytmu jest sprawdzane spełnienie nierówności < wśród elementów od najniżej położonego do najwyższego (włącznie) spośród tych, które zostały przestawione w poprzednim przebiegu. Uzasadnij poprawność tego uproszczenia. 7.16. Podaj przykład ciągu, dla którego algorytm bąbelkowy wykonuje tyle samo porównań co algorytm naiwny. Postaraj się uogólnić swój przykład na ciąg o m elementach, gdzie m może być dowolną liczbą. 7.17. Przeanalizuj złożoność algorytmu porządkowania, w którym na każdym kroku są scalane ciągi o długościach 1 i m — 1. Opisz także ten algorytm bez korzystania z operacji scalania. 7.18. Przyjmij, że elementy, które mają być uporządkowane, są zapisane w ta- blicy typu CiagDanych złożonej z m składowych typu Element, zdefiniowanych następująco: TYPE Element=RECORD Klucz :REAL; Zadania 249 {inne pola} Wskaźnik:IMTEGER END; CiagDanych=ARRAY[l..m] OF Element Napisz procedurę porządkującą metodą scalania ciąg liczb umieszczony w tablicy x typu CiagDanych, której elementy nie zmieniają swojego miejsca, a ich kolejność jest wskazywana wartościami pól Wskaźnik. Dla naszego przykładu z p. 7.4 po- winniśmy więc otrzymać reprezentację pokazaną na rys. 7.7. Zatem procedura po- Klucz -1 Wskaźnik Rys. 7.7. Ilustracja do zadania 7.18 winna dodatkowo określać wskaźnik do pierwszego elementu w uporządkowanym ciągu, w naszym przykładzie jest nim 2. Zauważ, że ciąg kolejnych wskazań (w naszym przykładzie: 2, 6,1, 3, 5,4) jest permutacją wskaźników (ii, %2, ? ? ?, im) określającą szukane uporządkowanie. 7.19. Napisz procedurę scalającą dwa uporządkowane ciągi dane w plikach p i q. 7.20. Wykaż indukcyjnie, że każde drzewo binarne z n wierzchołkami końcowymi ma n — 1 wierzchołków pośrednich. Wskazówka: Zastanów się najpierw, jak można otrzymać drzewo binarne za- wierające n wierzchołków końcowych z drzewa on-1 wierzchołkach końcowych. 7.21. Przeprowadź eksperyment obliczeniowy z poznanymi algorytmami porząd- kowania: naiwnym, bąbelkowym i przez scalanie. W tym celu umieść procedury realizujące te algorytmy w jednym programie, który wyznacza ich czas działania dla tych samych danych. Jako dane przyjmij ciągi o długościach m = 50, 100, 300, 500, 1000 złożone z losowo generowanych liczb. Wyznacz także czasy działania procedur na ciągach uporządkowanych i ciągach w odwrotnej do szukanej ko- lejności (bardzo często są to ciągi, dla których algorytmy porządkujące wykonują najmniejszą lub największą liczbę operacji). I 8. BEZ KARTKI I OŁÓWKA - PRZETWARZANIE TEKSTÓW 8.1. O sztuce opracowywania tekstów W tym rozdziale zajmiemy się wykorzystaniem komputerów do redagowania tekstów. Ponieważ mamy już za sobą niejeden napisany program (w języku Logo lub Pascal), nie możemy nie zauważyć, że z komputerowym redagowaniem tekstów spotkaliśmy się już uprzednio, niejako mimochodem i z konieczności. Te- raz poświęcimy temu więcej uwagi. Przez redagowanie tekstu (w szczególności za pomocą komputerów) będziemy rozumieli rozwiązywanie technicznych pro- blemów opracowywania tekstu, w odróżnieniu od redagowania merytorycznego, to jest uzgadniania treści. Mimo że redagowanie merytoryczne i redagowanie techniczne są odrębne, jak pomyślenie słowa i jego napisanie; łatwość pisania z pomocą komputerów ma wpływ zarówno na jedną, jak i drugą stronę opra- cowywania tekstów. Lektura tego rozdziału, połączona z pewną dozą własnych doświadczeń z komputerem, pozwoli określić, na czym polegają zalety użycia komputera. Aby przygotować dobre wypracowanie, dowolną pisemną wypowiedź (list, podanie, artykuł, mowę itd.) musimy znać temat, który ma być przedstawiony, słownictwo oraz zasady gramatyki, ortografii i interpunkcji języka, a także jego stylistyki, frazeologii (tu również przydaje się znajomość odbiorcy, do którego się zwracamy) i innych elementów pisarskiego warsztatu (zob. zad. 8.1, 8.2). Nawet przy spełnieniu tych wymogów redagowanie tekstu w postaci ciągu zdań czy - w przypadku dłuższych tekstów - ciągu akapitów, paragrafów lub rozdziałów pozostaje nadal złożonym i trudnym zadaniem. Mało kto potrafi, wypróbowując warianty w pamięci, przelewać na papier treści w formie zbliżonej do tej, jaką uznałby za ostateczną. Jest to naturalne, a dowody można odnaleźć w niejednej bibliotece czy muzeum, gdzie efekty zmagania się z formą przez uzna- nych ludzi pióra lub nauki są udokumentowane w postaci pokreślonych, z trudem czytelnych rękopisów (zob. zad. 8.3). 8.2. Komputerowe redagowanie tekstu 251 Oprócz redagowania wypracowań, które w wieku szkolnym ćwiczą nasze u- miejętności uporządkowanego formułowania myśli, redagowanie różnych tekstów pochłania coraz więcej czasu coraz większej liczbie ludzi różnych zawodów. Po- nadto okazuje się, że poza literaturą piękną, dziełami naukowymi, publicystyką itp. sporo tekstów powstających w związku z handlem i zarządzaniem ma szablo- nowy charakter, co nie oznacza, iż mogą one wykazywać niedopracowaną formę. Jednocześnie typowość tego rodzaju tekstów pozwala na automatyzację ich przy- gotowywania również pod względem treści (zob. zad. 8.4, 8.5). Maszyna do pisania od chwili wynalezienia (H.R. Malling-Hansen, 1867) prze- szła liczne modyfikacje: od "jednopalcowego" pradziadka Mignona, poprzez różne mechaniczne Ideale, elektryczne Optimy, aż do współczesnych maszyn IBM wy- posażonych w pamięć i wymienne głowice z różnymi krojami pisma. Mimo wielu zmian i ulepszeń maszyna do pisania zautomatyzowała zada- nie właściwie tylko w odniesieniu do stawiania poszczególnych liter. Tam, gdzie oprócz przepisywania czy wpisywania w rubryki są potrzebne liczne zmiany oraz przekształcenia tekstu, czyli w złożonym procesie jego redagowania, maszyna do pisania przestaje być wygodnym narzędziem. W tym ostatnim wypadku brakuje jej elastyczności układu kartki i ołówka - z możliwością dokonywania skreśleń. Współczesny nam okres rozwoju środków technicznych usprawniających re- dagowanie tekstów można postrzegać jako przeobrażanie się maszyny do pisania, uwieńczone specjalizowanym komputerem i uniwersalnymi programami zwanymi edytorami lub procesorami tekstu. Komputery zastosowane do redagowania tekstów nie tylko naśladuj ą własności mechanicznych maszyn do pisania. Teksty przechowywane w pamięci komputera można kształtować nader elastycznie. Wprowadzanie poprawek i ulepszeń jest uproszczone. Odpowiednie środki techniczne umożliwiają posługiwanie się wie- loma alfabetami i krojami pisma. Komputerowe maszynopisanie, a mówiąc dokładniej - przetwarzanie tek- stów, stało się jednym z ważniejszych zastosowań komputerów osobistych. Kom- putery wprowadzają nową jakość w od wieków aktualne cyzelowanie tekstów. 8.2. Redagujemy tekst za pomocą komputera Dalej przedstawimy proces redagowania tekstu na przykładzie edytora TAG, bę- dącego w powszechnym użyciu na komputerach osobistych IBM PC, w tym także na szkolnych komputerach. Nazwa edytora TAG pochodzi od imion jego konstruktorów (Tomasz, Artur, Grzegorz). Jest to, obok edytora ChiWriter, jeden z najpopularniejszych obe- cnie programów redagowania tekstów używanych w Polsce. Edytor TAG daje bogaty przegląd możliwości komputerowych edytorów tekstu. Dalsze rozważania 252 8. Przetwarzanie tekstów są w znacznym stopniu ilustrowane operacjami zaczerpniętymi wprost z tego edy- tora. Podany dalej opis poszczególnych działań edytora TAG odnosi się zarówno do wczesnych, jak i do późniejszych wersji tego programu. Należy jednak zdawać sobie sprawę z tego, że w innych edytorach operacje podobne z logicznego punktu widzenia mogą być realizowane za pomocą innych rozwiązań technicznych, jak również z tego, że najbardziej interesuje nas przegląd różnorodnych działań użytecznych w przetwarzaniu tekstów. Opisu wszystkich własności edytora TAG należy szukać w jego dokumentacji firmowej, natomiast pełny spis cech odnajdywanych we współczesnych edytorach liczy blisko 300 po- zycji. Kompromis, jaki tu stosujemy, polega na omawianiu najważniejszych cech większości edytorów na przykładzie jednego edytora i wybranych własności innych edytorów, których edytor TAG nie zawiera. Edytor TAG zajmuje miejsce pośrednie między ograniczonymi typograficznie edytorami przeznaczonymi do pisania programów (które, ze wględu na używany przez nie zbiór znaków możemy określić wspólnie mianem edytorów tekstów ASCII), a skomplikowanymi systemami składu drukarskiego, takimi jak TęX lub Ventura, za pomocą których składa się obecnie na komputerach całe książki. Na przykład, ta książka została złożona przez autorów za pomocą systemu TgX. Zredagowanie i wydrukowanie książki jest również możliwe za pomocą edy- tora TAG, oszczędniejszymi jednak środkami wyrazu. Opanowanie umiejętności posługiwania się nim pozwala na opracowywanie dowolnych tekstów oraz rozwija intuicję pomocną w kontaktach z innymi edytorami. Edytor TAG może również służyć do pisania tekstów w kodzie ASCII - na przykład programów w Pascalu, C lub w innych językach programowania. Należy jednak pamiętać, że - podobnie jak w przypadku składu drukarskiego - do pisania dużych programów używa się innych edytorów. Prostym sprawdzianem przydatności edytora do pisania pro- gramów jest sposób wykonywania typowych operacji, np. liczba naciśnięć klawi- szy potrzebna do zamiany miejscami dwu wierszy tekstu. Inną ważną cechą edy- tora programów jest możliwość łatwego działania na wielu plikach jednocześnie. Podobnie jak w maszynach do pisania edytory przeznaczone do redagowa- nia tekstów artykułów, wypracowań itp. pozwalają użytkownikowi określać takie parametry druku jak: - szerokość wiersza tekstu, liczoną w znakach; - wysokość wiersza liczoną w minimalnych wysuwach pionowych pa- pieru, tzw. ząbkach (lub rządkach) - typowy wiersz ma 3 lub 4 ząbki wy- sokości; w przypadku edytorów współpracujących z drukarkami laserowymi możliwości przestrzennej kompozycji tekstu są o wiele bogatsze (stosuje się w nich zarówno miary tekstu w punktach zecerskich, jak i miary calowe oraz metryczne); - wysokość strony, liczoną w wierszach lub elementarnych wysuwach; 1.2. Komputerowe redagowanie tekstu 253 krój pisma (rys. 8.1), który może być dowolnie zmieniany w trakcie pisa- nia. Standard pismo pogrubione kursywa, czyli pismo pochyłe pismo maszynowe Pismo bezszeryfowe Pismo Wielkie znaki specjalne: § & # 0 © ... Rys. 8.1. Kroje pisma spotykane w edytorach tekstu W przypadku edytora TAG jest możliwe m.in. zwiększanie wysokości lub poszerzanie kroju pisma. Ogólnie, wybór czcionki w edytorze TAG polega na dokładaniu atrybutów do kroju podstawowego. Można więc zażądać, aby zwy- kłe proste litery stały się pochyłe {kursywa), po czym także pogrubione, a nas- tępnie jeszcze poszerzone itd. I na odwrót, krojowi, który został powiększony i poszerzony oraz pochylony i podkreślony można ująć atrybutów, by w końcu zamienić go na elegancki, choć skromny krój bezszeryfowy. Do ustalania kroju pisma służą klawisze | Fl | i |F2 |. Istnieje możliwość obejrzenia poszczególnych krojów pisma i zbiorów znaków na ekranie (klawisze |F2 |, |F9 |naciśnięte kolejno po sobie). TAG umożliwia w szczególności użycie cyrylicy. W edytorze TAG użytkownik może - zupełnie jak w zwykłej maszynie do pisania - swobodnie ustawiać marginesy, miejsca tabelacji, określać sposób nu- merowania stronic itp. Czynności te nazywają się w edytorze TAG ustala- niem wzorca i zwykle poprzedzają polecenie drukowania. Można je wykonać po naciśnięciu klawisza | F3 |. Pojedynczy redagowany moduł tekstu musi się zmieścić w 64 kB pamięci, czyli w około 64 tys. bajtów. Ograniczenie to rzadko daje znać o sobie, ponieważ edytor TAG umożliwia budowanie z modułów tekstu hierarchii rozdziałów i punktów. Jeśli jednak dojdzie do sygnalizacji braku miej- sca na pomieszczenie znaków modułu, użytkownik ma okazję zastanowić się, czy jego tekst nie powinien zostać napisany strukturalnie, zamiast w postaci nieprze- rwanego potoku zdań nie podzielonego na żadne jednostki logiczne. 254 8. Przetwarzanie tekstów 8.3. Uruchomienie edytora Edytor TAG rozpoczyna pracę po wydaniu zlecenia TAG, uzupełnionego ewentu alnie nazwą pliku zawierającego tekst, który ma być redagowany. Na przykła można wywołać TAG C:\TEKSTY\ESEJ gdzie ESEJ jest nazwą pliku z katalogu TEKSTY z tomu dyskowego C:. Pliki edytora TAG przyjmują rozszerzenia TAG, wobec czego powyższe zlecenie zostanie zinterpretowane następująco: TAG C:\TEKSTY\ESEJ.TAG Uruchomienie edytora TAG może zależeć od specyfiki instalacji komputera IBM PC, w szczególności od zawartości listy automatycznie przeszukiwanych kar-^ totek (por. informacje o systemie operacyjnym MS-DOS w rozdz. 2) i obecności odpowiednich makrodefinicji. Jeśli, na przykład, umieściliśmy w pliku ED.BAI ciąg zleceń: C: CD \TAG TAG C:\TEKSTY\7.1 to wtedy identyczny efekt jak wyżej osiągniemy wydając zlecenie ED ESEJ Po uruchomieniu edytora na ekranie pojawiają się dwie ramki. W ramce po i prawej stronie jest wyświetlana metryczka programu (dane o wersji, nazwiska ] autorów itp.), a w prawym górnym rogu pojawia się numer seryjny edytora. DL użytkownika najistotniejsza jest ramka po lewej stronie, w której wykonuje si| działania zaliczane do warstwy wyboru plików. 8.4. Trzy warstwy edytora TAG Edytor TAG jest dobrym przykładem realizacji projektu logicznych warstw oprogramowania. Użytkownik po uruchomieniu edytora wchodzi w warstwę wyboru plików. Na tym poziomie wybiera plik, który chce przetwarzać. Nastę- pnie przechodzi do warstwy hierarchii tekstu, w której rozstrzyga o ogólnej i strukturze redagowanego dokumentu, jego podziale na części, rozdziały, para-j grafy itp. Dopiero po określeniu warunków pracy w obu wstępnych warstw użytkownik przechodzi do zasadniczej warstwy redagowania tekstu. Wy chodzenie z warstw edytora odbywa się w odwrotnej kolejności. Do głębszych 8.4. Trzy warstwy edytora TAG 255 warstw przechodzi się naciskając klawisz | Enter | lub | Ins |. Wyjście na poziom zewnętrzny następuje po dwukrotnym naciśnięciu klawisza | Esc |. Warstwy edytora i związki między nimi odzwierciedlają logiczną kolejność działań przy redagowaniu tekstów: - najpierw zdecyduj, jaki tekst chcesz redagować, - następnie określ jego ramową strukturę, - po czym wykonaj prace redakcyjne nad tekstem. W praktyce, w czasie jednej sesji przechodzi się wielokrotnie z jednej warstwy do innej i z powrotem. Jeżeli tekst jest niewielki (na przykład jednostronicowe podanie), to warstwę hierarchii tekstu przechodzi się bez specjalnego namysłu. W każdej warstwie można wykonać podstawową - z punktu widzenia zabez- pieczenia danych - operację, jaką jest zapamiętanie stanu pracy (czyli redagowa- nego tekstu w aktualnej postaci) na dysku, naciskając dwukrotnie klawisz [F8 |. Warstwa wyboru plików W warstwie wyboru użytkownik wybiera plik, który chce redagować. W tym celu może albo jawnie podać nazwę pliku, albo wskazać za pomocą kursora plik znaj- dujący się na wyświetlanej liście. W tym drugim przypadku można uprzednio skorzystać z możliwości zmiany tomu dyskowego lub bieżącej kartoteki, selekcjo- nowania plików według podawanych przez siebie szablonów itp. Informacja o do- konywanych w danej chwili czynnościach i służących do ich wywołania klawiszach jest zawsze umieszczana wprost na ekranie. Warto także pamiętać o roli klawisza I Tab |, którego naciśnięcie powoduje przemieszczanie się między poszczególnymi segmentami ramek. Po wybraniu - przez naciśnięcie klawisza | Enter | lub | Ins [ - pliku już ist- niejącego na którymś z dysków lub określeniu nazwy nowego pliku (co można zrobić już przy uruchamianiu systemu TAG), po prawej stronie ekranu jest wy- świetlana ramka z metryczką pliku. W dolnej części okna pojawiają się stan- dardowe informacje o pliku (rozmiar, data założenia i ostatniej jego aktualizacji itp.). Górna część metryczki może zostać przez użytkownika wypełniona dodat- kową, ogólną informacją o pliku. Warstwa hierarchii tekstu Po zatwierdzeniu przez akceptację metryczki wyboru pliku (za pomocą klawisza | Enter | lub | Ins |) następuje przejście w warstwę hierarchii tekstu. Z tego po- ziomu można wydrukować tekst (klawisze | Fl | i |F2 |), natomiast najciekawsza - z punktu widzenia pracy nad tekstem - jest oferta wyświetlana po naciśnięciu kla- wisza | F4 |, umożliwiająca działania na strukturze tekstu. W zależności od przyję- tej metody pracy nad tekstem (najpierw utworzenie ogólnego szkicu-konspektu, 256 Przetwarzanie tekstów i bądź też najpierw wpisanie treści szczegółowej) z oferty tej można skorzystać na samym początku lub później. W praktyce powraca się do niej wielokrot- nie, opracowując tekst (w tym - jego strukturę) na zasadzie kolejnych ulepszeń. Użytkownik ma możliwość swobodnego rozplanowania swojego tekstu przez wy- odrębnienie w nim części i opatrzenie ich tytułami. Rozdziały tekstu, jak umow- nie nazywa się tu jednostki hierarchizacji (czyli podziału tekstu), można dowol- nie przemieszczać, usuwać, wstawiać; także wraz z całymi podporządkowanymi im drzewami podrozdziałów, punktów i podpunktów. Hierarchia tekstu może odzwierciedlać nie tylko tradycyjną strukturę tekstu-książki, ale - na przykład - także historię wymiany korespondencji w pewnej sprawie, dzięki czemu wszystkie akta mogą się znaleźć w jednej "teczce", czyli pliku dyskowym. Sposoby tworzenia hierarchii tekstu są łatwe do opanowania, najprościej na przykładach własnych, rzeczywistych zadań. W szczególności sam tytuł hierarchii (Hierarchia tekstu) może być zastąpiony innym określeniem, odpowiadającym zawartości tekstu, na przykład: Listy do N. Warstwa redagowania tekstu Zasadnicza praca nad fragmentem tekstu rozpoczyna się po przebyciu dwu warstw opisanych w poprzednich punktach. Na ekranie pojawiają się początkowe wiersze wybranego fragmentu tekstu. Jeśli rozpoczynamy pracę nad nowym tekstem, to centralna część ekranu, przeznaczona na redagowany tekst, jest pusta. Kursor wskazuje na pierwszy znak tekstu. W dwu dolnych wierszach ekranu jest stale wyświetlany status edytora. Znaj- dują się tu m.in. graficznie przedstawione informacje o ustawieniu marginesów i tabulatorów, jak cównież symbole trybu redagowania bieżącego wiersza: na przykład, czy przy zmianie wiersza obowiązuje automatyczne dzielenie wyrazów na sylaby, automatyczne justowanie (czyli wyrównywanie marginesów) infor- macja o wysokości bieżącego wiersza itp. Dalej są wyświetlane: numer bieżącej strony i ogólna liczba stron w redagowanym dokumencie, a ściślej, w jego mo- dule w sensie hierarchii tekstu (nazwa modułu jest wyświetlana w lewym górnym rogu ekranu), numer rządka na stronie (wysokość wiersza wynosi np. 2 rządki), liczba rządków na stronie, numer kolumny, w której znajduje się kursor, ilość wolnej pamięci przeznaczonej do zapamiętywania tekstu, tryb wpisywania tekstu (wstawianie lub zamienianie liter), a także aktualny czas w godzinach, minutach i sekundach. Podkreślmy znaczenie wierszy statusowych edytora. Stanowią one element komunikacji edytora z użytkownikiem (zob. zad. 8.6). Podczas redagowania do dyspozycji użytkownika pozostaje klawiatura kom- putera w funkcji klawiatury zwykłej maszyny do pisania plus kilkadziesiąt dzia- łań specjalnych, uzyskiwanych za pomocą operacji klawiszowych, służących 8.5. Systemy podpowiedzi 257 m.in. do wybierania ofert (klawisze funkcyjne jFl |, |F2 |, ..., |F8 |, strzałki, [Enter |, | Ins |). Tytuły ofert są umieszczane w górnym wierszu ekranu. Przemieszczanie kursora w obrębie tekstu umożliwiają klawisze oznaczone strzałkami oraz klawisze PgUp , PgDn Poza tym użytkownik może odnajdywać określone fragmenty tekstu i przechodzić do ich redagowania za pomocą oferty ukazującej się po naciśnięciu klawisza | F6 |. Operacje klawiszowe wymagają czasami naciśnięcia określonego klawisza z li- terą po uprzednim naciśnięciu i przytrzymaniu innego klawisza, na przykład I Ctrl I lub Alt Polskie litery, czyli litery ze znakami diakrytycznymi (takimi jak ogonki), otrzymuje się przez naciśnięcie i przytrzymanie klawisza | Alt | oraz naciśnięcie klawisza z odpowiednią literą bez znaku diakrytycznego. Literę "ż" uzyskujemy naciskając klawisze [Alt z|, natomiast do napisania li- tery "ź" należy użyć klawiszy [Alt XJ. Wielkie litery pisze się przytrzymując klawisz I Shif 11 lub po naciśnięciu klawisza-przełącznika o nazwie Caps Lock Przykładowo, sekwencja klawiszy potrzebnych do napisania nazwiska Stanisław Witkiewicz wygląda następująco: Shift S TANISAltLAW Sp Shift W ITKIEWICZ Uzyskanie niektórych znaków - na przykład, pisanie wielkich polskich liter - wymaga naciśnięcia trzech klawiszy. Innymi przykładami operacji klawiszowych są: przeskok do następnego (po- przedniego) wyrazu, uzyskiwany za pomocą strzałek przy przytrzymanym klawi- szu 1 Ctrl | lub wpisanie twardej spacji, czyli odstępu, który nie jest usuwany przy automatycznym justowaniu wiersza (wykonywane po naciśnięciu klawiszy Alt Sp ). 8.5. Użytkowniku, pomóż sobie sam! Liczba różnych operacji w edytorach tekstów sięga zwykle kilkudziesięciu i prze- kracza możliwości łatwego ich zapamiętania. Jednak budowa edytorów, podob- nie jak innych programów usługowych, na ogól umożliwia stopniowe zagłębianie się i poznawanie ich właściwości poprzez poruszanie się po ścieżkach ofert gru- pujących operacje. Hierarchiczność ofert (ang.: puli down menu) ułatwia za- pamiętywanie dróg wyboru operacji przez ich uporządkowanie. Posłużenie się edytorem do najprostszych zadań nie wymaga jednak dużej wprawy. Podstawowa wiedza sprowadza się do umiejętności uruchomienia edy- tora, przejścia w tryb redagowania, wpisania tekstu i ewentualnego skorygowania 17 — Elementy informatyki 258 8. Przetwarzanie tekstów Backspace - rozdz. 2), zapamiętania go w pliku (stosując klawisze |Del | i wydrukowania oraz zakończenia pracy z programem. Edytor TAG ma wbudowane dwa słowniki (ortograficzny i wyrazów blisko- znacznych) oraz wypisy z zasad ortografii i interpunkcji języka polskiego. Wgląd w dane słownikowe można uzyskać z oferty | F7 | w warstwie redagowania tekstu. Wbudowane w edytor bazy słownikowe mogą być rozszerzane przez użytkownika. Nawet przy intensywnym korzystaniu z edytora nie wszystkich operacji używa się równie często. Aby użytkownik mógł zorientować się w zasobach możliwości, edytory są wyposażone w operacje, których wykonanie powoduje wyświetlenie na ekranie wykazu dostępnych działań wraz z krótkim opisem. Edytor TAG nie ma specjalnego systemu podpowiedzi. Jednak przeglądnięcie jego ofert i wykazów (wyświetlanych za pomocą klawiszy funkcyjnych) i lektura zawartych tam uwag (zob. zad. 8.11) w znacznym stopniu pozwalają orientować się w działaniach edy- tora. Co więcej, jest to informacja kontekstowa w tym sensie, że opisy działań nieefektywnych w danej sytuacji są wyświetlane bledszym pismem. Dzięki temu wiadomo, że dana możliwość istnieje, ale można ją uzyskać w innym kontekście (na przykład, po wykonaniu innego ciągu działań). Komputerowe systemy podpowiedzi czy też wbudowane dokumentacje, okre- ślane w żargonie informatycznym angielską nazwą help, są wyświetlane na ogół po naciśnięciu klawisza | Fl [. W innych edytorach pomoc jest wyświetlana po jednoczesnym naciśnięciu klawiszy | Alt H | lub podobnych (zob. zad. 8.7). i 8.6. Okna i ich zastosowanie Po naciśnięciu któregoś z klawiszy funkcyjnych edytor TAG wyświetla na ekranie prostokątne pole z wykazem możliwych do wykonania czynności. Mówimy, że na ekranie zostało otwarte okno. Użycie okien pozwala - mówiąc obrazowo - nakładać na już istniejący na ekranie obraz (tekst) inną informację (tekst, obraz) w sposób nie niszczący poprzednio wyświetlanej informacji (por. zad. 8.8). Do- konywanie wyborów z niektórych ofert (za pomocą klawiszy | Enter | lub | Ins |) powoduje otwieranie kolejnych okien. Jako przykład zastosowania okien w edyto- rze TAG można prześledzić uzyskiwanie podpowiedzi z zakresu ortografii, otwie- rając w warstwie redagowania okno z odpowiednią informacją za pomocą klawisza | F7 | i używając następnych klawiszy - zgodnie z wyborem w ofercie. Zamknięcie okna i przywrócenie poprzedniej zawartości ekranu następuje po naciśnięciu kla- wisza [Esc |. Inną zaletą związaną z użyciem okien, niedostępną jednak w edytorze TAG, jest wykonywany na polecenie użytkownika podział ekranu na części, w których można wyświetlać nie sąsiadujące ze sobą fragmenty redagowanego pliku, a nawet informacje z różnych plików. Ta możliwość jest cenna przy montowaniu tekstów 8.7. Manewrowanie kursorem 259 (w tym także tekstów programów) złożonych z wielu oddzielnych modułów (na przykład procedur lub grup procedur opracowywanych osobno i przechowywa- nych w osobnych plikach). Z jednym oknem na ekranie może być związanych wiele plików, tzn. za pomocą prostego przełączenia (najczęściej jest nim operacja klawiszowa) można w danym oknie oglądać różne pliki. Dowolne porcje tekstu z plików przyłączonych do różnych okien można wymieniać między plikami. Sy- stem zakładek umożliwia natychmiastowe przeskoki z kontekstu jednego pliku do innego, z dokładnością do położenia kursora w tekście. Taki mechanizm wy- boru i przesyłania tekstów daje użytkownikowi możność korzystania z informacji tekstowych nagromadzonych w całej pamięci masowej komputera, tzn. przecho- wywanych w dowolnych plikach na dyskach. W edytorze TAG funkcje tak rozumianego zarządzania informacją spełniają opisane uprzednio warstwy wyboru i struktury tekstu wraz z możliwością wy- syłania wybranych porcji tekstu do odrębnych plików dyskowych i pobierania informacji z plików. 8.7. Komputerowy "brudnopis", manewrowanie kursorem Opracowywanie tekstu na komputerze rzadko kiedy odbywa się "od lewej do pra- wej", przeciwnie - przedstawia się jako nieustanne ulepszanie zarówno treści jak i formy tekstu w różnych jego fragmentach. W odróżnieniu od ręcznej "techno- logii" w komputerze każda wersja tekstu jest czysta: bez skreśleń, widocznych wstawek, odsyłaczy, zamian itd. Na etapie opracowywania tekstu z pomocą edy- tora nie trzeba zużywać papieru. Pisząc tekst na ekranie możemy w każdej chwili przejść do dowolnego jego miejsca, aby coś zmienić lub poprawić. Miejsce na ekranie, tj. położenie kur- sora w tekście, zmienia się za pomocą klawiszy oznaczonych strzałkami. Strzałka wskazująca w górę oznacza przejście do poprzedniego wiersza, strzałka w dół - przejście do następnego wiersza tekstu (jeśli taki istnieje). Oprócz możliwości użycia strzałek edytor TAG ma inne operacje manewrujące kursorem. Podajemy je w przyjętej symbolice łącznego naciskania klawiszy: - przemieszczanie kursora z dokładnością do pojedynczego słowa: Ctrl Ctrl - manewrowanie kursorem w obrębie wiersza tekstu: End | (przejście na ko- niec wiersza), | Home | (przejście na początek wiersza); - przenoszenie kursora na następną stronę ekranu: PgDn - przenoszenie kursora na poprzednią stronę ekranu: PgUp - przenoszenie kursora na skraj pliku: Ctrl End (na koniec), Ctrl Home (na początek); 260 8. Przetwarzanie tekstów - zmiana aktualnie redagowanego modułu tekstu: Ctrl PgDn (przejście do następnego modułu w hierarchii tekstu), Ctrl PgUp (przejście do poprze- dniego modułu); przy tej operacji w lewym górnym rogu ukazuje się auto- matycznie nazwa nowego modułu (rozdziału, punktu itp.) - moduły reda- gowanego tekstu można również zmieniać w warstwie hierarchii tekstu (za pomocą klawiszy: | Esc |, |Esc |, strzałki, |Enter [). W poruszaniu się po tekście może dopomóc myszka. Niektóre edytory wyświe- tlają w obramowaniu tekstu na ekranie specjalne symbole (np. małe prostokąciki) określające położenie pokazywanego na ekranie fragmentu tekstu względem całego pliku. Ustawienie kursora (za pomocą myszy) na takim symbolu i przeciąganie go myszką wzdłuż obramowania powoduje szybkie przemieszczanie się w obrębie całego pliku. W przypadku edytora TAG wędrowanie po tekście za pomocą myszy wymaga odrywania jej od podłoża po przejściu jednej ekranowej porcji tekstu, co nie jest wygodne zwłaszcza przy dużych przemieszczeniach; w przeciwnym razie powrotny ruch myszy po stole spowoduje zmianę kierunku przesuwania tekstu na ekranie. Edytory mogą być wyposażone w jeszcze inne operacje przemieszczania kur- sora w tekście, na przykład przez umożliwianie wstawiania wspomnianych za- kładek w plikach. Ponadto opisane wyżej typowe przemieszczania kursora mogą być wykonywane za pomocą innych klawiszy. Oto przykład konsekwentnego rozwiązania zastosowanego w jednym z edytorów: |End | - powoduje przeniesie- nie kursora na koniec wiersza, [ End 11 End | - przeniesienie do ostatniego wiersza na ekranie, [ End 11 End 11 End | - przeniesienie na koniec pliku; klawisz [ Home | jest używany analogicznie. Jeszcze innym przykładem może być technika przewija- nia, kiedy kursor pozostaje na ekranie nieruchomy, natomiast wszystkie wiersze są przesuwane w górę lub w dół (zob. zad. 8.9). 8.8. Usuwanie i wstawianie tekstu Edytor TAG - jak każdy inny tego typu program - podczas redagowania tekstu może pracować w jednym z dwu trybów: wstawiania lub zastępowania znaków. W trybie wstawiania znak wpisywany w pozycji kursora powoduje przesunięcie wszystkich znaków występujących w wierszu na prawo od niego o jedną pozycję w prawo. W trybie zastępowania nowy znak zastępuje w miejscu wskazywa- nym przez kursor znak, który znajdował się tam uprzednio. Przełączenie między obydwoma trybami pracy uzyskuje się za pomocą klawisza | Ins |. Pamiętamy, że klawisz | Ins | w edytorze TAG jest też używany w roli klawisza akceptacji, podob- nie jak klawisz JEnter |. Informacja o aktualnym trybie pracy jest wyświetlana w wierszu statusowym. 8.8. Usuwanie i wstawianie tekstu 261 Pojedyncze znaki leżące na lewo od kursora można usuwać za pomocą klawisza Backspace , a naciśnięcie klawisza |Del | powoduje usunięcie znaku wskazywa- nego przez kursor. Ponadto specjalne operacje pozwalają usuwać: Ctrl Del - część słowa na prawo od kursora, Ctrl Backspace - część słowa na lewo od kursora, Ctrl Ins — cały wiersz, w którym znajduje się kursor. Przez naciskanie klawisza | Enter | w pozycji pierwszej kolumny zyskuje się dodatkowe puste wiersze. Użycie w tej kolumnie klawisza Backspace powo- duje natomiast złączenie wierszy tekstu ze sobą (efekt jest widoczny dopiero po przejściu z kursorem do sąsiedniego wiersza). Większe jednostki tekstu można usuwać lub wstawiać za pomocą omówionych dalej operacji blokowych.______ Jako ciekawostkę edytora TAG można podać operację Ctrl szara gwiazdka (prawy moduł klawiatury), która zamienia miejscami dwa sąsiednie znaki i może służyć do szybkiego poprawiania tego rodzaju błędów. Przykład 8.1. Załóżmy, że szukając dobrego początku wypracowania na temat współoddziaływania techniki i sztuki napisaliśmy na ekranie te słowa (darujmy so- bie w tym miejscu i w następnych ocenę wartości cytatu, jesteśmy zainteresowani obserwowaniem jego ewolucji przy użyciu edytora): Poczucie piękna i formy ornamentuje wytwory technicznej myśli ludzkiej._ Podkreślenie oznacza położenie końcowe kursora. Zaraz potem - jak to przy wypracowaniach bywa - popadliśmy w zadumę, w efekcie której postanowiliśmy wzbogacić orzeczenie okolicznikiem. Aby wstawić nowy wyraz, wykonujemy następujący ciąg operacji: strzałka w górę (kursor w górę), | Ins | (przejście do trybu wstawiania, potrzebne tylko wtedy, jeśli obowiązywał tryb zastępowania znaków), subtelnie (litery wstawianego wyrazu), strzałka w dół (kursor w dół), JEnd | (kursor na koniec wiersza) i (ewentualnie) | Ins |. Początek wypracowania brzmi obecnie: Poczucie piękna i formy subtelnie ornamentuje wytwory technicznej myśli ludzkiej._ Teraz przestaje się nam podobać przydawka "ludzkiej". Zamieniamy ją na inną, naciskając po prostu 9 razy klawisz |Del | i wpisując: człowieka. Nowa wersja brzmi: Poczucie piękna i formy subtelnie ornamentuje wytwory technicznej myśli człowieka.- 262 8. Przetwarzanie tekstów Za chwilę ten sam los spotyka wytwory. Operacje: strzałka w górę, | Ctrl I End I Ctrl-> Ins "produkty": produkty | Ins |, strzałka w dół, Home zmieniają je na Poczucie piękna i formy subtelnie ornamentuje produkty technicznej myśli człowieka.. Spoglądamy jeszcze przez chwilę krytycznym okiem i, jak to się często zdarza, całość wędruje do kosza: Ctrl Ins[, Ctrl Ins]. Po czym - robiąc jeszcze lep- szy początek! - wpisujemy z przekonaniem: Produkty cywilizacji technicznej niepostrzeżenie kształtują odczucia sfery ducha._ W ten sposób powoli wyłania się tekst wypracowania. 8.9. Operacje na blokach tekstu W edytorze TAG blok tekstu określa się po wejściu w tryb działań na blokach (klawisz | F5 |). Od tej chwili manipulacje kursorem będą powodowały zaznacza- nie bloku (zaznaczony fragment tekstu przybiera inny odcień na ekranie). Kursor można przesuwać znak po znaku, wiersz po wierszu, lecz również można zaznaczyć jako blok większy fragment, na przykład przez przejście na koniec redagowanego modułu tekstu (naciskając klawisze Ctrl End|). Za zakończenie oznaczania gra- nic bloku jest przyjmowane w edytorze TAG powtórne naciśnięcie klawisza |F5 |. Na ekranie ukazuje się wtedy okienko z odpowiednią ofertą. Z blokami tekstu można postępować tak jak z pojedynczymi znakami (wsta- wiać, kasować, przemieszczać) oraz podobnie jak z plikami - sprowadzać z dysku do pamięci roboczej edytora i wysyłać na dysk. Usuwany z tekstu blok jest prze- chowywany w buforze pamięci zakładanym automatycznie przez edytor, skąd można go na życzenie odzyskać - na przykład, by wstawić później w inne miej- sce. Należy jednak pamiętać, że posłanie innego bloku do bufora powoduje utratę poprzedniej zawartości bufora. Jednym z celów zaznaczania bloku może być chęć wykonania wybranej ope- racji na całym fragmencie tekstu zawartym w bloku. W szczególności blokiem można uczynić cały moduł. Blok można w całości formatować, czyli automa- tycznie zmienić szerokość i wysokość wierszy oraz marginesów, justować (oferta F3 |) lub automatycznie łączyć wszystkie akapity w bloku w jeden akapit. (Roz- poczęcie pisania tekstu od nowego akapitu uzyskuje się przez naciśnięcie klawisza | Enter | - pisząc tekst nie naciska się klawisza | Enter | na końcu każdego wier- sza, gdyż podczas pisania przejście do nowego wiersza następuje automatycznie.) 8.9. Operacje na blokach tekstu 263 Można również automatycznie zmienić w bloku krój i atrybuty pisma (korzy- stając z ofert | Fl |, | F2 | wybieranych przy oznaczonym bloku). Szczegółowy wykaz operacji na blokach ukazuje się za każdym razem na ekranie monitora. Warto zwrócić uwagę na kontekstowe działanie oferty działań na blokach. Po jednorazowym naciśnięciu klawisza | F5 | i oznaczeniu bloku, kolejne naciśnięcie klawisza | F5 | powoduje wyświetlenie innej oferty, niż dwukrotne naciśnięcie kla- wisza | F5 | bezpośrednio po sobie i bez zaznaczenia bloku w redagowanym tekście. W pierwszym wypadku z oferty można wybrać m.in. przechowanie bloku w pa- mięci lub wysłanie go na dysk, a w drugim - wstawienie bloku ostatnio prze- chowywanego w buforze lub sprowadzenie tekstu z pliku dyskowego. Przy okazji takich transferów bloków z tekstami można wykonać konwersję danych przyj- mując jeden z popularnych standardów kodów liter polskich: Mazovia lub Latin II - albo przesłać plik bez konwersji (czyli w standardzie kodu ASCII). Ostatnia możliwość jest szczególnie pożyteczna w przypadku pisania za pomocą edytora TAG programów i danych dla programów. Operacje plikowe na blokach umożliwiają podział redagowanego dokumentu na części lub odwrotnie - jego składanie z różnych fragmentów zapamiętanych w być może różnych kartotekach. Możliwość wymiany informacji między plikami rozszerza koncepcję modułów tekstu definiowanych w warstwie hierarchii tekstu i pozwala na dysponowanie tekstami bez konieczności zakończenia pracy z edytorem. Działania takie mogą być szczególnie przydatne przy budowaniu większych programów, których po- szczególne fragmenty są przechowywane w osobnych plikach. Operacje na blokach stanowią ważne i silne narzędzie w rękach użytkownika edytora tekstu. Umiejętność posługiwania się nimi należy zaliczyć do podstawo- wych. Nie warto więc odkładać nauczenia się ich na potem. Przykład 8.2. Pamiętamy, że w poszukiwaniach dobrego początku dla naszego przykładowego wypracowania jego pierwsze zdanie przybrało ostatnio postać: Produkty cywilizacji technicznej niepostrzeżenie kształtują odczucia sfery ducha._ Kontynuując przeobrażenia tekstu, dokonujemy następujących zabiegów: | Home J - kursor na początek wiersza, - kursor o jedno słowo w prawo, - przejście w tryb operacji blokowych, - oznaczenie bloku odczucia sfery ducha, - skasowanie oznaczonego bloku tekstu z jednoczesnym przeniesieniem go do bufora, - kursor na początek ekranu, Ctrl ->? | manewry strzałkami Ctrl Home 264 8. Przetwarzanie tekstów |F5|IF5 I~fT| - przejście w tryb operacji odczytywania bloków, - wstawienie bloku pamiętanego w buforze, którym tutaj jest tekst odczucia sfery ducha, w miejsce wskazywane przez kursor, czyli na początek zdania. Dalej zamieniamy o na początku bloku na 0, zamieniamy P na p, oznaczamy jako blok napis produkty cywilizacji technicznej i przemieszczamy go na koniec zdania. Otrzymujemy w rezultacie zdanie: Odczucia sfery ducha niepostrzeżenie kształtują produkty cywilizacji technicznej.. - obiecujący punkt wyjścia do dalszych zmagań z tekstem. ? 8.10. Wyszukiwanie i zamiana tekstów Edytor TAG, podobnie jak inne programy o tym przeznaczeniu, umożliwia re- dagowanie systematyczne, czyli automatyzację zmian o cechach regularnych oraz powtarzających się w tekście. Jako przykład możemy rozważyć zadanie zmiany pewnej nazwy występującej wielokrotnie w całym tekście. Dla ustalenia uwagi przyjmijmy, że chodzi o zastąpienie napisu wiek XX napisem wiek XXI na 20 stro- nach tekstu. Przejrzenie tak znacznej ilości tekstu wiersz po wierszu za pomocą komputera bywa nie mniej uciążliwe niż tradycyjne wertowanie kartek. Przy ta- kich okazjach daje znać o sobie ujemna strona wycinkowosci tekstu widocznego jednorazowo na ekranie, czyli widzenie tunelowe. To i podobne zadania można wykonać szybko za pomocą operacji szukania i zastępowania - w edytorze TAG operacje tego rodzaju są zgrupowane w ofercie otwieranej naciśnięciem klawisza [~| W następstwie otrzymujemy wykaz możliwości, a wśród nich wyszukiwanie ). F2 Naci- napisów (|F11) lub wyszukiwanie połączone z zastępowaniem ( skamy więc klawisz | F2 | i otrzymujemy zaproszenie do napisania poszukiwanej frazy. Wprowadzamy z klawiatury napis iek XX. Następnie musimy podać tekst zastępujący oraz zdecydować czy podczas szukania mają być utożsamiane wiel- kie i małe litery, czy też nie. Kolejne zamiany w tekście mogą podlegać kontroli ze strony użytkownika (klawisze |Enter | lub | F3 |) albo dokonywać się auto- matycznie (|Fl |). W naszym przypadku wpisujemy tekst iek XXI i wybieramy kontrolę indywidualną, przy której każdą zamianę tekstu musimy zakceptować - naciskamy wtedy klawisz |Enter |, jeśli należy spowodować zamianę w danym miejscu, lub klawisz |F3 |, gdy odnaleziony kontekst powinienien być pozosta- wiony bez zmian. Po takim przetworzeniu tekstu możemy być pewni, że wszystkie wystąpienia napisu wiek XX zostały zamienione na wiek XXI. 8.11. Wycofywanie pochopnych decyzji 265 Przykładem sytuacji, w której zautomatyzowanie zamiany mogłoby doprowa- dzić do powstania błędów, jest zamiana nazw w programie wykonana bez dozoru użytkownika. Edytor nie odróżnia nazw zmiennych i procedur od ewentualnych tych samych nazw (np. spójników "i") użytych w komentarzach. W takich wy- padkach korzystamy z możliwości decydowania o każdej zamianie w zależności od kontekstu. Inną operacją systematycznego redagowania tekstu w edytorze TAG jest mo- żliwość półautomatycznej korekty ortograficznej. Działanie to wybiera się z oferty |F7 I jako czynność |F2 |. Odnajdywanie w tekście cząstek wyrazów podejrzanych o błąd wskutek ich braku w słowniku edytora wymaga również określenia, ile razy ma być automatycznie powtórzone przez edytor - tę krotność wpisujemy w od- powiedzi na dodatkowe pytanie edytora. Po wykonaniu pierwszego przeszukania kolejne poszukiwania są wykonywane za pomocą klawisza |Enter |, co pozwala pominąć miejsca, w których błąd w istocie nie występuje. Przy okazji tych poszu- kiwań można dołączać do słownika nowe wyrazy, eliminując w ten sposób dalsze ich kwestionowanie. Korekta odnalezionego błędu polega na ręcznym zastąpieniu wyrazu jego poprawną wersją. Zarówno operacja szukania łańcucha znaków z zastępowaniem jak i samego szukania są łatwe do nadzorowania dzięki bezpośredniej konwersacji z edytorem. Samodzielnie wykonane ćwiczenie z tekstem wyjaśnia tu więcej niż szczegółowy opis. Długość łańcucha znaków określanego przy przeszukiwaniach jest na ogół ograniczona i nie może przekraczać kilkudziesięciu znaków (20 znaków w przy- padku edytora TAG). 8.11. Wycofywanie pochopnych decyzji Tytułowe zagadnienie jest jedną z cech przyjaznego oprogramowania powszech- nego użytku. Przy redagowaniu tekstów daje czasami znać o sobie pośpiech. Oto skasowaliśmy bezwiednie o kilka znaków więcej, niż było potrzeba. To błahostka, nieco gorzej przedstawia się sprawa, gdy niebacznie wypadnie nam z tekstu cały wiersz. A co zrobić, gdy po wielu przeróbkach dochodzimy do wniosku, że naj- lepiej byłoby... powrócić do stanu początkowego pliku?! Na tego rodzaju oko- liczności edytory przewidują operacje odwoływania niektórych (lub wszystkich) wykonanych czynności. Operacja, o którą tutaj chodzi, nazywa się w oryginale angielskim undo i po- zwala na anulowanie pojedynczych operacji, w tym także blokowych, a nawet ich ciągu. Niezależnie od złożoności operacji, tzn. czy dotyczyły pojedynczego znaku, przesunięcia kursora o jedno pole czy działania na całym bloku, edytory z dobrze zaprojetowanym anulowaniem działań po naciśnięciu jednego klawisza (zawsze 266 8. Przetwarzanie tekstów tego samego) powodują cofanie "komputerowej historii" w odniesieniu do reda- gowanego tekstu. Użytkownik edytora, dysponujący taką operacją "przywraca- nia" przeszłości, nabiera zupełnie innych przyzwyczajeń (nie zawsze najlepszych z punktu widzenia edytorów bez takich środków) - ma większą swobodę stawia- nia nie do końca przemyślanych kroków, bo zawsze może je odwołać. Operacja ta, poza celami ratunkowymi, może być również stosowana do realizowania za- mierzonych działań, na przykład do szybkiego obejrzenia tekstu w innym miejscu pliku i automatycznego powrotu do punktu wyjścia. 8.12. Składowanie informacji Koncentrując uwagę nad tekstem wypracowania lub programu można zapomnieć o bardzo ważnej zasadzie okresowego składowania informacji, czyli zapamię- tywania w pamięci trwałej (na dysku lub taśmie magnetycznej) przejściowych stanów pliku zawierającego opracowywany tekst. Pamiętanie o wykonywaniu składowania informacji niektóre edytory biorą na siebie: jednym z rozwiązań jest określenie przez użytkownika przedziału czasu między kolejnymi składowaniami. Zasada taka jest stosowana m.in. w edytorze TAG. Poza tym użytkownik w wy- branych przez siebie chwilach może zawsze wykonać składowanie bieżącego stanu redagowanego tekstu. W edytorze TAG do wykonania składowania służy operacja | F8 1 umieszczona w ofercie wywoływanej klawiszem [ F8 |. Wystarczy zatem w do- wolnej chwili (także w warstwie redagowania hierarchii tekstu) nacisnąć dwukrot- nie klawisz funkcyjny |F8 |, aby mieć pewność, że bieżąca postać zostanie utrwa- lona w pamięci dyskowej. Dodatkowo edytor sam w określonych odstępach czasu wykonuje automatycznie składowanie w osobnym pliku, któremu, dla odróżnienia od pliku zapisywanego przez użytkownika, nadaje rozszerzenie BAK. Pamiętajmy, aby przy pracy nad tekstem za pomocą komputera nie narażać się na przypadkową - na przykład z powodu zaniku napięcia w sieci lub zablo- kowania programu - utratę efektów tej pracy. Od początku warto wyrobić sobie nawyk wykonywania składowania co pewien czas, na przykład co 10 minut, nie zważając na automatyczne składowania wykonywane okresowo przez sam edytor. 8.13. Przeglądanie plików W poszukiwaniach dobrego początku dla nowego tekstu mogą okazać się przy- datne nasze doświadczenia i wyniki uzyskane przy pisaniu innych tekstów. Za- kładając, że przechowujemy je w plikach na dysku, możemy za pomocą edytora TAG szybko je przeglądnąć. W tym celu stosujemy operację | F8 [ |~F8~|, która poleca zapamiętać na dysku redagowany plik, po czym przechodzimy do warstwy wyboru pliku ([ Esc | |Esc |...) i wprowadzamy do pamięci edytora interesujące 8.14. Zakończenie pracy 267 nas dane, postępując podobnie jak to ma miejsce w popularnych programach pośredniczących w wykonywaniu zleceń systemu operacyjnego. Edytor TAG sta- nowi tu przykład programu tworzącego środowisko szersze niż na potrzeby re- dagowania pojedynczego pliku. Wykazy i zawartości plików można oglądać bez konieczności kończenia sesji redagowania. Przypomnijmy, że dla uwidocznienia plików o rozszerzeniach innych niż TAG, należy uprzednio zmienić na *. * szablon wyświetlanych nazw plików w górnym segmencie okna warstwy wyboru (klawisz [Tab |). Przechodzenie w górę drzewa katalogów odbywa się przez zaakceptowanie wiersza z wpisem ". .". Wejście do katalogu o nazwie podanej na wykazie nastę- puje po wybraniu nazwy katalogu kursorem i naciśnięciu klawisza | Enter | lub llnsl. 8.14. Zakończenie pracy Pracę z edytorem można zakończyć dwoma sposobami: z zapamiętaniem wy- ników redagowania, czyli tekstu ze wszystkimi naniesionymi w nim zmianami, albo z zaniechaniem zapamiętania zmienionego tekstu. W edytorze TAG do planowego zakończenia pracy z zachowaniem wszyst- kich wniesionych do pliku modyfikacji służy operacja | Fl | w ofercie |F8 | (tzn. naciskamy klawisz funkcyjny JF8 |, a po nim | Fl |). Operacja ta powoduje za- pamiętanie na dysku aktualnej wersji redagowanego tekstu i przejście do zewnę- trznej warstwy edytora. Zatem do całkowitego zakończenia pracy z programem trzeba tę operację powtórzyć dwukrotnie lub trzykrotnie w zależności od miej- sca aktualnego pobytu w edytorze. Innym - manualnie prostszym — sposobem zakończenia redagowania z zachowaniem wykonanych zmian jest wielokrotne na- ciskanie klawisza |Esc | (po dwa naciśnięcia na opuszczenie jednej warstwy edy- tora). Do zaniechania prac nad tekstem i przywrócenia jego stanu początkowego, czyli odstąpienia od pamiętania jakichkolwiek zmian wprowadzonych do pliku, służy w edytorze TAG operacja |F2 [, również wybierana z oferty |F8 |. Rezygna- cja także i tym wypadku oznacza powrót do warstwy poprzedniej, toteż należy ją ewentualnie powtórzyć w zewnętrznej warstwie edytora. Rezygnacja z redagowania, a ogólnie — zaniechanie jakiejś czynności lub zakoń- czenie pracy, bywa oznaczana w programach literą Q (lecz nie w edytorze TAG). Jest to drugie (obok funkcji klawisza |Esc |) ważne z praktycznych powodów standardowe zakończenie korzystania z programów usługowych komputerów oso- bistych. Edytory, w przypadku zapamiętania zmodyfikowanego pliku, na wszelki wy- padek przechowują na dysku często również wersję pliku sprzed edycji, nadając 268 8. Przetwarzanie tekstów jej rozszerzenie BAK. Jeśli chcemy szczególnie chronić początkową zawartość wy- branych plików, powinniśmy przed rozpoczęciem edycji skopiować je w osobne miejsce na dysku, gdyż nie wszystkie edytory zapamiętują faktyczny początkowy stan pliku, ograniczając się do pamiętania stanu po ostatnim składowaniu. Przykład 8.3. Po wykonaniu poprawek w pliku o nazwie BAJKA-24. TAG i zakoń- czeniu sesji z edytorem za pomocą zwielokrotnionej operacji |Esc | w kartotece zostaną zapisane dwa pliki: BAJKA-24.TAG - zawierający wszystkie poprawki i zmiany, BAJKA-24. BAK - zawierający poprzednią wersję pliku. Zaniechanie sesji za pomocą operacji | F8 | BAJKA-24.TAG w niezmienionej postaci. | F2 |... spowoduje zachowanie pliku 8.15. Inne własności edytorów Edytory tekstów ogólnego przeznaczenia, w odróżnieniu od edytorów tekstów programów, wykonują operacje na całych akapitach. Do akapitu, jako do pew- nej całości, odnoszą się: formatowanie, zmiana kroju pisma, przemieszczanie itp. Przy posługiwaniu się edytorami działającymi na akapitach nie używa się klawisza | Enter | na końcu wierszy. Łamanie tekstu w wierszach następuje automatycz- nie, a w wypadku edytora TAG może temu dodatkowo towarzyszyć automatyczne dzielenie wyrazów. Inną szczególną ofertą edytorów (dostępną także w edytorze TAG) jest możli- wość rysowania ramek. Stosuje się różne techniki: ramkę mqżna utworzyć ze znaków z rozszerzonego kodu ASCII lub kreśląc za pomocą kursora (TAG). Edytory, podobnie jak inne rozbudowane programy, mogą być konfiguro- wane. Pozwala to użytkownikowi ustalać pewne preferencje, na przykład kolory na ekranie, odstępy czasu między kolejnymi składowaniami itp. Taką możliwość ma również edytor TAG od drugiej wersji począwszy. Komputerowe redagowanie tekstów jest bardzo elastyczne. Niemniej, przygo- towanie wypracowania z pomocą komputera również wymaga pewnego nakładu pracy. W pewnych sytuacjach, gdy dzisiejsze wypracowanie może się jutro okazać cenne jako artykuł na łamy gazetki szkolnej - w związku z czym wypadnie zmienić mu format kolumn i krój pisma - komputerowe edytory okazuj ą się niezastąpione. W niektórych edytorach kroje pisma mogą być definiowane przez samego u- żytkownika. Inną cechą przydatną w cyzelowaniu tekstów jest druk propor- cjonalny, czyli kształtowanie liter na podobieństwo składu drukarskiego - li- tera "i" jest węższa niż "m" itp. Z kolei użyteczną w pewnych zastosowaniach własnością edytorów może być makrodefiniowanie operacji klawiszowych, czyli możliwość ujmowania wspólną nazwą ciągów uderzeń w klawisze tak, by za- Zadania 269 miast za każdym razem wystukiwać litera po literze te same, często powtarzające się wyrazy, wzory, dane bibliograficzne lub inne fragmenty tekstu powodować ich "samopisanie się" poprzez wypisanie krótkiej nazwy (makrowywołania). Rolę makrowywołań można przyrównać do znaczenia procedur w językach programo- wania. Dodajmy jeszcze, że z obecności w niektórych edytorach korektora ortogra- ficznego (np. w edytorze TAG) nie trzeba wyprowadzać pochopnych przewidywań o zmierzchu przydatności zasad i wyczucia ortografii wynoszonych ze szkoły. Wszystkie wspomniane sprawy wiążą się ze specjalizowanymi zastosowaniami programów redagowania tekstów, wszelako ogólne cechy tych programów są po- dobne do opisanego tutaj edytora. Z pomocą komputerów wyposażonych w systemy przetwarzania tekstów pro- wadzi się doraźną korespondencję, notatki, również administruje pisaniem listów (z częściową automatyzacją samej zawartości listów włącznie), opracowuje się raporty, artykuły. Komputery pozwalają przygotowywać całe książki. Redagowanie tekstów, noszące w międzynarodowej literaturze fachowej miano word processing, jest dominującym, lecz nie jedynym zastosowaniem komputerów związanym z przetwarzaniem tekstów. Można oczekiwać, iż niedługo nie będzie licealisty, który by nie opanował posługiwania sie jakimś edytorem tekstów, tak jak nie było dawniej gimnazjalisty nie znającego sztuki kaligrafii. Zadania 8.1. Weź dowolny podręcznik i przyjrzyj się jego układowi oraz opracowaniu tech- nicznemu, tzn. takim jego cechom, jak podział na rozdziały i mniejsze jednostki, zastosowane kroje liter, sposoby wydzielania akapitów, opisy rysunków, postać spisu treści itp. Spróbuj wyodrębnić i nazwać jak najwięcej tego rodzaju cech. Jeżeli w bibliotece, do której masz dostęp, znajdują się opracowania omawiające techniczne redagowanie książek (np. Encyklopedia wiedzy o książce, Ossolineum, Wrocław 1971), przejrzyj je, po czym spróbuj odnaleźć opisy i nazwy tych ele- mentów, które najbardziej wpływają na wygląd książki (tekstu). 8.2. Zastosuj swoje obserwacje z zadania 8.1 do analizy tekstów innych niż książki, na przykład gazet, wydawnictw okresowych, instrukcji obsługi urządzeń domowych, korespondencji urzędowej. 8.3. Obejrzyj teksty kilku programów z tego podręcznika. Wymień regularności w ich budowie, które spostrzeżesz. 8.4. Zapewne przeglądasz nieraz popularne czasopisma informatyczne czy po pro- stu gazety. Wskaż wśród zamieszczanych tam ogłoszeń kilka takich, które zostały 270 8. Przetwarzanie tekstów przygotowane za pomocą prostych edytorów tekstu. Popatrz od strony kompu- terowej techniki składu na pisemko reklamowe, które właśnie podrzucono Ci pod drzwi. 8.5. Prostym, lecz bardzo przydatnym zastosowaniem komputera do opracowy- wania tekstów jest przygotowanie i drukowanie etykiet z adresami, przeznaczo- nych do umieszczania na przesyłkach. Znajdź inne tego typu przykłady prostych zastosowań. 8.6. Uruchom jakiś edytor tekstów na swoim komputerze (na komputerach IBM PC oprócz edytora TAG można często spotkać inne edytory, np. edytor ChiWri- ter) i przeanalizuj informacje wyświetlane w jego wierszu statusowym. 8.7. Sprawdź, czy wśród informacji wyświetlanych w wierszu statusowym Two- jego edytora (por. zad. 8.6) znajduje się wskazówka o sposobie korzystania z kom- puterowego systemu podpowiedzi. Jeśli tak, to postąp zgodnie z nią i zapoznaj się z wyświetlanymi objaśnieniami. 8.8. Informacja znikająca z ekranu w momencie otworzenia na nim okna pojawia się z powrotem z chwilą usunięcia (zamknięcia) okna z ekranu. Objaśnij mecha- nizm programowej realizacji okien, jeśli się go domyślasz. 8.9. Przećwicz dostępne w Twoim edytorze operacje manewrowania kursorem. Czy używany przez Ciebie edytor umożliwia automatyczne przenoszenie kursora nad większymi jednostkami leksykalnymi (słowami, wierszami, akapitami)? 8.10. Korzystając z możliwości oznaczania i kopiowania bloków tekstu, wyko- naj za pomocą edytora zadanie przygotowania 50 zaproszeń. Porównaj ten styl działania z osiągnięciem podobnego celu za pomocą napisania programu (por. rozdz. 4). 8.11. Za pomocą edytora TAG wykonaj diagram lub hierarchiczny spis wszy- stkich ofert edytora TAG, umieszczając przy symbolach klawiszy funkcyjnych własne zwięzłe objaśnienia ich działania. Opracuj diagram stopniowo, poczy- nając od tych działań, które spotykasz najczęściej. 9. ŁATWE I SPRAWNE ZARZĄDZANIE FIRMĄ - ARKUSZ KALKULACYJNY Arkusz kalkulacyjny jest drugim - po edytorze tekstów - najpopularniejszym pro- gramem wykorzystywanym przez użytkowników komputerów. "Program, który pchnął Amerykę w objęcia komputerów osobistych" - już to określenie suge- ruje, że jest on jedną z najbardziej pomysłowych i zarazem prostych koncepcji programowania użytkowego. Poniżej przedstawiamy ogólną ideę tego programu. Następnie zapoznamy się bliżej z jego realizacją o nazwie Quattro Pro, rozpo- wszechnioną na komputerach IBM PC, pracujących pod kontrolą systemu opera- cyjnego MS-DOS. Na koniec omawiamy wybrane obszary zastosowań programu, zarówno klasyczne - ekonomię i handel, jak i nowe - modelowanie i rozwiązywanie problemów, m.in. w matematyce. Jak usprawnić żmudne obliczenia? Czym zastąpić papier, ołówek, gumkę i kalkulator? Takie pytania zadał sobie w 1978 roku student uniwersytetu w Harvardzie (USA), zirytowany faktem, że zajmując się problemami z ekonomii, wymaga- jącymi wykonywania rutynowych działań arytmetycznych, więcej czasu zużywa na żmudne i nieskomplikowane obliczenia niż na efektywne rozwiązanie samego problemu. Zaprojektował i skonstruował więc program nazwany później arku- szem kalkulacyjnym (ang. spreadsheet). Arkusz kalkulacyjny jest typowym programem usługowym, który po uruchomieniu zamienia komputer w gotowe do obsługi narzędzie dla użytkownika. Omówiony w poprzednim rozdziale edy- tor tekstów jest programem, przeobrażającym komputer w niezwykle wygodną maszynę do pisania, pełniącą w dodatku funkcje zecera, archiwisty, a nawet kon- sultanta językowego. Porównanie edytora tekstów z maszyną do pisania wypada mniej więcej podobnie jak porównanie arkusza kalkulacyjnego z tradycyjnymi narzędziami: kartką kratkowanego papieru, ołówkiem i kalkulatorem. 272 9. Arkusz kalkulacyjny Arkusz kalkulacyjny pozwala na bezpośrednie zapisywanie na ekranie moni- tora wzorów, według których są wykonywane obliczenia, na bieżąco wyświetlając na tym samym ekranie wyniki otrzymane dla konkretnych danych metodą wpi- saną w arkusz. Zmiana wartości jednej z danych powoduje automatyczne prze- liczenie wszystkich zależnych od niej wielkości. Te dwie cechy odróżniają korzy- stanie z arkusza kalkulacyjnego od tradycyjnego podejścia - napisania programu w języku programowania. 9.1. Co to właściwie jest arkusz kalkulacyjny? Odpowiedź na to pytanie uzyskamy analizując kilka prostych przykładów. Je- den z nich jest przedstawiony na rys. 9.1. Widać na nim obraz ekranu moni- tora podzielony na wiersze i kolumny tworzące umowny arkusz, tak jak pionowe i poziome linie tworzą zwykły arkusz papieru kancelaryjnego. Jeśli poprowa- dzimy linie oddzielające wiersze i kolumny, to dokonamy podziału ekranu na małe prostokątne fragmenty zwane komórkami. Wiersze są oznaczane zwykle kolejnymi liczbami naturalnymi (1, 2,...), a kolumny - literami alfabetu (A, B,...). Umożliwia to łatwe odwoływanie się do komórek, np. Al jest adresem (współrzędnymi) komórki w lewym górnym rogu ekranu (kolumna A, wiersz 1). Każda komórka może zawierać liczbę, wzór, czyli wyrażenie arytmetyczne (zwany również formułą) lub dowolny ciąg znaków, który będziemy nazywać napisem. ABC 1 Przykład pierwszy 2 3 Lp. 4 1 25 5 2 31 6 3 50 7 8 Suma 106 9 10 Rys. 9.1. Arkusz kalkulacyjny - obliczanie sumy liczb W powyższym przykładzie zawartością komórki Al jest napis (komentarz) Przykład pierwszy. Napisami są również Lp. (komórka A3),---------(B7) oraz Suma (A8). Mówiąc ogólnie, napis jest ciągiem znaków nie analizowanych przez program, służących jako komentarz lub nagłówek. Wiersze czwarty, piąty i szósty 9.1. CO TO JEST ARKUSZ KALKULACYJNY? 273 zawierają liczby. W komórce B8 jest umieszczone wyrażenie arytmetyczne, obli- czające sumę liczb z komórek B4, B5 i B6. Na ekranie widzimy tę obliczoną sumę równą 106 (za chwilę wyjaśnimy, jak obejrzeć samo wyrażenie). Czy nie jest to jednak zbyt niewygodne? Skoro suma liczb 25, 31 i 50 wy- nosi 106, czy nie można by wpisać tej liczby do komórki B8, zamiast definiować wyrażenie, obliczające tak prostą sumę? Za przyjętym rozwiązaniem przemawia jego uniwersalność. Łatwo bowiem odpowiedzieć na przykład na pytanie, jak zmieni się ta suma, jeśli 25 zastąpimy liczbą 1142. W przyjętym rozwiązaniu, po wprowadzeniu zmienionej wartości, nowa suma zostanie automatycznie obliczona i wyświetlona. Wspomniane wyrażenie pełni rolę kalkulatora wyświetlającego wynik w ko- mórce, w której je umieszczono. Każda komórka może mieć swój własny "kal- kulator" ; innymi słowy w każdej komórce można zapisać odpowiednie wyrażenie. Na ekranie możemy oglądać zarówno wartości wyrażeń, jak i same wzory umie- szczone w szablonie arkusza. Szablonem posługujemy się najczęściej podczas konstruowania i modyfiko- wania arkusza, a gdy szablon jest już gotowy, interesujemy się bieżącą jego za- wartością. Na rysunku 9.2 jest przedstawiony szablon arkusza, którego zawartość jest pokazana na rysunku 9.1. 1 Przykład pierwszy 2 3 Lp. 4 1 25 5 2 31 6 3 50 7 8 Suma @SUM(B4..B6) 9 10 Rys. 9.2. Szablon arkusza kalkulacyjnego - obliczanie sumy liczb Wyrażenie w komórce B8 mogłoby mieć postać B4+B5+B6. W dalszej części rozdziału wyjaśnimy zalety zapisu ©SUM(B4. .B6), polecającego obliczyć sumę liczb umieszczonych w komórkach od B4 do B6 włącznie. Na koniec zmodyfikujmy arkusz tak, aby obliczał również średnią arytmetyczną liczb. Jednym z rozwiązań jest umieszczenie w komórce A9 napisu-komentarza Średnia, a w komórce B9 - wyrażenia @SUM(B4. .B6)/3 (znak / oznacza tutaj operację dzielenia). Inne rozwiązanie jest pokazane na rysunku 9.3. 18 — Elementy informatyki 274 9. Arkusz kalkulacyjny 1 Przykład drugi 2 3 Lp. 4 1 25 5 2 31 6 3 50 7 8 Suma 0SUMCB4..B6) 9 Średnia +B8/3 10 Rys. 9.3. Szablon arkusza kalkulacyjnego - obliczanie sumy i średniej liczb 9.2. Rozpoczynamy pracę Wiemy już, co to jest arkusz kalkulacyjny: "elektroniczny papier w kratkę", na którym można utworzyć dowolny formularz, zawierający w poszczególnych kratkach-komórkach napisy, liczby i wyrażenia, zgodnie z którymi są wykony- wane obliczenia. Aby rozpocząć pracę nad własnym szablonem, należy przede wszystkim wiedzieć, jak duży może być arkusz i jak można wpisywać do niego dane. Dowiedzieliśmy się także, że arkusz składa się z wierszy i kolumn, wyzna- czających podział na komórki. Arkusz zawierający k wierszy i I kolumn ma więc k x I komórek. Maksymalna liczba dostępnych komórek zależy od konkretnego arkusza; w systemie Quattro Pro, mamy do dyspozycji arkusz o 8192 wierszach i 256 kolumnach, a więc ten arkusz zawiera 2097152 komórki. Początkowe 26 komórek z pierwszego wiersza ma adresy Al, Bl, Cl, ..., Yl, Zl. Adresami następnych komórek są AAl, AB1, AC1, ..., AZ1 i dalej BA1, BB1, BCl, ..., aż do IV1. Cztery rogi naszego arkusza mają więc współrzędne (idąc zgodnie z ruchem wskazówek zegara) Al, IV1, IV8192 i A8192. Pełny arkusz wydrukowany na papierze zająłby całą ścianę sporego budynku, trudno więc oczekiwać, że zmieści się on na ekranie monitora. Podobnie więc jak w przypadku edytora tekstów ekran jest oknem, przesuwającym się w dowolnym kierunku w obrębie arkusza. Wielkość tego okna zależy od jakości obrazu wytwa- rzanego przez monitor (tak zwanej rozdzielczości monitora); tutaj zakładamy, że na ekranie można wyświetlić 25 wierszy po 80 znaków w każdym. Skoncentrujmy teraz uwagę na obrazie z ekranu, pokazującym fragment arku- sza. Po rozpoczęciu pracy z nowym arkuszem jest wyświetlany jego lewy górny róg. Punktem odniesienia na ekranie jest kursor, znajdujący się w komórce, 9.2. Rozpoczynamy pracę 275 której zawartość możemy w danej chwili zmienić lub obejrzeć. Komórka ta na- zywa się komórką bieżącą i jest podświetlona lub zaznaczona innym kolorem. Położenie kursora zmieniamy za pomocą klawiszy sterujących kursorem (f, i. Jeżeli podczas ruchu kursora PgUp , PgDn Ctrl Ctrl dojdziemy do krawędzi ekranu, to dalsze jego przesuwanie w tym samym kierunku przesunie również okno ekranu względem całego arkusza. Aby móc zmieniać zawartości komórek arkusza, oprócz metody adresowania komórek, powinniśmy znać jeszcze polecenia wydawane programowi. Przyj- rzyjmy się dokładnie wyglądowi całego obrazu na ekranie (rys. 9.4). File Edit Style Graph Frint Database TodIs Options Windou fil: U A E C D E F G 1 Z 3 4 5 6 7 8 9 19 11 IZ 13 14 15 16 17 18 19 Z0 3- SHEET1.UQ1 [1] ? Tl i i 111 i i i i n! 111 i 1111 u i i 111 i 11111 im pm t n prrtw uni rui n n ftn n FEADV Rys. 9.4. Początkowy wygląd arkusza kalkulacyjnego na ekranie Obraz na ekranie jest podzielony na trzy części. Centralna część pełni rolę okna, przez które można oglądać fragment arkusza, składający się z 20 wierszy i 7 kolumn. Wzdłuż lewej krawędzi są umieszczone kolejne liczby naturalne nu- merujące wiersze, u góry zaś - litery opisujące kolumny. U dołu ekranu znajduje się wiersz stanu programu, natomiast dwa górne wiersze służą do komunikowania się użytkownika z programem. Polecenia dla programu można z grubsza podzielić na dwie grupy: 1. Wpisz coś do wskazanej komórki (napis, liczbę lub wyrażenie). 2. Wykonaj inną, na ogół bardziej złożoną operację (skasuj, skopiuj, przenieś, zapisz itp.). 276 9. Arkusz kalkulacyjny Aby wydać polecenie z pierwszej grupy, należy ustalić za pomocą kursora współrzędne komórki, w której ma być wykonany zapis, po czym wpisać odpo- wiedni tekst w wierszu poleceń dla programu. Pierwszy wpisany znak informuje program, co zamierzamy napisać. Jeżeli jest to litera, to zostanie ona uznana za początek napisu i cały wiersz zostanie wiernie skopiowany do odpowiedniej komórki. Również znaki specjalne ' (apostrof), " (podwójny apostrof) i " (da- szek, na klawiaturze znajduje się nad cyfrą 6) oznaczają początek napisu. Dodat- kowo każdy z nich inaczej umieszcza napis w komórce: po podaniu ' napis będzie wyrównany do lewej krawędzi komórki, po " - wyrównany do prawej krawędzi, a po * - umieszczony w środku komórki (centrowany). Znak specjalny nie jest widoczny na ekranie - w komórce pojawia się tylko efekt jego działania. Jeżeli pierwszy wpisany znak jest cyfrą lub którymś z operatorów (+, -, (, @ itp.), to wprowadzany tekst zostanie uznany za wyrażenie lub liczbę. Naturalnie musi to być poprawne wyrażenie arytmetyczne - nawiasy muszą się zgadzać, funkcje muszą mieć prawidłowe argumenty itp. Polecenia z drugiej grupy są umieszczone w ofercie wyświetlanej w najwyż- szym wierszu ekranu. Aby z niej skorzystać, należy nacisnąć klawisz /. Wówczas jedno z poleceń zostaje podświetlone i zostanie wykonane, jeżeli naciśniemy kla- wisz 1 Enter |. Jeśli chcemy wydać inne polecenie, to najpierw przenosimy pod- świetlenie na jego nazwę, posługując się klawiszami strzałek lub naciskamy klawisz z literą wyróżnioną w nazwie polecenia (oczywiście po naciśnięciu klawisza /). Każde z poleceń u góry ekranu, po wybraniu, rozwija nową ofertę poleceń po- tomnych, z których każde może być poleceniem ostatecznym (czyli do wykonania) lub też rozwijać się dalej. Zasady poruszania się po podofertach są takie same, jak w ofercie głównej. Z każdego poziomu ofert programu można wycofać się na poprzedni poziom klawiszem JEsc |. Po wydaniu polecenia program zazwyczaj pyta o wartości parametrów uściślających czynności, które mają być wykonane. Arkusz akceptuje ponadto kilka poleceń wywoływanych przez naciśnięcie poje- dynczego klawisza. Jednym z tych poleceń jest przejście kursorem do wybranego fragmentu arkusza. W tym celu należy nacisnąć klawisz | F5 |, a następnie podać adres komórki, którą chcemy mieć w lewym górnym rogu fragmentu arkusza wyświetlanego na ekranie. Przećwiczmy teraz podane wiadomości. Załóżmy, że w komórce Al chcemy umieścić nazwisko Brzęczy szczykiewicz, a w komórce Bl — jego rok urodzenia, np. 1972. Przesuwamy więc kursor do komórki Al, po czym piszemy wymienione nazwisko i na końcu naciskamy klawisz [Enter [. Następnie przesuwamy kur- sor do Bl (klawiszem —?), wpisujemy liczbę 1972 i ponownie naciskamy klawisz I Enter [. Pojawia się jednak przeszkoda gdyż komórka na prawo od komórki Al jest zapełniona (liczbą 1972) i na ekranie widzimy jedynie fragment nazwiska z komórki Al - Brzęczysz. Wynika to z niedopasowania rozmiarów komórki 9.3. Wyświetlanie liczb i zasięg poleceń 277 do długości nazwiska. Musimy zatem zmienić szerokość kolumny A. W tym celu wybieramy z oferty polecenie /Style\ Column Width, a jako parametry poda- jemy adres komórki (Al) i pożądaną szerokość (20 znaków). Możemy to uczynić następującą sekwencją klawiszy: /SCAl|Enter |20[Enter |. Poznaliśmy dwie ważne cechy elektronicznego arkusza: pamięta wszystko, co umieszczamy w jego komórkach oraz potrafi zmieniać swój wygląd, na przykład poszerzając pierwszą kolumnę. Ponadto w trakcie pracy można dodawać lub usuwać wiersze bądź kolumny, kopiować lub przestawiać fragmenty arkusza, re- dagować zawartość komórek (por. p. 9.6). Arkusz zatem ma podstawowe ce- chy edytora tekstów - raz wprowadzone dane mogą być zmieniane, a następnie wyświetlone w sposób najbardziej odpowiadający użytkownikowi. W ostatnim wierszu ekranu jest umieszczany wiersz stanu programu. Opi- suje on aktualny stan arkusza (nazwę bieżącego arkusza, numer okna itp.) lub zawiera komentarz do wybieranego polecenia. Najistotniejszy dla użytkownika jest wiersz wprowadzania danych, wyś- wietlany w drugim wierszu ekranu. Pojawiają się w nim m.in.: - dane wprowadzane do bieżącej komórki; - aktualnie poprawiana zawartość komórki (po naciśnięciu klawisza | F2 |); - rzeczywista zawartość bieżącej komórki oraz wartości jej parametrów: sze- rokość, format numeryczny, krój pisma itp. (podczas przeglądania arkusza); - pytania o wartości parametrów (podczas wykonywania poleceń z oferty). 9.3. Sposoby wyświetlania liczb, zasięg działania poleceń Załóżmy, że do komórki Bl wpisaliśmy liczbę 4600. Liczbę tę można wyświetlić na wiele sposobów, zależnych od formatu wyświetlania, który wybieramy pole- ceniem /Style\Numeric Format. Przykłady formatów i odpowiadająca im postać liczby są podane w tablicy 9.1. Tablica 9.1. Formaty numeryczne Format Postać liczby Uwagi General 4600 Najkrótsza postać (stalopozycyjna lub wykładnicza) Fixed 4600.00 Postać stałopozycyjna Scientific 4.6E+03 Postać wykładnicza 4,600.00 Tysiące oddzielone przecinkami We wszystkich przypadkach możemy również wybrać liczbę cyfr dziesiętnych w części ułamkowej. 278 9. Arkusz kalkulacyjny Zawartość komórki może być ukryta przed niepowołanym okiem (format Hid- den) lub wyświetlona w postaci zapisanego w niej wyrażenia - w szablonie arku- sza, por. rys. 9.2 (format Text). Zasięgiem działania formatu może być pojedyncza komórka (np. Cl), frag- ment wiersza (np. D3..H3), fragment kolumny (np. G1..G20) lub najogólniej - dowolny prostokątny fragment arkusza (np. C3..G15). Umiejętność określania fragmentu arkusza (zwanego często blokiem) o jaki nam chodzi, jest bardzo istotna - program pyta nas o to niemal przy każdym wydawanym mu poleceniu. i 9.4. Nieco o wyrażeniach Przypomnijmy, że w każdej komórce arkusza można umieścić napis albo wzór, czyli wyrażenie, symbolizujące pewną wartość liczbową. Zacznijmy od najprost- szych (zakładamy, że umieszczono je w komórce Al): 4600 - Jest to stała liczbowa. Zgodnie z informacjami z p. 9.3 sposób wyś- wietlania liczb zależy od obowiązującego w danej chwili formatu wyś- wietlania, pełniącego funkcję pośrednika pomiędzy wyrażeniem, a jego wartością. +C3 - Jest to adres komórki i oznacza skopiowanie do komórki Al wartości wyrażenia znajdującego się w komórce C3. Wyrażenie to jest poprze- dzone znakiem + (plus), gdyż sam adres C3 zostałby potraktowany przez arkusz jako napis (ponieważ zaczyna się od litery - por. p. 9.2). Większość wyrażeń w arkuszu rozpoczyna się znakiem +, który w tym kontekście jest najwygodniejszy, gdyż nie zmienia wartości wyrażenia. Mając do dyspozycji stałe liczbowe, adresy komórek i operatory arytmetyczne, możemy konstruować wyrażenia arytmetyczne (por. rozdz. 4). Umożliwiają one wykonywanie obliczeń na podanych argumentach. Zacznijmy od wyliczenia ope- ratorów (w kolejności malejących priorytetów — tablica 9.2). Tablica 9.2. Operatory arytmetyczne Priorytet Operator Znaczenie 4 ( ) zmiana kolejności obliczeń 3 podniesienie do potęgi 2 * mnożenie 2 1 dzielenie 1 + dodawanie 1 - odejmowanie 9.5. Prosty model symulacyjny 279 Teraz kilka przykładów wyrażeń z komórek arkusza: 2~7 +A1-7 +C3+B5*2.5 (Bl+44)/2 @SIN(C5)~2 Jak widać, wyrażenie, ów kalkulator związany z komórką, w której go umie- szczono, dzięki możliwościom pobierania danych z innych komórek dysponuje większymi możliwościami niż typowy kalkulator. Arkusz stawia ponadto do dys- pozycji użytkownika dużą liczbę funkcji (nazwy wszystkich funkcji zaczynają się od znaku @ - jedną z nich poznaliśmy już w p. 9.1). Są to zarówno funkcje znane użytkownikom kalkulatorów (obliczanie pierwiastka kwadratowego, funkcje try- gonometryczne itp.), jak i funkcje specyficzne dla arkusza (operacje na datach, obliczenia finansowe, funkcje logiczne). W następnych punktach przekonamy się, że dzięki tym możliwościom postać wyrażenia może być bardzo złożona, w dużej mierze decydując o atrakcyjności arkusza. 9.5. Prosty model symulacyjny Zastosujmy w praktyce nabytą wiedzę, próbując odpowiedzieć na pytanie: jaki będzie mój kapitał pieniężny po kilku latach, jeżeli złożę 1000 tys. zł w banku gwarantującym odsetki w wysokości 10% w skali rocznej. Nasze rozterki rozwiąże arkusz o szablonie przedstawionym na rysunku 9.5. 1 2 3 4 5 6 7 8 A odsetki: kapitał: B 10 1000 Bank PKO Wysokość kapitału na końcu: roku 1 +B2*(l+Bl/100) roku 2 +B7*(l+Bl/100) roku 3 +C7*(l+Bl/100) Rys. 9.5. Naliczanie odsetek od złożonego kapitału - szablon arkusza Z wyglądu arkusza wynika, że wydano już polecenie powiększenia szerokości kolumn B, C i D do 14 znaków (poleceniem /Style\Block Size\Set Width z para- metrem 14). Dla napisu w komórce B4 (Wysokość kapitału na końcu:) jest to jednak nadal za mało miejsca - napis rozciąga się na dwie kolumny. W ten sposób 280 9. Arkusz kalkulacyjny arkusz wyświetla długie napisy: zasłaniają one komórki na prawo od zajmowanej, ale pod warunkiem, że te komórki są wolne. Dla zwiększenia czytelności arkusza wskazane byłoby jeszcze dosuwanie war- tości liczbowych do prawego marginesu i wyświetlanie ich z dwoma miejscami po kropce. Zawartość arkusza po tych operacjach jest przedstawiona na rys. 9.6. A B C D 1 odsetki: 10. 00 Bank PKO 2 kapitał: 1000. 00 3 4 Wysokość kapitału na końcu: 5 6 roku 1 roku 2 roku 3 7 1100. 00 1210.00 1331.00 8 Rys. 9.6. Naliczanie odsetek od złożonego kapitału - zawartość arkusza Jeżeli chcemy prześledzić narastanie kapitału dla zmienionego oprocentowa- nia lub innego kapitału początkowego, to wystarczy zmienić dane w komórkach odpowiednio Bl lub B2. Program automatycznie obliczy i wyświetli w wierszu 7 nowe wartości. Jeżeli założymy, że rozbudowujemy nasz arkusz w ten sposób, aby wysokość kapitału na końcu trzeciego roku była wielkością początkową dla wykonania 100 dalszych obliczeń, zysk czasowy będzie naprawdę spory. 9.6. Nanoszenie poprawek Arkusz kalkulacyjny ma wszelkie cechy zwykłej kartki papieru: można wymazać z niego niepotrzebne dane (/Edit\EraseBlock), zmodyfikować istniejące (klawisz |F2 |), lub też rozciąć arkusz wzdłuż wybranego wiersza lub kolumny i usunąć (/Edit\Delete) bądź dodać (/Edit\Insert) wiersz lub kolumnę. Jeżeli skonstru- owany arkusz zupełnie nie przypadł nam do gustu, wyrzucamy całą kartkę do kosza (/File\Erase) i rozpoczynamy pracę od nowa. Przeredagujmy nieco arkusz z rys. 9.6. Najpierw usuwamy nazwę banku, prze- chowującego nasze oszczędności - polecenie /Edit\Erase Błock Cl |Enter |. Jeśli chcemy uzupełnić napis w komórce B4, nie pisząc go od nowa, to możemy sko- piować go najpierw do wiersza poleceń (naprowadzamy kursor na B4 i naciskamy |~F2~|) a następnie zredagować według potrzeb. Drażni nas pusty wiersz 5 - usu- wamy go poleceniem /Edit\Delete\Rows A5|Enter |. Chcemy dodać pusty wiersz i pustą kolumnę odpowiednio na górnym i lewym obrzeżu arkusza - realizują to polecenia /Edit\InserĄRow Al | Enter | i /Edit\Insert\ Column Al | Enter |. 9.6. Nanoszenie poprawek 281 Usunięcie piątego wiersza, a w istocie zbliżenie wierszy 4 i 6, można rozwiązać inaczej, przenosząc dolny fragment arkusza o jeden wiersz w górę poleceniem /Edit\Move B6..D7] Enter]B51 Enter]. Po dodaniu skrajnej kolumny zaczynamy mieć wątpliwości, gdyż w dawnym wierszu siódmym były wyrażenia zawierające adresy komórek (por. rys. 9.6). Po wstawieniu nowej pustej kolumny numer 1, komórka B2 stała się komórką C2, B7 przeszła na C7 itd. Nie musimy jednak przeredagowywać całego arkusza, gdyż program zrobił to już automatycznie. Ogólnie, arkusz traktuje adresy komórek na trzy sposoby. Przedstawimy je, analizując możliwe warianty skopiowania lub przeniesienia wzoru z komórki A2 do komórki D4: 1. Adres jest wielkością względną. Na przykład wyrażenie +A1 umieszczone w komórce A2 oznacza wartość wyrażenia z komórki położonej w tej sa- mej kolumnie, ale o jeden wiersz wyżej (rys. 9.7). Po skopiowaniu do komórki D4 wyrażenie to przybierze postać +D3 (tzn. ta sama kolumna, wiersz bezpośrednio wyżej). B D 1 2 3 4 +A1 +D3 Rys. 9.7. Adres względny 2. Adres jest wielkością bezwzględną, niezależną od zmian dokonywanych w arkuszu. Takie adresy wpisujemy poprzedzając numer wiersza i literę kolumny komórki znakiem $ (rys. 9.8). A B C D 2 3 4 +$A$1 +$A$1 Rys. 9.8. Adres bezwzględny 3. Część adresów w wyrażeniu jest względna, a część bezwzględna, np. wyra- żenie +$A1 w komórce A2 oznacza "wartość wyrażenia z komórki w kolu- mnie A i w wierszu bezpośrednio powyżej". Przy kopiowaniu do komórki D4 wyrażenie ulegnie zmianie na +$A3 - kolumna A, wiersz bezpośrednio powyżej wiersza czwartego (zob. rys. 9.9). 282 9. Arkusz kalkulacyjny .C 1 2 +$A1+B$2 - 3 4 D +$A3+E$2 Rys. 9.9. Adresy mieszane 9.7. Zakończenie pracy Aby zakończyć pracę z arkuszem, wydajemy polecenie /File\Exit. Wykonanie tego polecenia powoduje powrót pod nadzór systemu operacyjnego. Mogłoby zatem spowodować utratę zawartości arkusza, jeśli uprzednio nie zapisaliśmy wy- ników naszej pracy na dysku lub dyskietce. Służy do tego polecenie /File\Save. Jeśli nie pamiętaliśmy o tym, to przed zakończeniem pracy program sam to nam zaproponuje, dając szansę zapisania bieżącego stanu arkusza. Jeśli po jakimś cza- sie chcemy wrócić do naszego arkusza, to należy odczytać go z pliku poleceniem /File\ Open. Podobnie, jak w przypadku korzystania z innych systemów oprogramowania (takich jak język Pascal czy edytor TAG), operację składowania rezultatów pracy w pamięci masowej powinno się powtarzać przynajmniej co pół godziny, gdyż nic nie przywróci nam informacji utraconych w następstwie chwilowego spadku napięcia lub innych zakłóceń. Wymienione tutaj polecenia, być może inaczej nazwane i inaczej wywoływane, występują w większości programów usługowych i warto je zapamiętać. 9.8. Skomputeryzowane przyznawanie premii Uzbrojeni w znaczną już wiedzę przystępujemy do rozwiązania praktycznego pro- blemu - zarządzania firmą. Przypuśćmy, że jesteśmy właścicielem małego, dobrze prosperującego przedsiębiorstwa i jako dobry szef chcemy wynagrodzić pracow- ników, przyznając im premie. W celu określenia premii (liczonej w procentach pensji) sumujemy dwa składniki: naszą własną opinię o podwładnych oraz ich staż pracy (który będziemy mnożyć przez dwa). Stawiamy tylko jedno ograniczenie, by suma premii nie przekroczyła 10% zysku firmy. Na przeszkodzie do szybkiego rozwiązania postawionego zadania stoi trudność z obliczeniem stażu pracy. W przypadku arkusza dysponujemy jednak całą gamą funkcji działających na datach. Umożliwiają one wpisywanie dat do arkusza oraz wykonywanie niektórych działań na datach (dodanie i odjęcie liczby, odejmowanie dat od siebie itp.). 9.8. Skomputeryzowane przyznawanie premii 283 Wpisywanie dat odbywa się w arkuszu za pomocą funkcji @DATE, której trzema parametrami są rok, miesiąc i dzień. Jeżeli jakiś pracownik został zatrudniony 15 października 1987 roku, to w odpowiedniej komórce umieszczamy następujące wyrażenie @DATE(87,10,15). Bieżąca data jest wartością funkcji (3T0DAY (bez parametrów). A B C D 1 Imię Data zatrudnienia Pensja Staż pracy 2 Andrzej <§DATE(87,10,15) 1800 @INT((@T0DAY-B2)/365) 1 Składnik 2 6 E Premia +C2*(E2+D2*2)/100 Rys. 9.10. Obliczanie premii - szkic szablonu arkusza Obliczenie stażu pracy, który jest liczony w pełnych latach, polega na odjęciu daty zatrudnienia od bieżącej daty, podzieleniu wyniku przez 365 (tyle dni liczy rok) i zaokrągleniu ilorazu w dół. Zatem jeśli data zatrudnienia jest umieszczona w komórce B3, to w komórce np. D3 możemy wpisać wzór realizujący obliczanie lat stażu: @INT((@T0DAY-B3)/365). Wartością użytej tu funkcji @INT jest część całkowita z podanego argumentu. Jeśli oceniamy pracownika na 6-procentową premię, a jego staż pracy wynosi 1 rok, to premia powinna wynieść 6+1*2 procent. Początkowy fragment szablonu arkusza jest przedstawiony na rys. 9.10 (z braku miejsca arkusz został złamany i przedstawiony w dwóch wierszach). Zakładamy, że wszystkie kwoty są podane w tysiącach złotych. Widać już, że przy wpisywaniu danych o następnych pracownikach wyrażenia w kolumnach D i F będą się różnić jedynie numerami wiersza, np. w komórce D3 zamiast @T0DAY-B2 będzie OT0DAY-B3 itd. Powielenie wyrażenia z uwzględnieniem wymienionej modyfikacji można zlecić arkuszowi. Polecenie /Edit\ Copy umożli- wia kopiowanie wyrażenia, traktując zawarte w nim adresy jako względne (gdyż oznaczenia wierszy i kolumn nie są poprzedzone znakiem $ - por. p. 9.6). Jeśli chcemy więc dopisać jeszcze trzech pracowników do naszej listy osób nagrodzo- nych premią, to kolumnę F wypełniamy stosując polecenie kopiowania z parame- trami F2 (komórka źródłowa) i F3..F5 (blok komórek docelowych). Analogicznie wypełniamy kolumnę D. Postać szablonu po tym uzupełnieniu jest pokazana na rysunku 9.11. 286 9. Arkusz kalkulacyjny A B C D 1 Imię Data zatrudnienia Pensja Staż pracy 2 Andrzej 15/10/87 1800.00 1 3 Jacek 01/06/85 2000.00 3 4 Piotr 15/09/86 1700.00 2 5 Anna 01/07/87 1650.00 0 6 7 8 Zysk firmy: 8820.00 9 Pula na premie: 882.00 10 Suma premii: 880.50 1 2 3 4 5 E Składnik 7.5 8.5 10 11 F Premia 171.00 290.00 238.00 181.50 Rys. 9.13. Obliczanie premii - wersja końcowa wyników 300-1 250- 200- 150- 100- 50- I Andrzej Jacek Piotr Anna Rys. 9.14. Ilustracja graficzna wielkości przyznanych premii - wykres słupkowy 9.10. Funkcje logiczne 287 Możliwości arkusza Quattro Pro w dziedzinie graficznej prezentacji danych są bardzo duże. W ofercie programu są one umieszczone pod wspólnym poleceniem /Graph. Aby narysować wykres taki, jak na rys. 9.14, wystarczy zdefiniować od- powiednie serie (czyli ciągi liczb lub napisów, definiujących argumenty i wartości wykreślanych funkcji). Serię dla osi Ox (w naszym przypadku są to imiona pra- cowników) definiujemy wydając polecenie /Graph\Series\X-Axis Series i podając jako parametr blok A2..A5. Podobnie definiujemy pierwszą (i w naszym przy- padku jedyną) serię dla osi Oy /Graph\Series\lst Series z parametrem F2..F5. Wykonany wykres możemy obejrzeć wybierając z oferty polecenie /Graph\ View. Jeżeli nie jesteśmy w pełni zadowoleni z postaci wykresu, to możemy zmienić niektóre jego parametry. Na przykład aby obejrzeć obliczone wysokości premii w postaci wykresu kołowego, można zmienić rodzaj wykresu za pomocą po- lecenia /Graph\Graph Type\Pie (por. rys. 9.15). W każdym przypadku program automatycznie dobiera skalę dla wykresu - jeżeli nam nie odpowiada, to możemy oczywiście ją zmienić. Anna (20.6%)-^ Piotr (27.0%) Andrzej (19.4%) Jacek (32.9%) Rys. 9.15. Ilustracja graficzna wielkości przyznanych premii - wykres kołowy 9.10. Funkcje logiczne W arkuszu czasami jest konieczne uzależnienie wykonania jakiejś operacji od danych umieszczonych w innym miejscu. Przykładowo, wzór obliczający premię (por. rys. 9.10) moglibyśmy zmodyfikować i każdemu pracownikowi ze stażem przynajmniej 10-letnim dodawać ekstra 5% do premii. Do zapisywania operacji warunkowych służy funkcja @IF. Jej ogólna postać jest następująca: 288 9. Arkusz kalkulacyjny (9IF (warunek, wyrażenie-tak, wyrażenie-nie) a działanie - analogiczne do opisanej w rozdziale 4 instrukcji if... then.,. else... Oznacza to, że jeśli warunek jest spełniony, to obliczana jest wartość wyrażenia- tak, a w przeciwnym razie - wyrażenia-nie. Zatem, aby dodawać 5% premii pracownikom ze stażem przynajmniej 10-letnim, w komórce F2 z rys. 9.11 należy umieścić następujące wyrażenie: +C2/100*(E2+D2*2+@IF(D2<0,0,5)) Następnie należy skopiować zawartość komórki F2 do bloku F3..F5, aby ta mo- dyfikacja dotyczyła wszystkich pracowników. nn Uwaga: Arkusz obliczający premie znajduje się na dyskietce w pliku PREMIE.WQ1 umie- szczonym w kartotece R0ZDZ9. Korzystając z funkcji @IF, zmodyfikujmy teraz arkusz z rys. 9.5 tak, aby obliczał wielkość kapitału po dowolnej liczbie lat. Szablon w nowej postaci jest przedstawiony na rys. 9.16, a sam arkusz - na rysunku 9.17. A B 1 Start obliczeń : 0 2 Procent: 10 3 Kapitał pocz: 1000.00 1 2 Koniec roku: 3 Kapitał: D ®IF(Bl=0,0,l+D2) @IF(B1=O,B3,(l+B2/100)*D3) Rys. 9.14. Obliczanie odsetek od kapitału - druga wersja szablonu z rys. 9.5 A B 1 Start obliczeń: 0 2 Procent: 10 3 Kapitał początkowy: 1000.00 Koniec roku: Kapitał: 0 1000.00 Rys. 9.15. Obliczanie odsetek od kapitału - stan początkowy obliczeń Obliczenia w tym arkuszu są inicjowane w komórce Bl i po zmianie jej za- wartości na różną od zera (np. na 1), arkusz przybiera postać jak na rys. 9.18. 9.11. Arkusz a metody numeryczne 289 Naciśnięcie następnie klawisza |F9 | (co wymusza jednokrotne przeliczenie wszyst- kich wyrażeń) spowoduje zmianę wartości odpowiednich komórek (por. rys. 9.19). A B 1 Start obliczeń: 1 2 Procent: 10 3 Kapitał początkowy: 1000.00 Koniec roku: Kapitał: 1100.00 Rys. 9.16. Obliczanie odsetek od kapitału - rozpoczęcie obliczeń Cechą tej modyfikacji jest m.in. niewychodzenie poza obręb ekranu niezależnie od tego czy analizujemy wzrost kapitału po trzech, czy po dwudziestu latach. Za- uważmy bowiem, że w szablonie z rys. 9.5 wyrażenie obliczające wielkość kapitału po 7 latach musielibyśmy umieścić w skrajnej kolumnie H, a wpisanie następnych wzorów wiązałoby się z koniecznością przesunięcia okna ekranu w prawo po ar- kuszu. A B C D 1 Start obliczeń: 1 2 Procent: 10 Koniec roku: 2 3 Kapitał początkowy: 1000.00 Kapitał: 1210.00 Rys. 9.17. Obliczanie odsetek od kapitału - kolejny krok obliczeń 9.11. Arkusz a metody numeryczne Arkusz kalkulacyjny został szybko dostrzeżony i doceniony przez użytkowników spoza kręgu handlu i ekonomii. Jednym z jego możliwych zastosowań jest wy- konywanie obliczeń według algorytmów numerycznych. Rozważmy algorytm Newtona-Raphsona, obliczający pierwiastek kwadratowy z nieujemnej liczby rzeczywistej a (por. p. 6.7.2 i zad. 6.4). Po ustaleniu przybliżenia początkowego xq, następne przybliżenia są obliczane według wzoru: 1 a H ) Tworzenie arkusza zaczniemy od rzeczy najprostszych: wpisania wartości po- czątkowych i powyższego wzoru. Przyjmijmy a = 45 i xq = 7. Szkic tworzonego szablonu jest przedstawiony na rysunku 9.20. 19 — Elementy informatyki 290 9. Arkusz kalkulacyjny A B C D 1 Pierwiastek z liczby: 45 2 Przybliżenie początkowe: 7 3 4 Krok iteracji Wartość przybliżenia 5 0 +C2 6 +B5+1 0 5*(C5+($C$1/C5)) Rys. 9.18. Szkic szablonu arkusza dla algorytmu Newtona-Raphsona Ułatwiamy sobie zadanie przy wpisywaniu kolejnych numerów kroku iteracji - w kolumnie B będziemy po prostu zwiększać o 1 wartości w kolejnych wierszach. Do skopiowania wzorów z wiersza 6 użyjemy polecenia /Edit\ Copy z parametrami B6..C6 (blok źródłowy) i B7..C14 (blok docelowy). Kompletny szablon arkusza jest przedstawiony na rysunku 9.21. Pierwiastek z liczby: Przybliżenie początkowe: B C 45 we: 7 Krok iteracji Wartość przybliżenia 0 +B2 +B5+1 0.5*(C5+($B$l/C5)) +B6+1 0.5*(C6+($B$l/C6)) +B7+1 0.5*(C7+($B$l/C7)) +B8+1 0.5*(C8+($B$l/C8)) +B9+1 0.5*(C9+($B$l/C9)) +B10+1 0.5*(C10+($B$l/C10)) +B11+1 0.5*(Cll+($B$l/Cll)) +B12+1 0.5*(C12+($B$l/C12)) +B13+1 0.5*(C13+($B$l/C13)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Rys. 9.19. Kompletny szablon arkusza dla algorytmu Newtona-Raphsona Po obliczeniu wartości wyrażeń zawartość arkusza ma postać przedstawioną na rysunku 9.22. Jeżeli chcemy zbadać wrażliwość algorytmu na przybliżenie początkowe, to wystarczy zmienić liczbę w komórce B2 i ponownie obejrzeć obraz na ekranie (rys. 9.23). Te dwa wykonania algorytmu przekonują nas, że zgodnie z opisem teoretycznym, algorytm Newtona-Raphsona jest dość szybko zbieżny, niezależnie od wybranego przybliżenia początkowego. 9.11. Arkusz a metody numeryczne 291 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Pierwiastek z liczby: Przybliżenie początkowe: 45 7 Krok iteracji Wartość przybliżenia 0 7 1 6.7142857142857 2 6.7082066869301 3 6.7082039324999 4 6.7082039324994 5 6.7082039324994 6 6.7082039324994 7 6.7082039324994 8 6.7082039324994 9 6.7082039324994 Rys. 9.20. Obliczanie pierwiastka kwadratowego - wyniki obliczeń 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Pierwiastek z liczby: Przybliżenie początkowe: 45 100 Krok iteracji Wartość przybliżenia 0 100 1 50.225 2 25.560484071677 3 13.660507054956 4 8.4773373369942 5 6.892803935925 6 6.7106758700143 7 6.7082043877795 8 6.7082039324994 9 6.7082039324994 Rys. 9.21. Obliczanie pierwiastka kwadratowego - wyniki dla innego przybliżenia początkowego Uwaga: Arkusz realizujący algorytm Newtona-Raphsona znajduje się na dyskietce w pliku PIER.WIAS.WQ1 umieszczonym w kartotece R0ZDZ9. 292 9. Arkusz kalkulacyjny Przedstawiony powyżej szablon jest klasycznym przykładem sposobu realizo- wania w arkuszu algorytmów iteracyjnych. Pętlę iteracyjną zastępuje się tutaj iteracją wzdłuż jednego z wymiarów arkusza. W ten sposób zawsze widzimy wy- niki wszystkich obliczeń i możemy natychmiast ocenić skuteczność metody (na nodstra»tlanvch liczbowych lub korzystając z wykresu obrazującego odpowie- dnie zEMości). Również badanie zależności wyników od danych początkowych jest ufljpfone - wystarczy zmienić wartość w odpowiedniej komórce, a arkusz natychmiast wykona wszystkie zapisane w nim obliczenia. 9.12. Nowy system programowania? * Spróbujmy teraz krytycznie spojrzeć na arkusz kalkulacyjny. Cechą rzucającą się w oczy i wielką zaletą tego programu jest naturalność zapisu algorytmów. Kon- struując każdy z omawianych arkuszy postępowaliśmy przecież praktycznie tak samo, jak przy wykonywaniu obliczeń ręcznych na kartce papieru i z ewentualną pomocą kalkulatora. Ponieważ omawiane przykłady można również rozwiązać wykorzystując język programowania, np. znany już z wcześniejszych rozdziałów Pascal, naturalnym będzie porównanie tych dwóch sposobów. Arkusz kalkulacyjny na ogół zawodzi przy rozwiązywaniu złożonych dnień, gdzie przydatna jest m.in. technika programowania strukturalnego, ułat- wiająca rozwiązywanie problemów i zwiększająca czytelność opisu rozwiązań. Po- nadto porównanie szybkości wykonania algorytmu zapisanego w języku progra- mowania z szybkością oferowaną przez arkusz również wypada najczęściej na niekorzyść tego ostatniego. Stosowanie arkusza zwalnia nas jednak z obowiązku pamiętania o sztywnej składni, właściwej większości języków programowania, a także dokładniejszej znajomości sprzętu. Użytkownik w niemal naturalny sposób podaje, co ma być zrobione (wpisz do komórki liczbę 10; posortuj pierwsze dziesięć wierszy rosnąco według zawartości trzeciej kolumny itp.) i może nie interesować się, jak będzie to realizowane. Nie ma tu mowy o niezgodności typów, brakującym średniku, niewłaściwej kolejności parametrów. Zapominamy o uciążliwych ope- racjach czytania danych i wyprowadzania wyników - są one po prostu tam, gdzie umieściliśmy wzory, a konwersacja z programem odbywa się w sposób ciągły. Wpisywanie danych i nanoszenie poprawek jest wykonywane w miejscu, w którym dane są wyświetlane. Wyniki otrzymujemy na bieżąco, również w tym samym miejscu. Posługiwanie się w arkuszu bardziej złożonymi strukturami danych jest moż- liwe dzięki dopuszczeniu odwołań symbolicznych w miejsce adresów komórek. Realizuje się to poleceniem /Edit\Names\Create (parametry: nazwa symboliczna 9.13. Podsumowanie 293 i blok komórek, który ma reprezentować). W ten sposób można np. obszar F2..F5 z rys. 9.11 opatrzyć nazwą PREMIE, po czym zamiast wyrażenia @SUM(F2. .F5) napisać <3SUM(PREMIE). Ważkim argumentem na korzyść arkusza jest także znacznie krótszy czas po- trzebny do nabrania wprawy w korzystaniu z niego w porównaniu zM gfm> P° którym będziemy umieli równie sprawnie zapisywać algorytmy uży\\R| języka programowania. Stwarza to nowe perspektywy w stosowaniu kompulŁpJF przez osoby mało obeznane z językami programowania. Niemniej, używanie arkusza, podobnie jak wielu innych gotowych programów, wymaga od użytkownika po- siadania wielu cech charakteryzujących m.in. programistę. Osoba nie umjejąca sformułować algorytmu rozwiązującego dany problem, nie rozumiejąca np. pojęcia warunku logicznego czy też podstawowych pojęć matematycznych, będzie równie bezradna pisząc program w języku Pascal, jak i zasiadając przed ekranem z ar- kuszem kalkulacyjnym. Czy można więc uznać arkusz za system programowania? Wielu użytkowni- ków daje na to pytanie odpowiedź twierdzącą. 9.13. Podsumowanie Ę tego rozdziału było przede wszystkim zachęcenie do korzystania z arkusza kalkulacyjnego na przykładzie programu Quattro Pro. Aby skutecznie i umiejętnie prowadzić konwersację' z arkuszem, trzeba nau- czyć się przewidywać jego działanie w odpowiedzi na nasze polecenia. W tym celu należy poznać funkcjonalny model działania arkusza. Zamiast więc przeka- zywać wszystkie szczegółowe informacje o programie chcieliśmy, aby Czytelnik zrozumiał koncepcję i poznał niektóre z możliwości arkusza, by następnie móc eksperymentować z dowolnymi programami tego typu. Opisane wyżej cechy programu Quattro Pro ma większość programów z grupy arkuszy kalkulacyjnych. Różnice mogą dotyczyć m.in. sekwencji klawiszy używa- nych do wykonania poszczególnych czynności, szczegółów w sposobie ich działania oraz obecności lub braku udogodnień dla użytkownika (istniejące funkcje, możli- wości graficzne, układ poleceń w ofercie itp.). Tak więc zasiadając przed ekranem komputera, po uruchomieniu dowolnego programu typu arkusz kalkulacyjny powinniśmy umieć zadawać pytania i od- powiadać na nie. Przykładowo, w jaki sposób odbywa się wydawanie poleceń: przez ich napisanie w wyodrębnionym do tego wierszu czy przez wybór z gotowej oferty? Jakie są możliwe sposoby wyświetlania liczb? Jakie są dostępne działania na datach? Odpowiedzi znajdujemy przeglądając dokumentację, pytając innego użytkownika lub metodą prób i błędów. Droga do opanowania arkusza - tak jak każdego innego programu użytkowego - wiedzie przez praktykę. 294 9. Arkusz kalkulacyjny Arkusz może stanowić cenne narzędzie nie tylko dla profesjonalnych użytkow- ników komputerów, ale również dla przeciętnego "zjadacza bitów". Tak więc, jeżeli zajdzie potrzeba kontrolowania własnych wydatków albo szybkiego spraw- dzenia przyrostu konta po trzech latach, z uwzględnieniem pięciu wariantów opro- centowania lub gdy po prostu zapragniemy nietypowej rozrywki intelektualnej - pamiętajmy o arkuszu kalkulacyjnym. Zadania 9.1. Wyjaśnij różnicę między liczbą (wyrażeniem) 123 a napisem 123. Czy ich postać podczas wyświetlania zawartości arkusza może być taka sama? Zapropo- nuj metodę łączenia w jednej komórce napisów i liczb. 9.2. Podaj sposób zamiany miejscami bloków kolumnowych A1..A10 i Cl..CIO, korzystając z polecenia przenoszenia (/Edit\Move). Wskazówka: Zamiana wartości zmiennych a i c w języku Pascal jest wyko- nywana za pomocą zmiennej pomocniczej rob w następujący sposób: rob:=a; a:=c; c:=rob. 9.3. Znajdź i wypisz podobieństwa między Twoim ulubionym edytorem tekstów, a arkuszem kalkulacyjnym w zakresie czynności redakcyjnych (np. przenoszenie bloków, wyszukiwanie tekstów itp.). 9.4. Zaprojektuj szablon arkusza obliczającego miesięczne wydatki z budżetu do- mowego (z podziałem na grupy: żywność, opłaty stałe itp.). 9.5. Zaprojektuj szablon arkusza zawierającego nazwiska uczniów, ich oceny cząstkowe i końcowe z matematyki, średnią z ocen dla ucznia oraz średnią ocen dla całej klasy (por. zadania 4.10 i 4.11). 9.6. Zaprojektuj szablon arkusza kontrolującego dłużników firmy; uwzględnij wy- sokość długu, termin płatności oraz kary za przekroczenie tych terminów. 9.7. Zaprojektuj szablon arkusza obliczającego największy wspólny dzielnik dwóch liczb metodą Euklidesa (por. rozdz. 4 i algorytm 4.4). 9.8. Zaprojektuj szablon arkusza obliczającego metodą Homera wartość wielo- mianu o podanych współczynnikach w zadanym punkcie (por. p. 6.3). 9.9. Zaprojektuj szablon arkusza obliczającego 10 kolejnych wyrazów (od dj do ciągu Fibonacciego (por. zad. 4.4 i 4.5). 9.10. Zaprojektuj szablon arkusza obliczającego średnią arytmetyczną i odchy- lenie standardowe 20 podanych liczb (por. rozdz. 4 i algorytm 4.6). DODATEK Tabela kodów ASCII Znak Kod Znak Kod Znak Kod Znak Kod spacja 32 8 56 P 80 h 104 ! 33 9 57 Q 81 i 105 it 34 58 R 82 j 106 # 35 i 59 S 83 k 107 $ 36 < 60 T 84 1 108 1 37 = 61 U 85 m 109 k 38 > 62 V 86 n 110 y 39 63 W 87 o 111 ( 40 @ 64 X 88 P 112 ) 41 A 65 Y 89 q 113 * 42 B 66 Z 90 r 114 + 43 C 67 [ 91 s 115 > 44 D 68 \ 92 t 116 - 45 E 69 ] 93 u 117 46 F 70 - 94 V 118 / 47 G 71 95 w 119 0 48 H 72 c 96 X 120 i 49 I 73 a 97 y 121 2 50 J 74 b 98 z 122 3 51 K 75 c 99 { 123 4 52 L 76 d 100 1 124 5 53 M 77 e 101 > 125 6 54 N 78 f 102 126 7 55 0 79 g 103 Del 127 Kody od 0 do 31 są przyporządkowane znakom sterującym. Tabela kodów liter polskich w standardzie Mazovia Znak Kod Znak Kod Znak Kod] ą 134 1 146 ś 158 ć 141 ń 164 ź 166 ę 145 ó 162 ż 167 Ą 143 Ł 156 Ś 152 Ć 149 N 165 Ź 160 Ę 144 O 163 Z 161 •?• OMÓWIENIE LITERATURY UZUPEŁNIAJĄCEJ Wymienione poniżej książki polecamy jako literaturę uzupełniającą rozważania prowadzone w podręczniku (EI-I) i w rozwiązaniach zadań (EI-II). Informatyka, jako dziedzina zajmująca się algorytmami, jest przystępnie przed- stawiona w następującej książce, która powstała na kanwie pogadanek radiowych wygłaszanych przez jej autora: D. Harel, Rzecz o istocie informatyki. Algorytmika, WNT, Warszawa 1992. Najpełniejszy opis historii komputerów w języku polskim, od starożytności do końca II wojny światowej, jest zawarty w książce: R. Ligonniere, Prehistoria i historia komputerów, Ossolineum, Wrocław 1992. Z historią komputerów w zwartej postaci można się zapoznać czytając: H. Kaufman, Dzieje komputerów, PWN, Warszawa 1980. Wszechstronne omówienie wpływu komputerów, a w ogólności - mikroelek- troniki, na stosunki w społeczeństwie przedstawia Raport opracowany dla Klubu Rzymskiego: Mikroelektronika i społeczeństwo. Na dobre czy na złe?, red. G. Friedricks, A. Schaff, Książka i Wiedza, Warszawa 1987. System operacyjny MS-DOS w wersji 3.3 jest opisany w książce: J. Deminet, System operacyjny MS-DOS, WNT, Warszawa 1990. Pełny opis systemu i języka AC-Logo można znaleźć w jego dokumentacji opracowanej przez autorów tego systemu: Podręcznik użytkownika AC-Logo. Wersja 1.2 dla IBM-PC, Wydawnictwo OFEK Jelenia Góra, Jelenia Góra 1993. Następujące opracowania (podajemy je w porządku chronologicznym) trak- tują o metodach programowania wykorzystujących wersje języka Logo dla różnych komputerów. Większa część każdej z tych książek zawiera materiał, który nie zależy od wybranej wersji języka, mogą więc one być przydatne także dla użyt- kowników systemu AC-Logo. E. Gurbiel, H. Krupicka, Z. Ploski, Programowanie i Logo, Wydawnictwo Uni- wersytetu Wrocławskiego, Wrocław 1987. E. Kolczyk, M. Malicka, Materiały pomocnicze do nauczania Logo w szkole średniej, Wydawnictwo Uniwersytetu Wrocławskiego, Wrocław 1988. S. Waligórski, Programowanie w języku Logo, WNT, Warszawa 1990. I I Literatura 297 M. Borzęcki, Programowanie od podstaw w ćwiczeniach i zadaniach z języka Logo, PROSET, Gdańsk 1992. Standardowa wersja języka Pascal jest opisana w: H. Iglewski, J. Madey, S. Matwin, Pascal, WNT, Warszawa 1986. Zainteresowanych szczegółowymi informacjami o języku i systemie Turbo Pa- scal odsyłamy do opracowania: J. Szczepkowicz, Turbo Pascal 5.0 z przykładami konstrukcji oprogramowania podstawowego, WNT, Warszawa 1990. Następująca książka zawiera m.in. opis systemu dBASE, którego kolejne po- lecenia są wprowadzane na przykładzie bazy obejmującej dane o zwierzętach ży- jących w ogrodzie zoologicznym: T. Mykowiecki, dBase, FoxBase bazy danych, WNT, Warszawa 1992. Brak jest książki, która zawierałaby opisy metod numerycznych dostosowane do wiadomości z matematyki na poziomie szkoły średniej. Możemy polecić jedynie w miarę elementarny wykład z tej dziedziny w podręczniku akademickim: G. Dahlquist, A. Bjórk, Metody numeryczne, PWN, Warszawa 1983. Podstawowym opracowaniem o projektowaniu algorytmów i ich złożoności, które może stanowić uzupełnienie i rozszerzenie rozważań zamieszczonych w rozdz. 7, jest: A.V. Aho, J.E. Hopcroft, J.D. Ullman, Projektowanie i analiza algorytmów komputerowych, PWN, Warszwa 1983. Polecamy także ciekawe książki o różnorodnych metodach konstruowania al- gorytmów, doboru struktur danych i programowania: L. Banachowski, A. Kreczmar. Elementy analizy algorytmów, WNT, Warszawa 1982. E.W. Dijkstra, Umiejętność programowania, WNT, wyd. 2, Warszawa 1985. N. Wirth, Algorytmy•+struktury danych=programy, WNT, Warszawa 1980. Nie wymieniliśmy żadnych opracowań (z wyjątkiem odnoszących się do sy- stemu AC-Logo), będących jedynie leksykonami systemów oprogramowania, które wykorzystujemy w opracowaniach EL Zawierają one bowiem najczęściej opisy tych systemów w postaci listy haseł, a pozbawione są uporządkowania materiału zagadnieniami lub głębszą myślą przewodnią. Czasem zmuszeni jesteśmy jednak sięgnąć po takie leksykony - ich wybór pozostawiamy do indywidualnego uznania Czytelnika. • Skorowidz Abak 19 abakus 19 AC-Logo 10, 70 Ada, Lovelace 24 adres 272 bezwzględny 281 komórki 272 pusty (NIL) 147 w pamięci 147 względny 281 akapit 262, 268 al-Chorezmi 20 algorytm 9, 17, 20, 107, 189 Euklidesa 20, 125, 132, 225 Newtona-Raphsona 289 niestabilny 198 optymalny 231 porządkowania, bąbelkowy 236 , koszykowy 248 , naiwny 236 przez scalanie 238 stabilny 198 , złożoność obliczeniowa 226 argument funkcji 78 wyrażenia 78 arkusz kalkulacyjny 12, 271 arytmetyka ^-cyfrowa 193 arytmometr 35 asembler 60 atrybut 37 kroju pisma 253 Babbage, Charles 22 bajt 34 baza danych 158 dBASE 11, 179 dBASE III 179 , ochrona 177 bit 32 znaku 33 blok arkusza 278 tekstu 262 błąd bezwzględny 192 błąd kwadratury 211 względny 193 bufor 262 Całkowanie numeryczne 211 cecha 191 ChiWriter 251 ciąg Fibonacciego 155 Coloss 27 cyfra znacząca 199 cykl rozkazowy 36 Dane 17, 20 dBASE 11, 179 definicja funkcji 79, 121 procedury 73, 111 stałej 134 typu 134 deklaracja pakietu 113 zmiennej 114 dobroć przybliżenia funkcji 206 druk proporcjonalny 268 drukarka 37 drzewo binarne 104, 242 kartotek 48 , korzeń 242 , krawędź 242 obliczeń 242, 246 Pitagorasa 104 , poziom 244 , wierzchołek końcowy 242, 246 , wierzchołek pośredni 242, 246 , wysokość 243 dyrektywa 110, 208 dysk bieżący 50 elastyczny 37 stały 37 dyskietka 37 dywan Sierpińskiego 90 EDVAC 28 edytor ChiWriter 251 , konfigurowanie 268 Skorowidz 299 edytor TAG 11, 251 tekstów ASCII 252 ekran monitora 37 użytkownika 110 ENIAC 28 Enigma 26 Euklides 20 Format 137, 144 wyświetlania 277 formatowanie 47, 63 tekstu 262 formuła 272 funkcja 78 rekurencyjna 132 standardowa 137, 190 warunkowa 287 Głośnik 38 grafika żółwia 10, 71 Hollerith, Herman 24 IBM PC 9 iloraz różnicowy 204 indeks 133 informacja 17 informatyka 17 instrukcja iteracyjna 72 powtarzania 72, 116, 119, 120 przypisania 95, 117 pusta 111 warunkowa 88, 115 wiążąca 146 wyboru 141 złożona 116 interpolacja 203 interpretator 72 Jednostka 71 sterująca 35 język AC-Logo 10, 70 algorytmiczny 60 Logo 10, 70 Pascal 11, 107 programowania 60 symboliczny 60 język Turbo Pascal 11, 107 wewnętrzny 60 justowanie tekstu 256 Karta graficzna 37 perforowana 24, 25 kartoteka 48, 50 katalog 48 klawiatura 37 numeryczna 42 klawisz funkcyjny 43 wyboru 61 klucz 49, 167 wyszukiwania 167, 235 kod ASCII 31 uzupełnieniowy 34, 66 kodowanie 31 kolejka 153 komenda 45 komentarz 83, 110 komórka 272 bieżąca 275 komputer 17 IBM PC 9 krój pisma 253 kursor 37, 274 wyboru 61 kwadratura 211 Simpsona 213 trapezów 211 Leibniz, Gottfried Wilhelm 21 licznik rozkazów 36 liczydło 19 lista 80, 93, 147, 148, 153 Logo 10, 70 Łamanie tekstu 268 Makrowywolanie 269 mantysa 191 , denormalizacja 223 , normalizacja 222 maszyna analityczna 24 Coloss 27 EDVAC 28 ENIAC 28 300 Skorowidz maszyna Pascalina 21 różnicowa 22 Turinga 25 matryca znaków 37 Mazovia 44, 263 metoda iteracyjna 214, 216 Newtona 216 od-lewej-do-prawej 246 różnicowa 22 zstępująca 128 miara odległości 207 minimum 231 moduł klawiatury 39 pomocniczy 42 monitor 37 motyw wzoru 86 mózg elektronowy 29 MS-DOS 10, 45 mysz 38 Nadmiar zmiennopozycyjny 192 nagłówek funkcji 79, 122 procedury 73, 111 programu 108 napis 109, 272 nazwa 73, 108 Neper, John 20 Neumann, von, John 28 neurokomputer 30 niedomiar zmiennopozycyjny 192 niezmiennik 74 Obliczenia równoległe 29 szeregowe 29 odczyt 47 oferta (menu) 61, 276 okno 61, 258 operacja klawiszowa 42, 256 operator 78 dosłowności 80 oprogramowanie przyjazne 265 Pakiet 113 pałeczki Nepera 21 pamięć 34 , adres 34 pamięć buforowa 35 obrazu 37 operacyjna 35 , pojemność 34 RAM 35 ROM 35 stała 35 wewnętrzna 35 zewnętrzna 36 parametr 72 aktualny 77, 129 formalny 77, 126, 129 przekazywany przez wartość 129 przekazywany przez zmienną 129 party ej a dysku 47 Pascal 11, 107 Pascal, Blaise 21 Pascalina 21 permutacja 235, 247 pętla 119 nieskończona 123 piksel 37 ?plik 45, 159 aktywny 181 bazy danych 180 , dostęp sekwencyjny 159 , drukowanie 57, 164 fizyczny 159 , kasowanie 59 , kopiowanie 56 , scalanie 56 tekstowy 159 , wyświetlanie 57, 164 , zmiana nazwy 59 płatek Kocha 104 podstawa reprezentacji 32 pole argumentów 36 operacji 36 rekordu 142, 144, 158 polskie litery 257 porządek łeksykograficzny 234 słownikowy 234 porządkowanie 234 w miejscu 237 pracochłonność algorytmu 225 procedura pierwotna 78 Skorowidz 301 procedura rekurencyjna 88, 131 standardowa 78, 109 z wartością 78 procesor centralny 35 numeryczny 208 tekstu 251 program 45 główny 111 usługowy 271 programowanie 17 strukturalne 128 przewijanie tekstu 260 Quattro Pro 12, 271 QWERTY 38, 39 Redagowanie tekstu 250 rejestr 35 górny 40 Rejewski, Marian 27 . rekord 142, 158 bieżący 181 z wariantami 170, 171 rekurencja 88 , zależność 240 reprezentacja liczby stałopozycyjna 191 zmiennopozycyjna 191 rozdzielczość ekranu 37 rozkaz 36 rozmiar pola 180 rozwinięcie liczby 32 równanie algebraiczne 219 Scalanie ciągów liczb 229 plików 56 schemat Homera 195, 196 Schickard, Wilhelm 21 separator 73, 109 Shannon, Claude 27 silnia 242 składowanie okresowe 266 słowo 93 kluczowe 109 maszynowe 34 soroban 19 sortowanie 234, 284 specyfikacja problemu 107 stabilność algorytmu 198 stała 134 status edytora 256 Stern, Abraham 22 struktura danych 93, 133 superkomputer 242 system AC-Logo 62, 70 baz danych 175 dBase 11, 179 operacyjny 45 MS-DOS 45 system pozycyjny binarny 21, 32 dwójkowy 21, 32 dziesiętny 31 system Quattro Pro 12, 271 TeX252 TP 11, 62 Turbo Pascal 11, 62 szablon arkusza 273 Ścieżka dostępu 50 Tablica 133 tabulator 41 TAG 11, 251 tekst ASCII 252 , blok 262 , edytor 251 , formatowanie 262 , justowanie 256 , łamanie 268 , procesor 251 , przetwarzanie 251, 256 , przewijanie 260 , redagowanie 251 TeX252 tłumienie błędów zaokrągleń 203 tom dyskowy 47 TP 11, 62 translator 60 interpretator 60 kompilator 60 treść funkcji 79 procedury 73 302 Skorowidz trójkąt Pascala 21 tryb pracy, graficzny 37 tekstowy 37 Turbo Pascal 11, 107 Turing, Alan 25 twarda spacja 257 typ 114 całkowity 114, 191 logiczny 121 napisowy 126 rekordowy 142 rzeczywisty 134, 191 tablicowy 133 wskazywany 147 wskaźnikowy 147 wyliczeniowy 139 znakowy 121 Układ dziesiętny 31 urządzenie zewnętrzne 36 ustalanie wzorca druku 253 Warstwa edytora TAG 254 hierarchii tekstu 254 redagowania tekstu 254 wyboru plików 254 wartownik 160 warunek 89 węzły interpolacji 203 kwadratury 211 widzenie tunelowe 264 wielomian Czebyszewa 223 interpolacyjny 203 Newtona 203 wiersz stanu 62, 277 wprowadzania danych 277 wskaźnik 147 współczynniki interpolacji 204 kwadratury 211 wykres 285 kołowy 287 słupkowy 285 wyniki 20 wyrażenie 78 arytmetyczne 78, 118, 272 logiczne 89, 115, 118, 121 wysuw pionowy 252 względna dokładność komputera 193 wzór 272 rekurencyjny 195 Zadanie numeryczne 189 źle uwarunkowane 190, 201 zakładka 260 zależność rekurencyjna 196, 240 zaokrąglenie 191 ząbek 252 zegar 38 zlecenie 48 wewnętrzne 49 zewnętrzne 49 złożoność obliczeniowa algorytmu 225 pesymistyczna 243 złożony wzór Simpsona 213 trapezów 211 zmienna 95, 114 dynamiczna 147 globalna 122 lokalna 122 znaki diakrytyczne 257 znormalizowana postać liczby 191 Zuse, Konrad 27 Żółw 71 J WYDAWNICTWO NAUKOWE PWN Wydanie III zmienione Arkuszy druk. 19 Druk ukończono w październiku 1993 r. Skład i łamanie Autorzy Druk i oprawa: Rzeszowskie Zakłady Graficzne, Rzeszów, ul płk. L. Lisa-Kuli 19 Zam. 1985/93 Księgarnie promocyjne PWN, w których można kupić i zamówić wszystkie publikacje naszego wydawnictwa: BIAŁYSTOK Księgarnia, ul. Lipowa 43 15-424 Biatystok Księgarnia ORPAN ul. Świętojańska 13 15-082 Białystok BIELSKO-BIAŁA Księgarnia „Oświata" ul. 11 Listopada 33 43-300 Bielsko-Biala BYDGOSZCZ Księgarnia „Współczesna" ul. Gdańska 5 85-005 Bydgoszcz CZĘSTOCHOWA Księgarnia „Antykwariat" Al. N.M.P. 18 42-200 Częstochowa GDAŃSK „Księgarnia Naukowa" ul. Grunwaldzka 111/113 80-244 Gdańsk Księgarnia Publikacji Naukowych„Libra" ul. Wita Stwosza 55 80-308 Gdańsk GDYNIA Księgarnia „Książnica" ul. Władysława IV 61 81-384 Gdynia GLIWICE Księgarnia „Mercurius" ul. Konstytucji 146 44-100 Gliwice KATOWICE Księgarnia ORPAN ul. Bankowa 11 40-007 Katowice Księgarnia Powszechna ul. 3 Maja 13 40-096 Katowice KIELCE Księgarnia "Naukowa" ul. Buczka 19/25 25-536 Kielce KOSZALIN Księgarnia "Naukowa" Rynek Staromiejski 2 75-007 Koszalin KRAKÓW Księgarnia „Skarbnica" Os. Centrum C bl. 1 31-929 Kraków Księgarnia „Techniczna" ul. Podwale 4 31-118 Kraków Księgarnia „Elefant" RZESZÓW ul. Podwale 6 Księgarnia nr 208 31-118 Kraków ul. Dąbrowskiego 58a Księgarnia ORPAN 35-036 Rzeszów ul. Św. Marka 22 Księgarnia Szkolno- 31-020 Kraków Pedagogiczna LUBLIN ul. Kościuszki 3 Księgarnia Współczesna 35-100 Rzeszów Aleje Racławickie 26 SIEDLCE 20 -037 Lublin Księgarnia „Współczesna" Księgarnia Techniczna ul. Pitsudskiego 68 Krakowskie Przedmieście 39 08-110 Siedlce 20-076 Lublin Księgarnia ORPAN ul. Marii Sktodowskiej-Curie 5 20 -031 Lublin SŁUPSK Księgarnia „Ratuszowa" ul. Filmowa 5 Księgarnia „Naukowo-Techniczna" 76-200 Słupsk ul. Nadbystrzycka 36 SZCZECIN 20 -618 Lublin Księgarnia „Naukowa" ŁÓDŹ ul. Wyzwolenia 12/14 Księgarnia PWN 70-555 Szczecin ul. Więckowskiego 13 TORUŃ 90-721 Łódź Księgarnia Księgarnia Akademicka ul. Szeroka 46 ul. Narutowicza 50 87-100 Toruń 90-135 Łódź Księgarnia „Eureka" ul. Pitsudskiego 12 90-330 Łódź WARSZAWA Księgarnia PWN ul. Miodowa 10 Księgarnia Naukowa ul. Piotrkowska 102a 00-251 Warszawa Główna Księgarnia Naukowa 90-004 Łódź im. Bolesława Prusa Księgarnia „Ethos" ul. Piotrkowska 11 Krakowskie Przedmieście 7 00-068 Warszawa 90-406 Łódź Księgarnia ORPAN Pałac Kultury i Nauki OPOLE 00-901 Warszawa Księgarnia „Omega" Główna Księgarnia Techniczna Rynek 19 ul. Świętokrzyska 14 45-015 Opole 00-050 Warszawa PIŁA Księgarnia Fundacji Bibliotekom Księgarnia Polskim ul. 14 Lutego 2 ul. Marszałkowska 74 64-920 Piła 00-524 Warszawa POZNAŃ Księgarnia Naukowa Księgarnia Wydawnictwa Bellona im. St. Żeromskiego Al. Solidarności 119 Ossolineum 00-897 Warszawa al. Marcinkowskiego 30 Księgarnia Uniwersytecka Libra 61-745 Poznań Krakowskie Przedmieście 24 Księgarnia ORPAN 00-927 Warszawa ul. Mielżyńskiego 27/29 61-725 Poznań Księgarnia Uniwresytecka „Unimarket" Księgarnia Studencka ul. Rakowiecka 41 02-521 Warszawa ul. Zwierzyniecka 7 ZIELONA GÓRA 60-586 PoznańKsięgarnia Księgarnia Naukowa ul. Gwarna 13 Pod Filarami 3 61-702 Poznań 65-068 Zielona Góra