SlideShare a Scribd company logo
1 of 12
Download to read offline
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   Praktyczny
                                         kurs Delphi
           KATALOG KSI¥¯EK
                                         Autor: Tomasz M. Sadowski
                      KATALOG ONLINE     ISBN: 83-7361-013-8
                                         Format: B5, stron: 396
       ZAMÓW DRUKOWANY KATALOG


              TWÓJ KOSZYK
                    DODAJ DO KOSZYKA     Tomasz Sadowski, autor wielokrotnie wznawianego, podrêcznika „Praktyczny kurs
                                         Turbo Pascala”, zaprasza Ciê tym razem do krainy Delphi. Delphi to system szybkiego
                                         tworzenia aplikacji (RAD), w którym programy w du¿ym stopniu buduje siê z gotowych
         CENNIK I INFORMACJE             komponentów. O ile Turbo Pascal u¿ywany jest g³ównie w dydaktyce informatyki,
                                         o tyle Delphi jest stale rozwijanym i szeroko rozpowszechnionym rodowiskiem
                   ZAMÓW INFORMACJE      programistycznym, ³¹cz¹cym przejrzysto æ ObjectPascala z przyjaznym interfejsem
                     O NOWO CIACH        Windows. Byæ mo¿e niektóre z programów u¿ywanych przez Ciebie na co dzieñ zosta³y
                                         napisane w³a nie w Delphi.
                       ZAMÓW CENNIK      Ksi¹¿ka „Praktyczny kurs Delphi” napisana jest ¿ywym, przystêpnym jêzykiem.
                                         Po³o¿ono w niej nacisk raczej na praktykê ni¿ teoriê, i dlatego to wspania³e
                                         wprowadzenie w programowanie dla osób, które wcze niej nie zetknê³y siê z t¹
                 CZYTELNIA               tematyk¹. Ju¿ po przeczytaniu kilku stron bêdziesz móg³ napisaæ pierwszy program!
                                         Dziêki ksi¹¿ce poznasz:
          FRAGMENTY KSI¥¯EK ONLINE
                                            • rodowisko Delphi
                                            • Jêzyk ObjectPascal: jego podstawowe konstrukcje i typy danych
                                            • Komponenty zawarte w Delphi
                                            • Sposoby pisania w³asnych funkcji i procedur
                                            • Programowanie obiektowe
                                            • Programowanie grafiki
                                         Po lekturze „Praktycznego kursu Delphi” przekonasz siê, ¿e pisanie profesjonalnych
                                         aplikacji nie jest tak trudne, jak by siê mog³o wydawaæ. Przekonasz siê równie¿,
                                         ¿e ksi¹¿ki po wiêcone programowaniu nie musz¹ byæ nudn¹ i przepe³nion¹
                                         niezrozumia³¹ techniczn¹ terminologi¹ lektur¹. Ta ksi¹¿ka nauczy Ciê programowaæ
                                         w Delphi — mo¿esz byæ tego pewien.
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treści
                Wstęp ............................................................................................... 5
Rozdział 1. Pierwszy krok .................................................................................. 11
Rozdział 2. Narzędzie......................................................................................... 19
            Dodatek — IDE w pigułce ................................................................ 30
Rozdział 3. Pierwszy prawdziwy program ............................................................ 33
Rozdział 4. Jak to było dawniej…....................................................................... 43
Rozdział 5. Nieco elementarnej matematyki ....................................................... 51
Rozdział 6. Gdzie przechowywać dane?.............................................................. 57
            Dodatek — Pozostałe typy proste .................................................... 62
Rozdział 7. Jak wprowadzić dane? ..................................................................... 65
            Dodatek — Formularz to też komponent........................................... 76
Rozdział 8. Instrukcja warunkowa...................................................................... 79
            Dodatek — Kalkulator, wersja 2.0.................................................... 86
Rozdział 9. Jak zrobić to samo kilka razy, czyli pętle .......................................... 91
            Dodatek — Pułapki i niespodzianki................................................. 102
Rozdział 10. Jak nie robić tego samego więcej niż raz,
             czyli procedury i funkcje................................................................. 105
Rozdział 11. Komunikacja z procedurami............................................................ 117
             Dodatek — Rekurencja.................................................................. 125
Rozdział 12. Zapisujemy więcej danych, czyli tablice ......................................... 129
Rozdział 13. Porządki w danych......................................................................... 139
Rozdział 14. Typy i argumenty strukturalne........................................................ 149
Rozdział 15. Stałe symboliczne.......................................................................... 157
Rozdział 16. O ulotności danych i jak jej zaradzić ............................................... 163
4                                                                                     Praktyczny kurs Delphi


Rozdział 17. Pliki tekstowe, czyli jak zapisać dane w czytelny sposób ................ 175
             Dodatek — Pliki jeszcze inaczej ..................................................... 182
Rozdział 18. Czym naprawdę zajmują się komputery........................................... 185
Rozdział 19. Konkurencja dla Microsoftu?.......................................................... 195
Rozdział 20. Programowanie na poważnie .......................................................... 205
Rozdział 21. Jak uruchamiać oporne programy ................................................... 219
Rozdział 22. Dwa (i więcej) w jednym, czyli rekordy ........................................... 229
Rozdział 23. Zmienne dynamiczne i wskaźniki .................................................... 251
Rozdział 24. Rekord + wskaźnik = lista .............................................................. 265
Rozdział 25. O grafice słów kilka ....................................................................... 275
Rozdział 26. Od programowania strukturalnego do obiektowego ......................... 289
Rozdział 27. Dziedziczenie, polimorfizm i metody wirtualne ................................. 301
Rozdział 28. Co jeszcze warto wiedzieć o IDE..................................................... 317
Rozdział 29. Kilka dobrych rad, czyli co czynić należy… ..................................... 327
Rozdział 30. …a czego unikać ........................................................................... 337
Dodatek A Instalacja wersji próbnej Delphi 7 Architect.................................... 343
Dodatek B Odpowiedzi do zadań...................................................................... 347
Dodatek C Kilka przydatnych pojęć komputerowych......................................... 365
Dodatek D Mikrosłownik angielsko-polski........................................................ 375
                Skorowidz...................................................................................... 379
Rozdział 12.
Zapisujemy
więcej danych,
czyli tablice
       Powtórka ze statystyki
       Typy strukturalne
       Tworzenie i wykorzystanie tablic
       Wektory i macierze

   Jak powszechnie wiadomo, komputer jest narzędziem słu ącym do szybkiego prze-
   twarzania du ych ilości danych. Przedstawione do tej pory programy nie dawały naszemu
   wielkiemu kalkulatorowi specjalnego pola do popisu — dane, na których operowali-
   śmy, sprowadzały się zwykle do kilku liczb. Nikogo jednak nie trzeba przekonywać,
    e większość zadań, z którymi mierzą się komputery w praktyce, wymaga wprowa-
   dzania, przechowywania i przetwarzania ogromnych ilości danych. Cel, który posta-
   wimy sobie na początku tego rozdziału, będzie znacznie mniej ambitny — spróbuje-
   my mianowicie rozwiązać prosty problem statystyczny, jakim jest obliczenie wartości
   średniej i miary rozrzutu w zadanej grupie pomiarów pewnej wielkości. Obliczanie
   średniej i odchylenia standardowego (ono właśnie jest miarą rozrzutu) jest równie
   typowym zadaniem in ynierskim, tote jego zaprogramowanie mo e przydać się nam
   w przyszłości.

   Jak powszechnie wiadomo, wartość średnia dla N liczb wyra a się wzorem:
               N
           1
      x=
           N   ∑x
               i =1
                      i


   gdzie i jest numerem kolejnej wartości w zestawie. Przeło enie tego zapisu na Pascal
   jest na pierwszy rzut oka banalne, ale… gdzie właściwie będą przechowywane kolejne
