Lekcja 3 - Coś naprawdę trudnego ale niezbędnego
Źródła programów zamieszczonych w tej lekcji

Na tej lekcji dowiesz się jak pisać własne procedury i co to są tablice. Są to wystarczająco złożone rzeczy, aby zajeły nam całą lekcję. Na rozruszanie kolejne prawo Murphiego: "Programista jest ostatnią osobą, która chciałaby używać własnego programu", No to zaczynajmy, niech moc będzie z Tobą :))


Tworzenie Procedur

Powiedzmy że w wielu miejscach programu potrzebujemy wyczyścić ekran i narysować identyczną ramkę:

Uses CRT;

Var
 Numer:byte;

Begin
  Write('1 - Ramka pierwsza     2 - Ramka druga    :');
  Read(numer);
  If numer=1 Then
    Begin
      ClrScr;
      Writeln('I-------------------------------------------I');
      Writeln('I                                           I');
      Writeln('I                                           I');
      Writeln('I                                           I');
      Writeln('I-------------------------------------------I');
      GotoXY(8,3);
      Write('Oto Ramka 1');
   End;
  If numer=2 Then
    Begin
      ClrScr;
      Writeln('I-------------------------------------------I');
      Writeln('I                                           I');
      Writeln('I                                           I');
      Writeln('I                                           I');
      Writeln('I-------------------------------------------I');
      GotoXY(8,3);
      Write('Oto Ramka 2');
   End;
End.
Jak widzisz część programu zawiera identyczne polecenia czy jest więc sens pisać kilka razy to samo ? Właśnie wtedy z pomocą przychodzą nam WŁASNE procedury. Procedury tworzy się jeszcze tuż przed naszym głównym programem podobnie jak zmienne i stałe. Deklaruje się ją tak:
PROCEDURE JakasTam;
Begin
  { Treść procedury }
End;
I od tego momentu nasz program posiada dodatkową procedurę o nazwie "JakasTam" i jeżeli użyjemy jej nazwy gdzieś w programie to zostanie wykonane to co jest jej treścią. Aby to pokazać jaśniej wstawię do poprzedniego programu procedurę o nazwie "Ramka" i sam będziesz mógł się przekonać co to zmieniło.
Uses CRT;

Var
 Numer:byte;

PROCEDURE Ramka;
Begin
  ClrScr;
  Writeln('I-------------------------------------------I');
  Writeln('I                                           I');
  Writeln('I                                           I');
  Writeln('I                                           I');
  Writeln('I-------------------------------------------I');
  GotoXY(8,3);
End;

Begin
  Write('1 - Ramka pierwsza     2 - Ramka druga    :');
  Read(numer);
  If numer=1 Then
    Begin
      Ramka;
      Write('Oto Ramka 1');
    End;
  If numer=2 Then
    Begin
      Ramka;
      Write('Oto Ramka 2');
    End;
End.
Widzisz teraz różnicę ? 7 linijek zostało zastąpionych jedną: "Ramka" !! Program jest teraz po pierwsze: bardziej przejrzysty, po drugie: jest krótszy ( może przy wykorzystaniu procedury 2 razy tego nie widać, ale jeżeli wykonamy ją więcej powiedzmy 5..10...100... to jest to bardzo zauważalne ), i po trzecie chyba najważniejsze: Jeżeli chcemy zmienić tą ramkę w programie bez procedury musielibyśmy zmieniać ją wiele razy w każdym miejscu gdzie by się znajdowała, a tutaj wystarczy w jednym miejscu i już gotowe :)


Tworzenie Procedur z Parametrami

Wyobraź sobie teraz, że masz taki program, który będzie wypisywał kilka linijek tekstu zaczynających się w różnych miejscach ekranu:

Uses CRT;

Begin
  GotoXY(10,8);
  Write('Linijka 1');
  GotoXY(42,2);
  Write('Linijka 2');
  GotoXY(30,6);
  Write('Linijka 3');
  GotoXY(13,14);
  Write('Linijka 4');
  GotoXY(63,19);
  Write('Linijka 5');
End.
Pokażę Ci teraz jak zrobić procedurę która będzie przyjmować 3 zmienne, 2 będą typu BYTE i 1 typu STRING. Nazywać się będzie WriteXY i będzie miała za zadanie wyświetlenie tekstu bezpośrednio w wybranym miejscu ekranu ( połączenie GotoXY i Write )
Uses CRT;

PROCEDURE WriteXY(x,y:byte; s:string);
Begin
  GotoXY(x,y);
  Write(s);
