Rekordy
Oprócz omawianych już typów strukturalnych takich jak tablice, zbiory i pliki, można jeszcze wyróżnić takie typy złożone jak rekordy oraz obiekty. Obiektom poświęcimy następny wykład.
typ strukturalny +---------+
------------------------>| array |
| ^ +---------+
| +---------+ | | set |
+-->| packed |--+ +---------+
+---------+ | file |
+---------+
| record |
+---------+
| object |--------->
+---------+
Definicja syntaktyczna typu rekordowego, który będziemy
teraz omawiać, jest następująca.
typ rekordowy
-------------->( record )-----------------^-->( end )----->
| |
+-[ Lista pol ]-+
Pola rekordu mogą być dowolnego typu. Jest to cecha, która
różni zasadniczo, rekord od tablicy.
Lista pól | +--[ Cześć stała ]--------------------------------------------------------> | | ^ ^ | ^ | | | | | | | +---( ; )--->[ Część wariantowa ]->+ +-->( ; )--+ | ^ +---------------------------->+Stała część rekordu zbudowana jest z listy nazw (identyfikatorów) pól oraz ich typów. Oddzielają je średniki.
Część stała
-----------------[ Lista nazw ]---( : ) [ typ ]------------->
^ |
| |
+<---------------------( ; )<-----------------+
Każde pole zawiera informację, którą można zawsze uzyskać w ten
sam sposób.
Przykład.
type
Data=record
dzien : 1..31;
miesiac: (St,Lu,Ma,Kw,Ma,Cz,Li,Si,Wr,Pa,Li,Gr);
rok: integer
end;
type
zespolona=record
re, im: real
end;
Osoba=record
Nazwisko: string;
Imie : string;
DataUrodzenia: Data;
plec : (mezczyzna,kobieta);
StanCywilny : (wolny,zonaty,owdowialy,rozwiedziony)
end;
Za pomocą konstruktora rekordowego można utworzyć wartość
danego typu i przypisać ją jakiejś zmiennej tegoż typu.
Jażeli, przykładowo, mamy zmienne
z: zespolona; d: Data; o: Ossoba;to konkretne wartości można przypiszć następująco:
z:=zespolona(1.0.,-1.0);
d:=Data(1,St,1999);
o:=Osoba('Wirth','Chris',Data(18,St,1966),mezczyzna,wolny);
Można to przedstawić na diagramach następująco.
+--------------+ +---------------+ +---------------+
| 1.0 | | 1 | | Wirth |
+--------------+ +---------------+ +---------------+
| -1.0 | | St | | Chris |
+--------------+ +---------------+ +---------------+
| 1999 | | 18| St | 1996|
+---------------+ +---------------+
| mezczyzna |
+---------------+
| wolny |
+---------------+
zespolona z Data d Osoba o
Jak dotrzeć do poszczególnych pól rekordu?
Jeśli zmienna x jest typu rekordowego T, a s jest
nazwą pola rekordu, to
x.s:=xioznacza przypisanie polu s tegoż rekordu, wartości xi. Typ xi i typ pola x rekordu są takie same. W przykładach, które były podane wyżej mamy
typ
z.im (real)
d.miesiac (St, ..., Gr)
o.nazwisko (string)
o.DataUrodzenia (Data)
o.DataUrodzenia.Dzien (1..31)
itd.
(Proszę zwrócić uwagę na złożoność struktury Osoba,
która zawiera Datę, itd. )
var a : array[1..N] of Osoba;
licznik: integer;
begin
licznik:=0;
for i:=1 to N do
if (a[i].plec=kobieta) and (a[i].stancywilny=wolny) then
licznik:=licznik+1;
end;
(* liczba kobiet w stanie wolnym zapisanych w tablicy a *)
Inny sposób dostępu do pól rekordu polega na użyciu instrukcji
wiążącej | with |
Przykład.
var a : array[1..N] of Osoba;
licznik: integer;
begin
licznik:=0;
for i:=1 to N do
with a[i] do
if (plec=kobieta) and (stancywilny=wolny) then
licznik:=licznik+1;
end;
(* liczba kobiet w stanie wolnym zapisanych w tablicy a *)
Konstrukcja with r do s oznacza, że można
używać nazw selektorów pól zmiennej rekordowej r bez
poprzedzania
ich nazwą zmiennej, ponieważ wiadomo, że będą się do niej odnosiły.
Skraca to tekst programu i zapobiega wielokrotnemu wyliczaniu od
nowa składowej indeksowanej a[i].
Poniższy program stosuje strukturę rekordu do reprezentowania
liczb zespolonych
Rekordy z wariantami
Czasami wygodnie jest korzystać z tzw. rekordów z wariantami. Tak jest np. w przypadku współrzędnych punktu płaszczyzny. Czasami potrzebna jest ich postać biegunowa, z czasami kartezjańska. rekordy wariantowe pozwalają na przechowywanie w nich takich lub innych informacji w zależności od sytuacji. Dla rozpoznania wariantu (rodzajy współrzędnych) potrzebujemy dodatkowego wyróżnika, wielkości, która przyjmuje odpowiednie wartości odróżniające występujące sytuacje (tak jak to jest w przypadku współrzędnych kartezjańskich lub biegunowych). Wyróżnik typu nazywa się też polem wariantowym.
[ Czesc wariantowa ]
|
+--( case )-------------------------[ typ pola ]--( of )-->[ wariant ]--->
| ^ wyróżnika ^ |
| | | |
+->[ nazwa ]-->( : )--+ | |
+-( ; )<------+
typ pola wyróżnika
|
-------------->[ Identyfikator typu wyliczeniowego ]----->
wariant
|
+---->[ stała ]---->( : )----( ( )----------------->( ) )----->
^ | | |
| | +->[ Lista ]-+
+----( , )----+ pól
Na podstawie diagramu widzimy, że każdy wariant identyfikowany jest przez
conajmniej jedną stałą. Stałe muszą być różne i muszą być typu
wyliczeniowego zgodnego z typem pola wyróżnika.
Identyfikator pola wyróżnika jest opcjonalny.
Przykład.
type
Wspolrzedne=record
case rodzaj:(kartezjanskie,biegunowe) of
kartezjanskie:(x,y :real);
biegunowe :(r,fi:real)
end;
Nazwą pola znacznikowego jest w tym wypadku rodzaj, a współrzędne mają nazwy
x, y lub r, fi w zależności od rodzaju.
Typ Osoba, który został zdefiniowany poprzednio, zawiera informacje dotyczące
płci osób itp. Można tam również umieścić informację ozaroście,
w przypadku mężczyzn oraz o trzech wymiarach sylwetki kobiecej (Przykład z Wirtha).
Dobrze jest zredefiniowaqć ten rekord tak by rozróżniany był ten fakt.
Zapiszmy:
Przykład.
Osoba=record
Nazwisko, Imie : string;
DataUrodzenia: Data;
StanCywilny : (wolny,zonaty,owdowialy,rozwiedziony);
case plec:(mezczyzna,kobieta) of
mezczyzna: (waga: real;
brodaty: boolean);
kobieta: (wymiary: array[1..3] of real)
end;
Operacje na wariantach najlepiej jest pogrupować w instrukcję
wybiórczą (case), której struktura odzwierciedla strukturę
rekordu z wariantami.
case x.sn of c1: s1; c2: s2; ... cm: sm end;Podam teraz przykład obliczania odległości na płaszczyźnie przy zadanych kartezjańskich lub biegunowych współrzędnych punktów.
Przykład.
(*
podprogram OdlAB oblicza odległość między dwoma punktami
A i B zadanymi w postaci zmiennych a i b typu rekordowego
Wspolrzedne, będącego typem rekordowym z wariantami
(patrz: Iglewski,...)
*)
function OdlAB(a, b: Wspolrzedne): real;
var d: real;
begin
case a.rodzaj of
kartezjanskie: case b.rodzaj of
kartezjanskie: d:=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
biegunowe : d:=sqrt(sqr(a.x-b.r*cos(b.fi))+sqr(a.y-b.r*sin(b.fi))
end
biegunowe: case b.rodzaj of
kartezjanskie: d:=sqrt(sqr(b.x-a.r*cos(a.fi))+sqr(b.y-a.r*sin(a.fi));
biegunowe : d:=sqrt(sqr(a.r)+sqr(b.r)-2*a.r*b.r*cos(a.fi-b.fi))
end;
OdlAB:=d;
end;
Następny przykład został wzięty z podręcznika Turbo Pascal 7,
Language Guide, str. 33.
Przykład.
TWielobok=record X, Y : Real; case Rodzaj : Figura of TProstokat: (Wysokosc,Szerokosc: real); TTrojkat: (bok1,bok2,kat: real); TOkrag: (promien: real) end;
Stałe typu rekordowego
stała rekordowa
|
+-->( ( )--->[ Nazwa pola ]--->( : )---[ stała określonego ]-->( ) )-->
| typu |
+----------------( ; )<------------------------------+
Przykład.
const a: integer=3;
type TPunkt=record X,Y: real end;
TWektor=array[0..1] of TPunkt;
TMiesiac=(Sty,Lut,Mar,Kwi,Maj,Cze,Lip,Sie,Wrz,Paz,Lis,Gru);
TData=record D:1..31; M: TMiesiac; R: 1900..1999 end;
const Poczatek: TPunkt=(X: 0.0, Y: 0.0);
Linia: TWektor=((X:-3.1; Y:1.5), (X:5.8; Y:3.0));
Dzien: TData=(D:2; M:Gru; R:1998);
Pola musimy podawać w takim porządku w jakim pojawiły się w definicji
typu rekordowego.
Jeśli rekord zawiera pola typu plikowego to stałe tego
typu nie mogą być definiowane.
Jeśli rekord posiada warianty, to tylko pola wybranego wariantu
można ustalić.
W przypadku gdy wariant zawiera pole wyróżnika musimy to pole
wyspecyfikować.
File translated from TEX by TTH, version 4.03.
On 16 Oct 2013, 21:50.

