home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1997 #3
/
amigamamagazinepolishissue03-1
/
ma_1995
/
03
/
ami041.txt
< prev
next >
Wrap
Text File
|
1997-04-06
|
11KB
|
424 lines
/* >...< pogrubiê i nie zmieniaê tytuîu!*/
siEdem
<a>Rafaî Wiosna
<txt>Witam wszystkich zwolenników E w siódmym juû wydaniu naszego
cyklu. Rozpocznë bez zbëdnych wstëpów, przypominajâc o tym, ûeby
dla rozluúnienia mózgownicy zapuôciê jakiô dobry muzak w tîo. Tym
razem polecam krâûek Tori Amos "Under The Pink".
W dzisiejszym odcinku rozwinë przedstawianie zestawu komend,
rzâdzâcych przebiegiem programu. W poprzednich dwóch odcinkach
wyjaôniîem zasadë obsîugi bîëdów, jak i konstrukcjë SELECT, teraz
przyszîa pora na...
<sr>IF
<txt>Instrukcje warunkowe sâ jednymi z podstawowych konstrukcji
uûywanych w programowaniu. To wiekopomne stwierdzenie nie wymaga
chyba ûadnego komentarza. Przyjrzyjmy sië, "jak sië to robi w E":
<l>IF warunek_1
instrukcje_1
ELSEIF warunek_2
instrukcje_2
ELSE
instrukcje_3
ENDIF
<txt>Moûna to przetîumaczyê jako:
^* Jeôli 'warunek_1' jest speîniony (tzn. w wyniku daje TRUE lub
dowolnâ niezerowâ wartoôê), to wykonaj 'instrukcje_1'.
^* Jeôli 'warunek_1' nie jest speîniony (tzn. w wyniku daje FALSE
lub wartoôê zero), NATOMIAST 'warunek_2' jest speîniony, wykonaj
'instrukcje_2'.
^* Jeôli 'warunek_1' oraz 'warunek_2' nie sâ speînione, to wykonaj
'instrukcje_3'.
Czëôê ELSEIF moûe byê powtarzana wiele razy. Natomiast czëôê ELSE
moûna ominâê (wtedy nie bëdzie ûadnej reakcji na niespeînienie
warunku), ale jeûeli jest, MUSI byê ona umieszczona na samym
koïcu konstrukcji, zaraz przed zamkniëciem bloku IF...ENDIF.
Natomiast czëôci ELSEIF moûe byê dowolna liczba, ale muszâ byê
zawarte w bloku instrukcji IF...ELSE, co znaczy, ûe nie mogâ
wystëpowaê w czëôci ELSE.
Innâ formâ zapisu instrukcji warunkowej jest:
<l>IF warunek THEN instrukcja_1 ELSE instrukcja_2
<txt>Uûywajâc tej konwencji, nie moûna wykorzystywaê ELSEIF oraz
wszystko naleûy umieôciê w jednej linii.
Aby przybliûyê konstrukcjë IF...ELSEIF...ELSE...ENDIF, przytoczë
kilka przykîadów jej uûycia:
<l>
IF x>0 THEN x:=x+1 ELSE x:=0
IF x>0
x:=x+1
ELSE
x:=0
ENDIF
IF x=0 THEN WriteF('x to zero\n')
IF x=0
WriteF('x to zero\n')
ENDIF
IF x<0
Write('x jest ujemne\n')
ELSIF x>2000
Write('x jest za duûe\n')
ELSIF (x=2000) OR (x=0)
Write('Wartoôê graniczna x\n')
ENDIF
IF x>0
IF x>2000
WriteF('Za duûe x\n')
ELSE
WriteF('Dobre x\n')
ENDIF
ELSE
IF x<-800 THEN WriteF('Za maîe x\n') ELSE Write('Ujemne, ale dobre x')
ENDIF
<txt>W ostatnim przykîadzie zastosowano tzw. zagnieûdûone bloki
warunkowe (tzn. IF...ENDIF wewnâtrz innego bloku IF...ENDIF). Dla
lepszego zaznaczenia tej sytuacji, a takûe do podkreôlenia
czytelnoôci warto stosowaê wciëcia. Wtedy nie bëdzie problemów z
rozróûnieniem zagnieûdûonych instrukcji ELSE (tzn. do którego
IF-a sië stosuje).
W tym miejscu naleûy zwróciê uwagë, ûe warunki zawarte po
instrukcjach IF i ELSEIF nie powinny sië nakîadaê. Spójrzmy na
przykîad:
<l>
IF x>0
WriteF('x jest wiëksze od zera\n')
ELSEIF x>200
WriteF('x jest wiëksze niû 200\n')
ELSE
WriteF('x jest za maîe\n')
ENDIF
<txt>Blok instrukcji po ELSEIF nie zostanie NIGDY wykonany, gdyû
warunki x>0 i x>200 wzajemnie sië na siebie nakîadajâ, a
dokîadniej warunek x>200 wynika z warunku x>0. Proszë zwróciê
uwagë, ûe przy zamianie warunków konstrukcja ta bëdzie dobra.
Konstrukcjë IF...THEN...ELSE (bez ENDIF!) moûna wykorzystaê nie
tylko w blokach warunkowych, ale takûe przy obliczaniu wartoôci.
Oto przykîad:
<l>
IF x>0
y:=x+1
ELSE
y:=0
ENDIF
<txt>Takâ czësto spotykanâ konstrukcjë moûna zastâpiê jednâ liniâ
kodu úródîowego:
<l>
y:=(IF x>0 THEN x+1 ELSE 0)
<txt>Umieszczenie IF...THEN...ELSE w nawiasie nie jest niezbëdne,
ale poprawia czytelnoôê kodu programu. Taki zapis konstrukcji
warunkowej róûni sië od przedstawionego wczeôniej gîównie jednâ
rzeczâ: tutaj instruckja ELSE jest niezbëdna.
Teraz czas na omówienie pëtli.
<sr>FOR
<txt>Pëtle pozwalajâ na wielokrotne wykonywanie serii instrukcji.
Najprostszâ formâ pëtli jest pëtla FOR, szeroko znana z BASIC-a.
Jeôli, nie wiadomo czemu, chcesz wypisaê na ekranie wszystkie
liczby od jednego do stu, moûesz to zrobiê na dwa sposoby: albo
wklepaê je rëcznie, zdzierajâc klawiaturë i palce, albo napisaê
prosty program, który bëdzie uûywaî pëtli FOR:
<l>
PROC main()
DEF x
FOR x:=1 TO 100
WriteF('\d ', x)
ENDFOR
WriteF('\n')
ENDPROC
<txt>Pamiëtaj o wpisaniu spacji po \d w czwartej linii! Po
skompilowaniu zobaczysz na ekranie wielce zajmujâce rzâdki cyfr,
tak jak chciaîeô. Program dziaîa nastëpujâco:
^* Definiowana jest zmienna lokalna o nazwie x (lokalna, gdyû
definicja jest w ôrodku procedury).
^* Nastëpnie instrukcja FOR rozpoczyna pëtle i przyporzâdkowuje
zmiennej x wartoôê poczâtkowâ, czyli 1.
^* Drukowana jest liczba, bëdâca wartoôciâ zmiennej x.
^* Instrukcja ENDFOR koïczy pëtlë, dodaje jeden do zmiennej x i
sprawdza, czy przekroczony zostaî limit wartoôci x, okreôlony na
poczâtku pëtli. Jeûeli nie, wykonywany jest skok do pierwszej
instrukcji po FOR, jeûeli tak -- bieg programu nie zostaje
zmieniony. W BASIC-u ENDFOR nazywa sië NEXT oraz wymaga podania
nazwy zmiennej, która ma byê zwiëkszona i sprawdzona. W E nie
przewiduje tego, tutaj ENDFOR zamyka ostatnâ pëtlë otworzonâ
instrukcjâ FOR.
^* Na samym koïcu, ûeby îadnie zakoïczyê wydruk, drukowany jest
znak nowej linii.
Ogólna forma pëtli FOR...ENDFOR jest nastëpujâca:
<l>FOR zmienna := wartoôê_1 TO wartoôê_2 STEP liczba
instrukcje
ENDFOR
<txt>Pamiëtaj, ûe zmiennâ o niezwykle mówiâcej nazwie 'zmienna'
naleûy wczeôniej zdefiniowaê dyrektywâ DEF (to nie BASIC!)
'wartoôê_1'okreôla poczâtkowâ wartoôê zmiennej 'zmienna',
nadawanâ przez FOR przy rozpoczëciu pëtli. 'wartoôê_2' okreôla
limit, którego przekroczenie (tzn. zmienna>wartoôê_2) koïczy
pëtlë. Czëôê 'instrukcje' bëdzie wykonywana aû do przekroczenia
limitu. Opcjonalnie 'liczba' okreôla, ile ENDFOR ma dodaê do
zmiennej 'zmienna' (przed sprawdzeniem limitu). Jeûeli nie
wpiszemy kawaîka 'STEP coôtam', ENDFOR domyôlnie bëdzie dodawaîo
jeden. 'wartoôê_1' i 'wartoôê_2' mogâ byê wyraûeniami, a nie
tylko liczbami, ale w tym wypadku bëdâ obliczone tylko raz, na
samym poczâtku, a wyniki zostanâ potraktowane jako liczby.
'liczba' moûe byê tylko i wyîâcznie staîâ, nie moûe byê
obliczana, ale za to moûe byê ujemna, ale naleûy wtedy pamiëtaê,
ûe zmienia sië warunek koïcowy (wtedy ENDFOR oblicza
zmienna<wartoôê_2). Uwaga: nie moûna napisaê 'STEP 0'.
Tak samo jak IF pëtlë FOR moûna zapisaê w jednej linii:
<l>
FOR zmienna := wartoôê_1 TO wartoôê_2 STEP liczba DO instrukcja
<txt>Od tradycyjnego zapisu róûni sië tylko tym, ûe po 'DO' moûna
wpisaê tylko jednâ instrukcjë.
<sr>WHILE
<txt>Pëtla WHILE róûni sië od FOR zasadniczo. Najwaûniejszâ
róûnicâ jest to, ûe programista sam okreôla warunek koïczâcy
wykonywanie pëtli. Druga waûna rzecz to fakt, ûe warunek jest za
kaûdym razem obliczany i moûe byê okreôlony logicznie -- TRUE
albo FALSE (co zresztâ kompilator zamienia na odpowiednio 1 i 0).
Warunkiem moûe wiëc byê na przykîad wartoôê zwracana przez jakâô
procedurë systemowâ.
Na przykîad, pasjonujâcy program wypisujâcy na ekranie liczby od 1 do
100 moûna napisaê z wykorzystaniem pëtli WHILE:
<l>
PROC main()
DEF x
x:=1
WHILE x<=100
WriteF('\d ', x)
x:=x+1
ENDWHILE
WriteF('\n')
ENDPROC
<txt>Wyglâda to na mniej efektywnâ konstrukcjë niû FOR...ENDFOR,
ale w tym wypadku to prawda -- do prostych pëtli ze
zwiëkszaniem/zmniejszaniem zmiennej o staîâ wartoôê FOR nadaje
sië lepiej.
Dziaîanie programu jest proste: zdefiniowana zmienna x przybiera
wartoôê 1. Nastëpnie otwierana jest pëtla WHILE...ENDWHILE,
wykonywana DOPÓKI speîniony jest warunek x<=100. W jej ôrodku
wypisywana jest na ekran liczba okreôlona wartoôciâ zmiennej x, a
potem zmienna ta zwiëkszana jest o jeden.
Waûnâ wiadomoôciâ jest fakt, ûe warunek okreôlony w instrukcji
WHILE sprawdzany jest PRZED wykonaniem pëtli. Oznacza to, ûe w
ekstremalnym wypadku pëtla nigdy nie zostanie wykonana! Na
przykîad, gdybyômy w powyûszym programie zmienili warunek na
x>=100, pëtla nie byîaby wykonana, a bieg programu zostaîby
przeniesiony za instrukcjë ENDWHILE.
WHILE ma teû, jak inne omawiane konstrukcje, wersjë jednoliniowâ:
<l>WHILE warunek DO instrukcja
<txt>Waûnym problemem, który pojawia sië przy wykorzystywaniu
pëtli WHILE...ENDWHILE, a jak sië niedîugo okaûe nie tylko wtedy,
jest zagroûenie wejôcia w pëtlë bez wyjôcia. Na przykîad, gdyby
warunkiem WHILE byîo wyraûenie 1<2, instrukcje w ôrodku pëtli
byîyby wykonywane aû do resetu komputera lub zatrzymania programu
w sposób zewnëtrzny (np. poprzez 'zamroûenie' lub 'zabicie'
odpowiedniego tasku programem ARTM). Oczywiôcie przykîad ten jest
bezsensowny, gdyû nikt takiego warunku nie wpisze, ale moûe sië
zdarzyê sytuacja, ûe warunek przybierze takâ postaê po jego
obliczeniu.
<sr>REPEAT
<txt>Pëtla REPEAT...UNTIL jest bardzo podobna do
WHILE...ENDWHILE. Tutaj jednakûe warunek jest obliczany PO
wykonaniu caîej pëtli, w instrukcji UNTIL, która skacze na
poczâtek pëtli wtedy, gdy warunek NIE JEST speîniony. Posîuûmy
sië znowu nieômiertelnym programem 'Wypisz_Wszysykie_Liczby
v1.0':
<l>
PROC main()
DEF x
x:=1
REPEAT
WriteF('\d ', x)
x:=x+1
UNTIL x>100
WriteF('\n')
ENDPROC
<txt>Przy porównaniu dwóch ostatnich wersji tego programu widaê
subtelnâ róûnicë miëdzy REPEAT...UNTIL a WHILE...ENDWHILE.
Najwaûniejszâ róûnicâ jest fakt, ûe pëtla zostanie wykonana co
najmniej raz.
Przykîadem zastosowania WHILE w "prawdziwym" programie,
korzystajâcym z systemu operacyjnego Amigi, moûe byê pëtla
oczekujâca na wiadomoôci IDCMP. Jednoczeônie bardzo îadnie ona
ilustruje wykorzystanie IF i ELSEIF:
<l>
REPEAT
mes:=Gt_GetIMsg(wnd.userport)
type:=mes.class
IF type=IDCMP_MENUPICK
info:=mes.code
menupick(info) /* procedura obsîugujâca sytuacjë, gdy uûytkownik wybraî coô z menu */
ELSEIF (type=IDCMP_GADGETDOWN) OR (type=IDCMP_GADGETUP)
gadget:=mes.iaddress
info:=g.gadgetid
gadetaction(info) /* procedura obsîugujâca sytuacjë, gdy uûytkownik wcisnâî jakiô gadûet */
ELSEIF type=IDCMP_REFRESHWINDOW
Gt_BeginRefresh(wnd)
Gt_EndRefresh(wnd,TRUE)
ENDIF
Gt_ReplyIMsg(mes)
UNTIL type<>IDCMP_CLOSEWINDOW
<txt>Taka albo podobna pëtla stanowi zwykle najczëôciej
wykonywany fragment programu komunikujâcego sië z uûytkownikiem
za pomocâ GUI (graficznego interfejsu).
<sr>*
<txt>Ooops, ale sië zapëdziîem. Dobra wiadomoôê! Dotarîa juû do
Polski wersja 3.1a Amiga E, a w niej SOURCE LEVEL DEBUGGER!
Niestety, zmiejszono limit wielkoôci kodu wynikowego,
generowanego przez kompilator w wersji nie zarejestrowanej, z 12
do 8 KB. A widzisz, nie trzeba byîo sië ociâgaê z kupnem
rejestrowanej wersji E, to tylko 40 zielonych papierków (35 --
jeôli masz Internet)...
<przyp>Literatura: Jason R. Hulance, plik 'Beginners.guide'
rozprowadzany z Amiga E 3.x.