home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1997 #3
/
amigamamagazinepolishissue03-1
/
ma_1995
/
06
/
ami071.txt
< prev
next >
Wrap
Text File
|
1997-04-07
|
13KB
|
434 lines
/* wyraûenia zawarte w >...< proszë pogrubiê */
10 RAZY E
<a>Rafaî Wiosna
<txt>Tym razem bez zbëdnych wstëpów przystâpimy do omawiania
nowego typu danej:
<sr>Listy
<txt>Stanowiâ podstawë jëzyka LISP. Moûna je traktowaê jako
ciâgi, których elementami sâ nie znaki (CHAR), ale wskaúniki
(LONG, czyli liczby 4-bajtowe -- longi). Zupeînie jak ARRAY OF
LONG, tablica wskaúników. Listy majâ jednak të przewagë nad
tablicami, ûe ich rozmiar moûe byê zmieniony. Mówiâc dokîadniej,
rozmiar E-list moûe byê zmieniony, gdyû podobnie jak przy
ciâgach, Amiga E dba o definiowane przez uûytkownika listy, a co
za tym idzie, musi gdzieô skîadowaê pewne nadmiarowe informacje
(nie sâ one dostëpne dla uûytkownika). Normalne listy sâ podobne
do, wspomnianych dwa odcinki temu, zwykîych ciâgów -- nie moûna
na nich prowadziê ûadnych operacji, posîugujâc sië specjalnymi
funkcjami, chyba ûe jej opis na to pozwala. W przeciwieïstwie do
ciâgów, lista nie musi zawieraê staîych (ciâg zawsze zawiera
okreôlony napis), jej elementami mogâ byê zmienne.
Listy zapisujemy uûywajâc nawiasów kwadratowych. Wewnâtrz nich,
porozdzielane przecinkami, powinny sië znajdowaê elementy listy.
Po jej zdefiniowaniu zwracany jest wskaúnik, oznaczajâcy
poîoûenie w pamiëci.
Oto pierwszy przykîad z uûyciem listy:
<l>DEF lista:PTR TO LONG, liczba
liczba:=22
lista:=[1,2,3,liczba]
<txt>Jak juû wspomniaîem, lista jest rozszerzonâ wersjâ tablicy
wskaúników. Tak wiëc moûna by byîo napisaê tak:
<l>DEF lista[4]:ARRAY OF LONG, liczba
liczba:=22
lista[0]:=1
lista[0]:=2
lista[0]:=3
lista[0]:=liczba
<txt>Którâ wersjë wybierzesz, zaleûy tylko od Ciebie. Jednak, jak
sië okaûe, korzystanie z list moûe uczyniê Twój program
îatwiejszym do napisania i odczytania (pamiëtaj teû o
komentarzach, bez nich po miesiâcu zupeînie niepotrzebnie
bëdziesz sië zastanawiaî, "co ja chciaîem tu napisaê?"). Poza tym
listy dajâ o wiele wiëcej niû tablice, ale o tym póúniej.
Róûnicë miëdzy zwykîymi listami a E-listami moûna ujâê jednym
zdaniem. E-listy definiujesz w DEF-ach procedury, okreôlajâc jej
elementy potem, zwykîâ listë definiujesz w dowolnym miejscu i od
razu okreôlasz jej elementy. E-listë, jak juû zauwaûyîeô,
definiuje sië w nastëpujâcy sposób:
<l>DEF lista[30]:LIST
<txt>Powyûszy przykîad zdefiniowaî listë o zaskasujâco
oryginalnej nazwie "lista". Moûe ona liczyê maksymalnie 30
elementów (zupeînie jak przy E-ciâgach, tylko pamiëtaj, ûe tu
jeden element to wskaúnik-LONG, a nie bajt-CHAR). Przy okazji
zmienna o nazwie "lista" wskazuje na obszar pamiëci zarezerwowany
przez definicjë.
Listy sâ bardzo pomocne przy tworzeniu tzw. tagów, czyli wîaônie
list. Odsyîam do czwartego odcinka kursu E, gdzie ta kwestia
byîa szeroko omówiona.
Amiga E oferuje programiôcie zestaw funkcji operujâcych na
listach. Podobieïstwo do ciâgów jest znaczne, zarówno w nazwach
funkcji, jak i ich przeznaczeniu. Takûe caîy mëtlik ze zwykîymi
listami i E-listami jest niemalûe taki sam, jak w wypadku ciâgów
i E-ciâgów. Dla przypomnienia: dîugoôê E-ciâgu moûe byê dowolnie
zmieniana przez odpowiednie funkcje, a takûe E-ciâg jest zgodny
"w dóî" z ciâgiem, co oznacza tyle, ûe wszëdzie tam, gdzie
funkcja oczekuje podania zwykîego ciâgu, moûna wpisaê E-ciâg.
Dokîadnie tak samo jest z listami. Wîaôciwie mógîbym przepisaê
poczâtek tego akapitu, zastëpujâc sîowo "ciâg" sîowem "lista"...
Pierwszâ funkcjâ, zwiâzanâ z listami, jest >List(MAX)<. Funkcja
ta (tu kompletne zaskoczenie) rezerwuje w pamiëci miejsce na
E-listë o MAX elementach.
<l>DEF lista[30]:LIST
<txt>to to samo co:
<l>DEF lista:PTR TO LONG
lista:=List(30)
<txt>Funkcja zwraca wskaúnik do obszaru pamiëci, zarezerwowanego
na nowo tworzonâ listë. Moûe teû zwróciê zero (NIL), co bëdzie
oznaczaê, ûe system nie przydzieliî pamiëci ("I'm very sorry, out
of memory"). Pamiëtaj, ûe zawsze naleûy sprawdzaê, czy funkcje
podobne do List(), które rezerwujâ jakiô element w pamiëci, nie
zwracajâ NIL. Inaczej, Twój program moûe spektakularnie zawiesiê
czyjô komputer, chyba ûe stosujesz narzëdzia opracy, czyli
opisane w numerach 12/94 i 1/95 MA programiki do testowania
software (w tym wypadku chodzi o Memoration). Przy okazji:
pamiëê zarezerwowana przez List() jest automatycznie zwalniana
przy wyjôciu z programu.
Nastëpnâ funkcjâ jest >ListCmp(LISTA1,LISTA2,DÎUGOÔÊ=ALL)<, która
porównuje zawartoôê dwóch list lub E-list (lub E-listy i listy).
Trzecim parametrem jest liczba porównywanych elementów list.
Jeûeli go opuôcimy lub wpiszemy "ALL" (co jest wymagane w Amiga E
2.x, dopiero od trójki moûna uûywaê parametrów domyôlnych),
porównane zostanâ wszstkie elementy list. Oto przykîady, dla
których funkcja ListCmp() zwraca TRUE:
<l>ListCmp([1,2,3,4],[1,2,3,4])
ListCmp([1,2,3,4],[1,2,3,7],3)
ListCmp([1,2,3,4,5],[1,2,3],3)
<txt>Zauwaû, ûe w przykîadach uûyîem samych list, nie E-list, ale
w tym wypadku nie ma to wiëkszego znaczenia. Waûny natomiast jest
fakt, ûe ListCmp() porównuje elementy listy jako WARTOÔCI. Tak
wiëc listy zawierajâce wskaúnik do ciâgów, które tak samo
wyglâdajâ:
<l>['blablabla',2,3] i ['blablabla',2,3]
<txt>bëdâ dla ListCmp() RÓÛNE, gdyû pokazane tu ciâgi sâ
reprezentowane przez róûne wskaúniki do nich.
Typowâ funkcjâ jest >ListCopy(E-LISTA,LISTA,DÎUGOÔÊ=ALL)<. Jak
moûna sië domyôliê, dziaîa ona tak samo jak StrCopy() z ciâgami
-- kopiuje (E-)listë okreôlonâ przez drugi parametr do E-listy
okreôlonej pierwszym. Przy okazji, moûna okreôliê teû liczbë
kopiowanych elementów listy (parametr trzeci, domyôlnie --
wszystkie). Oto przykîad pokazujâcy, jak naleûy stworzyê E-listë:
<l>DEF li[7]:LIST, blabla
blabla:=4
ListCopy(li, [1,2,3,blabla])
<txt>W wyniku wykonania powyûszego przykîadu powstanie nowa,
uômiechniëta, czteroelementowa E-lista. Gdyby próbowaê funckcjâ
ListCopy() skopiowaê do E-listy "li" (E-)listë o liczbie
elementów wiëkszej niû siedem, to kompilator sam zadba o to, aby
rozmiar "li", zdefiniowany w DEF-ach, nie zostaî przekroczony.
(No i co na to zaparci zwolennicy asemblera?).
Funkcja >ListAdd(E-LISTA,LISTA,DÎUGOÔÊ=ALL)< dodaje do
istniejâcej E-listy wszystkie (albo i nie) elementy listy,
bëdâcej drugim argumentem funkcji. Tak jak w poprzednim
przykîadzie, trzeci argument oznacza liczbë elementów (w tym
wypadku) dodawanych do E-listy (domyôlnie -- wszystkie).
Kompilator zadba o to, aby zadeklarowany rozmiar E-listy nie
zostaî przekroczony.
Kolejne trzy funkcje nie wymagajâ przykîadów, gdyû sâ niemal
identyczne z fukcjami operujâcymi na (E-)ciâgach.
>ListLen(LISTA)< podaje liczbë elementów (E-)listy, bëdâcej
argumentem funkcji. Podobna do niej jest inna funkcja,
>ListMax(E-LISTA)<, która zwraca maksymalny rozmiar podanej
E-listy. Przydatna jest jeszcze funkcja
>SetList(E-LISTA,DÎUGOÔÊ)<, która okreôla dîugoôê E-listy,
obcinajâc nadmiarowe elementy z tyîu. Zadeklarowana w drugim
argumencie nowa dîugoôê E-listy nie moûe przekraczaê dîugoôci
zadeklarowanej w DEF-ach.
Bardzo przydatnâ funkcjâ jest >ListItem(LISTA,ELEMENT)<. Zwraca
ona wskaúnik do danego elementu (E-)listy. Porównujâc do tablic
moûna stwierdziê, ûe jeûeli "li" jest listâ, to "ListItem(li,3)"
jest odpowiednikiem wyraûenia "li[3]". Oto przykîad
podrëcznikowy:
<l>WriteF(ListItem(['pc-zîom','szmatari','Amiga','jabol'],2))
<txt>wypisze na ekranie nazwë naszego ulubionego komputera. (Przy
okazji wychodzi na jaw, ûe elementy listy numerowane sâ od 0, a
nie od 1). A oto przykîad z ûycia wziëty:
<l>ENUM OKAY,RTOPEN,SCROPEN,WINOPEN,FONTOPEN
PROC main() HANDLE
...
EXCEPT
WriteF('Wystâpiî bîâd \d: \s\n',ListItem(
['nie moûna otworzyê reqtools.library',
'nie moûna otworzyê ekranu',
'nie moûna otworzyê okna',
'nie moûna otworzyê czcionki'],exception))
<sr>Nie tylko LONG
<txt>Jednâ z zalet list jest fakt, ûe nie muszâ one zawieraê
tylko danych typu LONG. Programista moûe w dowolny wîaôciwie
sposób ksztaîtowaê pojedynczy element listy. Moûe to byê dana
typu CHAR, INT, LONG lub typu definiowanego przez uûytkownika.
Najpierw jednak krótkie wyjaônienie tego terminu.
Typ definiowany przez uûytkownika jest okreôlany w Amiga E jako
obiekt (OBJECT). Jest to odpowiednik struktury w C/C++, klasy w
C++ lub rekordu w Pascalu. Nie bëdziemy sië zagîëbiaê w dokîadne
omówienie obiektów, wystarczy krótki przykîad:
<l>OBJECT osoba
imie:PTR TO CHAR
nazwisko:PTR TO CHAR
wiek:BYTE
funkcja:PTR TO CHAR
ENDOBJECT
<txt>Na razie przyjmij bez tîumaczenia fakt, ûe zdefiniowaliômy
nowy typ danej -- "osoba". Skîada sië on z trzech pól,
"osoba.imië" (wzkaúnik), "osoba.nazwisko" (wskaúnik),
"osoba.wiek" (bajt) i "osoba.funkcja" (wzkaúnik). Podobnie jak
zmienne, obiekty moûna definiowaê globalnie (przed "PROC main()"
jak i lokalnie). Wszystkie struktury systemowe sâ obiektami.
No dobra, powróêmy do list. Otóû listë z okreôlonym typem danej
(z angielska -- typed list) definiuje sië przez dodanie ":TYP" do
jej definicji, np.:
<l>[1,2,3,4]:INT
<txt>Oznacza listë o danych typu INT. No i tu sië drogi
rozwidlajâ, gdyû definiujâc takâ listë odcinamy sië od
wymienionych wczeôniej funkcji, operujâcych na (E-)listach. Po
prostu na tym typie list nie bëdâ one dziaîaîy. Ûeby byîo
ômieszniej, dwie listy:
<l>[1,2,3,4] oraz [1,2,3,4]:LONG
<txt>mimo tego, ûe uûywajâ tego samego typu danej, nie sâ ze sobâ zgodne!
Czas na przykîad uûywania "typed lists".
<txt>OBJECT osoba
imie:PTR TO CHAR
nazwisko:PTR TO CHAR
wiek:CHAR
funkcja:PTR TO CHAR
ENDOBJECT
DEF bajty:PTR TO CHAR, mag_amiga:PTR TO osoba, los
PROC main()
bajty:=[1,2,3,4]:INT
mag_amiga:=['Marek','Pampuch',98,'red nacz',
'Rafal','Wiosna',56,'z-ca red nacz',
'Elzbieta','Kozakiewicz',19,'sekr red',
'Roman','Sadowski',73,'gry']:osoba
los:=Rnd(4)
WriteF('Gîodówka Rotacyjna V3.59 (c) 1995 Dyrekcja\n')
WriteF('Dziô gîoduje: \s \s, nasz \s (wiek \d)\n',
mag_amiga[los].imie,
mag_amiga[los].nazwisko,
mag_amiga[los].funkcja,
mag_amiga[los].wiek)
ENDPROC
<sr>Dane statyczne
<txt>Ciâgi i listy (nie myliê z E-ciâgami i E-listami) sâ danymi
statycznymi. Znaczy to, ûe adres w pamiëci jednego z wymienionych
typów danych jest zawsze na poczâtku programu okreôlony. Zwykle
nie musisz sië tym przejmowaê, ale gdy zachce Ci sië stworzyê
tablicë skîadajâcâ sië z list o elementach obliczanych przez
program, zapewne napisaîyô coô takiego:
<l>PROC main()
DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG
FOR i:=0 TO 9
a[i]:=[1, i, i*i] -> BÎÂD!
ENDFOR
FOR i:=0 TO 9
p:=a[i]
WriteF('a[\d] zawiera listë o adresie \d\n', i, p)
WriteF('Drugim elementem tej listy jest \d\n', p[1])
ENDFOR
ENDPROC
Amiga E Compiler/Assembler/Linker/PP v3.1a (c) '91-95 Wouter
lexical analysing ...
parsing and compiling ...
no errors
a[0] zawiera listë o adresie 19748938
Drugim elementem tej listy jest 9
a[1] zawiera listë o adresie 19748938
Drugim elementem tej listy jest 9
a[2] zawiera listë o adresie 19748938
Drugim elementem tej listy jest 9
a[3] zawiera listë o adresie 19748938
Drugim elementem tej listy jest 9
<txt>No i jesteô ugotowany. Tablica "a" zawiera wskaúniki do
trzyelementowej STATYCZNEJ listy! Znaczy to, ûe jej adres jest z
góry okreôlony przez kompilator i sië nie zmienia.
Zaradziê temu problemowi moûna na kilka sposobów, jednak
najproôciej jest uûyê funkcji List(), która dynamicznie
zarezerwuje E-listë. Oto "dobra" wersja programu:
<l>PROC main()
DEF i, a[10]:ARRAY OF LONG, p:PTR TO LONG
FOR i:=0 TO 9
a[i]:=List(3)
ListCopy(a[i],[1, i, i*i])
ENDFOR
FOR i:=0 TO 9
p:=a[i]
WriteF('a[\d] zawiera listë o adresie \d\n', i, p)
WriteF('Drugim elementem tej listy jest \d\n', p[1])
ENDFOR
ENDPROC
Amiga E Compiler/Assembler/Linker/PP v3.1a demo (c) '91-95 Wouter
lexical analysing ...
parsing and compiling ...
no errors
a[0] zawiera listë o adresie 19200232
Drugim elementem tej listy jest 0
a[1] zawiera listë o adresie 19200696
Drugim elementem tej listy jest 1
a[2] zawiera listë o adresie 19200728
Drugim elementem tej listy jest 2
<txt>No i o to chodziîo!
<sr>*
<txt>Na nastëpny odcinek zostawiîem gwóúdú wykîadu z list --
listy îâczone. Tymczasem proponujë poszukaê archiwów CAPUS.LHA i
CAPUS2.LHA. Sâ to zestawy przeróûnych uûytków, utorstwa Capus
André (francuz, "dziëki" czemu niektóre opisy sâ w tym
niezrozumiaîym jëzyku), kaûdy napisany w E, z peînym kodem
úródîowym. Wspaniale nadajâ sië jako materiaî dydaktyczny do
nauki Amiga E. Oprócz tego w archiwum znajdujâ sië gotowe moduîy
(.m) do przeróûnych bibliotek (np. lh.library, nofrag.library,
xpk.library)!!!
Archiwa te moûna znaleúê w Aminecie, w katalogu dev/e, oraz w
naszym redakcyjnym BBS-ie.
<przyp>Literatura: Jason R. Hulance, plik "Beginners.guide"
rozprowadzany z Amiga E 3.x.