Opowieść o programowaniu w Adzie



Pobieranie 0.69 Mb.
Strona11/16
Data28.04.2016
Rozmiar0.69 Mb.
1   ...   8   9   10   11   12   13   14   15   16

Tablice


W poprzednim rozdziale ustawialiśmy znaki na ponumerowanych miejscach tworząc łańcuchy. Obecnie poznamy podobną złożoną strukturę danych - tablicę. Tablica jest obiektem złożonym z wielu elementów (tzw. składowych) należących do tego samego typu. Do całej tej struktury odwołujemy się za pomocą pojedynczego identyfikatora. Możemy również odwoływać się do poszczególnych jej składników.

Tablice jednowymiarowe


Tablice mogą byc jedno- i wielowymiarowe. Na początek zajmiemy się tablicami jednowymiarowymi. Mogą być one zadeklarowane jako tzw. anonimowy typ tablicowy
zmienna : array (określenie_indeksu) of typ_składowych;
lub jako typ tablicowy posiadający własną nazwę:
type typ_tablicowy is array (okreslenie_indeksu) of typ_składowych;
co pozwala następnie na deklarowanie zmiennych lub stałych należących do typu_tablicowego.

Określenie_indeksu może mieć jedną z postaci:


dolne_ograniczenie_zakresu .. górne_ograniczenie_zakresu

typ_indeksu

typ_indeksu range

dolne_ograniczenie_zakresu .. górne_ograniczenie_zakresu
przy czym indeks - niezależnie od sposobu jego zadeklarowania - musi należeć do typu dyskretnego (jeśli typ nie jest podany bezpośrednio, przyjmowana jest wartość uniwersalna, np. Universal_Integer).

Oto przykłady deklaracji tablic:


ciag1 : array (1..10) of integer;
ciag : array (integer range 1..10) of float;
n: integer := 7;

type xx is array (n .. 10+n) of float;

x1: xx;
type miesiace is (styczen, luty, marzec, kwiecien, maj, czerwiec, lipiec, sierpien, wrzesien, pazdziernik, listopad, grudzien);

opady_Polska_97 : constant array (miesiace) of float:=(others=>0.0);

type opady is array (miesiace) of float;

opady_Warszawa_98, opady_Lodz_98 : opady;


subtype miesiace_wakacyjne is miesiace range lipiec..wrzesien;

type miejsca is (morze, gory, jeziora, wlasny_dom);

wakacje : array (miesiace_letnie) of miejsca;
type ciag_liczbowy is array (integer range 0..100) of integer;

ciag_A, ciag_B : ciag_liczbowy;


Do elementów tablicy odwołujemy się poprzez nazwę zmiennej tablicowej i wartość indeksu umieszczoną w nawiasach okrągłych. Indeks może być wyrażeniem, stałą lub zmienną.
ciag_A(1) := 12;

put(opady_Lodz_98(styczen));

put(opady_Polska_97(wrzesien));

k:=7;


put(ciag_A(1+k));
Tablica może zostać wypełniona poprzez kolejne przypisywanie wartości poszczególnym jej elementom, jak w przedstawionym przykładzie:
for i in miesiace loop

opady_Warszawa_98(i):=0.0;

end loop;
lub przez użycie tzw. agregatu tablicy (ang. array aggregate), tzn. wartości przypisywanej całej tablicy od razu, a złożonej z wartości poszczególnych jej składowych, np.
wakacje := (morze, gory, jeziora);
Jest to tzw. notacja pozycyjna (ang. positional notation). Poszczególne liczby z agregatu tablicy przypisywane są kolejnym składowym. Stanowi to odpowiednik ciągu instrukcji
wakacje (lipiec) := morze;

wakacje (sierpien) := gory;

wakacje (wrzesien) := jeziora;
Oczywiście ilość elementów w agregacie tablicy musi być równa ilości elementów w samej tablicy.

Oprócz notacji pozycyjnej możemy używać notacji nazywanej (ang. named notation), w której określamy wyraźnie, na które miejsce w tablicy ma być wstawiona dana wartość:


wakacje := (lipiec => morze, wrzesien=>jeziora, sierpien => gory);
Unikamy w ten sposób pomyłek (porządek podstawiania nie ma znaczenia), a poza tym łatwo jest odczytać, jaką wartość przypisaliśmy poszcególnym elementom tablicy. Notacja pozycyjna zezwala ponadto na uzywanie słowa others pozwalającego na nadanie wartości wszystkim elementom, którym nie została ona nadana bezpośrednio:
wakacje : (lipiec => morze, others => wlasny_dom);
Podstawienie takie oznacza, że w lipcu byliśmy nad morzem, zaś pozostałe miesiące wakacji spędziliśmy w domu... Używając tego sposobu można również przypisać jednakową wartość wszystkim elementom tablicy:
wakacje := (others => wlasny_dom);
Można to również zrobić pisząc
wakacje := (miesiace_wakacyjne => wlasny_dom);
albo
wakacje := (lipiec.. wrzesien => wlasny_dom);
Notacja pozycyjna oferuje jeszce kilka możliwości:
ciag_A := (1..3 => 2, others => 0);
(elementy o indeksie 1, 2 i 3 otrzymają wartość 2, pozostałe - wartość 0),
ciag_A := (2|4|6|8|10 => 1, others => 0);
(wyrazy ciągu o numerach parzystych otrzymują wartość 1, pozostałe - 0).
Notację pozycyjną i nazywaną można łączyć tylko w jednym przypadku: gdy w agregacie tablicy wymienimy kolejno pewną ilość wartości składowych (w notacji pozycyjnej), a następnie pozostałym elementom (mającym wyższe indeksy) nadamy taką samą wartość używając others (notacja nazywana):
ciag_A := (1, 12, 0, 3, others => 9);
Zauważmy, że słowo others, jeśli występuje, musi być ostatnią pozycją w agregacie tablicy. Należy również pamiętać, że elementami agregatu tablicy nie muszą byc konkretne wartości, jak w powyższych przykładach, lecz również zmienne, stałe i wyrażenia.
Z tablic możemy "wydobywać" nie tylko pojedyncze elementy, ale również podtablice - fragmenty tablicy wyjściowej (podobnie jak podłańcuchy z łańcucha). Tablice i ich fragmenty wolno nam (o ile należą do tego samego typu) podstawiać, porównywać przy użyciu operatorów = i /=, a także łączyć (operatorem jest wtedy &, podobnie jak dla typu string). Oczywiście podstawiając czy łącząc fragmenty tablic musimy zwracać uwagę na ich rozmiary, w przeciwnym wypadku otrzymamy Constraint_Error. Jeżeli składowe tablic są typu dyskretnego, dozwolone jest również porównywanie ich przy użyciu operatorów <, <=, >, >=.
-- rozne eksperymenty na ciagach:

-- porownywanie, podstawianie...


with ada.text_io,ada.integer_text_io,ada.float_text_io;

use ada.text_io, ada.integer_text_io,ada.float_text_io;


procedure pr36 is
type dni is (pon, wt, sr, czw, pt, sob, nie);
type ciag_dluzszy is array(1..10) of integer;

type ciag_krotszy is array(1..5) of integer;

type ciag_rzeczywisty is array(1..5) of float;

type ciag_wyliczeniowy is array(1..10) of dni;


cd : ciag_dluzszy;

ck1,ck2 : ciag_krotszy;

cr1,cr2: ciag_rzeczywisty;

cw1, cw2: ciag_wyliczeniowy;


begin
cd := (2|4|6|8|10 => 1, others => 0);

ck1:=(others=>7);

ck2:=(others=>7);

cr1:=(others=>3.2);

cr2:=(others=>4.1);

cw1:=(others=>pt);

cw2:=cw1;

-- ck1(1..2):=cd(3..4); -- nie da sie zrobic takiego -- podstawienia (ciagi roznego typu)


ck1(1):=cd(3); -- tak sie da (elementy w ciagach sa

-- tego samego typu)


ck1(1..3):=ck2(2..4); -- tak sie da (ten sam typ tablicowy)

-- tak mozna porownac tablice tego

-- samego typu
if ck1=ck2 then

put_line("tablice - ""krotsze ciagi calkowite"" - rowne ");

else

put_line("tablice - ""krotsze ciagi calkowite"" - rozne");



end if;
if cr1=cr2 then

put_line("tablice - ""ciagi rzeczywiste"" - rowne ");

else

put_line("tablice - ""ciagi rzeczywiste"" - rozne");



end if;
if cw1=cw2 then

put_line("tablice - ciagi dni - rowne ");

else

put_line("tablice - ciagi dni - rozne");



end if;
-- te tablice nie sa tego samego typu,

-- zatem nie mozna ich porownac


-- if ck1(1..2)=cd(1..2) then put("kawalki rowne"); end if;

-- takie porownywanie mozna zrobic

-- tylko dla tablic o skladowych dyskretnych
if ck1>ck2 then

put_line("tablica liczb calkowitych ck1 jest ""wieksza""");

else

put_line("tablica liczb cakowitych ck1 nie jest ""wieksza""");



end if;
if cw1>cw2 then

put_line("tablica dni cw1 jest ""wieksza""");

else

put_line("tablica dni cw1 nie jest ""wieksza""");



end if;
-- niewykonalne - typ float nie jest dyskretny

--if cr1>cr2 then

-- put_line("tablica liczb rzeczywistych cr1 jest ""wieksza""");

--else


-- put_line("tablica liczb rzeczywistych cr1 nie jest ""wieksza""");

--end if;


cr2:=cr1(1..2) & cr2(2..4); -- wykonalne