End;

Begin
  WriteXY(10,8,'Linijka 1');
  WriteXY(42,2,'Linijka 2');
  WriteXY(30,6,'Linijka 3');
  WriteXY(13,14,'Linijka 4');
  WriteXY(63,19,'Linijka 5');
End.
Może zwróciłeś uwagę na to, że nie ma tutaj definicji poprzez "Var" zmiennych X,Y i S. Zostały one natomiast podane w nawiasie po procedurze i zadeklarowane automatycznie przy jej tworzeniu, ważną rzeczą jest to że będą one dostępne TYLKO w jej obrębie ! Od tego momentu procedura ta BĘDZIE WYMAGAĆ tych parametrów ( dwóch typu Byte i jednego String oddzielonych przecinkami )


Tworzenie Tablic

Teraz będzie coś co jak wiem z doświadczenia jest dla początkujących bardzo trudne do zrozumienia i może doprowadzić do załamania nerwowego ;) więc poświęcę temu trochę miejsca i opiszę chociaż same podstawy krok po kroku.

Zacznę od najprostszego przykładu. Program wczytuje 5 zmiennych i wyświetla je w odwrotnej kolejności:

Var
  a1,a2,a3,a4,a5:string;

Begin
  ReadLn(a1);
  ReadLn(a2);
  ReadLn(a3);
  ReadLn(a4);
  ReadLn(a5);
  WriteLn(a5);
  WriteLn(a4);
  WriteLn(a3);
  WriteLn(a2);
  WriteLn(a1);
End.
Jak widzisz to bardzo prosty prymitywny program, teraz spróbuję wyjaśnić jak używać tablic, a coś mi się zdaje że będzie ciężko :(

Załóżmy teraz takie coś ( poniższe 2 linijki działać nie będą ! są napisane tylko na potrzeby wytłumaczenia ) że posiadasz zmienne podobnie jak w programie powyżej ale nazywają się:
Var
 a[1],a[2],a[3],a[4],a[5]:string;
A tak naprawdę to jest JEDNA zmienna tablicowa nazywająca się "a" poprawna deklaracja takiej zmiennej to:
Var
 a:array[1..5]of string;
i oznacza to: zadeklaruj zmienną "a" która będzie posiadać elementy ponumerowane od 1 do 5 i będą one typu String, będą więc to kolejno: a[1], a[2], a[3], a[4], a[5] tak więc program teraz będzie wyglądał tak:
Var
  a:array[1..5] of string;

Begin
  ReadLn(a[1]);
  ReadLn(a[2]);
  ReadLn(a[3]);
  ReadLn(a[4]);
  ReadLn(a[5]);
  WriteLn(a[5]);
  WriteLn(a[4]);
  WriteLn(a[3]);
  WriteLn(a[2]);
  WriteLn(a[1]);
End.
Do tej pory niewiele się więc zmieniło, zmienne zostały po prostu zastąpione na takie co się tylko inaczej zapisuje. Na razie powinno być wszystko jasne. Teraz trochę zagmatwam ( nadal rozpatrujemy ten sam program )
Var
  a:array[1..5] of string;
  kolejna:byte;

Begin
  kolejna:=1;
  ReadLn(a[kolejna]);
  kolejna:=2;
  ReadLn(a[kolejna]);
  kolejna:=3;
  ReadLn(a[kolejna]);
  kolejna:=4;
  ReadLn(a[kolejna]);
  kolejna:=5;
  ReadLn(a[kolejna]);
  kolejna:=5;
  WriteLn(a[kolejna]);
  kolejna:=4;
  WriteLn(a[kolejna]);
  kolejna:=3;
  WriteLn(a[kolejna]);
  kolejna:=2;
  WriteLn(a[kolejna]);
  kolejna:=1;
  WriteLn(a[kolejna]);
End.
W tym momencie już pewnie jesteś zakręcony :) ale zobacz do czego doszliśmy ( ten program wykonuje dokładnie to samo co ten na początku ), dokonaliśmy takiego czegoś że mimo że występują te same linijki przy wpisywaniu i wyświetlaniu zmiennych to jednak zawartość tych zmiennych zmienia się tak samo jak w poprzednich programach !! Dokonaliśmy tego używając zmiennej tablicowej, to właśnie przez zmieniającą się zmienną "kolejna" zmienia się "a" ! Zobacz teraz jak wygląda końcowa wersja tego programu ( przepisz go sobie na kartkę albo wydrukuj bo zaraz będziemy go analizować) :
Var
  a:array[1..5] of string;
  kolejna:byte;

