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 oJak 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ólNa 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.