130                                                                       Praktyczny kurs Delphi


      wartości xi? Wykorzystanie do tego celu pojedynczych zmiennych typu prostego
      (a tylko takie na razie znamy) jest praktycznie niemo liwe — nawet gdybyśmy uparli
      się przy zadeklarowaniu zmiennych Z, Z, Z…, nie wiemy ile nale ałoby ich zade-
      klarować, nie mówiąc ju o problemach z odwoływaniem się do nich w pętli sumują-
      cej. Zauwa my jednak, e nasze liczby tworzą jednolity ciąg danych tego samego ty-
      pu, w matematyce zapisywany w postaci tzw. wektora:
         [x1 , x 2 , x 3 , K , x N ]
      Być mo e kompilator potrafi posłu yć się podobną reprezentacją i zna jakiś sposób na
      „poszufladkowanie” danych w pamięci tak, by dało się odwoływać do nich poprzez
      kolejny numer w ciągu?

      Opisane powy ej rozwiązanie znane jest w programowaniu od kilkudziesięciu lat pod
      nazwą tablicy (ang. array). Jest ona zestawem danych tego samego typu, zajmującym
      pewien (na ogół ciągły) obszar w pamięci i pozwalającym na odwoływanie się do po-
      szczególnych elementów poprzez podanie ich numeru, czyli tzw. indeksu. Mówiąc
      ogólniej, tablica jest strukturą zło oną z danych innego typu, dlatego te nale y ona
      do grupy tzw. strukturalnych typów danych. Zmienna typu strukturalnego składa się
      z innych danych, zorganizowanych zgodnie z regułami obowiązującymi dla danego
      typu (w przypadku tablic jednowymiarowych dane ustawiane są po prostu w pamięci
      jedna za drugą). Poszczególne elementy zmiennej strukturalnej mogą być typu pro-
      stego (np. liczby całkowite) lub strukturalnego (np. tablice lub rekordy) — innymi
      słowy, mo emy tworzyć „piętrowe” dane strukturalne. Dwa najwa niejsze typy da-
      nych strukturalnych, którymi zajmiemy się w naszej ksią ce, to tablice (grupujące
      elementy tego samego typu) oraz rekordy (grupujące elementy ró nych typów).

      Jak ka da inna zmienna, tablica identyfikowana jest w programie poprzez nazwę
      (np. NKED[), natomiast dostęp do jej poszczególnych elementów odbywa się poprzez
      podanie ich indeksu. Ten ostatni jest po prostu numerem danego elementu tablicy, za-
      pisanym w nawiasach kwadratowych, np.:
        Z  NKED[=? ] QFE[VCL EYCTV[ GNGOGPV VCDNKE[ NKED[ _

      Graficznie mo na to przedstawić następująco:

                             indeks     1      2      3      4      5      6

                             wartość   1,43   1,66   2,01   1,23   1,98   3,11


      Jak mo na się domyślać, przed u yciem tablicę nale y zadeklarować, do czego słu y
      słowo kluczowe CTTC[:
        XCT
          NKED[  CTTC[=? QH TGCN

      Po słowie CTTC[ następuje para nawiasów kwadratowych, w których zapisujemy indeks
      pierwszego i ostatniego elementu tablicy, rozdzielone dwiema kropkami (nie dwu-
      kropkiem!). Niezbędne jest równie poinformowanie kompilatora o typie poszczególnych
      elementów tablicy — w naszym przypadku są to wartości typu TGCN. Cały powy szy
Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice                                                    131


            zapis mo na przetłumaczyć na polski jako „tablica o stu elementach, numerowanych
            od 1 do 100, zło ona z liczb rzeczywistych”. Podobnie jak w przypadku zmiennych pro-
            stych, bezpośrednio po zadeklarowaniu elementy tablicy mają wartość przypadkową1.

            Deklarując tablicę nale y pamiętać o dwóch ograniczeniach:
                 indeksy muszą być stałymi (innymi słowy, w Pascalu nie mo na deklarować
                 tzw. tablic dynamicznych w sensie znanym np. z BASIC-a),
                 indeksy muszą być typu porządkowego (chocia nie muszą być liczbami
                 — mo na np. zadeklarować tablicę indeksowaną wartością typu EJCT).

            W większości zastosowań tablice indeksowane są od jedynki, chocia Pascal tego nie
            wymaga — równie dobrze mo na indeksować tablicę od zera (jak w języku C) lub ty-
            siąca. Rzecz jasna, indeks końcowy musi być większy lub równy początkowemu.

               Niestandardowe indeksowanie tablic może być źródłem problemów, bowiem od-
               wołanie do elementu spoza zadeklarowanego przedziału kończy się często trud-
               nymi do wykrycia błędami wykonania. O ile nie ma naprawdę ważnego powodu,
               najlepiej zawsze stosować jednolity sposób indeksowania (zwykle od jedynki, cho-
               ciaż programiści piszący w języku C preferują indeksowanie od zera).


            Warto przy okazji wspomnieć o funkcjach .QY i *KIJ, które dla tablic zwracają odpo-
            wiednio wartość pierwszego i ostatniego indeksu. Pozwalają one pominąć przekazywanie
            informacji o zakresie indeksów, o ile oczywiście mamy pewność, e obliczenia będą
            zawsze dotyczyły całej tablicy.

            Poszczególne elementy tablicy mogą być dowolnego typu (ale wszystkie tego samego),
            przy czym niekoniecznie musi to być typ prosty, jak TGCN czy DQQNGCP — równie dobrze
            mo na zadeklarować tablicę zło oną z elementów typu strukturalnego, np. innych tablic
            lub rekordów. Przykładowa deklaracja:
               XCT
                 /CEKGT  CTTC[=? QH CTTC[ =? QH TGCN

            utworzy dwuwymiarową tablicę zło oną z 50 wektorów (tablic jednowymiarowych),
            z których ka dy zawiera 50 liczb rzeczywistych. Składnia Pascala pozwala na skrócenie
            powy szego zapisu do postaci:
               XCT
                 /CEKGT  CTTC[= ? QH TGCN

            która lepiej odzwierciedla strukturę tablicy dwuwymiarowej, a przy okazji jest prostsza
            w zapisie. Mo liwe jest tak e tworzenie tablic trój- i więcejwymiarowych (Pascal nie
            narzuca ograniczeń na liczbę wymiarów tablicy ani wartości indeksów), jednak sto-
            sowane są one rzadko.



1
    Ściślej rzecz biorąc, tablice deklarowane globalnie inicjalizowane są zerami, jednak lepiej wyrobić sobie
    nawyk dmuchania na zimne i nie zakładać, e świe o zadeklarowana tablica zawiera sensowne wartości.
132                                                                              Praktyczny kurs Delphi


                  Zanim zabierzemy się do pracy, jeszcze jedna uwaga praktyczna. W porównaniu
                  do starych aplikacji 16-bitowych, Delphi umożliwia tworzenie znacznie większych
                  struktur danych (maksymalny rozmiar tablicy w Turbo Pascalu wynosił około 64 kB,
                  w Delphi ograniczony jest w zasadzie wielkością dostępnej pamięci). Deklarując
                  tablice wewnątrz procedur należy jednak pamiętać, że są one tworzone na stosie,
                  którego pojemność jest ograniczona (domyślnie do 1 megabajta). O ile Pascal nie
                  narzuca formalnych ograniczeń na liczbę wymiarów i elementów tablicy, musimy
                  pamiętać o ograniczeniu praktycznym, wynikającym z rozmiarów dostępnej pamięci.
                  Dodatkowym haczykiem jest fakt, iż wszystkie zmienne lokalne tworzone są do-
                  piero w momencie wywołania funkcji, a zatem do przepełnienia stosu (i krytycznego
                  błędu wykonania) dochodzi w dość nieprzewidzianym momencie podczas pracy
                  programu. W przeciwieństwie do lokalnych, tablice deklarowane globalnie mają do
                  dyspozycji całą pamięć dostępną dla programu (znacznie więcej, niż zajmuje stos),
                  zaś zadeklarowanie zbyt dużej struktury powoduje błąd bezpośrednio po urucho-
                  mieniu. Innymi słowy, deklaracja:
                       XCT
                         NKED[  CTTC[=? QH TGCN ] OKNKQP NKED TGE[YKUV[EJ _

                  ma szansę „przejść” w przypadku umieszczenia jej w sekcji globalnej programu
                  lub modułu, natomiast raczej na pewno spowoduje błąd wykonania (nie kompilacji!),
                  jeśli umieścimy ją wewnątrz procedury. Nie znaczy to oczywiście, że tablice najle-
                  piej deklarować jako globalne — pamiętajmy, że zmienna globalna istnieje (i zajmuje
                  pamięć) przez cały czas działania programu, natomiast zmienna lokalna znika po
                  wykonaniu swojego zadania, zwalniając zajętą przez siebie pamięć.


               Pora na czyny. Nasz program powinien umo liwić wprowadzenie ciągu liczb o dowolnej
               długości, zapamiętać go, a następnie wyliczyć i wyświetlić wartość średnią i odchylenie
               standardowe, dane wzorem:
                                      N

                                      ∑ (x            )
                             1                        2
                   s=                        i   −x
                            N −1      i =1


               Bardziej spostrzegawczy Czytelnicy być mo e zauwa yli, e wyliczenie średniej wcale
               nie wymaga tablicowania danych, bowiem sumowanie mo na prowadzić na bie ąco,
               w miarę wprowadzania kolejnych liczb. Niestety obliczenie odchylenia standardowego
               wymaga z jednej strony wcześniejszego ustalenia wartości średniej, z drugiej zaś
               — ponownego dostępu do poszczególnych liczb. Innymi słowy, wprowadzone wartości
               trzeba gdzieś zapamiętać, przynajmniej na chwilę2.


2
    Ściślej rzecz biorąc, wcale nie trzeba — kilka przekształceń pozwala zapisać ostatni wzór w postaci
                                  2
                      N      
          N
                     
                     ∑    xi 
                              
                      i =1 
         ∑
         i=1
               xi2 −
                           N
                  N −1
    która, jak widać, nie zawiera odwołań do poszczególnych liczb, a jedynie do ich sumy i sumy kwadratów.
    Metoda ta wykorzystywana jest powszechnie np. w kalkulatorach, jednak jej zastosowanie odebrałoby
    nam pretekst do wprowadzenia pojęcia tablicy…
Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice                                     133


        Jako podstawę do budowy naszego programu mo emy wykorzystać projekt Sumowanie
        z rozdziału 9. Po dokonaniu kilku modyfikacji (zmiana nazw komponentów wyjścio-
        wych i etykiet) powinien on prezentować się następująco:




        Co prawda potrafimy ju korzystać z procedur i funkcji (a obliczenia statystyczne
        a proszą się o ich zastosowanie), ale na razie pójdziemy po linii najmniejszego oporu
        i całość kodu upakujemy w procedurze obsługi przycisku Oblicz:
           RTQEGFWTG 6(QTO$WVVQP%NKEM
5GPFGT 61DLGEV
           XCT
             K  KPVGIGT                          ] PWOGT YKGTUC CYKGTCLæEGIQ NKEDú _
             NKED[  CTTC[=? QH TGCN      ] K LGL YCTVQ è _
             KNG.KED  KPVGIGT                   ] KNG LGUV NKED  RQOKLCO[ RWUVG YKGTUG _
             UWOC UWOC-YCFT  TGCN               ] QDNKECPG UWO[ _
             UTGFPKC QFEJ5VF  TGCN              ] K UVCV[UV[MK _
           DGIKP
             UWOC                            ] CKPKELCNKWL UWO[    DCTFQ YC PG _
             UWOC-YCFT  
             KNG.KED                          ] CM CFCO[ G PKG RQFCPQ CFPGL NKED[ _
             ] RTGPKG NKED[  RQNC YGL EKQYGIQ FQ VCDNKE[ NKED[ _
             HQT K   VQ 9GL.KED[.KPGU%QWPV FQ      ] RTGLF RQ YU[UVMKEJ YKGTUCEJ _
                KH 9GL.KED[.KPGU=K?      VJGP           ] LG NK YKGTU CYKGTC YCTVQ è _
                  DGIKP
                    +PE
KNG.KED
                    NKED[=KNG.KED?  5VT6Q(NQCV
9GL.KED[.KPGU=K? ] RQDKGT NKEDú _
                  GPF
             ] QDNKE TGFPKæ _
             HQT K   VQ KNG.KED FQ
                UWOC  UWOC 
 NKED[=K?                           ] UWOWL NKED[ _
             UTGFPKC  UWOCKNG.KED                              ] QDNKE UVCV[UV[Mú _
             ] QDNKE QFEJ[NGPKG UVCPFCTFQYG _
             HQT K   VQ KNG.KED FQ
                UWOC-YCFT  UWOC-YCFT 
 UST
NKED[=K?  UTGFPKC ] UWOWL MYCFTCV[ QFEJ[NG _
             QFEJ5VF  USTV
UWOC-YCFT
KNG.KED               ] QDNKE UVCV[UV[Mú _
             9[L5WOC6GZV  (NQCV6Q5VT(
UWOC HH(KZGF       ] Y[RTQYCF UWO[ _
             9[L5TGFPKC6GZV  (NQCV6Q5VT(
UTGFPKC HH(KZGF  
             9[L1FEJ5VF6GZV  (NQCV6Q5VT(
QFEJ5VF HH(KZGF  
           GPF

        Same obliczenia nie wymagają chyba komentarza. Deklaracja tablicy NKED[ umo li-
        wia obsłu enie do tysiąca wartości, co na potrzeby tego eksperymentu chyba wystar-
        czy. Warto zauwa yć, e na siłę moglibyśmy się obejść bez tablicy, bowiem nasze
        liczby cały czas przechowywane są w komponencie 9GL.KED[ (skąd notabene pobie-
        ramy je za pomocą operatora indeksowania, tak samo jak z tablic). Nikogo jednak nie
134                                                                          Praktyczny kurs Delphi


           trzeba przekonywać, e pole tekstowe nie jest najlepszym narzędziem do przechowy-
           wania liczb rzeczywistych, a poza tym narzut związany z pobieraniem poszczególnych
           wierszy i przekształcaniem ich na wartości typu TGCN jest zbyt du y, by rozwiązanie
           takie miało sens. Na koniec zwróćmy uwagę na intensywne wykorzystanie w progra-
           mie pętli HQT — obsługa tablic i dostępu indeksowanego to jej ulubione zastosowania.

           Jak widać, wykorzystanie tablic jednowymiarowych (a takich w programach spotyka się
           najwięcej) nie jest specjalnie skomplikowane. Przejdźmy zatem na kolejny poziom
           i powiedzmy kilka słów na temat tablic dwuwymiarowych. Wspomniana ju deklaracja:
              XCT
                /CEKGT  CTTC[= ? QH TGCN

           tworzy dwuwymiarową tablicę zło oną o wymiarach 50 na 50 elementów, zawierającą
           liczby rzeczywiste. W matematyce tablica taka nosi nazwę macierzy i mo e być zapisana
           symbolicznie jako:
               x1,1     x1,2     L  x1,50 
                                            
               x 2,1    x 2, 2     x 2,50 
               M          M      M    M 
                                            
               x 50,1
                        x 50,2   L x 50 ,50 
                                             

           Zarówno wektory (tablice jednowymiarowe), jak i macierze stosowane są szeroko
           w obliczeniach naukowych i in ynierskich, tote umiejętność posługiwania się nimi
           mo e okazać się bardzo istotna. Skoro tak, przedstawimy obecnie kilka podstawo-
           wych technik obsługi tablic dwuwymiarowych.

           Dostęp do pojedynczego elementu tablicy /CEKGT mo na zapisać następująco:
              Z  /CEKGT= ?

           W powy szym zapisie posługujemy się dwoma indeksami — wiersza i kolumny — roz-
           dzielonymi przecinkiem. W ogólnym przypadku tablicy N-wymiarowej nasz zapis miałby
           postać:
              Z  6CDNKEC=KPFGMU KPFGMU   KPFGMU0?

           Odwołania do pojedynczych elementów macierzy spotykane są dość rzadko; na ogół
           obliczenia dotyczą całych wierszy lub kolumn, a indeksy przybierają kolejno wartości
           od pierwszego do ostatniego elementu wiersza lub kolumny. Poniewa do indekso-
           wania w pojedynczym wymiarze najlepiej nadaje się pętla HQT, a wymiary są dwa,
           musimy wykorzystać dwie pętle. Przykładowa konstrukcja tworząca tzw. macierz
           jednostkową (zawiera ona same zera za wyjątkiem głównej przekątnej3, na której
           znajdują się jedynki) ma postać:
              HQT K   VQ  FQ
                HQT L   VQ  FQ
                  KH K  L VJGP /CEKGT=K L?  
                  GNUG          /CEKGT=K L?  

3
    Przekątną główną macierzy kwadratowej tworzą elementy, dla których indeks wiersza jest równy
    indeksowi kolumny. Jak łatwo się przekonać, są one uło one wzdłu przekątnej biegnącej od lewego
    górnego do prawego dolnego „wierzchołka” macierzy.
Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice                                        135


           Jak widać, w pętli zewnętrznej, indeksującej wiersze (licznik K) znajduje się pętla
           wewnętrzna, indeksująca kolumny (licznik L). W niej z kolei umieszczono instrukcję
           warunkową, wstawiającą do danego elementu wartość 0 lub 1. Konstrukcja taka nosi
           nazwę pętli zagnie d onych i jest powszechnie stosowana w przetwarzaniu tablic
           dwuwymiarowych. Oczywiście obie pętle sterowane są ró nymi licznikami, co zresztą
           jest dość naturalne. Nie dość tego, próba u ycia tej samej zmiennej jako licznika obu
           pętli (co zdarzało się roztargnionym programistom piszącym np. w Turbo Pascalu)
           jest w Delphi nielegalna — zapis:
              HQT K   VQ  FQ
                HQT K   VQ  FQ ]  _

           zostanie przez kompilator potraktowany jako próba zmodyfikowania wartości licznika
           zewnętrznej pętli w jej treści, co doprowadzi do błędu kompilacji.

           Przy okazji indeksowania warto wspomnieć o jeszcze jednej interesującej kwestii.
           Na pozór wydawałoby się, e kolejność pętli w powy szym zapisie nie ma znaczenia
           — innymi słowy obojętne jest, czy licznik pętli zewnętrznej indeksuje wiersze a we-
           wnętrznej kolumny, czy odwrotnie. Okazuje się jednak, e zamiana liczników pętli
           miejscami:
              HQT L   VQ  FQ
                HQT K   VQ  FQ ]  _

           ma powa ny wpływ na czas wykonania programu! Aby to zaobserwować, nale y
           oczywiście powiększyć rozmiary macierzy (być mo e trzeba będzie zadeklarować ją
           jako globalną) i u yć precyzyjnego narzędzia do pomiaru czasu (w naszym przykła-
           dzie wykorzystaliśmy klasę 65VQRGT, którą przedstawimy szczegółowo w części
           ksią ki poświęconej programowaniu obiektowemu). Czas wypełnienia tablicy o roz-
           miarach 1000 na 1000 elementów, zmierzony na komputerze z procesorem AMD
           Athlon 1.2 GHz, wyniósł 20 milisekund w przypadku indeksowania wzdłu wierszy
           i 37 milisekund (czyli prawie dwa razy dłu ej!) w przypadku indeksowania wzdłu
           kolumn. Dlaczego?

           Kluczem do rozwiązania zagadki jest sposób przechowywania zawartości tablicy
           w pamięci. W Pascalu, podobnie jak w języku C, tablice dwuwymiarowe zapisywane są
           w pamięci kolejno wierszami 4. Oznacza to, e następujące po sobie odwołania do
           kolejnych elementów wiersza będą trafiały pod kolejne adresy pamięci, podczas gdy
           odwołania „wzdłu ” kolumny będą kierowane pod adresy oddalone od siebie o liczbę
           bajtów odpowiadającą długości pojedynczego wiersza. Działanie mechanizmów do-
           stępu do pamięci (w tym tak e stosowane w nowoczesnych komputerach tzw. pamię-
           ci podręczne) powoduje, e odwołania do adresów le ących „blisko” siebie są znacz-
           nie szybsze, ni odwołania do adresów rozproszonych w większym obszarze pamięci.
           A zatem zapisanie w pętli kolejnych elementów wiersza (poło onych jeden za drugim)
           odbędzie się znacznie szybciej ni zapisanie kolejnych elementów kolumny (oddalo-
           nych od siebie o wiele bajtów). Oczywiście na cały proces mają wpływ inne czynniki,
           jak choćby rozmiar tablicy, jednak ogólna reguła jest zawsze ta sama — indeksując
           tablicę dwuwymiarową nale y robić to odpowiednio do sposobu jej przechowywania
           w pamięci.

4
    Nie jest to bynajmniej powszechna reguła — w Fortranie tablice zapisywane są kolumnami.
136                                                                         Praktyczny kurs Delphi


           Wróćmy teraz do zagadnień bardziej przyziemnych i zastanówmy się, w jaki sposób
           obliczyć sumę elementów le ących w „górnym trójkącie” macierzy, tj. na jej przekątnej
           i ponad nią:

               x1,1   x1, 2    L  x1,50 
              
                      x 2 ,2     x 2 ,50 
               M        M      M    M 
                                          
              
                               L x 50 ,50 
                                           

           Jak łatwo sprawdzić, dla ka dego sumowanego elementu spełniony jest warunek:
              i≤ j
           gdzie K jest indeksem wiersza, zaś L — indeksem kolumny. Wykorzystując tę regułę,
           mo emy zapisać sumowanie jako:
              UWOC  
              HQT K   VQ  FQ
                HQT L   VQ  FQ
                  KH K  L VJGP UWOC  UWOC 
 /CEKGT=K L?

           Jak nietrudno wyliczyć, całkowita liczba przebiegów obu pętli wynosi 2500 (50 razy 50),
           przy czym tylko część z nich (dokładnie 1275) będzie „pełnych” — w pozostałych
           przypadkach instrukcja warunkowa nie wykona się. Jeśli podejrzewasz, e powy szy
           zapis da się ulepszyć, masz rację. Zauwa my, e w ka dym wierszu sumowaniu pod-
           legają tylko te elementy, dla których numer kolumny (L) jest większy lub równy nu-
           merowi danego wiersza (K). Dlaczego zatem nie zapisać:
              UWOC  
              HQT K   VQ  FQ
                HQT L  K VQ  FQ
                  UWOC  UWOC 
 /CEKGT=K L?

           Nikt przecie nie powiedział, e pętla musi rozpoczynać się od jedynki, ani e do inicja-
           lizacji licznika nie mo na wykorzystać innej zmiennej (np. licznika pętli zewnętrznej)!
           W ten sposób obcięliśmy prawie połowę przebiegów, co prawda pustych, ale jednak
           zajmujących jakiś czas — pomiary wykonane przez autora wykazały przyrost prędkości
           o ponad 20 procent, co jest zyskiem niebagatelnym.

           Opisane tu zabiegi to nic innego, jak optymalizacja programu — poprawienie jego
           wydajności poprzez odpowiednią modyfikację kodu źródłowego. W przypadku sumo-
           wania elementów ponad przekątniowych optymalizacja polegała na zmianie struktury
           pętli, co wyeliminowało część niepotrzebnych obliczeń. Usprawnienie ma w tym przy-
           padku naturę ogólną — jest niezale ne od u ywanego języka programowania, kom-
           pilatora czy te sprzętu. Z kolei technika zademonstrowana przy okazji tworzenia ma-
           cierzy jednostkowej jest specyficzna, wykorzystuje bowiem charakterystyczną dla
           Pascala organizację danych w pamięci oraz mechanizmy sprzętowe, które w innych
           komputerach mogą być niedostępne lub działać inaczej5.
5
    Przemilczmy dyskretnie fakt, i w zasadzie nie dokonaliśmy tu adnej optymalizacji — kod był
    optymalny w swojej pierwotnej wersji, my zaś z premedytacją popsuliśmy go, aby zademonstrować
    efekt zamiany indeksów.
Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice                                     137



Zapamiętaj
             Typy zło one z danych innych typów noszą nazwę typów strukturalnych.
             Nale ą do nich tablice i rekordy.
             Tablice umo liwiają przechowywanie większych ilości danych tego samego typu.
             Tablice mogą być jedno-lub wielowymiarowe. Tablice jednowymiarowe
             zwane są wektorami, zaś wielowymiarowe — macierzami.
             Dostęp do elementów tablicy realizuje się poprzez indeksowanie. Indeksy
             tablicy są wartościami całkowitymi; Pascal nie narzuca ograniczeń na zakres
             i liczbę indeksów.
             Do indeksowania tablic wykorzystuje się najczęściej pętle HQT.
             Operacje na tablicach często mo na zoptymalizować, bądź to poprzez zmianę
             układu kodu źródłowego, bądź te poprzez wykorzystanie specyficznych cech
             samego komputera.



Pomyśl
          1. Napisz procedurę wyszukującą i zwracającą najmniejszą i największą wartość
             w jednowymiarowej tablicy liczb rzeczywistych.
          2. Transpozycją macierzy nazywamy zamianę miejscami jej kolumn i wierszy.
             Napisz procedurę VTCPUR, dokonującą transpozycji macierzy kwadratowej /
             (macierz kwadratowa ma tyle samo wierszy, ile kolumn).

More Related Content

Viewers also liked

Fotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIFotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIWydawnictwo Helion
 
CorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneCorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneWydawnictwo Helion
 
Mikroprocesory jednoukładowe PIC
Mikroprocesory jednoukładowe PICMikroprocesory jednoukładowe PIC
Mikroprocesory jednoukładowe PICWydawnictwo Helion
 
Techniki obróbki zdjęć cyfrowych. Praktyczne projekty
Techniki obróbki zdjęć cyfrowych. Praktyczne projektyTechniki obróbki zdjęć cyfrowych. Praktyczne projekty
Techniki obróbki zdjęć cyfrowych. Praktyczne projektyWydawnictwo Helion
 
Sieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieSieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieWydawnictwo Helion
 
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBA
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBAMS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBA
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBAWydawnictwo Helion
 
Hack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaHack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaWydawnictwo Helion
 

Viewers also liked (12)

Fotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie IIFotografia cyfrowa. Edycja zdjęć. Wydanie II
Fotografia cyfrowa. Edycja zdjęć. Wydanie II
 
CorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczneCorelDRAW 11. Ćwiczenia praktyczne
CorelDRAW 11. Ćwiczenia praktyczne
 
Po prostu Flash MX
Po prostu Flash MXPo prostu Flash MX
Po prostu Flash MX
 
Mikroprocesory jednoukładowe PIC
Mikroprocesory jednoukładowe PICMikroprocesory jednoukładowe PIC
Mikroprocesory jednoukładowe PIC
 
Linux w sieci
Linux w sieciLinux w sieci
Linux w sieci
 
Word w biurze i nie tylko
Word w biurze i nie tylkoWord w biurze i nie tylko
Word w biurze i nie tylko
 
Techniki obróbki zdjęć cyfrowych. Praktyczne projekty
Techniki obróbki zdjęć cyfrowych. Praktyczne projektyTechniki obróbki zdjęć cyfrowych. Praktyczne projekty
Techniki obróbki zdjęć cyfrowych. Praktyczne projekty
 
Java. Wprowadzenie
Java. WprowadzenieJava. Wprowadzenie
Java. Wprowadzenie
 
Sieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieSieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanie
 
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBA
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBAMS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBA
MS Office 2000 i 2002/XP. Tworzenie własnych aplikacji w VBA
 
Prolog. Programowanie
Prolog. ProgramowanieProlog. Programowanie
Prolog. Programowanie
 
Hack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaHack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polska
 

Similar to Praktyczny kurs Delphi

Delphi 2005. Ćwiczenia praktyczne
Delphi 2005. Ćwiczenia praktyczneDelphi 2005. Ćwiczenia praktyczne
Delphi 2005. Ćwiczenia praktyczneWydawnictwo Helion
 
Delphi 2005. 303 gotowe rozwiązania
Delphi 2005. 303 gotowe rozwiązaniaDelphi 2005. 303 gotowe rozwiązania
Delphi 2005. 303 gotowe rozwiązaniaWydawnictwo Helion
 
Aplikacje w Delphi. Przykłady. Wydanie II
Aplikacje w Delphi. Przykłady. Wydanie IIAplikacje w Delphi. Przykłady. Wydanie II
Aplikacje w Delphi. Przykłady. Wydanie IIWydawnictwo Helion
 
Delphi 2007 dla WIN32 i bazy danych
Delphi 2007 dla WIN32 i bazy danychDelphi 2007 dla WIN32 i bazy danych
Delphi 2007 dla WIN32 i bazy danychWydawnictwo Helion
 
Delphi dla .NET. Vademecum profesjonalisty
Delphi dla .NET. Vademecum profesjonalistyDelphi dla .NET. Vademecum profesjonalisty
Delphi dla .NET. Vademecum profesjonalistyWydawnictwo Helion
 
Delphi 2006. Ćwiczenia praktyczne
Delphi 2006. Ćwiczenia praktyczneDelphi 2006. Ćwiczenia praktyczne
Delphi 2006. Ćwiczenia praktyczneWydawnictwo Helion
 
Delphi 7. Ćwiczenia zaawansowane
Delphi 7. Ćwiczenia zaawansowaneDelphi 7. Ćwiczenia zaawansowane
Delphi 7. Ćwiczenia zaawansowaneWydawnictwo Helion
 
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyC++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyWydawnictwo Helion
 
PHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowaniePHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowanieWydawnictwo Helion
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wydawnictwo Helion
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuWydawnictwo Helion
 

Similar to Praktyczny kurs Delphi (20)

Delphi 7 dla każdego
Delphi 7 dla każdegoDelphi 7 dla każdego
Delphi 7 dla każdego
 
Delphi 2005. Ćwiczenia praktyczne
Delphi 2005. Ćwiczenia praktyczneDelphi 2005. Ćwiczenia praktyczne
Delphi 2005. Ćwiczenia praktyczne
 
Delphi 2005. 303 gotowe rozwiązania
Delphi 2005. 303 gotowe rozwiązaniaDelphi 2005. 303 gotowe rozwiązania
Delphi 2005. 303 gotowe rozwiązania
 
ABC Delphi 2006
ABC Delphi 2006ABC Delphi 2006
ABC Delphi 2006
 
Aplikacje w Delphi. Przykłady. Wydanie II
Aplikacje w Delphi. Przykłady. Wydanie IIAplikacje w Delphi. Przykłady. Wydanie II
Aplikacje w Delphi. Przykłady. Wydanie II
 
Delphi 2007 dla WIN32 i bazy danych
Delphi 2007 dla WIN32 i bazy danychDelphi 2007 dla WIN32 i bazy danych
Delphi 2007 dla WIN32 i bazy danych
 
Delphi dla .NET. Vademecum profesjonalisty
Delphi dla .NET. Vademecum profesjonalistyDelphi dla .NET. Vademecum profesjonalisty
Delphi dla .NET. Vademecum profesjonalisty
 
ABC Delphi 6
ABC Delphi 6ABC Delphi 6
ABC Delphi 6
 
Delphi 2005
Delphi 2005Delphi 2005
Delphi 2005
 
Delphi. Szybki start
Delphi. Szybki startDelphi. Szybki start
Delphi. Szybki start
 
Praktyczny kurs Java
Praktyczny kurs JavaPraktyczny kurs Java
Praktyczny kurs Java
 
Delphi 7 i bazy danych
Delphi 7 i bazy danychDelphi 7 i bazy danych
Delphi 7 i bazy danych
 
Delphi 2006. Ćwiczenia praktyczne
Delphi 2006. Ćwiczenia praktyczneDelphi 2006. Ćwiczenia praktyczne
Delphi 2006. Ćwiczenia praktyczne
 
Delphi 7. Ćwiczenia zaawansowane
Delphi 7. Ćwiczenia zaawansowaneDelphi 7. Ćwiczenia zaawansowane
Delphi 7. Ćwiczenia zaawansowane
 
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalistyC++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
C++. Programowanie zorientowane obiektowo. Vademecum profesjonalisty
 
PHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowaniePHP5. Zaawansowane programowanie
PHP5. Zaawansowane programowanie
 
Wstęp do programowania w języku C#
Wstęp do programowania w języku C#Wstęp do programowania w języku C#
Wstęp do programowania w języku C#
 
Java. Rozmówki
Java. RozmówkiJava. Rozmówki
Java. Rozmówki
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładu
 
Java. Kompendium programisty
Java. Kompendium programistyJava. Kompendium programisty
Java. Kompendium programisty
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

Praktyczny kurs Delphi

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI Praktyczny kurs Delphi KATALOG KSI¥¯EK Autor: Tomasz M. Sadowski KATALOG ONLINE ISBN: 83-7361-013-8 Format: B5, stron: 396 ZAMÓW DRUKOWANY KATALOG TWÓJ KOSZYK DODAJ DO KOSZYKA Tomasz Sadowski, autor wielokrotnie wznawianego, podrêcznika „Praktyczny kurs Turbo Pascala”, zaprasza Ciê tym razem do krainy Delphi. Delphi to system szybkiego tworzenia aplikacji (RAD), w którym programy w du¿ym stopniu buduje siê z gotowych CENNIK I INFORMACJE komponentów. O ile Turbo Pascal u¿ywany jest g³ównie w dydaktyce informatyki, o tyle Delphi jest stale rozwijanym i szeroko rozpowszechnionym rodowiskiem ZAMÓW INFORMACJE programistycznym, ³¹cz¹cym przejrzysto æ ObjectPascala z przyjaznym interfejsem O NOWO CIACH Windows. Byæ mo¿e niektóre z programów u¿ywanych przez Ciebie na co dzieñ zosta³y napisane w³a nie w Delphi. ZAMÓW CENNIK Ksi¹¿ka „Praktyczny kurs Delphi” napisana jest ¿ywym, przystêpnym jêzykiem. Po³o¿ono w niej nacisk raczej na praktykê ni¿ teoriê, i dlatego to wspania³e wprowadzenie w programowanie dla osób, które wcze niej nie zetknê³y siê z t¹ CZYTELNIA tematyk¹. Ju¿ po przeczytaniu kilku stron bêdziesz móg³ napisaæ pierwszy program! Dziêki ksi¹¿ce poznasz: FRAGMENTY KSI¥¯EK ONLINE • rodowisko Delphi • Jêzyk ObjectPascal: jego podstawowe konstrukcje i typy danych • Komponenty zawarte w Delphi • Sposoby pisania w³asnych funkcji i procedur • Programowanie obiektowe • Programowanie grafiki Po lekturze „Praktycznego kursu Delphi” przekonasz siê, ¿e pisanie profesjonalnych aplikacji nie jest tak trudne, jak by siê mog³o wydawaæ. Przekonasz siê równie¿, ¿e ksi¹¿ki po wiêcone programowaniu nie musz¹ byæ nudn¹ i przepe³nion¹ niezrozumia³¹ techniczn¹ terminologi¹ lektur¹. Ta ksi¹¿ka nauczy Ciê programowaæ w Delphi — mo¿esz byæ tego pewien. Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl
  • 2. Spis treści Wstęp ............................................................................................... 5 Rozdział 1. Pierwszy krok .................................................................................. 11 Rozdział 2. Narzędzie......................................................................................... 19 Dodatek — IDE w pigułce ................................................................ 30 Rozdział 3. Pierwszy prawdziwy program ............................................................ 33 Rozdział 4. Jak to było dawniej…....................................................................... 43 Rozdział 5. Nieco elementarnej matematyki ....................................................... 51 Rozdział 6. Gdzie przechowywać dane?.............................................................. 57 Dodatek — Pozostałe typy proste .................................................... 62 Rozdział 7. Jak wprowadzić dane? ..................................................................... 65 Dodatek — Formularz to też komponent........................................... 76 Rozdział 8. Instrukcja warunkowa...................................................................... 79 Dodatek — Kalkulator, wersja 2.0.................................................... 86 Rozdział 9. Jak zrobić to samo kilka razy, czyli pętle .......................................... 91 Dodatek — Pułapki i niespodzianki................................................. 102 Rozdział 10. Jak nie robić tego samego więcej niż raz, czyli procedury i funkcje................................................................. 105 Rozdział 11. Komunikacja z procedurami............................................................ 117 Dodatek — Rekurencja.................................................................. 125 Rozdział 12. Zapisujemy więcej danych, czyli tablice ......................................... 129 Rozdział 13. Porządki w danych......................................................................... 139 Rozdział 14. Typy i argumenty strukturalne........................................................ 149 Rozdział 15. Stałe symboliczne.......................................................................... 157 Rozdział 16. O ulotności danych i jak jej zaradzić ............................................... 163
  • 3. 4 Praktyczny kurs Delphi Rozdział 17. Pliki tekstowe, czyli jak zapisać dane w czytelny sposób ................ 175 Dodatek — Pliki jeszcze inaczej ..................................................... 182 Rozdział 18. Czym naprawdę zajmują się komputery........................................... 185 Rozdział 19. Konkurencja dla Microsoftu?.......................................................... 195 Rozdział 20. Programowanie na poważnie .......................................................... 205 Rozdział 21. Jak uruchamiać oporne programy ................................................... 219 Rozdział 22. Dwa (i więcej) w jednym, czyli rekordy ........................................... 229 Rozdział 23. Zmienne dynamiczne i wskaźniki .................................................... 251 Rozdział 24. Rekord + wskaźnik = lista .............................................................. 265 Rozdział 25. O grafice słów kilka ....................................................................... 275 Rozdział 26. Od programowania strukturalnego do obiektowego ......................... 289 Rozdział 27. Dziedziczenie, polimorfizm i metody wirtualne ................................. 301 Rozdział 28. Co jeszcze warto wiedzieć o IDE..................................................... 317 Rozdział 29. Kilka dobrych rad, czyli co czynić należy… ..................................... 327 Rozdział 30. …a czego unikać ........................................................................... 337 Dodatek A Instalacja wersji próbnej Delphi 7 Architect.................................... 343 Dodatek B Odpowiedzi do zadań...................................................................... 347 Dodatek C Kilka przydatnych pojęć komputerowych......................................... 365 Dodatek D Mikrosłownik angielsko-polski........................................................ 375 Skorowidz...................................................................................... 379
  • 4. Rozdział 12. Zapisujemy więcej danych, czyli tablice Powtórka ze statystyki Typy strukturalne Tworzenie i wykorzystanie tablic Wektory i macierze Jak powszechnie wiadomo, komputer jest narzędziem słu ącym do szybkiego prze- twarzania du ych ilości danych. Przedstawione do tej pory programy nie dawały naszemu wielkiemu kalkulatorowi specjalnego pola do popisu — dane, na których operowali- śmy, sprowadzały się zwykle do kilku liczb. Nikogo jednak nie trzeba przekonywać, e większość zadań, z którymi mierzą się komputery w praktyce, wymaga wprowa- dzania, przechowywania i przetwarzania ogromnych ilości danych. Cel, który posta- wimy sobie na początku tego rozdziału, będzie znacznie mniej ambitny — spróbuje- my mianowicie rozwiązać prosty problem statystyczny, jakim jest obliczenie wartości średniej i miary rozrzutu w zadanej grupie pomiarów pewnej wielkości. Obliczanie średniej i odchylenia standardowego (ono właśnie jest miarą rozrzutu) jest równie typowym zadaniem in ynierskim, tote jego zaprogramowanie mo e przydać się nam w przyszłości. Jak powszechnie wiadomo, wartość średnia dla N liczb wyra a się wzorem: N 1 x= N ∑x i =1 i gdzie i jest numerem kolejnej wartości w zestawie. Przeło enie tego zapisu na Pascal jest na pierwszy rzut oka banalne, ale… gdzie właściwie będą przechowywane kolejne
  • 5. 130 Praktyczny kurs Delphi wartości xi? Wykorzystanie do tego celu pojedynczych zmiennych typu prostego (a tylko takie na razie znamy) jest praktycznie niemo liwe — nawet gdybyśmy uparli się przy zadeklarowaniu zmiennych Z, Z, Z…, nie wiemy ile nale ałoby ich zade- klarować, nie mówiąc ju o problemach z odwoływaniem się do nich w pętli sumują- cej. Zauwa my jednak, e nasze liczby tworzą jednolity ciąg danych tego samego ty- pu, w matematyce zapisywany w postaci tzw. wektora: [x1 , x 2 , x 3 , K , x N ] Być mo e kompilator potrafi posłu yć się podobną reprezentacją i zna jakiś sposób na „poszufladkowanie” danych w pamięci tak, by dało się odwoływać do nich poprzez kolejny numer w ciągu? Opisane powy ej rozwiązanie znane jest w programowaniu od kilkudziesięciu lat pod nazwą tablicy (ang. array). Jest ona zestawem danych tego samego typu, zajmującym pewien (na ogół ciągły) obszar w pamięci i pozwalającym na odwoływanie się do po- szczególnych elementów poprzez podanie ich numeru, czyli tzw. indeksu. Mówiąc ogólniej, tablica jest strukturą zło oną z danych innego typu, dlatego te nale y ona do grupy tzw. strukturalnych typów danych. Zmienna typu strukturalnego składa się z innych danych, zorganizowanych zgodnie z regułami obowiązującymi dla danego typu (w przypadku tablic jednowymiarowych dane ustawiane są po prostu w pamięci jedna za drugą). Poszczególne elementy zmiennej strukturalnej mogą być typu pro- stego (np. liczby całkowite) lub strukturalnego (np. tablice lub rekordy) — innymi słowy, mo emy tworzyć „piętrowe” dane strukturalne. Dwa najwa niejsze typy da- nych strukturalnych, którymi zajmiemy się w naszej ksią ce, to tablice (grupujące elementy tego samego typu) oraz rekordy (grupujące elementy ró nych typów). Jak ka da inna zmienna, tablica identyfikowana jest w programie poprzez nazwę (np. NKED[), natomiast dostęp do jej poszczególnych elementów odbywa się poprzez podanie ich indeksu. Ten ostatni jest po prostu numerem danego elementu tablicy, za- pisanym w nawiasach kwadratowych, np.: Z NKED[=? ] QFE[VCL EYCTV[ GNGOGPV VCDNKE[ NKED[ _ Graficznie mo na to przedstawić następująco: indeks 1 2 3 4 5 6 wartość 1,43 1,66 2,01 1,23 1,98 3,11 Jak mo na się domyślać, przed u yciem tablicę nale y zadeklarować, do czego słu y słowo kluczowe CTTC[: XCT NKED[ CTTC[=? QH TGCN Po słowie CTTC[ następuje para nawiasów kwadratowych, w których zapisujemy indeks pierwszego i ostatniego elementu tablicy, rozdzielone dwiema kropkami (nie dwu- kropkiem!). Niezbędne jest równie poinformowanie kompilatora o typie poszczególnych elementów tablicy — w naszym przypadku są to wartości typu TGCN. Cały powy szy
  • 6. Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice 131 zapis mo na przetłumaczyć na polski jako „tablica o stu elementach, numerowanych od 1 do 100, zło ona z liczb rzeczywistych”. Podobnie jak w przypadku zmiennych pro- stych, bezpośrednio po zadeklarowaniu elementy tablicy mają wartość przypadkową1. Deklarując tablicę nale y pamiętać o dwóch ograniczeniach: indeksy muszą być stałymi (innymi słowy, w Pascalu nie mo na deklarować tzw. tablic dynamicznych w sensie znanym np. z BASIC-a), indeksy muszą być typu porządkowego (chocia nie muszą być liczbami — mo na np. zadeklarować tablicę indeksowaną wartością typu EJCT). W większości zastosowań tablice indeksowane są od jedynki, chocia Pascal tego nie wymaga — równie dobrze mo na indeksować tablicę od zera (jak w języku C) lub ty- siąca. Rzecz jasna, indeks końcowy musi być większy lub równy początkowemu. Niestandardowe indeksowanie tablic może być źródłem problemów, bowiem od- wołanie do elementu spoza zadeklarowanego przedziału kończy się często trud- nymi do wykrycia błędami wykonania. O ile nie ma naprawdę ważnego powodu, najlepiej zawsze stosować jednolity sposób indeksowania (zwykle od jedynki, cho- ciaż programiści piszący w języku C preferują indeksowanie od zera). Warto przy okazji wspomnieć o funkcjach .QY i *KIJ, które dla tablic zwracają odpo- wiednio wartość pierwszego i ostatniego indeksu. Pozwalają one pominąć przekazywanie informacji o zakresie indeksów, o ile oczywiście mamy pewność, e obliczenia będą zawsze dotyczyły całej tablicy. Poszczególne elementy tablicy mogą być dowolnego typu (ale wszystkie tego samego), przy czym niekoniecznie musi to być typ prosty, jak TGCN czy DQQNGCP — równie dobrze mo na zadeklarować tablicę zło oną z elementów typu strukturalnego, np. innych tablic lub rekordów. Przykładowa deklaracja: XCT /CEKGT CTTC[=? QH CTTC[ =? QH TGCN utworzy dwuwymiarową tablicę zło oną z 50 wektorów (tablic jednowymiarowych), z których ka dy zawiera 50 liczb rzeczywistych. Składnia Pascala pozwala na skrócenie powy szego zapisu do postaci: XCT /CEKGT CTTC[= ? QH TGCN która lepiej odzwierciedla strukturę tablicy dwuwymiarowej, a przy okazji jest prostsza w zapisie. Mo liwe jest tak e tworzenie tablic trój- i więcejwymiarowych (Pascal nie narzuca ograniczeń na liczbę wymiarów tablicy ani wartości indeksów), jednak sto- sowane są one rzadko. 1 Ściślej rzecz biorąc, tablice deklarowane globalnie inicjalizowane są zerami, jednak lepiej wyrobić sobie nawyk dmuchania na zimne i nie zakładać, e świe o zadeklarowana tablica zawiera sensowne wartości.
  • 7. 132 Praktyczny kurs Delphi Zanim zabierzemy się do pracy, jeszcze jedna uwaga praktyczna. W porównaniu do starych aplikacji 16-bitowych, Delphi umożliwia tworzenie znacznie większych struktur danych (maksymalny rozmiar tablicy w Turbo Pascalu wynosił około 64 kB, w Delphi ograniczony jest w zasadzie wielkością dostępnej pamięci). Deklarując tablice wewnątrz procedur należy jednak pamiętać, że są one tworzone na stosie, którego pojemność jest ograniczona (domyślnie do 1 megabajta). O ile Pascal nie narzuca formalnych ograniczeń na liczbę wymiarów i elementów tablicy, musimy pamiętać o ograniczeniu praktycznym, wynikającym z rozmiarów dostępnej pamięci. Dodatkowym haczykiem jest fakt, iż wszystkie zmienne lokalne tworzone są do- piero w momencie wywołania funkcji, a zatem do przepełnienia stosu (i krytycznego błędu wykonania) dochodzi w dość nieprzewidzianym momencie podczas pracy programu. W przeciwieństwie do lokalnych, tablice deklarowane globalnie mają do dyspozycji całą pamięć dostępną dla programu (znacznie więcej, niż zajmuje stos), zaś zadeklarowanie zbyt dużej struktury powoduje błąd bezpośrednio po urucho- mieniu. Innymi słowy, deklaracja: XCT NKED[ CTTC[=? QH TGCN ] OKNKQP NKED TGE[YKUV[EJ _ ma szansę „przejść” w przypadku umieszczenia jej w sekcji globalnej programu lub modułu, natomiast raczej na pewno spowoduje błąd wykonania (nie kompilacji!), jeśli umieścimy ją wewnątrz procedury. Nie znaczy to oczywiście, że tablice najle- piej deklarować jako globalne — pamiętajmy, że zmienna globalna istnieje (i zajmuje pamięć) przez cały czas działania programu, natomiast zmienna lokalna znika po wykonaniu swojego zadania, zwalniając zajętą przez siebie pamięć. Pora na czyny. Nasz program powinien umo liwić wprowadzenie ciągu liczb o dowolnej długości, zapamiętać go, a następnie wyliczyć i wyświetlić wartość średnią i odchylenie standardowe, dane wzorem: N ∑ (x ) 1 2 s= i −x N −1 i =1 Bardziej spostrzegawczy Czytelnicy być mo e zauwa yli, e wyliczenie średniej wcale nie wymaga tablicowania danych, bowiem sumowanie mo na prowadzić na bie ąco, w miarę wprowadzania kolejnych liczb. Niestety obliczenie odchylenia standardowego wymaga z jednej strony wcześniejszego ustalenia wartości średniej, z drugiej zaś — ponownego dostępu do poszczególnych liczb. Innymi słowy, wprowadzone wartości trzeba gdzieś zapamiętać, przynajmniej na chwilę2. 2 Ściślej rzecz biorąc, wcale nie trzeba — kilka przekształceń pozwala zapisać ostatni wzór w postaci 2  N  N  ∑ xi    i =1  ∑ i=1 xi2 − N N −1 która, jak widać, nie zawiera odwołań do poszczególnych liczb, a jedynie do ich sumy i sumy kwadratów. Metoda ta wykorzystywana jest powszechnie np. w kalkulatorach, jednak jej zastosowanie odebrałoby nam pretekst do wprowadzenia pojęcia tablicy…
  • 8. Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice 133 Jako podstawę do budowy naszego programu mo emy wykorzystać projekt Sumowanie z rozdziału 9. Po dokonaniu kilku modyfikacji (zmiana nazw komponentów wyjścio- wych i etykiet) powinien on prezentować się następująco: Co prawda potrafimy ju korzystać z procedur i funkcji (a obliczenia statystyczne a proszą się o ich zastosowanie), ale na razie pójdziemy po linii najmniejszego oporu i całość kodu upakujemy w procedurze obsługi przycisku Oblicz: RTQEGFWTG 6(QTO$WVVQP%NKEM 5GPFGT 61DLGEV XCT K KPVGIGT ] PWOGT YKGTUC CYKGTCLæEGIQ NKEDú _ NKED[ CTTC[=? QH TGCN ] K LGL YCTVQ è _ KNG.KED KPVGIGT ] KNG LGUV NKED RQOKLCO[ RWUVG YKGTUG _ UWOC UWOC-YCFT TGCN ] QDNKECPG UWO[ _ UTGFPKC QFEJ5VF TGCN ] K UVCV[UV[MK _ DGIKP UWOC ] CKPKELCNKWL UWO[ DCTFQ YC PG _ UWOC-YCFT KNG.KED ] CM CFCO[ G PKG RQFCPQ CFPGL NKED[ _ ] RTGPKG NKED[ RQNC YGL EKQYGIQ FQ VCDNKE[ NKED[ _ HQT K VQ 9GL.KED[.KPGU%QWPV FQ ] RTGLF RQ YU[UVMKEJ YKGTUCEJ _ KH 9GL.KED[.KPGU=K? VJGP ] LG NK YKGTU CYKGTC YCTVQ è _ DGIKP +PE KNG.KED NKED[=KNG.KED? 5VT6Q(NQCV 9GL.KED[.KPGU=K? ] RQDKGT NKEDú _ GPF ] QDNKE TGFPKæ _ HQT K VQ KNG.KED FQ UWOC UWOC NKED[=K? ] UWOWL NKED[ _ UTGFPKC UWOCKNG.KED ] QDNKE UVCV[UV[Mú _ ] QDNKE QFEJ[NGPKG UVCPFCTFQYG _ HQT K VQ KNG.KED FQ UWOC-YCFT UWOC-YCFT UST NKED[=K? UTGFPKC ] UWOWL MYCFTCV[ QFEJ[NG _ QFEJ5VF USTV UWOC-YCFT KNG.KED ] QDNKE UVCV[UV[Mú _ 9[L5WOC6GZV (NQCV6Q5VT( UWOC HH(KZGF ] Y[RTQYCF UWO[ _ 9[L5TGFPKC6GZV (NQCV6Q5VT( UTGFPKC HH(KZGF 9[L1FEJ5VF6GZV (NQCV6Q5VT( QFEJ5VF HH(KZGF GPF Same obliczenia nie wymagają chyba komentarza. Deklaracja tablicy NKED[ umo li- wia obsłu enie do tysiąca wartości, co na potrzeby tego eksperymentu chyba wystar- czy. Warto zauwa yć, e na siłę moglibyśmy się obejść bez tablicy, bowiem nasze liczby cały czas przechowywane są w komponencie 9GL.KED[ (skąd notabene pobie- ramy je za pomocą operatora indeksowania, tak samo jak z tablic). Nikogo jednak nie
  • 9. 134 Praktyczny kurs Delphi trzeba przekonywać, e pole tekstowe nie jest najlepszym narzędziem do przechowy- wania liczb rzeczywistych, a poza tym narzut związany z pobieraniem poszczególnych wierszy i przekształcaniem ich na wartości typu TGCN jest zbyt du y, by rozwiązanie takie miało sens. Na koniec zwróćmy uwagę na intensywne wykorzystanie w progra- mie pętli HQT — obsługa tablic i dostępu indeksowanego to jej ulubione zastosowania. Jak widać, wykorzystanie tablic jednowymiarowych (a takich w programach spotyka się najwięcej) nie jest specjalnie skomplikowane. Przejdźmy zatem na kolejny poziom i powiedzmy kilka słów na temat tablic dwuwymiarowych. Wspomniana ju deklaracja: XCT /CEKGT CTTC[= ? QH TGCN tworzy dwuwymiarową tablicę zło oną o wymiarach 50 na 50 elementów, zawierającą liczby rzeczywiste. W matematyce tablica taka nosi nazwę macierzy i mo e być zapisana symbolicznie jako:  x1,1 x1,2 L x1,50     x 2,1 x 2, 2 x 2,50   M M M M     x 50,1  x 50,2 L x 50 ,50   Zarówno wektory (tablice jednowymiarowe), jak i macierze stosowane są szeroko w obliczeniach naukowych i in ynierskich, tote umiejętność posługiwania się nimi mo e okazać się bardzo istotna. Skoro tak, przedstawimy obecnie kilka podstawo- wych technik obsługi tablic dwuwymiarowych. Dostęp do pojedynczego elementu tablicy /CEKGT mo na zapisać następująco: Z /CEKGT= ? W powy szym zapisie posługujemy się dwoma indeksami — wiersza i kolumny — roz- dzielonymi przecinkiem. W ogólnym przypadku tablicy N-wymiarowej nasz zapis miałby postać: Z 6CDNKEC=KPFGMU KPFGMU KPFGMU0? Odwołania do pojedynczych elementów macierzy spotykane są dość rzadko; na ogół obliczenia dotyczą całych wierszy lub kolumn, a indeksy przybierają kolejno wartości od pierwszego do ostatniego elementu wiersza lub kolumny. Poniewa do indekso- wania w pojedynczym wymiarze najlepiej nadaje się pętla HQT, a wymiary są dwa, musimy wykorzystać dwie pętle. Przykładowa konstrukcja tworząca tzw. macierz jednostkową (zawiera ona same zera za wyjątkiem głównej przekątnej3, na której znajdują się jedynki) ma postać: HQT K VQ FQ HQT L VQ FQ KH K L VJGP /CEKGT=K L? GNUG /CEKGT=K L? 3 Przekątną główną macierzy kwadratowej tworzą elementy, dla których indeks wiersza jest równy indeksowi kolumny. Jak łatwo się przekonać, są one uło one wzdłu przekątnej biegnącej od lewego górnego do prawego dolnego „wierzchołka” macierzy.
  • 10. Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice 135 Jak widać, w pętli zewnętrznej, indeksującej wiersze (licznik K) znajduje się pętla wewnętrzna, indeksująca kolumny (licznik L). W niej z kolei umieszczono instrukcję warunkową, wstawiającą do danego elementu wartość 0 lub 1. Konstrukcja taka nosi nazwę pętli zagnie d onych i jest powszechnie stosowana w przetwarzaniu tablic dwuwymiarowych. Oczywiście obie pętle sterowane są ró nymi licznikami, co zresztą jest dość naturalne. Nie dość tego, próba u ycia tej samej zmiennej jako licznika obu pętli (co zdarzało się roztargnionym programistom piszącym np. w Turbo Pascalu) jest w Delphi nielegalna — zapis: HQT K VQ FQ HQT K VQ FQ ] _ zostanie przez kompilator potraktowany jako próba zmodyfikowania wartości licznika zewnętrznej pętli w jej treści, co doprowadzi do błędu kompilacji. Przy okazji indeksowania warto wspomnieć o jeszcze jednej interesującej kwestii. Na pozór wydawałoby się, e kolejność pętli w powy szym zapisie nie ma znaczenia — innymi słowy obojętne jest, czy licznik pętli zewnętrznej indeksuje wiersze a we- wnętrznej kolumny, czy odwrotnie. Okazuje się jednak, e zamiana liczników pętli miejscami: HQT L VQ FQ HQT K VQ FQ ] _ ma powa ny wpływ na czas wykonania programu! Aby to zaobserwować, nale y oczywiście powiększyć rozmiary macierzy (być mo e trzeba będzie zadeklarować ją jako globalną) i u yć precyzyjnego narzędzia do pomiaru czasu (w naszym przykła- dzie wykorzystaliśmy klasę 65VQRGT, którą przedstawimy szczegółowo w części ksią ki poświęconej programowaniu obiektowemu). Czas wypełnienia tablicy o roz- miarach 1000 na 1000 elementów, zmierzony na komputerze z procesorem AMD Athlon 1.2 GHz, wyniósł 20 milisekund w przypadku indeksowania wzdłu wierszy i 37 milisekund (czyli prawie dwa razy dłu ej!) w przypadku indeksowania wzdłu kolumn. Dlaczego? Kluczem do rozwiązania zagadki jest sposób przechowywania zawartości tablicy w pamięci. W Pascalu, podobnie jak w języku C, tablice dwuwymiarowe zapisywane są w pamięci kolejno wierszami 4. Oznacza to, e następujące po sobie odwołania do kolejnych elementów wiersza będą trafiały pod kolejne adresy pamięci, podczas gdy odwołania „wzdłu ” kolumny będą kierowane pod adresy oddalone od siebie o liczbę bajtów odpowiadającą długości pojedynczego wiersza. Działanie mechanizmów do- stępu do pamięci (w tym tak e stosowane w nowoczesnych komputerach tzw. pamię- ci podręczne) powoduje, e odwołania do adresów le ących „blisko” siebie są znacz- nie szybsze, ni odwołania do adresów rozproszonych w większym obszarze pamięci. A zatem zapisanie w pętli kolejnych elementów wiersza (poło onych jeden za drugim) odbędzie się znacznie szybciej ni zapisanie kolejnych elementów kolumny (oddalo- nych od siebie o wiele bajtów). Oczywiście na cały proces mają wpływ inne czynniki, jak choćby rozmiar tablicy, jednak ogólna reguła jest zawsze ta sama — indeksując tablicę dwuwymiarową nale y robić to odpowiednio do sposobu jej przechowywania w pamięci. 4 Nie jest to bynajmniej powszechna reguła — w Fortranie tablice zapisywane są kolumnami.
  • 11. 136 Praktyczny kurs Delphi Wróćmy teraz do zagadnień bardziej przyziemnych i zastanówmy się, w jaki sposób obliczyć sumę elementów le ących w „górnym trójkącie” macierzy, tj. na jej przekątnej i ponad nią:  x1,1 x1, 2 L x1,50    x 2 ,2 x 2 ,50   M M M M      L x 50 ,50   Jak łatwo sprawdzić, dla ka dego sumowanego elementu spełniony jest warunek: i≤ j gdzie K jest indeksem wiersza, zaś L — indeksem kolumny. Wykorzystując tę regułę, mo emy zapisać sumowanie jako: UWOC HQT K VQ FQ HQT L VQ FQ KH K L VJGP UWOC UWOC /CEKGT=K L? Jak nietrudno wyliczyć, całkowita liczba przebiegów obu pętli wynosi 2500 (50 razy 50), przy czym tylko część z nich (dokładnie 1275) będzie „pełnych” — w pozostałych przypadkach instrukcja warunkowa nie wykona się. Jeśli podejrzewasz, e powy szy zapis da się ulepszyć, masz rację. Zauwa my, e w ka dym wierszu sumowaniu pod- legają tylko te elementy, dla których numer kolumny (L) jest większy lub równy nu- merowi danego wiersza (K). Dlaczego zatem nie zapisać: UWOC HQT K VQ FQ HQT L K VQ FQ UWOC UWOC /CEKGT=K L? Nikt przecie nie powiedział, e pętla musi rozpoczynać się od jedynki, ani e do inicja- lizacji licznika nie mo na wykorzystać innej zmiennej (np. licznika pętli zewnętrznej)! W ten sposób obcięliśmy prawie połowę przebiegów, co prawda pustych, ale jednak zajmujących jakiś czas — pomiary wykonane przez autora wykazały przyrost prędkości o ponad 20 procent, co jest zyskiem niebagatelnym. Opisane tu zabiegi to nic innego, jak optymalizacja programu — poprawienie jego wydajności poprzez odpowiednią modyfikację kodu źródłowego. W przypadku sumo- wania elementów ponad przekątniowych optymalizacja polegała na zmianie struktury pętli, co wyeliminowało część niepotrzebnych obliczeń. Usprawnienie ma w tym przy- padku naturę ogólną — jest niezale ne od u ywanego języka programowania, kom- pilatora czy te sprzętu. Z kolei technika zademonstrowana przy okazji tworzenia ma- cierzy jednostkowej jest specyficzna, wykorzystuje bowiem charakterystyczną dla Pascala organizację danych w pamięci oraz mechanizmy sprzętowe, które w innych komputerach mogą być niedostępne lub działać inaczej5. 5 Przemilczmy dyskretnie fakt, i w zasadzie nie dokonaliśmy tu adnej optymalizacji — kod był optymalny w swojej pierwotnej wersji, my zaś z premedytacją popsuliśmy go, aby zademonstrować efekt zamiany indeksów.
  • 12. Rozdział 12. ♦ Zapisujemy więcej danych, czyli tablice 137 Zapamiętaj Typy zło one z danych innych typów noszą nazwę typów strukturalnych. Nale ą do nich tablice i rekordy. Tablice umo liwiają przechowywanie większych ilości danych tego samego typu. Tablice mogą być jedno-lub wielowymiarowe. Tablice jednowymiarowe zwane są wektorami, zaś wielowymiarowe — macierzami. Dostęp do elementów tablicy realizuje się poprzez indeksowanie. Indeksy tablicy są wartościami całkowitymi; Pascal nie narzuca ograniczeń na zakres i liczbę indeksów. Do indeksowania tablic wykorzystuje się najczęściej pętle HQT. Operacje na tablicach często mo na zoptymalizować, bądź to poprzez zmianę układu kodu źródłowego, bądź te poprzez wykorzystanie specyficznych cech samego komputera. Pomyśl 1. Napisz procedurę wyszukującą i zwracającą najmniejszą i największą wartość w jednowymiarowej tablicy liczb rzeczywistych. 2. Transpozycją macierzy nazywamy zamianę miejscami jej kolumn i wierszy. Napisz procedurę VTCPUR, dokonującą transpozycji macierzy kwadratowej / (macierz kwadratowa ma tyle samo wierszy, ile kolumn).