Opowieść o programowaniu w Adzie



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

Operacje na tablicach


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

· Atrybuty 'first, 'last, 'length i 'range (opisane w poprzednich rozdziałach). w przypadku typów tablicowych bez okreslenia rozmiaru zwracają odpowiednie wartości indeksu podtypu typu rodzicielskiego.

· Operacje logiczne (not, and, or, xor), wykonywalne jedynie dla jednowymiarowych tablic złożonych z elementów typu boolean; tablice te muszą być tego samego typu i tej samej długości (zob. program pr38).

· Konkatenacja (&) określona dla jednowymiarowych tablic tego samego typu.

· "Wycinanie" fragmentów z tablicy (ang. array slicing) określone dla tablic jednowymiarowych
type tablica is array(integer range 1..10) of integer;

t1:tablica:=(others=>6);

t2:tablica:=(others=>8);
t1(1..3):=t1(2..4); --tu "wycinamy" fragmenty

put(t1(2..8));


· Operacja przypisania (:=) - przypisać sobie można tablice tego samego typu i rozmiaru

· Konwersja typów. Tablica może być przekonwertowana do tablicy innego typu tylko wówczas, gdy obie mają ten sam rozmiar, typ składowych oraz te same lub konwertowalne odpowiednie typy indeksów.


type typ1 is array (positive range 1..10) of integer;

type typ2 is array (integer range 1..10) of integer;

t1 : typ1 := (others=>0);

t2 : typ2;

t2:=t1; -- niewykonalne - niezgodność typów

t2:=typ2(t1); -- wykonalne dzieki konwersji

t1:=typ1(t2); -- wykonalne dzieki konwersji
· Relacje <, <=, >, >= - wykonalne dla jednowymiarowych tablic o elementach typu dyskretnego. Tablice muszą być tego samego typu. Porównywanie odbywa się element po elemencie, od lewej do prawej, do momentu wykrycia składowych o różnych wartościach lub do wyczerpania sie elementów w którejś tablicy. Jeżeli napotkana została różniąca tablice składowa, za "większą" uznawana jest ta z tablic, w ktorej wymieniona wyżej składowa ma większą wartość. Jeżeli nie wykryto różnic, natomiast składowe jednej z tablic zostały wyczerpane, jako "większa" przyjmowana jest tablica dłuższa.
type typ1 is array (positive range 1..3) of integer;

t1,t11 : typ1;


t1 := (1,2,4);

t11 := (1,2,0);

put( t1>t11 ); -- wypisze TRUE

put( t1(1..2) > t1(1..3)); -- wypisze FALSE


· Test równości (=, /=). Można porównywać tablice tego samego typu. Dwie tablice są równe, gdy mają tę samą ilość składowych, a odpowiednie składowe obu tablic są jednakowe.

· Test przynależności tablicy do podtypu (in). Testowane w ten sposób tablica i podtyp muszą należeć do tego samego typu bazowego. Wynik jest typu boolean - true, gdy testowana tablica ma dla mażdego z wymiarów taki sam zakres indeksu jak podtyp. do którego przynależność testujemy, false w przeciwnym przypadku.


type macierz is array (positive range <>,

positive range <>) of float;

subtype macierz_3_na_3 is macierz(1..3,1..3);

subtype macierz_2_na_2 is macierz(1..2,1..2);

subtype tez_macierz_2_na_2 is macierz(2..4,1..3);
m2: macierz(1..2,1..2);

m3_1, m3_2: macierz_3_na_3;


put(m2 in macierz_2_na_2); -- wypisze TRUE

put(m3_1 in macierz_2_na_2); -- wypisze FALSE

put(m2 in tez_macierz_2_na_2); -- wypisze FALSE

Rekordy


Poznana w poprzednich rozdziałach złożona struktura danych - tablica - składała się z elementów jednego typu. Możliwe jest również tworzenie struktur, w których typ każdej ze składowych może być inny. Taką złożoną strukturą danych jest rekord. Podobnie jak w przypadku tablic, do rekordu (przechowującego np. imię i nazwisko osoby - dane typu łańcuchowego, jej rok urodzenia i wzrost - dane typu positive itp) możemy zarównoodwoływać się za pomocą pojedynczego identyfikatora, jak i działać na poszczególnych jego składnikach. Kolejną analogią są agregaty rekordów, które - podobnie jak w przypadku tablic - pozwalają na przypisanie wartości równocześnie wszystkim składowym (tu zwanym polami). Także i tu można - jak w tablicach stosować notację pozycyjną lub nazywaną.

Rekordy "zwykłe" (bez wyróżników)


Typ rekordowy definiujemy następująco:
type nazwa_typu_rekordowego is record

pole_1 : typ_pola_1 ;

...


pole_n : typ_pola_n ;

end record;