Begin
  kolejna:=0;                   {1}
  Repeat                        {2}
    kolejna:=kolejna+1;         {3}
    ReadLn(a[kolejna]);         {4}
  Until kolejna=5;              {5}
  Repeat                        {6}
    WriteLn(a[kolejna]);        {7}
    kolejna:=kolejna-1;         {8}
  Until kolejna=0;              {9}
End.
Zobacz jak nam się drastycznie skrócił program ! ( jak poznasz później jeszcze parę poleceń to program ten będziesz mógł zmieścić w 2 ( dosłownie dwóch ) linijkach ! Ale to tak na marginesie :) Przeanalizujmy go teraz krok po kroku ( jeżeli jeszcze nie rozumiesz i teraz nie zaskoczysz to klops, bo nie wiem czy da się to jeszcze prościej wytłumaczyć tak więc skup się :)

1. w linii {1} nadajemy zmiennej "kolejna" wartość "0"
2. w linii {2} rozpoczynamy pętlę
3. w linii {3} zwiększamy wartość zmiennej "kolejna" o "1" ma teraz wartość "1"
4. w linii {4} ponieważ "kolejna" jest równa "1" wprowadzamy zmienną "a[1]"
5. w linii {5} sprawdzamy czy "kolejna" jest równa 5, ponieważ nie powracamy do linii {3}
6. w linii {3} znowu zwiększamy "kolejna", ma teraz wartość 2
7. w linii {4} ponieważ "kolejna" jest równa "2" wprowadzamy zmienną "a[2]"
8. w linii {5} sprawdzamy czy "kolejna" jest równa 5, ponieważ nie powracamy do linii {3}
9. w linii {3} znowu zwiększamy "kolejna", ma teraz wartość 3
10. w linii {4} ponieważ "kolejna" jest równa "3" wprowadzamy zmienną "a[3]"

I tak dalej aż "kolejna" osiągnie wartość "5"

11. w linii {6} rozpoczynamy kolejną pętlę, a ponieważ teraz chcemy wyświetlać od końca ( od 5 do 1 ) to nie musimy wstawiać liczby do zmiennej "kolejna" bo wiemy jaka tam się znajduje, właśnie owe "5"
12. w linii {7} ponieważ "kolejna=5" wyświetla zmienną "a[5]"
13. w linii {8} zmniejszamy wartość zmiennej "kolejna" o "1" ma teraz wartość "4"
14. w linii {9} sprawdzamy czy "kolejna" ma wartość "0" jak nie to wracamy do linii {7}
15. w linii {7} ponieważ "kolejna=4" wyświetla zmienną "a[4]"
16. w linii {8} zmniejszamy wartość zmiennej "kolejna" o "1" ma teraz wartość "3"
17. w linii {9} sprawdzamy czy "kolejna" ma wartość "0" jak nie to wracamy do linii {7}
18. w linii {7} ponieważ "kolejna=3" wyświetla zmienną "a[3]"

I tak dalej aż "kolejna" osiągnie wartość "0" wtedy następuje koniec programu.

Teraz na waszym miejscu zastanowiłbym się "a po cholerę mi tyle kłopotów dla tak prostego programu ?" Odpowiedź nie jest prosta ale zobacz jedną rzecz: Aby zwiększyć o jedną zmienną pierwotny program należy dopisać dwie dodatkowe linijki a w końcowym zmienić tylko parę wartości ( dokładnie tylko dwie "5" na "6", a ilość linii pozostaje bez zmian ), a gdy potrzebujesz zwiększyć o 50 zmiennych ? Pierwotny program rośnie o 100 linijek, a końcowy pozostaje nadal z taką samą ilością ! To nie jest jedyna zaleta stosowania tablic, dzięki nim można sortować dane, wyświetlać je w dowolnej kolejności, łączyć z innymi... i jeszcze wiele, wiele więcej możliwości bez których ciężko byłoby napisać jakiś poważniejszy program.


Uff myślę że starczy :) wystarczająco dużo było na tej lekcji. Odpocznij teraz trochę i zabierz się za naukę dopiero jak będziesz gotowy do kolejnego wyzwania. Na następnej lekcji poznasz jak zbudować prostą bazę danych ( jeżeli jednak nadal nie rozumiesz tablic to radzę wrócić i jeszcze raz powoli przestudiować tą lekcję. Bez ich zrozumienia nie ma sensu iść dalej gdyż właściwie w każdym programie będziemy je teraz stosować )


Powrot na Strone Glowna