Struktury danych "wielokrotnie złożone"
Nie ma właściwie żadnych ograniczeń w łączeniu ze sobą poznanych już złożonych struktur danych - tablic i rekordów. Możemy zadeklarować tablicę złożoną z tablic, rekord o polu będącym innym rekordem czy tablicą, tablicę złożoną z rekordów... Ilustrują to poniższe przykłady. Zwróćmy uwagę na przedstawiony w nich sposób odwoływania się do elementów danej struktury:
-- przyklad rekordu, ktorego polem jest rekord
with ada.text_io,ada.integer_text_io;
use ada.text_io,ada.integer_text_io;
procedure pr44 is
type data is record
dzien: integer range 1..31;
miesiac: integer range 1..12;
rok: integer;
end record;
type osoba is record
imie:string(1..20):=(others=>' ');
nazwisko: string(1..30):=(others=>' ');
data_urodzenia:data;
end record;
ktos1, ktos2 : osoba;
rr,rm,rd,n:integer;
begin
put_line("Podaj dane dwoch osob:");
new_line;
put_line("OSOBA PIERWSZA");
put("Imie: "); get_line(ktos1.imie,n);
put("Nazwisko: "); get_line(ktos1.nazwisko,n);
put_line("Data urodzenia: ");
put("dzien: "); get(ktos1.data_urodzenia.dzien);
put("miesiac (liczba): ");get(ktos1.data_urodzenia.miesiac);
put("rok: "); get(ktos1.data_urodzenia.rok);
skip_line;
new_line(2);
put_line("OSOBA DRUGA");
put("Imie: "); get_line(ktos2.imie,n);
put("Nazwisko: "); get_line(ktos2.nazwisko,n);
put_line("Data urodzenia: ");
put("dzien: "); get(ktos2.data_urodzenia.dzien);
put("miesiac (liczba): ");get(ktos2.data_urodzenia.miesiac);
put("rok: "); get(ktos2.data_urodzenia.rok);
new_line(4);
put(ktos1.imie);set_col(40);put_line(ktos2.imie);
put(ktos1.nazwisko);set_col(40);put_line(ktos2.nazwisko);
rr:=ktos1.data_urodzenia.rok-ktos2.data_urodzenia.rok;
rm:=ktos1.data_urodzenia.miesiac-ktos2.data_urodzenia.miesiac;
rd:=ktos1.data_urodzenia.dzien-ktos2.data_urodzenia.dzien;
if rr=0 and rm=0 and rd=0 then
put("urodzili sie tego samego roku, miesiaca i dnia");
else
if rr=0 then
put("urodzili sie w tym samym roku");
if rm=0 then
put(", miesiacu ");
if rd=0 then
put("i dniu");
elsif rd>0 then
put("i pierwsza z tych osob jest starsza o ");
put(rd,0);put(" dni");
else
put("i pierwsza z tych osob jest mlodsza o ");
put(abs(rd),0);put(" dni");
end if;
end if;
else
put("roznica rocznikow tych osob: ");put(abs(rr),0);
end if;
end if;
end pr44;
A oto przykład zastosowania tablicy, której składowymi są tablice innego typu:
-- przyklad tablicy tablic
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 pr45 is
type odpowiedzi_do_pytania is array(1..4) of boolean;
type tablica_odpowiedzi is array(1..5) of odpowiedzi_do_pytania;
type pytanie_i_odpowiedzi is array (0..4) of string(1..100);
type tablica_pytan is array(1..5) of pytanie_i_odpowiedzi;
test : tablica_pytan;
odpowiedzi : tablica_odpowiedzi;
podane_odp : tablica_odpowiedzi:=(others=>(others=>false));
op : integer;
punkty : float:=0.0;
begin
--nadanie początkowych wartości
--pytaniom i odpowiedziom
test:=(others=>(others=>(others=>' ')));
test(1)(0)(1..33):="Swiatla drogowe moga byc uzywane:";
test(1)(1)(1..25):="poza obszarem zabudowanym";
test(1)(2)(1..22):="w obszarze zabudowanym";
test(1)(3)(1..53):="poza obszarem zabudowanym, na drogach "&
"szybkiego ruchu";
test(1)(4)(1..85):="w obszarze zabudowanym, lecz tylko na "&
"drogach o dopuszczalnej " &
" predk. powyzej 60 km/h";
odpowiedzi(1):=(true,false,false,false);
test(2)(0)(1..91):="Jadac pasem ruchu dla pojazdow powolnych "&
"i zblizajac sie do jego konca, kierujacy"&
" pojazdem";
test(2)(1)(1..53):="powinien zmienic pas zachowujac szczegolna"&
" ostroznosc";
test(2)(2)(1..52):="posiada pierwszenstwo przed jadacymi pasem"& " sasiednim";
test(2)(3)(1..35):="powinien wlaczyc lewy kierunkowskaz";
test(2)(4)(1..44):="zmieniajac pas jest wlaczajacym sie do "&
"ruchu";
odpowiedzi(2):=(true,false,true,true);
test(3)(0)(1..28):="Wyprzedzanie jest zabronione";
test(3)(1)(1..41):="bezposrednio przed przejazdami kolejowymi";
test(3)(2)(1..40):="na przejazdach kolejowych i tramwajowych";
test(3)(3)(1..43):="bezposrednio przed przejsciami dla pieszych";
test(3)(4)(1..27):="na przejsciach dla pieszych";
odpowiedzi(3):=(true,true,true,true);
test(4)(0)(1..43):="W ktorych miejscach cofanie jest dozwolone:";
test(4)(1)(1..26):="na drodze jednokierunkowej";
test(4)(2)(1..21):="na drodze ekspresowej";
test(4)(3)(1..24):="na jezdni dwukierunkowej";
test(4)(4)(1..15):="na autostradzie";
odpowiedzi(4):=(true,false,true,false);
test(5)(0)(1..69):="Wjazd na skrzyzowanie jest zabroniony, " &
"jezeli wyswietlany jest sygnal";
test(5)(1)(1..8):="czerwony";
test(5)(2)(1..14):="zolty migajacy";
test(5)(3)(1..12):="zolty ciagly";
test(5)(4)(1..81):="zielony, ale warunki ruchu uniemozliwiaja"& " dalsza jazde i opuszczenie skrzyzowania";
odpowiedzi(5):=(true,false,true,true);
--test
put_line(" ------ TEST - PRAWO JAZDY ----- ");
new_line;
put_line("Za kazda prawidlowa odpowiedz czastkowa dostajesz"&
" 0.25 pkt. ");
put_line("Jesli poprawnie odpowiesz na cale pytanie, dostajesz"&
" dodatkowo 1 pkt.");
new_line;
set_col(45);
put_line("Powodzenia!");
new_line(2);
for i in test'range loop
for j in 0..4 loop
if j/=0 then put(j,0);put(')');end if;
put_line(test(i)(j));
end loop;
new_line;
put_line("podaj numery poprawnych odpowiedzi," &
" 0 zakancza podawanie");
for k in podane_odp(2)'range loop
--1..4 (ilosc odp. w pytaniu)
put("> "); get(op);
exit when op=0;
podane_odp(i)(op):=true;
end loop;
new_line;
end loop;
-- zliczanie punktow
for i in odpowiedzi'range loop
for j in odpowiedzi(2)'range loop
if odpowiedzi(i)(j)=podane_odp(i)(j) then
punkty:=punkty+0.25; end if;
end loop;
if odpowiedzi(i)=podane_odp(i) then
punkty:=punkty+1.0;
end if;
end loop;
-- wyniki
put("Uzyskales ");put(punkty,exp=>0,aft=>1);put(" punktow");
end pr45;
A teraz tablica, której elementami są rekordy. Jednym z pól rekordu jest tablica:
-- tablica rekordow
with ada.text_io,ada.float_text_io,ada.integer_text_io;
use ada.text_io,ada.float_text_io,ada.integer_text_io;
procedure pr46 is
type przedmioty is (polski, niemiecki, angielski, matematyka, fizyka, chemia, biologia, geografia, historia, wf);
package przedmioty_io is new enumeration_io(przedmioty);
subtype ocena is integer range 1..6;
type tabela_ocen is array (przedmioty) of ocena;
type uczen is record
imie : string(1..20) := (others=>' ');
nazwisko : string(1..30) := (others=>' ');
oceny : tabela_ocen;
srednia : float;
end record;
klasa : array(1..3) of uczen;
s, sr_klasy : float;
n : integer;
begin
-- wprowadzanie danych uczniow
sr_klasy:=0.0;
for i in klasa'range loop
put_line("Uczen nr " & integer'image(i));
put("Imie: ");get_line(klasa(i).imie,n);
put("Nazwisko: ");get_line(klasa(i).nazwisko,n);
s:=0.0;
for j in przedmioty loop
przedmioty_io.put(j);put(" ");
get(klasa(i).oceny(j));
skip_line;
s:=s+float(klasa(i).oceny(j));
end loop;
klasa(i).srednia:=s/float(przedmioty'pos(przedmioty'last)+1);
sr_klasy:=sr_klasy+klasa(i).srednia;
new_line;
end loop;
sr_klasy:=sr_klasy/float(klasa'length);
for i in klasa'range loop
put(klasa(i).imie);put(klasa(i).nazwisko);
put("Srednia ocen: "); put(klasa(i).srednia,exp=>0); new_line;
end loop;
new_line(2);
put("Srednia ocen klasy: "); put(sr_klasy,aft=>2,exp=>0);
end pr46;
Możliwe jest skrócenie sposobu odwołania do składowej struktury złożonej poprzez jej przemianowanie (ang. renaming). Robimy to w części deklaracyjnej programu pisząc na przykład:
rok1:integer renames ktos1.data_urodzenia.rok;
(deklarujemy nową zmienną wiążąc ją ze składową rekordu - oczywiście muszą być one tego samego typu). Odtąd do roku urodzenia osoby ktos1 mamy dostęp zarówno przez pełną jej nazwę (ktos1.data_urodzenia.rok), jak i przez zmienną rok1.
|