cw1:=cw1(1..5) & cw2(6..10);
--cw1:=cw1(2..4) & cw2(3..6); -- niewykonalne - niezgodne rozmiary

--ck1:=ck2(1..2) & cd(3..5); -- niewykonalne - niezgodne typy tablic


end pr36;

Dla tablic określone są następujące atrybuty:


zmienna_tablicowa'first zwracający najmniejszą wartość indeksu wdanej tablicy

zmienna_tablicowa'last zwracający największą wartość indeksu wdanej tablicy

zmienna_tablicowa'range zwracający zakres indeksu tablicy (odpowiednik

tablica'first .. tablica'last)

zmienna_tablicowa'length zwracający długość tablicy (ilość jej elementów).
Oto przykład zastosowania atrybutów w praktyce. Chcąc działać na ciągu innej długości wystarczy jedynie zmienić deklarację typu ciag, cała reszta może pozostać bez zmian.

-- sortowanie ciagu liczb calkowitych

-- oraz znajdowanie najwiekszego elementu

-- tego ciagu


with ada.text_io,ada.integer_text_io;

use ada.text_io,ada.integer_text_io;


procedure pr37 is
type ciag is array(1..10) of integer;

c,d:ciag;


pom,max,miejsce_maxa:integer;
begin
put("mozesz wprowadzic ciag liczb calkowitych o dlugosci ");

put(c'length,0);new_line;

put_line("podaj wyrazy ciagu : ");

for i in c'range loop

put("c(");put(i,0);put(")= ");

get(c(i));

end loop;
-- znajdowanie najwiekszej liczby w ciagu

max:=c(c'first);

miejsce_maxa:=c'first;

for i in c'first+1..c'last loop

if c(i)>max then

max:=c(i);

miejsce_maxa:=i;

end if;


end loop;
put("Najwiekszy wyraz w ciagu to "); put(max,0); new_line;

put("Stoi on na miejscu "); put(miejsce_maxa,0);

new_line(3);
-- sortowanie ciagu

d:=c;


for i in d'first+1..d'last loop

for j in reverse i..d'last loop

if d(j)

pom:=d(j);

d(j):=d(j-1);

d(j-1):=pom;

end if;

end loop;



end loop;
put_line("Oto Twoj ciag: ");

for i in c'range loop

put(c(i),0);put(' ');

end loop;

new_line;
put_line("A oto Twoj ciag posortowany: ");

for i in d'range loop

put(d(i),0);put(' ');

end loop;


end pr37;
Szczególnym przypadkiem tablic jednowymiarowych są wektory logiczne (boolowskie) - jednowymiarowe tablice złożone z elementów typu boolean. Oprócz podstawiania i porównywania możemy dokonywać na nich operacji logicznych, używając not, and, or , xor. Wszystkie powyższe operatory (prócz not) wymagają jako argumentów dwóch tablic tego samego typu i długości (not operuje na jednej tablicy). Otrzymujemy w ten sposob agregat tablicy, którego składowe są wynikami wykonania odpowiedniej operacji logicznej na odpowiednich składowych tablic będących argumentami.
-- program ilustruje dzialania

-- na wektorach logicznych


with ada.text_io,ada.integer_text_io;

use ada.text_io,ada.integer_text_io;


procedure pr38 is

package b_io is new ada.text_io.enumeration_io(boolean);

use b_io;

type wektor_logiczny is array(1..4) of boolean;

p,q: wektor_logiczny;

w_and,w_or,w_xor,w_not:wektor_logiczny;


k:positive_count;
begin

p:=(others=>true);

put_line("Podaj wektor q - mozliwe wartosci jego skladowych" &

" to TRUE i FALSE");


for i in q'range loop

put("q(");put(i,0);put(")= ");

get(q(i));

end loop;


w_and:=p and q;

w_or:=p or q;

w_xor:=p xor q;

w_not:=not q;


put_line("A oto wyniki dzialan na wektorach: ");

put("wektor p : ");

k:=13;

for i in p'range loop k:=k+7; set_col(k); put(p(i)); end loop;



new_line;

put("wektor q : ");

k:=13;

for i in q'range loop k:=k+7; set_col(k); put(q(i));end loop;



new_line;

put("wektor not q : ");

k:=13;

for i in q'range loop k:=k+7; set_col(k); put(w_not(i));end loop;



new_line;

put("wektor p and q : ");

k:=13;

for i in w_and'range loop k:=k+7; set_col(k); put(w_and(i));end loop;



new_line;

put("wektor p or q : ");

k:=13;

for i in w_or'range loop k:=k+7; set_col(k); put(w_or(i));end loop;



new_line;

put("wektor p xor q: ");

k:=13;

for i in w_xor'range loop k:=k+7; set_col(k); put(w_xor(i));end loop;


end pr38;

1   ...   8   9   10   11   12   13   14   15   16


©absta.pl 2016
wyślij wiadomość

    Strona główna