Pola jednego typu możemy zadeklarować równocześnie, oddzielając ich nazwy przecinkami, np.
type punkt_plaszczyzny is record

x,y : float;

end record;
type osoba is record

imie: string (1..15);

nazwisko: string(1..30);

rok_urodzenia: positive;

wzrost: positive;

stanu_wolnego: boolean;

end record;
Zmienne danego typu deklarujemy w zwykly sposób:
student : osoba;

punkt_A : punkt_plaszczyzny;


zaś wartości przypisujemy im bądź używając kolejno poszczególnych pól rekordu - do których odwołujemy się poprzez nazwę zmiennej rekordowej i oddzieloną od niej kropką nazwę pola rekordu (student.imie, punkt_A.x) - jak w poniższym przykładzie,
student.imie:="Grzegorz ";

student.nazwisko:="Brzeczyszczykiewicz ";

student.rok_urodzenia:=1974;

wzrost:=201;

stanu_wolnego:=true;
punkt_A.x:=2.0;

punkt_A.y:=-1.1;


bądź za pomocą agregatu rekordu, w którym możemy zastosować notację pozycyjną (wartości poszczególnych pól wpisujemy w kolejności występowania tych pól w definicji typu rekordowego)
punkt_A:=(2.0,-1.1);

student:=("Grzegorz ", "Brzeczyszczykiewicz ", 1974, 201, true);


lub notację nazywaną:
punkt_A:=(x=>2.0, y=>-1.1);

student:=

(imie=>"Grzegorz ", nazwisko=>"Brzeczyszczykiewicz ", wzrost=> 201, rok_urodzenia=>1974, stanu_wolnego=>true);
Wówczas, jak widać, kolejność składników nie ma znaczenia.
Podobnie jak w przypadku agregatów tablic, w niektórych sytuacjach można w agregatach rekordow używać znaku | oraz słowa others . Oczywiście odnosić się one mogą tylko do komponentów jednego typu:
punkt_A:=(others=>0.0);

punkt_A:=(x|y=>0.0);


Poprawne są również agregaty rekordów użyte w poniższym przykładzie:
type miasto is record

wojewodztwo:string(1..2);

odleglosc_od_Warszawy, odleglosc_od_stolicy_wojewodztwa:natural;

ilosc_mieszkancow_w_tys:natural;

end record;
type miasto1 is record

wojewodztwo:string(1..2);

nadawana_rejestracja:string(1..2);

odleglosc_od_Warszawy, odleglosc_od_stolicy_wojewodztwa, il_mieszkancow_w_tys:natural;

end record;
m1,m2:miasto;

m:miasto1;


...

-- przyklady dla typu miasto


m1:=(wojewodztwo=>"WA",others=>50);

m1:=(wojewodztwo=>"WR", odleglosc_od_stolicy_wojewodztwa=>10, others=>300);

m1:=(wojewodztwo=>"RA", odleglosc_od_Warszawy|odleglosc_od_stolicy_wojewodztwa=>80, others=>20);

m1:=("WA",10,others=>20);


-- przyklady dla typu miasto1
m:=(wojewodztwo|nadawana_rejestracja=>"PL", others=>40);

m:=(odleglosc_od_Warszawy|odleglosc_od_stolicy_wojewodztwa=>0, il_mieszkancow_w_tys=>10,others=>"WA");


Jak widać słowo others występuje zawsze na końcu agregatu rekordu.

W agregatach rekordów, inaczej niż w przypadku tablic, niedozwolone jest natomiast używanie zakresów (..). Tak więc


punkt_A:=(1..2=>3.0);
jest zapisem nieprawidłowym.
Możliwe jest łączenie w jednym agregacie notacji pozycyjnej i nazywanej (przy czym występować one muszą w tej właśnie kolejności):
type xxx is record

x,y,z:integer;

end record;
a:xxx;
a:=(1,2,z=>3); -- zapis prawidłowy

a:=(x=>1,2,3); -- błąd


Nadawanie wartości zmiennym rekordowym może odbywać się również w inny sposób. Otóż typom rekordowym (jako jedynym w Adzie95) można nadać wartość początkową już w momencie definiowania tych typów:
type punkt_ekranu is record

x : natural range 0..80 := 0;

y : natural range 0..120 := 0;

end record;


type osoba is record

imie,nazwisko : string(1..20) := (others=>' ');

wiek : integer := 0;

end record;


(możliwe jest również nadanie wartości początkowych tylko niektórym polom rekordu):
type pracownik is record

imie, nazwisko : string(1..20) := (others=>' ');

staz_pracy : integer;

end record;


I tak na przykład każda z deklarowanych zmiennych typu punkt_ekranu będzie miała składowe o wartości 0, chyba że postanowimy inaczej:
p : punkt_ekranu; -- m.x i m.y mają wartość 0

