Rozdział 2.
Pascal bardziej zaawansowany
W tym rozdziale będziesz poznawać w dalszym ciągu tajniki języka Object Pascal. Za-
poznasz się z następującymi zagadnieniami:
υ
Instrukcja warunkowa
if
…
then
…
else
υ
Pętle:
for
,
while
i
repeat
υ
Instrukcja wyboru:
case
υ
Zakresy widzialności
υ
Rekordy
υ
Funkcje i procedury
if, then, else
Istnieją pewne słowa kluczowe, które występują we wszystkich językach programowania.
Jednym z nich jest instrukcja warunkowa if. Instrukcja ta służy do sprawdzania okre-
ślonego warunku w programie i w zależności od tego, czy warunek ten jest spełniony,
wykonywania różnych fragmentów kodu. Oto przykład:
var
X : Integer;
begin
X := StrToInt(Edit1.Text);
if X > 10 then
Label1.Caption := 'Podałeś liczbę większą od 10.';
end;
W przykładzie tym zawartość pola edycyjnego zapamiętywana jest w zmiennej typu
Integer. Jeżeli liczba ta jest większa od 10, wyrażenie x > 10 otrzymuje wartość
True i wyświetlany jest odpowiedni komunikat. W przeciwnym przypadku nic nie jest
wyświetlane. Innymi słowy – jeżeli wyrażenie warunkowe (zawarte między słowami
if i then) osiąga wartość True (prawda), wykonywana jest instrukcja znajdująca się
bezpośrednio za słowem then.
64
Część I
64
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Instrukcja warunkowa if służy do sprawdzania określonego warunku, i w zależno-
ści od jego spełnienia wykonywania jednej lub więcej linii kodu.
Wykonywanie wielu instrukcji
Załóżmy, że chcesz, aby w przypadku spełnienia warunku wykonywany był blok kodu
składający się z wielu linii. W tym celu musisz te linie objąć słowami kluczowymi
begin
i
end
:
if X > 10 then begin
Label1.Caption := 'Podałeś liczbę większą od 10.';
ZrobCosZLiczba(X);
end;
Kiedy wyrażenie warunkowe jest fałszywe, cały ten blok jest ignorowany i wykonywa-
na jest pierwsza instrukcja następująca po tym bloku.
Object Pascal posiada wiele zapisów skrótowych ułatwiających pisanie ko-
du i zwiększających jego czytelność. Jeden z nich pozwala sprawdzać, czy
jakaś zmienna typu
Boolean
ma wartość
True
, podając tylko jej nazwę,
np.:
if OtwartoPlik then CzytajDane;
Powyższa instrukcja ma takie samo znaczenie, co
if OtwartoPlik = True then CzytajDane;
Metoda ta ma zastosowanie tylko w przypadku zmiennych typu Boolean. Z
kolei sprawdzić fałszywość takiej zmiennej można dodając słowo
not
przed jej nazwą, np.:
var
OtwartoPlik : Boolean;
begin
OtwartoPlik := OtworzJakisPlik;
if not OtwartoPlik then WyswietlKomunikatOBledzie;
end;
Kod z takimi skrótami wygląda po prostu „elegancko”. Poza tym poznawa-
nie ich ułatwi Ci czytanie kodu w programach przykładowych.
1
1
Dla dociekliwych: może to zaskakujące, ale warunek if X nie jest dokładnie tym samym, co wa-
runek if X = TRUE – pierwszy z nich jest prawdziwy, jeżeli reprezentacja zmiennej X zawiera
przynajmniej jeden bit niezerowy, drugi natomiast prawdziwy jest tylko wtedy, jeśli reprezentacja
ta równa jest d o kła dn ie wartości TRUE (w Delphi 4 Ord(TRUE) równe jest 1) (przyp. red.)
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
65
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
65
Dodajemy else
W niektórych przypadkach istnieje potrzeba wykonania pewnej sekwencji instrukcji,
gdy wyrażenie warunkowe będzie prawdą, i wykonania innej sekwencji instrukcji, gdy
wyrażenie warunkowe będzie fałszem. Do instrukcji warunkowej należy wtedy dodać
słowo
else
:
if X = 20 then
ZrobCos(X)
else
ZrobCosInnego(X);
Słowo kluczowe else używane jest w połączeniu z if i oznacza początek
instrukcji, które wykonywane są, gdy wyrażenie warunkowe osiąga wartość
False.
W powyższym przykładzie w zależności od wartości X wywołana będzie jedna albo
druga funkcja (ale nie obie).
Zwracam też uwagę na to, że instrukcja następująca po słowie
then
nie jest zakończona
średnikiem. Dzieje się tak dlatego, że cała sekwencja
if … then … else
traktowana jest
jako jedna instrukcja. Przy tym średnika tego nie stosuje się tylko wtedy, gdy między
then
i
else
jest tylko jedna instrukcja (tzn. nie ma ich kilku między słowami
begin
i
end
).
Oto kilka przykładów prawidłowej składni instrukcji warunkowej:
if X = 20 then
ZrobCos(X) {brak średnika, ponieważ jest to pojedyncza linia}
else
ZrobCosInnego(X);
if X = 20 then begin
ZrobCos(X);
end
{brak średnika, ponieważ blok begin/end traktowany}
else
begin
{jest jak pojedyncza linia}
ZrobCosInnego(X);
end;
if X = 20 then begin
ZrobCos(X); {wiele instrukcji w bloku begin/end, po każdej
X := 200;
{jest średnik}
Y := 30;
end
else begin
ZrobCosInnego(X);
X := 100;
Y := 15;
end;
66
Część I
66
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Dla kompilatora nie ma znaczenia, czy słowa
then, begin
i
else
są
w jednej, czy też w wielu liniach. Poniższe dwa fragmenty kody są sobie
równoważne:
{Pierwsza wersja}
if X = 20 then begin
ZrobCos(X);
X := 200;
Y := 30;
end else begin
ZrobCosInnego(X);
X := 100;
Y := 15;
end;
{Druga wersja}
if X = 20
then
begin
ZrobCos(X);
X := 200;
Y := 30;
end
else
begin
ZrobCosInnego(X);
X := 100;
Y := 15;
end;
Najlepiej sam obierz sobie jakiś styl i stosuj go konsekwentnie. Najważ-
niejszym kryterium jest przy tym czytelność kodu.
Pamiętaj o tym, że znak „=” oznacza operator równości, natomiast „:=” jest
operatorem przypisania. Częstym błędem jest zamiana tych dwóch operato-
rów. Jednak w tym przypadku kompilator wyświetli odpowiedni komuni-
kat.
Zagnieżdżone instrukcje if
W razie potrzeby istnieje możliwość zagnieżdżania instrukcji
if
. Zagnieżdżanie jest niczym
innym, jak umieszczaniem instrukcji
if
wewnątrz innej instrukcji
if
.
if X > 10 then
if X < 20 then
Label1.Caption := 'Wartość X jest między 10 a 20.';
Jest to jednak bardzo uproszczona sytuacja. W rzeczywistości kod najczęściej jest
znacznie bardziej skomplikowany. Można się czasami naprawdę pogubić w gąszczu
słów
if
,
then
,
begin
i
end
. Spójrz na poniższy przykład:
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
67
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
67
if X > 100 then begin
Y := 20;
if X > 200 then begin
Y := 40;
if X > 400 then begin
Y := 60;
ZrobCos(Y);
end;
end;
end else if X < -100 then begin
Y := -20;
if X < -200 then begin
Y := -40;
if X < -400 then begin
Y := -60;
ZrobCos(Y);
end;
end;
end;
To jeszcze nie był najbardziej skomplikowany przykład, ale wiesz zapewne, o co mi
chodzi.
Jeżeli sytuacja wymaga zastosowania dwóch lub trzech zagnieżdżonych in-
strukcji if, może to być dobra okazja do użycia instrukcji case.
W przykładach przytoczonych do tej pory używałem tylko jednego wyrażenia warun-
kowego w instrukcji
if
. Kiedy stosowane jest tylko jedno wyrażenie warunkowe, można
je ująć w nawiasy lub nie. Jednakże, jeżeli tych wyrażeń warunkowych jest więcej niż
jedno, musisz ująć każde z nich w nawiasy. Na przykład:
if (X = 20) and (Y=50) then
ZrobCos;
Gdybyś zapomniał wstawić nawiasów, kompilator poinformowałby Cię o tym wyświe-
tlając odpowiedni komunikat.
Instrukcja warunkowa jest bardzo często spotykana w programach pisanych w Object
Pascalu. Nie jest ona wcale skomplikowana, więc nie będziesz miał z jej stosowaniem
prawdopodobnie żadnych kłopotów. Jedyne, o czym musisz pamiętać, to odpowiednia
liczba słów
begin
i
end
.
Wyrażenie if ... then ... else, wariant 1
Składnia
if wyrazenie_warunkowe then
instrukcja_wykonywana_gdy_true
else
instrukcja_wykonywana_gdy_false;
68
Część I
68
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Wyrażenie warunkowe if ... then ... else, wariant 2
Składnia
if wyrazenie_warunkowe_1 then
begin
instrukcje_wykonywane_gdy_true;
end
else
begin
instrukcje_wykonywane_gdy_false;
end;
Pętle
Pętle (instrukcje iteracyjne) są drugim elementem istniejącym chyba we wszystkich ję-
zykach programowania. Mogą być one używane do działań na kolejnych elementach
tablicy, do wykonywania pewnych instrukcji określoną liczbę razy, do sekwencyjnego
odczytywania pliku dyskowego, itd. Liczba zastosowań pętli jest chyba nieograniczona.
Omówię tutaj pętle typu
for
,
while
i
repeat
. Wszystkie te typy mają pewne wspólne
elementy, a mianowicie:
υ
Punkt startu
υ
Blok instrukcji wykonywanych przy każdej iteracji („ciało pętli”)
υ
Punkt stopu
υ
Sprawdzenie warunku zakończenia działania pętli
υ
Możliwość użycia procedur
Break
i
Continue
Pętla jest elementem języka programowania służącym do iteracyjnego wy-
konywania określonych instrukcji aż do spełnienia warunku zakończenia
działania.
Punktem startu pętli jest słowo kluczowe
for
,
while
albo
repeat
. Ciało pętli stanowi
jedna lub wiele dowolnych instrukcji Object Pascala. Jeżeli instrukcji jest więcej niż
jedna, muszą one być (z wyjątkiem pętli
repeat
) objęte słowami
begin
i
end
. Punktem
stopu jest w przypadku pętli
for
i
while
zamykające ciało słowo
end
, natomiast
w przypadku pętli
repeat
punktem stopu jest słowo kluczowe
until
.
Pętle z reguły działają następująco: Następuje wejście do pętli, następnie sprawdzany
jest warunek zakończenia działania. Jeżeli warunek ten jest fałszywy, wykonywane są
instrukcje stanowiące ciało pętli. Po osiągnięciu punktu stopu następuje skok na począ-
tek i ponowne sprawdzenie warunku zakończenia działania. Jeżeli będzie miał wartość
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
69
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
69
False
, cały cykl się powtarza. W przeciwnym przypadku następuje skok do instrukcji
następnej za punktem stopu, czyli wyjście z pętli. Wyjątkiem jest pętla
repeat
, w której
sprawdzanie warunku zakończenia działania następuje dopiero po wykonaniu ciała pętli.
Znaczenie warunku zakończenia działania pętli można wyrazić na przykład następująco:
„Wykonuj to i to, dopóki X jest różne od 10” albo „Czytaj kolejne bajty z pliku dopóki
nie osiągniesz jego końca”.
Częstym błędem jest takie skonstruowanie warunku zakończenia działania
pętli, że nie może on nigdy osiągnąć wartości
True
. W rezultacie tego pro-
gram wpada w nieskończoną pętlę. Jedynym wyjściem jest wtedy zastoso-
wanie kombinacji klawiszy
Ctrl+Alt+Del
i „zabicie” tego programu (w
oknie „Zamknij program” lub w Menedżerze Zadań Windows NT zapętlo-
ny program oznaczony jest jako „nie odpowiada”).
W Delphi IDE zwykle uruchamia się programy klikając ikonę „Run” albo
naciskając klawisz F9. Sposobem na „zabicie” tak uruchomionego progra-
mu jest wybranie z menu opcji Run | Program Reset albo naciśnię-
cie kombinacji klawiszy Ctrl+F2. Jednak Windows 95 może zawiesić się
całkowicie po kilkukrotnym użyciu tej opcji (Windows NT jest w tym
przypadku o wiele bardziej odporne). Staraj się więc jej nie nadużywać.
Uzbrojeni w dopiero co zdobytą wiedzę możemy teraz przystąpić do dokładniejszego
zapoznawania się z poszczególnymi typami pętli.
Pętla for
Jest to najpopularniejszy typ pętli. Parametrami tej pętli są wartość początkowa i war-
tość końcowa zmiennej sterującej. Jeżeli wartość początkowa jest mniejsza od wartości
końcowej, używane jest słówko
to
. Jeżeli natomiast wartość początkowa jest większa
od końcowej, stosowane jest słówko
downto
.
Składnia
Pętla for, odliczanie do góry
for wartosc_poczatkowa to wartosc_koncowa do begin
instrukcje;
end;
W tej wersji blok instrukcji oznaczonych jako
instrukcje
wykonywany jest dopóty,
dopóki zmienna sterująca zainicjowana wartością
wartosc_poczatkowa
nie osiągnie
wartości
wartosc_koncowa
. Zmienna sterująca jest inkrementowana (jej wartość zwiększa
się o 1) w trakcie każdej iteracji.
70
Część I
70
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Składnia
Pętla for, odliczanie do dołu
for wartosc_poczatkowa downto wartosc_koncowa do begin
instrukcje;
end;
Ta wersja pętli działa tak samo jak poprzednia z tą różnicą, że zmienna sterująca jest
dekrementowana.
Formalne zapisy zawsze są dość niejasne i trudne z początku do zrozumienia, w prze-
ciwieństwie do przykładów, których kilka przedstawiam poniżej.
Pierwszy z nich ilustruje użycie pętli
for
z odliczaniem do góry:
var
I : Integer;
begin
for I := 0 to 9 do begin
Memo1.Lines.Add('Iteracja nr ' + IntToStr(I));
end;
end;
Instrukcja dodająca linię tekstu do komponentu
Memo1
wykona się tutaj 10 razy. Zmienna
sterująca
I
przyjmuje kolejno wartości od 0 do 9.
Nazywanie zmiennej sterującej pętli for literą I jest tradycją wywodzącą
się jeszcze z Fortranu i jest często spotykane.
Oto następny przykład, który jest zmodyfikowaną wersją pierwszego:
var
I : Integer;
begin
for I := 9 downto 0 do begin
Memo1.Lines.Add('Iteracja nr ' + IntToStr(I));
end;
end;
W tym przypadku
I
osiąga kolejno wartości od 9 do 0. Słowo
downto
wskazuje na to, że
wartość zmiennej sterującej ma być zmniejszana o 1 przy każdym przebiegu pętli.
Stosowanie słów kluczowych begin i end obejmujących jedną instrukcję
(stanowiącą ciało pętli) nie jest wymagane.
Przykładowy program z pętlą for
Nic tak dobrze nie utrwala teorii jak praktyka. Napiszmy więc program, w którym za-
stosujemy pętlę
for
i komponent
Memo
(wspomniany już wcześniej w tym rozdziale).
Wykonaj następujące czynności:
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
71
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
71
1.
Utwórz nową aplikację (
File | New Application
).
2.
Umieść przycisk na formularzu.
3.
Znajdź komponent
Memo
na karcie „Standard” Palety Komponentów (powinien
znajdować się po lewej stronie komponentu
Button
) i umieść go na formularzu.
4.
Powiększ rozmiar umieszczonego na formularzu komponentu
Memo1
poprzez
przeciągnięcie czarnego prostokąta w jego prawym dolnym rogu.
5.
Kliknij podwójnie na przycisku. Otworzy się procedura obsługi
OnClick
tego
przycisku. Wpisz do niej:
procedure TForm1.Button1Click(Sender: TObject);
var
I : Integer;
begin
Memo1.Lines.Clear;
for I := 0 to 5 do
Memo1.Lines.Add('Iteracja nr: ' + IntToStr(I));
Memo1.Lines.Add('');
for I := 5 downto 0 do
Memo1.Lines.Add('Iteracja nr: ' + IntToStr(I));
end;
Uruchom teraz program. Po naciśnięciu przycisku zawartość komponentu
Memo1
po-
winna wyglądać jak na rysunku 2.1.
Rysunek 2.1.
Wynik działania
pętli for
Tak jak powiedziałem wcześniej, wartość zmiennej sterującej pętli
for
jest przy każ-
dym przebiegu zwiększana o 1. Nie ma niestety w Object Pascalu możliwości zmiany
tego kroku. Nie można na przykład odliczać od 0 do 100 z krokiem co 10. Aby uzyskać
taki efekt, należy użyć dodatkowej zmiennej:
72
Część I
72
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
var
I : Integer;
X : Integer;
begin
X := 0;
Memo1.Lines.Clear;
for I := 0 to 9 do begin
Memo1.Lines.Add('Wartość zmiennej w bieżącej iteracji: ' + IntToStr(X));
Inc(X, 10);
end;
end;
Po uruchomieniu tak zmodyfikowanego programu na komponencie
Memo1
pokazałyby
się linie:
Wartość zmiennej w bieżącej iteracji: 0
Wartość zmiennej w bieżącej iteracji: 10
Wartość zmiennej w bieżącej iteracji: 20
Wartość zmiennej w bieżącej iteracji: 30
Wartość zmiennej w bieżącej iteracji: 40
Wartość zmiennej w bieżącej iteracji: 50
Wartość zmiennej w bieżącej iteracji: 60
Wartość zmiennej w bieżącej iteracji: 70
Wartość zmiennej w bieżącej iteracji: 80
Wartość zmiennej w bieżącej iteracji: 90
Zwróć uwagę na wywołanie procedury Inc. Funkcja ta dodaje do zmiennej
będącej jej parametrem określoną wartość – w tym przypadku 10. Gdy nie po-
da się wartości, następuje zwiększenie o 1, tak jak w poniższym przykła-
dzie:
Inc(X);
{znaczy to samo, co X := X + 1}
Analogicznie do procedury Inc (zwiększanie) działa jej bliźniaczka – Dec
(zmniejszanie):
Dec(X);
{X := X - 1}
Dec(X, 10);
{X := X – 10}
Funkcje Pred i Succ
Funkcja
Pred
(od ang. predecessor) zwraca poprzednik swojego argumentu. Na przykład,
Pred(10)
daje 9,
Pred(100)
daje 99 itd. Poniższe 3 pętle
for
są więc równoważne (celem
jest 10-krotne wywołanie procedury
JakasProcedura
):
var
X : Integer;
begin
X := 10;
for I := 0 to 9 do
JakasProcedura;
for I := 0 to X – 1 do
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
73
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
73
JakasProcedura;
for I := 0 to Pred(X) do
JakasProcedura;
end;
Funkcja
Succ
(od ang. successor) – analogicznie - zwraca następnik argumentu. Przydaje
się ona często przy odliczaniu wstecz:
for I := 100 downto Succ(X) do
JakasProcedura;
Pętla while
Pętla
while
tym różni się od pętli
for
, że posiada warunek zakończenia działania
sprawdzany na początku każdej iteracji. Pętla wykonuje się tak długo, dopóki warunek
ten pozostaje prawdziwy.
var
X : Integer;
begin
X := 0;
while X < 1000 do begin
X := JakiesObliczenia;
JakasInnaProcedura;
end;
...
end;
W tym przykładzie w pętli wywoływana jest funkcja
JakiesObliczenia
, która zwraca
pewną wartość przypisywaną zmiennej X. Dopóty, dopóki wartość ta jest mniejsza od
1000, pętla jest wykonywana. Jeżeli natomiast zmienna X będzie równa lub większa niż
1000, nastąpi opuszczenie pętli (skok do pierwszej instrukcji po niej następującej). Czę-
sto w pętli
while
do sprawdzania warunku zakończenia działania używa się zmiennej
typu
Boolean
, którą można ustawiać w ciele pętli:
var
Zakonczone: Boolean;
begin
Zakonczone := False;
while not Zakonczone do begin
JakasProcedura;
Zakonczone := JakasFunkcjaZwracajacaWartoscBoolean;
JakasInnaProcedura;
end;
end;
Zmienna
Zakonczone
musi kiedyś przyjąć wartość
True
, aby pętla mogła się zakończyć.
Stwórzmy teraz inną przykładową aplikację z użyciem pętli
while
. Otwórz nowy pro-
jekt i umieść na formularzu
Button
oraz
Memo
. Kliknij podwójnie przycisk i jego proce-
durę obsługi zdarzenia
OnClick
zmodyfikuj następująco:
procedure TForm1.Button1Click(Sender: TObject);
var
74
Część I
74
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
I : Integer;
begin
I := 5;
Memo1.Lines.Clear;
while I > -1 do begin
Memo1.Lines.Add('Dzisiaj mam ' + IntToStr(I) + ' spraw do
załatwienia.');
Dec(I);
end;
Memo1.Lines.Add('Uff!');
end;
Po uruchomieniu programu i kliknięciu przycisku
Button1
w komponencie
Memo1
pojawi
się tekst:
Dzisiaj mam 5 spraw do załatwienia.
Dzisiaj mam 4 spraw do załatwienia.
Dzisiaj mam 3 spraw do załatwienia.
Dzisiaj mam 2 spraw do załatwienia.
Dzisiaj mam 1 spraw do załatwienia.
Dzisiaj mam 0 spraw do załatwienia.
Uff!
W programie tym zadeklarowałeś zmienną
I
i przypisałeś jej początkową wartość 5.
Następnym krokiem było wejście do pętli. Przy każdym przebiegu pętli następowało
dodanie jednej linii tekstu do komponentu
Memo1
i zmniejszenie o 1 wartości zmiennej
I
.
Gdy
I
osiągnęła wartość –1, nastąpiło wyjście z pętli i dodanie do
Memo1
ostatniej linii
tekstu.
Składnia
while wyrazenie_warunkowe do begin
Instrukcje;
end;
W pętli
while
blok instrukcji
Instrukcje
wykonywany jest tak długo, dopóki wyrażenie
warunkowe
wyrazenie_warunkowe
ma wartość
True
. Wartość wyrażenia warunkowego
musi być zainicjalizowana przed wejściem do pętli oraz określana w ciele pętli. Wyjście
z pętli następuje, gdy wyrażenie warunkowe sprawdzane na jej początku jest fałszywe.
Gdy w ciele pętli jest tylko jedna instrukcja, słowa kluczowe
begin
i
end
nie są wymagane.
Pętla repeat
Pętla
repeat
jest bardzo podobna do pętli
while
. Różnica między nimi jest niewielka,
ale jednak bardzo istotna. W pętli
while
warunek zakończenia działania sprawdzany
jest na początku (przed pierwszym wykonaniem ciała pętli), natomiast w pętli
repeat
warunek zakończenia działania sprawdzany jest na jej końcu. Oto poprzedni przykład,
w którym pętlę
while
zastąpiono pętlą
repeat
:
procedure TForm1.Button1Click(Sender: TObject);
var
I : Integer;
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
75
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
75
begin
I := 5;
Memo1.Clear;
repeat
Memo1.Lines.Add('Dzisiaj mam ' + IntToStr(I) + ' spraw do
∑ załatwienia.');
Dec(I);
until I = -1;
Memo1.Lines.Add('Uff!');
end;
Rezultat działania tego programu będzie taki sam, jak poprzednio. Zwróć uwagę, że nie
trzeba tu używać słów
begin
i
end
, ponieważ ich rolę spełniają w tej pętli słowa
repeat
i
until
.
Składnia
repeat
Instrukcje;
until wyrazenie_warunkowe;
W pętli tej blok kodu oznaczony jako Instrukcje wykonywany jest tak długo, dopóki
wyrażenie warunkowe jest fałszywe. Wartość wyrażenia warunkowego musi być zaini-
cjalizowana przed wejściem do pętli oraz określana w ciele pętli. Wyjście z pętli następuje,
gdy wyrażenie warunkowe sprawdzane na jej końcu jest prawdziwe.
W pętli
repeat
instrukcje stanowiące ciało pętli będą wykonane co naj-
mniej raz, niezależnie od wartości wyrażenia warunkowego. W pętli
while
wyrażenie warunkowe obliczane jest na początku, więc ciało pętli może
nigdy nie być wykonane.
Instrukcja goto
Instrukcja
goto
umożliwia skok wprost do umieszczonej w kodzie programu etykiety
zadeklarowanej uprzednio dyrektywą
Label
(nie mylić z komponentem
TLabel
– przyp.
red.) , a tym samym wykonanie pierwszej następującej po niej instrukcji. Ilustruje to
poniższy przykład:
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
label
Petelka;
begin
Memo1.Clear;
I := 0;
Petelka:
Inc(I);
Memo1.Lines.Add(IntToStr(I));
if I < 5 then
goto Petelka;
end;
76
Część I
76
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Nie jest tutaj konieczne użycie pary
begin
i
end
, ponieważ wykonywane będą po prostu
wszystkie linie kodu pomiędzy etykietą a instrukcją
goto
.
Stosowanie instrukcji
goto
w Object Pascalu jest uważane za zły zwyczaj.
Poza tym nie jest konieczne. Wszystko to, co można zrobić za pomocą in-
strukcji
goto
, można równie dobrze osiągnąć stosując pętle
while
albo
re-
peat
.
2
Składnia
label
nazwa_etykiety;
goto nazwa_etykiety;
...
nazwa_etykiety;
Po napotkaniu instrukcji
goto
następuje skok do miejsca programu oznaczonego etykietą.
2
Redakcja wydania polskiego nie podziela w pełni tego kategorycznego stwierdzenia. Fakt, iż użycie
instrukcji goto stwarza znakomitą okazję do zagmatwania programu nie oznacza jeszcze, iż każde
jej użycie czyni program zagmatwanym – ba, niekiedy program (paradoksalnie) zyskuje na czytelno-
ści. Tak się bowiem składa, że Object Pascal posiada np. znakomite mechanizmy natychmiastowego
„wyskoczenia” z pętli (break) lub procedury (exit), nie ma natomiast równoważnego mecha-
nizmu umożliwiającego wyskok z bloku begin…end – i wtedy użycie goto jest niezbędne, na
przykład:
X := 1; Y := 2;
BlokKompletny := FALSE;
Begin
...
if LiczbaBledow > 0
Then
Goto PozaBlok;
...
if BladFatalny
Then
Goto PozaBlok;
...
End;
BlokKompletny := TRUE;
PozaBlok:
If BlokKompletny Then
begin
X := X / 3; Y := Y + 1;
End
Else
Begin
X := 0; Y := 0;
End;
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
77
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
77
Procedury Continue i Break
Zanim zakończymy temat pętli, powinieneś jeszcze poznać dwie procedury, które czę-
sto stosowane są w połączeniu z nimi. Procedura
Continue
umieszczona gdziekolwiek
w ciele pętli powoduje natychmiastowy skok do punktu stopu. Przykład:
var
Zrobione : Boolean;
Wstrzymaj : Boolean;
begin
Zrobione := False;
while not Zrobione do begin
...
Wstrzymaj := SprawdzStan;
if Wstrzymaj then Continue;
{skok do punktu stopu petli}
{tutaj kod wykonywany, gdy Wstrzymaj = False}
end;
end;
Procedura
Break
jest używana do natychmiastowego i całkowitego zatrzymania pętli
(wyjścia z niej). Na przykład, szukasz jakiejś określonej liczby w tablicy liczb przeszukując
ją w pętli. W przypadku znalezienia tej liczby, można przerwać poszukiwania zapa-
miętując jednocześnie indeks tej liczby w tablicy:
var
Tablica
: array[0.99] of Integer;
Indeks
: Integer;
PoszukiwanaLiczba : Integer;
I
: Integer;
begin
WypelnijTablice;
{wypełnienie tablicy wartościami}
Indeks := -1;
PoszukiwanaLiczba := 50;
for I := to High(Tablica) do begin
if Tablica[I] = PoszukiwanaLiczba then begin
Indeks := I;
Break;
end;
end;
if Indeks <> -1 then
Label1.Caption := 'Poszukiwaną liczbę znaleziono pod indeksem '
∑+ IntToStr(Indeks)
else
Label1.Caption := 'Poszukiwanej liczby nie ma w tablicy.';
end;
Procedur
Continue
i
Break
używa się tylko wewnątrz pętli
for
,
repeat
albo
while
. Jeżeli
spróbujesz użyć tych procedur gdziekolwiek indziej, kompilator wypisze komunikat
„
BREAK or CONTINUE outside of loop
”.
78
Część I
78
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Instrukcja case
Instrukcję
case
można traktować jak rozbudowaną instrukcję
if
. Pozwala ona na wy-
konanie jednego z wielu bloków kodu bazując na wyniku określonego wyrażenia, funkcji
czy zmiennej. Wynik ten musi być typu porządkowego (
Integer
,
Word
,
Byte
itd.), nie
może to być łańcuch ani liczba zmiennoprzecinkowa. Oto przykład:
case PrzekroczeniePredkosci of
0 : Mandat := 0;
5 : Mandat := 50
10 : Mandat := 75;
15 : Mandat := 100;
20,
25,
30 : Mandat := PrzekroczeniePredkosci * 20;
else begin
Mandat := MaksymalnyMandat;
end;
end;
Wyrażeniem, na podstawie którego następuje wykonanie określonego fragmentu kodu,
jest w tym przypadku zmienna
PrzekroczeniePredkosci
. Jeżeli przyjmie ona wartość 0,
wykonana zostanie instrukcja
Mandat := 0
, gdy przyjmie wartość 5, wykonana zostanie
instrukcja
Mandat := 50
itd. Instrukcja ostatnia przed
else
wykona się, gdy
Przekrocze-
niePredkosci
będzie równe 20 albo 25 albo 30. Jeżeli natomiast zmienna ta będzie miała
wartość, której nie ma na liście, wykona się instrukcja
Mandat := MaksymalnyMandat
.
Część
else
instrukcji
case
jest opcjonalna. Oto przykład instrukcji
case
, w której nie
ma słowa
else
:
case X of
10 : PierwszaProcedura;
20 : DrugaProcedura;
30 : TrzeciaProcedura;
end;
Składnia
case wyrazenie of
wartosc1 : instrukcje_1;
wartosc2 : instrukcje_2;
...
wartoscn : instrukcje_n;
else
instrukcje_w_innym_przypadku;
end;
Instrukcja
case
pozwala na wykonanie różnych fragmentów kodu w zależności od
wartości wyrażenia
wyrazenie
. Jeżeli
wyrazenie
będzie równe
wartosc1
, wykonane
będą
instrukcje_1
, jeżeli
wyrazenie
będzie równe
wartosc2
, wykonane będą
in-
strukcje_2
, itd. Jeżeli
wyrazenie
nie będzie miało żadnej z wymienionych wartości,
zostaną wykonane
instrukcje_w_innym_przypadku
. Część
else
jest opcjonalna.
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
79
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
79
Zakres widzialności
Termin „zakres widzialności” odnosi się do nazw zmiennych i określa, w jakich czę-
ściach programu można odwoływać się do danej zmiennej. Większość zmiennych są to
tzw. „zmienne lokalne” tzn. takie, do których odwoływać się można tylko w tym bloku
kodu, w którym zostały zadeklarowane. Spójrz na listing 2.1 (jest to kompletny kod
źródłowy modułu wygenerowanego przez Delphi, te elementy, które nie były jeszcze
omawiane, możesz zignorować).
Listing 2.1. SCOPEU.PAS
unit ScopeU;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
var
X : Integer;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
procedure Test;
var
X : Integer;
begin
X := 300;
{ This X variable has a value of 300. }
Memo1.Lines.Add('Local Function X: ' + IntToStr(X));
end;
begin
X := 100;
Memo1.Lines.Clear;
{ Local X has a value of 100. }
80
Część I
80
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Memo1.Lines.Add('Local X: ' + IntToStr(X));
{ Unit scope X has a value of 200. }
Memo1.Lines.Add('Global X: ' + IntToStr(ScopeU.X));
{ Call the Test proecedure. }
Test;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{ Initialize the unit variable X. }
X := 200;
end;
end.
Pierwszą rzeczą, która się rzuca w oczy jest to, że zmienna X jest deklarowana w sumie
3 razy: w linii 27. w sekcji
implementation
, w linii 33. w metodzie
Button1Click
oraz
w linii 37. w procedurze lokalnej
Test
. Normalnie, jeżeli zadeklaruje się omyłkowo ja-
kąś zmienną więcej niż jeden raz, kompilator wyrzuca błąd
Identifier redeclared:
'X'
i kompilacja jest przerywana. Ten program jednak kompiluje się i uruchamia bez
żadnych problemów. Dlaczego? Ponieważ każda ze zmiennych X z listingu 2.1 ma inny
zakres widzialności.
Przyjrzyjmy się dokładniej listingowi 2.1. Deklaracja zmiennej X w linii 37. umieszczona
jest wewnątrz procedury
Test
i jest to zmienna lokalna tej procedury (wybiegam w tym
momencie trochę w przyszłość, ponieważ funkcje lokalne omówione będą dopiero
w rozdziale „Procedury i funkcje lokalne”). Zmienna X zadeklarowana w linii 37. wła-
ściwie nie istnieje poza procedurą
Test
. Podobnie, zmienna X zadeklarowana w linii 33. jest
lokalna dla procedury
Button1Click
i poza nią nie istnieje.
Spójrzmy teraz na zmienną
X
zadeklarowaną w sekcji
implementation
. Ta zmienna
widzialna jest w każdym miejscu modułu. Nasuwa się w tym momencie pytanie:
W procedurze
Button1Click
są w takim razie dwie zmienne
X
: jedna z linii 27. i druga
z linii 33, która jest używana, skoro obie są widzialne? Odpowiedź brzmi: ta z linii 33.
(zmienna lokalna procedury
Button1Click
). Druga, zmienna
X
widzialna w całym module,
jest w tym momencie przykryta. Można się do niej jednak odwołać podając kwalifikator
zakresu. Przykład takiego odwołania jest w linii 50:
Memo1.Lines.Add('Zmienna X widzialna w całym module: '
∑+ IntToStr(ScopeU.X));
Zapis
ScopeU.X
oznacza, że chodzi tu o zmienną
X
widzialną w całym module
ScopeU
, a nie
o zmienną lokalną o tej samej nazwie.
Jak już wcześniej wspominałem, deklarując zmienną w sekcji
implementation
, czyni
się ją widzialną w całym module. Jeżeli chcesz, żeby jakaś zmienna była widoczna
również w innych modułach projektu, musisz zadeklarować tę zmienną w sekcji
interface
(zmienna
Form1
na listingu 2.1 zadeklarowana jest w ten sposób). Do zmiennej takiej
można odwoływać się w innych modułach. Nazywane są one zmiennymi globalnymi.
Aby odwołać się do zmiennej zadeklarowanej w sekcji
interface
innego modułu
wystarczy jedynie dodać ten moduł do listy
uses
bieżącego modułu i można używać
nazwy tej zmiennej, jakby była ona zadeklarowana lokalnie (ewentualnie z użyciem
kwalifikatora zakresu, gdyby oprócz zmiennej globalnej istniałaby zmienna lokalna o tej
samej nazwie).
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
81
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
81
Zmienne deklarowane w sekcji
interface
nie są tak do końca zmiennymi
globalnymi. Prawdziwa zmienna globalna powinna być widoczna w całym
projekcie bez konieczności umieszczania deklarującego ją modułu na liście
uses
. W Delphi istnieje kilka prawdziwych zmiennych globalnych inicjali-
zowanych przez kompilator. Użytkownik nie może jednak sam tworzyć ta-
kich zmiennych.
Rekordy
Rekord jest zestawem powiązanych zwykle ze sobą danych „opakowanych” w jedną
całość. Powiedzmy, że chcesz przechowywać dane o nazwiskach i adresach osób. Wygod-
nie byłoby w tym przypadku wyodrębnić jakąś strukturę, w której dałoby się umieścić
wszystkie dane (imię, nazwisko, ulica, miasto). Rekordy są właśnie stworzone do takich
celów. Aby użyć rekordu, należy najpierw stworzyć nowy typ danej (rekord) o potrzeb-
nej strukturze, następnie należy zadeklarować zmienną typu „rekordowego”, do której
można już wpisywać dane. Rekord deklaruje się za pomocą słowa kluczowego
record
:
type
TKartaAdresowa = record
Imie : string;
Nazwisko : string;
Ulica : string;
Miasto : string;
KodPocztowy : Integer;
end;
Każdy element rekordu nazywany jest polem. Poszczególne pola muszą być deklarowa-
ne jak zmienne. W powyższym przykładzie w skład rekordu wchodzi 5 pól typu
string
oraz jedno pole typu
Integer
(kod pocztowy powinien być właściwie także typu
string
, ale dla celów edukacyjnych lepiej zadeklarować rekord o polach różnych typów).
Rekord jest zbiorem powiązanych ze sobą danych zgrupowanych w jednej
strukturze. Po zadeklarowaniu typu rekordowego trzeba zadeklarować
zmienną tego typu, aby móc umieszczać w niej dane. Składniki rekordu na-
zywane są polami.
Rekord z powyższego przykładu nadaje się dobrze do tego, o czym tu pi-
szę, lecz nie jest najlepszy, jeżeli chodzi o zapisywanie rekordów do pliku
dyskowego. Każdy rekord zapisywany w pliku musi mieć stałą długość w
bajtach. Ponieważ używane są tu długie łańcuchy, nie ma żadnej gwarancji,
że każdy rekord tego typu będzie miał taki sam rozmiar. Przy tworzeniu re-
kordów, które mają być zapisywane do pliku, lepiej użyć łańcuchów
shor-
tstring
lub nawet tablic znaków. Operacje na plikach omówię szczegóło-
wo w następnym rozdziale.
82
Część I
82
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Teraz, kiedy rekord mamy już zadeklarowany, trzeba zadeklarować zmienną, aby móc
z tego rekordu korzystać:
var
Karta001 : TKartaAdresowa;
Powyższa deklaracja przydziela pamięć dla zmiennej
Karta001
typu
TKartaAdresowa
.
Przypisanie wartości polom tej zmiennej wygląda następująco:
Karta001.Imie
:= 'Jan';
Karta001.Nazwisko
:= 'Kowalski';
Karta001.Ulica
:= 'Klonowa';
Karta001.Miasto :=
'Białystok';
Karta001.KodPocztowy
:= 15113;
Jak widać, do poszczególnych pól można się odwoływać stosując notację kropkową
(kwalifikowaną) – po nazwie zmiennej następuje kropka i nazwa pola. Umożliwia to za-
równo wpisywanie, jak i odczyt danych:
Label1.Caption := Karta001.Nazwisko;
Składnia
nazwa = record
pole_1 : typ;
pole_2 : typ;
...
pole_n : typ;
end;
Słowo kluczowe
record
deklaruje zbiór pól (
pole_1
,
pole_2
, ...,
pole_n
) i nadaje mu
nazwę (
nazwa
).
Instrukcja with
Instrukcja
with
, aczkolwiek nie tylko ona, jest często stosowana w połączeniu z rekor-
dami. Przytoczę tutaj poprzedni przykład, w którym następowało wypełnienie rekordu
Karta001
wartościami:
Karta001.Imie
:= 'Jan';
Karta001.Nazwisko
:= 'Kowalski';
Karta001.Ulica
:= 'Klonowa';
Karta001.Miasto :=
'Białystok';
Karta001.KodPocztowy
:= 15113;
Słowo kluczowe
with
może być w tym przypadku użyte w celu uproszczenia zapisu:
with Karta001 do begin
Imie
:= 'Jan';
Nazwisko
:= 'Kowalski';
Ulica
:= 'Klonowa';
Miasto
:= 'Białystok';
KodPocztowy
:= 15113;
end;
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
83
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
83
Słowo
with
znaczy „Zrób z tym obiektem (
Karta001
) następującą rzecz…”. Dzięki
niemu nie trzeba stosować zapisu kwalifikowanego. Wszystko pomiędzy słowami
begin
i
end
odnosi się do obiektu
Karta001
. Oszczędza to sporo pisania, oprócz tego kod staje
się znacznie czytelniejszy.
Tablice rekordów
Podobnie jak zmienne typu
Integer
,
Char
czy
Word
, rekordy można także grupować
w tablice. Przy tym deklarowanie i używanie tablic rekordów nie jest tak bardzo skom-
plikowane:
var
TablicaKart : array[0..9] of TKartaAdresowa;
begin
TablicaKart[0].Imie
:= 'Jan';
TablicaKart[0].Nazwisko
:= 'Kowalski';
TablicaKart[0].Ulica
:= 'Klonowa';
TablicaKart[0].Miasto
:= 'Białystok';
TablicaKart[0].KodPocztowy
:= 15425;
TablicaKart[1].Imie
:= 'Roman';
TablicaKart[1].Nazwisko
:= 'Kaleta';
TablicaKart[1].Ulica
:= 'Storczykowa';
TablicaKart[1].Miasto
:= 'Sopot';
TablicaKart[1].KodPocztowy
:= 81855;
Label1.Caption
:= TablicaKart[0].Nazwisko;
...
end;
Pliki dołączane
Pliki dołączane są to pliki tekstowe zawierające kod źródłowy, które w czasie kompilacji
traktowane są przez kompilator jak część pliku, do którego zostały dołączone. Zwykle
umieszcza się w plikach dołączanych deklaracje stałych albo dyrektywy kompilatora,
które mają być użyte w wielu plikach projektu lub wielu projektów, i których po prostu nie
opłaca się przepisywać za każdym razem. Pliki dołączane mają zwyczajowo rozszerzenie
.INC
. Na listingu 2.2 przedstawiony jest przykładowy plik dołączany:
Listing 2.2. TEST.INC
const
DomyslnaSzerokosc = 500;
DomyslnaWysokosc
= 300;
type
KartaAdresowa = record
Imie : string;
Nazwisko : string;
Ulica : string;
Miasto : string;
KodPocztowy : Integer;
end;
84
Część I
84
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Aby utworzyć plik dołączany, trzeba po prostu otworzyć nowy plik tekstowy i zapisać
go z rozszerzeniem
INC
. Najpierw wybierz opcję
File | New
z menu. Następnie kliknij
podwójnie ikonę „Text”. W Edytorze Kodu otworzy się nowy, pusty plik tekstowy.
Wpisz kod, który chcesz umieścić w pliku dołączanym i wybierz z menu
File | Save
As
. Podaj nazwę pliku z rozszerzeniem
.INC
(nie zapomnij o tym, gdyż standardowo
pliki tekstowe zapisywane są z rozszerzeniem
.TXT
).
Dołączanie pliku
.INC
do pliku głównego polega na wpisaniu w pliku głównym w miejscu
dołączenia dyrektywy kompilatora
$I
:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
StdCtrls;
{$I TEST.INC}
...
Rezultat jest taki, jakby plik
.INC
wklejono w tym miejscu do pliku głównego. Oczywiście
kod w pliku dołączanym musi być składniowo poprawny, inaczej przy kompilacji wy-
stąpią błędy.
Funkcje, procedury i metody
Funkcje i procedury to wydzielone bloki kodu wykonujące jakieś określone zadania.
Programy pisze się z reguły po to, żeby przy ich pomocy rozwiązać jakiś skomplikowany
i rozbudowany problem (np. wspomaganie sprzedaży w sklepie). Aby ułatwić sobie
rozwiązanie tego problemu, dzieli się go na mniejsze problemy cząstkowe (np. wyko-
nanie dziennego zestawienia sprzedaży). Każdy taki problem cząstkowy rozwiązuje
określona procedura albo funkcja. Problemy mogą być najróżniejsze. Na przykład mogą
być funkcje, które pobierają dwie liczby, wykonują na nich jakieś skomplikowane ope-
racje matematyczne i zwracają wynik – albo funkcje, które przetwarzają łańcuchy.
Można tych funkcji używać (wywoływać je) w dowolnym miejscu programu.
Funkcje i procedury bardziej ogólnie nazywa się podprogramami. Podprogramy są bardzo
ważną częścią każdego języka programowania – Object Pascal nie jest tu wyjątkiem.
Najprostszy rodzaj podprogramu nie pobiera żadnych danych wejściowych (parametrów)
oraz nie zwraca żadnego wyniku. Inne podprogramy mogą wymagać jednego lub więcej
parametrów i mogą też zwracać jakieś wyniki. Reguły nazewnictwa funkcji i procedur
są takie same jak dla zmiennych.
Funkcja jest to wydzielony blok kodu, który wykonuje określoną czynność i
zwraca wynik.
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
85
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
85
Parametr jest wartością przekazywaną do funkcji albo procedury, który
modyfikuje lub określa zakres jej działania.
Rysunek 2.2.
Budowa funkcji
Procedura jest to wydzielony blok kodu, który wykonuje określoną czyn-
ność, lecz nie zwraca wyniku.
Rysunek 2.3.
Budowa procedury
Metoda jest to procedura lub funkcja, która jest składnikiem klasy.
Jak widać z powyższych definicji, jedyną różnicą między funkcją a procedurą jest to,
że funkcja zwraca jakiś wynik, a procedura nie.
Napiszmy teraz przykładowy program, który będzie wykorzystywał funkcję:
1.
Utwórz nową aplikację.
2.
Umieść na formularzu po jednym komponencie
Label
i
Button
.
86
Część I
86
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
3.
Kliknij podwójnie na umieszczonym właśnie przycisku, żeby utworzyć dla
niego procedurę obsługi zdarzenia
OnClick
.
4.
Używając klawisza ze strzałką skierowaną do góry przesuń kursor w Edytorze
Kodu powyżej utworzonej przed momentem procedury.
5.
Wpisz do tekstu programu następującą funkcję:
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer;
begin
Result := Liczba1 * Liczba2;
end;
Plik źródłowy modułu w Edytorze Kodu powinien teraz wyglądać jak na rysunku 2.4.
Rysunek 2.4.
Edytor Kodu
z wyświetloną
funkcją Mnozenie
6.
Przesuń kursor z powrotem do procedury
TForm1.Button1Click
i zmodyfikuj
ją tak, żeby zawierała następujący kod:
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
begin
X := Mnozenie(10, 20);
Label1.Caption := IntToStr(X);
end;
Uruchom teraz program i naciśnij przycisk. Etykieta powinna teraz zawierać liczbę 200.
Program działa w następujący sposób: Po naciśnięciu przycisku wywoływana jest procedura
obsługi zdarzenia
OnClick
tego przycisku. Ta procedura z kolei wywołuje funkcję
Mnozenie
przekazując do niej dwa parametry – liczby 10 i 20. Wynik zwrócony przez funkcję
Mnozenie
zapamiętywany jest w zmiennej X, która z kolei wyświetlana jest na ekranie.
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
87
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
87
Przykład ten ilustruje stosowanie samodzielnych funkcji w programie Del-
phi. Normalnie, uczyniłbym tę funkcję składnikiem klasy formularza, jed-
nak ponieważ nie omawiałem jeszcze klas, nie chcę teraz za bardzo kom-
plikować przykładu.
Mogłeś analizując ten przykład pomyśleć: „No dobrze, ale skąd funkcja ma wiedzieć,
którą zmienną ma zwrócić jako swój wynik?” Przyjrzyjmy się jeszcze raz funkcji
Mnozenie
:
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer;
begin
Result := Liczba1 * Liczba2;
end;
Każda funkcja w Object Pascalu ma predefiniowaną zmienną lokalną o nazwie
Result
.
Używana jest ona właśnie do przechowywania wyniku zwracanego przez tę funkcję.
Wystarczy więc przypisać zmiennej
Result
wartość, którą funkcja ma zwrócić jako
wynik.
Jest oprócz tego drugi sposób przypisywania wartości wynikowi funkcji.
Zamiast zmiennej
Result
używa się po prostu nazwy funkcji:
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer;
begin
Mnozenie := Liczba1 * liczba2;
end;
Wersję tę często spotyka się w starszych wersjach Pascala i w programach
przeniesionych do Delphi z Turbo Pascala (jednego z poprzedników Delphi).
Funkcję
Mnozenie
można wywoływać na kilka sposobów. Jako parametry można prze-
kazywać do niej zmienne, wartości podane wprost lub nawet wyniki wywołań innych
funkcji. Na przykład:
X := Mnozenie(2, 5); {przekazywanie wartości podanych wprost}
X := Mnozenie(A, B); {przekazywanie zmiennych}
Label1.Caption := IntToStr(Mnozenie(X, Y));
{wynik funkcji użyty jako parametr innej funkcji}
Mnozenie(X, Y);
{zignorowanie wyniku funkcji}
W ostatniej linii, przy wywołaniu funkcji
Mnozenie
, wartość przez nią zwracana jest
ignorowana. Nie ma to w tym przypadku większego sensu, jednak pomijanie wyniku
funkcji jest często stosowaną praktyką w programowaniu. Spotyka się wiele funkcji,
które po wykonaniu określonej akcji zwracają jako wynik status tego wywołania (np.
informację, czy akcja się powiodła). Jeżeli ta informacja nie jest Ci do niczego potrzeb-
na, możesz ją po prostu zignorować.
88
Część I
88
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Dodajmy teraz do naszego programu przykładowego procedurę:
1.
Kliknij podwójnie na przycisku umieszczonym na formularzu. W Edytorze
Kodu wyświetlona będzie procedura
TForm1.Button1Click
.
2.
Przesuń kursor do góry o kilka linii tak, aby znajdował się on między procedurami
Mnozenie
i
TForm1.Button1Click
. Wpisz następujący kod:
procedure Powitanie;
begin
MessageDlg('Witaj!', mtInformation, [mbOk], 0);
end;
3.
Dodaj linię kodu na końcu procedury obsługi zdarzenia
OnClick
komponentu
Button
tak, aby wyglądała ona następująco:
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
begin
X := Mnozenie(10, 20);
Label1.Caption := IntToStr(X);
Powitanie;
end;
Teraz uruchom program ponownie. Tym razem, oprócz wyniku mnożenia wyświetlone-
go na etykiecie, pokaże się okienko informacyjne. Wyświetlenie okienka jest skutkiem
wywołania procedury
Powitanie
. Wywołanie to jest bardzo proste, ponieważ procedura
ta nie wymaga żadnych parametrów. Ważne jest tu zrozumienie tego, że kod umieszczony
w procedurze
Powitanie
wykonywany jest tylko wtedy, gdy wprost wywoła się tę pro-
cedurę.
Za każdym razem, kiedy zajdzie potrzeba powtórzenia jakiejś partii kodu
kilka lub więcej razy, rozważ umieszczenie jej w podprogramie. Będziesz
mógł wtedy wywoływać po prostu ten podprogram.
Podprogramy mogą (i często to robią) wywoływać inne podprogramy. Mogą one nawet
wywoływać same siebie. Wywoływanie samych siebie przez podprogramy nazywane
jest rekurencją i stosowane jest raczej w uzasadnionych przypadkach przez doświad-
czonych programistów.
Rekurencją nazywa się wywoływanie przez procedurę lub funkcję samych
siebie.
Deklaracja i definicja
Funkcje i procedury często posiadają deklarację, zawsze natomiast posiadają definicję.
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
89
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
89
Deklaracja jest pojedynczą instrukcją, która opisuje nazwę i parametry (je-
żeli występują) podprogramu. W przypadku funkcji deklaracja opisuje
również typ zwracanego przez nią wyniku.
Definicja procedury albo funkcji zawiera właściwą treść tej procedury albo
funkcji i umieszczona jest w sekcji
implementation
modułu.
Oto trzy główne przypadki, kiedy konieczne jest deklarowanie funkcji albo procedury:
υ
Gdy funkcja albo procedura ma być używana w innych modułach.
υ
Gdy definicja tej funkcji albo procedury znajduje się poniżej miejsca w pliku
źródłowym, w którym dana funkcja albo procedura jest wywoływana.
υ
Gdy funkcja albo procedura jest składnikiem klasy.
Do tej pory w tej książce nie używałem deklaracji funkcji i procedur, jedynie definicje.
Nie wystąpiła dotąd taka potrzeba – definicje te zawsze poprzedzały wywołanie. Deklaracja
funkcji
Mnozenie
wyglądałaby następująco:
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer;
Deklaracje funkcji i procedur umieszczane są w sekcji
interface
. Umożliwia do wy-
woływanie ich także w innych modułach. Są one publiczne. Jeżeli nie chcesz, żeby jakaś
funkcja lub procedura była publiczna, nie umieszczaj jej deklaracji w sekcji
interface
.
Zamiast tego umieść jej definicję w sekcji
implementation
na samym początku tak, żeby
była widoczna w jak największej części modułu. Mimo, że do tej pory nie stosowałem
deklaracji, mógłbym to robić w następujący sposób:
unit Unit1;
interface
...
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer; {deklaracja}
implementation
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
begin
X := Mnozenie(10, 20);
end;
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer;
begin
Result := Liczba1 * Liczba2;
end;
end.
90
Część I
90
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
W tym przypadku deklaracja funkcji
Mnozenie
jest konieczna, ponieważ jej definicja
jest poniżej procedury
Button1Click
, w której następuje jej wywołanie.
Jeżeli zadeklarujesz funkcję i zapomnisz ją potem zdefiniować, kompilator
wypisze komunikat o błędzie
Unsatisfied forward or external
declaration: 'Mnozenie'
.
Parametry przekazywane przez stałą, przez wartość
i przez referencję
Istnieją trzy sposoby przekazywania parametrów do procedur i funkcji (tak naprawdę więcej
niż trzy, ale tutaj tylko te będę omawiał): przez stałą, przez wartość i przez referencję.
Parametry przekazywane przez wartość
Wszystkie parametry, których używałeś do tej pory pracując z tą książką, były to parametry
przekazywane przez wartość. Parametry takie można porównać do zmiennych lokal-
nych w procedurze lub funkcji – można je modyfikować, lecz zmienna globalna o tej
samej nazwie pozostanie niezmieniona. Tak samo modyfikacja parametru przekazanego
do funkcji przez wartość nie zmienia oryginalnej zmiennej. Stwórzmy nową funkcję,
która będzie ilustrowała to zagadnienie. Nazwiemy ją
MnozenieKwadratow
. Będzie ona
podnosić do kwadratu dwie przekazane do niej liczby i mnożyć te kwadraty:
function MnozenieKwadratow(Liczba1, Liczba2 : Integer) : Integer;
begin
Liczba1 := Liczba1 * Liczba1;
Liczba2 := Liczba2 * Liczba2;
Result := Liczba1 * Liczba2;
end;
Wywołajmy teraz tę funkcję w następujący sposób:
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
Y : Integer;
Z : Integer;
begin
X := 2;
Y := 3;
Z := MnozenieKwadratow(X, Y);
Label1.Caption := 'X = ' + IntToStr(X) + 'Y = ' + IntToStr(Y) + 'Z = '
∑ + IntToStr(Z);
end;
Do funkcji
MnozenieKwadratow
przekazywane są wartości dwóch zmiennych (
X
i
Y
). Są
one modyfikowane wewnątrz funkcji (podnoszone do kwadratu). Oryginalne zmienne
jednak pozostają niezmienione, ponieważ do funkcji przekazywane są ich kopie.
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
91
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
91
Parametry przekazywane przez stałą
Innym sposobem na przekazywanie danych wejściowych do funkcji jest ich przekazanie
przez stała. Wartości tych parametrów nie mogą być zmieniane wewnątrz funkcji. Oto
przykład:
procedure PowiedzCos(const S : string);
begin
S := S + 'Test';
ShowMessage(S);
end;
To jest jeden z kilku przykładów kodu w tej książce, przy próbie kompilacji którego
wystąpi błąd. Odnosić się on będzie do pierwszej linii procedury i będzie brzmiał
Left
side cannot be assigned to
. Błąd ten będzie generowany, ponieważ słowo
const
znajdujące się przed parametrem oznacza, że nie może on być modyfikowany w ciele
procedury. Jeżeli chcesz zabezpieczyć jakieś parametry przekazywane do procedury lub
funkcji przed modyfikacją, to jest właśnie sposób na to.
Parametry przekazywane przez referencję
Przy przekazywaniu parametrów przez referencję
, kompilator nie robi ich kopii ani
w żaden inny sposób nie zabezpiecza tych parametrów przed modyfikacją wewnątrz
procedury. Referencja jest to po prostu odwołanie do jakiejś zmiennej. Znaczy to, że
wszelkie modyfikacje wykonywane na parametrach są de facto modyfikacjami wyko-
nywanymi na oryginalnych zmiennych. Poniżej przedstawiony jest przykład takiego
przekazania:
procedure DoKwadratu(var Liczba: Integer);
begin
Liczba := Liczba * Liczba;
end;
procedure TForm.Button1Click(Sender: TObject);
var
X : Integer;
begin
X := 20;
DoKwadratu(X);
Label1.Caption := IntToStr(X);
{X równe jest teraz 400}
end;
3
Dociekliwy Czytelnik mógłby zapytać w tym miejscu, czym właściwie różni się przekazywanie
parametru przez wartość od przekazywania przez stałą? Obydwa te sposoby uniemożliwiają zmianę
wartości przekazanego parametru – co osiągane jest w dwojaki sposób: przy przekazywaniu przez
wartość tworzona jest ad hoc kopia robocza parametru, na której wykonywane są wszelkie modyfi-
kacje tego ostatniego, zaś przy przekazywaniu przez stałą kompilator zabrania dokonywania jakich-
kolwiek modyfikacji parametru, eliminując konieczność tworzenia owej kopii; z tego też względu
przekazanie przez stałą jest efektywniejsze zarówno pamięciowo (oszczędza się pamięć, nie tworząc
kopii) jak i czasowo (wykonanie kopii zajmuje bowiem pewną ilość czasu). (przyp. red.)
4
Przekazywanie parametru przez referencję nazywane bywa również przekazaniem „przez adres” lub
„przez zmienną” (przyp. red.).
92
Część I
92
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Słówko
var
umieszczone przy parametrze oznacza, że jest on przekazywany przez refe-
rencję.
Wiele słów kluczowych w Object Pascalu ma kilka znaczeń. Słowo
var
na
przykład oznacza, że dany parametr przekazywany jest przez referencję.
Rozpoczyna też ono sekcję deklaracji zmiennych. Kompilator właściwie
interpretuje je za każdym razem wnioskując z kontekstu, w jakim się dane
słowo znajduje.
W procedurze
DoKwadratu
zmieniana jest wartość parametru
Liczba
. Tym samym wartość
zmiennej
X
, która jest przekazana do tej procedury, przed wywołaniem
DoKwadratu
wynosząca 20, po tym wywołaniu jest już inna (400).
Ponieważ parametr procedury
DoKwadratu
jest przekazywany przez referencję, musisz
w wywołaniu tej procedury użyć zmiennej takiego samego typu, jak parametr. Nie możesz
na przykład napisać:
DoKwadratu(30);
{Błąd przy kompilacji!}
Nie możesz też przekazać do tej procedury zmiennej innego typu niż typ parametru:
var
X : Word;
begin
X := 20;
DoKwadratu(X);
{Błąd przy kompilacji!}
Komunikat kompilatora wygenerowany przy próbie kompilacji powyższego kodu będzie
brzmiał
Types of actual and formal var parameters must be identical
.
Formalnie funkcja może zwracać tylko jedną wartość. Parametry przeka-
zywane przez referencję to sposób na obejście tego ograniczenia. Jeżeli
funkcja może je modyfikować (może ich być dowolnie dużo), można
uznać, że może zwracać w ten sposób wiele wartości.
Funkcje i procedury lokalne
Funkcje i procedury lokalne zawierają się w innych funkcjach lub procedurach. Na
przykład:
procedure TForm1.Button1Click(Sender: TObject);
var
X : Integer;
{procedura lokalna:}
procedure Test;
begin
Memo1.Lines.Add('Procedura lokalna, X = ' + IntToStr(X));
end;
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
93
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
93
begin
X := 100;
Memo1.Lines.Clear;
Memo1.Lines.Add('Procedura główna, X = ' + IntToStr(X));
Test;
end;
Procedura
Test
zawarta jest w sekcji
var
procedury
Button1Click
. Procedury takie nazy-
wają się procedurami lokalnymi podprogramu, w którym są zawarte. Mogą być one
wywołane tylko z poziomu zawierającego je podprogramu, nie są widoczne nigdzie indziej.
Ważną cechą charakteryzującą funkcje i procedury lokalne jest to, że widoczne są w niej
zmienne lokalne otaczającego je podprogramu. W powyższym przykładzie, zmienna
X
zadeklarowana jako zmienna lokalna procedury
Button1Click
, widoczna jest w procedurze
Button1Click
oraz w procedurze Test. Po uruchomieniu tego programu w komponen-
cie
Memo
widoczny będzie tekst:
Procedura główna, X = 100
Procedura lokalna, X = 100
Przeciążanie funkcji i procedur
Począwszy od wersji czwartej Delphi, Object Pascal pozwala na deklarowanie dwóch
lub więcej funkcji i procedur (metod) o tych samych nazwach, lecz o różnych parametrach
(w tym samym zakresie widzialności).
Przeciążanie metod jest to deklarowanie dwóch lub więcej funkcji albo pro-
cedur o tych samych nazwach, ale o różniących się listach parametrów.
Metody o tych samych nazwach nazywa się metodami przeciążonymi.
Przedstawiałem wcześniej przykładowy program, który zawierał funkcję o nazwie
Mnozenie
. Funkcja ta pobierała dwie liczby typu
Integer
i zwracała ich iloczyn. Co
jednak byłoby, gdyby trzeba było mnożyć także liczby typu
Double
albo
Word
? W po-
przednich wersjach Delphi konieczne było napisanie kilku funkcji o odpowiednich pa-
rametrach:
{deklaracje w programie napisanym w Delphi 1, 2 albo 3}
function MnozenieInt(Liczba1, Liczba2 : Integer) : Integer;
function MnozenieDouble(Liczba1, Liczba2 : Double) : Double;
function MnozenieWord(Liczba1, Liczba2 : Word) : Word;
Znacznie prostszym rozwiązaniem byłoby stworzenie jakiejś jednej uniwersalnej funkcji
Mnozenie
, która wiedziałaby, kiedy mnożyć liczby
Integer
, kiedy
Double
a kiedy
Word
.
W Delphi 4 jest to możliwe – właśnie dzięki przeciążaniu. Oto, jak deklaracje takiej
funkcji wyglądają w Delphi 4:
{deklaracje w programie napisanym w Delphi 4}
function Mnozenie(Liczba1, Liczba2 : Integer) : Integer; overload;
function Mnozenie(Liczba1, Liczba2 : Double) : Double; overload;
function Mnozenie(Liczba1, Liczba2 : Word) : Word; overload;
94
Część I
94
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Nadal trzeba napisać oddzielne definicje dla każdej z wersji, ale używając tych funkcji
można już posługiwać się jedną nazwą. Kompilator troszczy się o wywołanie odpo-
wiedniej wersji w zależności od parametrów wywołania. Na przykład:
var
X, Y, Z : Double;
begin
X := 1.5;
Y := 10.5;
Z := Mnozenie(X, Y);
end;
Kompilator widząc, że do funkcji przekazywane są liczby typu
Double
wywołuje funkcję
Mnozenie
, która mnoży liczby typu
Double
. Analogicznie, jeżeli parametrami są liczby
typu
Integer
, kompilator wywołuje funkcję mnożącą liczby typu
Integer
.
Przeciążane funkcje rozróżniane są między sobą tylko i wyłącznie na pod-
stawie typu lub liczby parametrów, nie na podstawie typu wyniku. Nie
można deklarować dwóch funkcji o tych samych nazwach, takich samych
parametrach, różniących się jedynie typem wyniku:
function Funkcja01 : Integer; overload;
function Funkcja01 : Word; overload;
Przy próbie kompilacji programu z dwiema powyższymi liniami wystąpi błąd
Declaration of 'Funkcja01' differs from previous decla-
ration.
Parametry domyślne procedur i funkcji
Procedura lub funkcja może posiadać parametry domyślne, tzn. takie, które
w przypadku braku odpowiednich parametrów przy wywołaniu zastępują
je, przekazując przy tym określoną wartość.
Przykład funkcji posiadającej parametr domyślny przedstawiony jest poniżej:
{Deklaracja procedury}
{Parametr 'NajpierwWyczysc' ma domyślną wartość False}
procedure Przerysuj(NajpierwWyczysc : Boolean = False);
[Definicja procedury}
procedure Przerysuj(NajpierwWyczysc : Boolean);
begin
if NajpierwWyczysc then begin
{instrukcje czyszczące ekran}
end;
{instrukcje rysujące na nowo}
end;
Można tę funkcję wywoływać z parametrem lub bez parametru. Gdy wywołuje się ją
z parametrem, zachowuje się ona tak, jak zwyczajna funkcja. Gdy natomiast nie poda się
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
95
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
95
parametru podczas wywołania, funkcja przyjmie, że ten parametr podano i że ma on
wartość
False
. Dwie następujące linie kodu działają więc identycznie:
Przerysuj;
Przerysuj(False);
Deklarując funkcję można łączyć parametry domyślne ze zwykłymi:
{deklaracja}
function GrajPlikWave(Nazwa : string; WPetli : Boolean = False;
LiczbaPowtorzen : Integer = 10) : Integer;
[wywołania funkcji GrajPlikWave}
R := GrajPlikWave('chime.wav');
{pojedyncze odtworzenie}
R := GrajPlikWave('ding.wav', True);
{odtworzenie 10 razy}
R := GrajPlikWave('bell.wave', True, 5);
{odtworzenie 5 razy}
Parametry domyślne mogą zaoszczędzić czasem dużo pisania przy tworzeniu programu.
Jeżeli na przykład napisałeś funkcję, która w 99 % wywołań ma te same parametry,
możesz je uczynić domyślnymi. Jeżeli trzeba podać inne parametry – wystarczy je po
prostu wpisać.
Jeżeli w deklaracji funkcji występują jakieś parametry domyślne, muszą wy-
stąpić na końcu listy parametrów. Poniższa deklaracja nie jest prawidłowa:
procedure MojaProcedura(X : Integer; Y : Integer = 10; Z :
Integer);
Aby ta funkcja mogła się prawidłowo kompilować, należy parametr do-
myślny
Y
przesunąć na koniec listy:
procedure MojaProcedura(X : Integer; Z : Integer; Y :
Integer = 10);
Podsumowanie
Poznałeś w tym rozdziale podstawowe zagadnienia Object Pascala. Było to konieczne,
żeby móc w ogóle rozpocząć pisanie programów w Delphi. Na początku rozdziału zaj-
mowaliśmy się różnymi typami pętli, następnie omawiałem instrukcję
case
i jej stosowanie.
Następnym zagadnieniem był zakres widzialności zmiennych, potem omawiałem rekordy.
Ukoronowaniem rozdziału były funkcje i procedury.
Warsztat
Warsztat składa się z pytań kontrolnych oraz ćwiczeń utrwalających i pogłębiających
zdobytą wiedzę. W razie trudności lub wątpliwości, odpowiedzi do tych pytań zamiesz-
czone są w Dodatku A, „Quiz – odpowiedzi”.
96
Część I
96
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
Pytania i odpowiedzi
υ
Jak głęboko można zagnieżdżać instrukcje
if
?
Formalnego ograniczenia nie ma. Zbyt skomplikowane konstrukcje jednak stają
się praktycznie nieczytelne i niemodyfikowalne.
υ
Czy pętle będą automatycznie kończyć swoje działanie, jeżeli coś pójdzie
nie tak?
Nie. Jeżeli program wpadnie w nieskończoną pętlę, jedynym sposobem na jej
przerwanie będzie zakończenie tego programu przez użytkownika z poziomu
Menadżera Zadań Windows lub poprzez wybranie opcji
Run | Program reset
z poziomu Delphi IDE.
υ
Czy w każdej instrukcji
case
musi być słowo
else
?
Nie, sekcja
else
jest opcjonalna.
υ
Czy w programie może istnieć więcej niż jedna zmienna o tej samej nazwie?
Tak, jeżeli będą one w różnych zakresach widzialności. Na przykład, można
zadeklarować zmienną globalną
X
i zmienną lokalną o tej samej nazwie.
υ
Jakie są korzyści z przeciążania procedur i funkcji?
Przeciążanie funkcji i procedur umożliwia deklarowanie kilku funkcji lub proce-
dur o tej samej nazwie, które wykonują te same operacje na parametrach różnych
typów. Na przykład można zadeklarować funkcję
RysujFigure
, której parametrem
raz może być odcinek, raz trójkąt, a raz koło. Unika się w ten sposób deklarowania
dużej liczby funkcji o różnych nazwach, przez co upraszcza się programowanie.
υ
Czy można używać typu rekordowego bez deklarowania zmiennych tego
typu?
Nie. Konieczne jest zadeklarowanie odpowiednich zmiennych, bez których
korzystanie z typów rekordowych nie jest możliwe.
Quiz
1.
Które instrukcje są wykonywane, jeżeli wyrażenie warunkowe w instrukcji
if
ma wartość
True
?
2.
Ile wyników może zwrócić funkcja?
3.
Jaka (oprócz składniowej) jest różnica między pętlą
while
i pętlą
repeat
?
4.
Jak działają procedury
Break
i
Continue
?
Rozdzia³ 2.
♦ Pascal bardziej zaawansowany
97
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc
97
5.
Co to jest zmienna globalna?
6.
Czy rekord może zawierać w sobie dane różnych typów (
Char
,
Integer
,
Word
itd.)?
7.
Jak można odwoływać się do pól rekordu?
8.
Ile może być w programie funkcji i procedur?
9.
Czy funkcja może wywołać inną funkcję lub procedurę?
10.
Czy rekordy można umieszczać w tablicach?
Ćwiczenia
1.
Napisz procedurę o nazwie
Test2
, która zmienia właściwość
Caption
kompo-
nentu
Label
. Umieść na formularzu przycisk, po naciśnięciu którego nastąpi
wywołanie procedury
Test2
.
2.
Dodaj do programu z ćwiczenia 1 procedurę
Test1
, która wywołuje procedurę
Test2
. Zmień procedurę obsługi zdarzenia
OnClick
komponentu
Button
tak,
żeby wywoływała ona procedurę
Test1
zamiast
Test2
.
3.
Napisz program wyświetlający w komponencie
Memo
20 razy tekst „Będę od
dzisiaj słuchał się mamy”.
4.
Stwórz rekord zawierający następujące dane o pracownikach: imię, nazwisko,
adres, data zatrudnienia oraz pole zawierające informację, czy dany pracownik
jest ubezpieczony.
98
Część I
98
C:\WINDOWS\Pulpit\Szymon\Delphi 4 dla każdego\02.doc