q : punkt_ekranu := (1,2); -- m.x=1, m.y=2


Należy pamiętać, że zmienne (dowolnego typu), którym nie została nadana wartość początkowa, posiadają już w chwili rozpoczęcia wykonywania programu pewną wartość, stanowiącą interpretację zawartości komórek pamięci przeznaczonych do przechowywania tej zmiennej. Nieznajomość tego faktu może być przyczyną pisania programów dających bardzo dziwne wyniki...
Predefiniowanymi operacjami określonymi dla typów rekordowych są podstawienie (:=) i porównywanie (=, /=). Oczywiście operacje te możemy wykonywać jedynie na elementach należących do tego samego typu.

Dla zmiennych p1, p2 typu punkt_ekranu podstawienie


p1:=p2;
jest odpowiednikiem wykonania kolejno instrukcji
p1.x:=p2.x;

p1.y:=p2.y;


Podczas operacji porównywania rekordów porównywane są ich kolejne pola.
Oprócz deklarowania zmiennych możemy deklarować stałe należące do danego typu rekordowego. Czynimy to w standardowy sposób:
type punkt_ekranu is record

x: natural range 0..80:=0;

y: natural range 0..120:=0;

end record;


type punkt_plaszczyzny is record

x,y:float;

end record;
gorny_rog_ekranu : constant punkt_ekranu := (0,0);

poczatek_ukladu_wspolrzednych : constant punkt_plaszczyzny

:=(0.0, 0.0);
(zauważmy, że wartość stałej należy podać niezależnie od tego, czy określiliśmy wartość początkową dla danego typu).

W zadeklarowanych w ten sposób stałych typu rekordowego każda ze składowych jest traktowana jako

stała:
gorny_rog_ekranu.x := 3; -- błąd, x jest stałą
Niemożliwe jest natomiast zadeklarowanie jako stałych poszczególnych składowych rekordu:
type jakis_typ is record

a: constant integer := 3; -- niedozwolone

b: float;

end record;


(zobacz jednak podrozdział Rekordy z wyróżnikami).
A oto praktyczny przykład wykorzystania typów rekordowych:

-- dzialania na liczbach zespolonych


with ada.text_io,ada.float_text_io;

use ada.text_io,ada.float_text_io;


procedure pr43 is
type zespolona is record

re,im:float;

end record;

i: constant zespolona := (re=>0.0, im=>1.0);

a,b : zespolona;

sprzezenie_a,sprzezenie_b,suma,roznica,iloczyn,

iloraz :zespolona;

mian:float;


begin

put_line("Podaj liczbe zespolona a : ");

put("a.re : ");get(a.re);

put("a.im : ");get(a.im);

put_line("Podaj liczbe zespolona b : ");

put("b.re : ");get(b.re);

put("b.im : ");get(b.im);
suma:=(a.re+b.re,a.im+b.im);

roznica.re:=a.re-b.re;

roznica.im:=a.im-b.im;

iloczyn:=(re=>a.re*b.re-a.im*b.im, im=>a.re*b.im+a.im+b.re);

mian:=b.re**2+b.im**2;

iloraz.re:=(a.re*b.re+a.im*b.im)/mian;

iloraz.im:=(b.re*a.im-a.re*b.im)/mian;

sprzezenie_a:=(re=>a.re,im=>-a.im);

sprzezenie_b:=(b.re,-b.im);

new_line(2);

if a=b then

put_line("Liczby a i b sa rowne");

else

put_line ("Liczby a i b nie sa rowne");



end if;

new_line;

put_line("Liczby sprzezone do : ");

put("a : "); put(sprzezenie_a.re,aft=>2,exp=>0);

if sprzezenie_a.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(sprzezenie_a.im),aft=>2,exp=>0);

put_line(" i");

put("b : "); put(sprzezenie_b.re,aft=>2,exp=>0);

if sprzezenie_b.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(sprzezenie_b.im),aft=>2,exp=>0);

put_line(" i");

new_line;

put_line("Wyniki dzialan : ");

new_line;

put("a + b = ");put(suma.re,aft=>2,exp=>0);

if suma.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(suma.im),aft=>2,exp=>0);put_line(" i");

put("a - b = ");put(roznica.re,aft=>2,exp=>0);

if roznica.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(roznica.im),aft=>2,exp=>0);

put_line(" i");

put("a * b = ");put(iloczyn.re,aft=>2,exp=>0);

if iloczyn.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(iloczyn.im),aft=>2,exp=>0);

put_line(" i");

put("a / b = ");put(iloraz.re,aft=>2,exp=>0);

if iloraz.im>=0.0 then put(" +");

else put(" -");end if;

put(abs(iloraz.im),aft=>2,exp=>0);

put_line(" i");
end pr43;

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


©absta.pl 2016
wyślij wiadomość

    Strona główna