SOISK - SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Tomasz Puchała

Rekordy pascal

 

Rekordy :

 

Rekordem nazywamy strukturę  złożoną z elementów niekoniecznie tego samego typu. Elementy rekordu, nazywane polami, są wskazywane przez swoje nazwy. Rekordy są bardzo użyteczne przy posługiwaniu się kompletami danych różnego typu. Pojęcie typ rekordowy odpowiada strukturze formularza, służącego do zapisywania danych. Na przykład komplet danych o studencie mogą stanowi_ : nazwisko, nr. indeksu, nazwa grupy i rok urodzenia. Dane te są różnego typu, ale stanowi_ logiczną całość  odnoszącą  się do jednego studenta, wygodnie jest więc manipulować nimi jako jednym obiektem. Umożliwiają to typy rekordowe. Opis typu rekordowego zawiera listę pól między słowami kluczowymi record oraz end. Lista pól składa się z ciągu sekcji oddzielonych od siebie średnikami. Sekcja ma budowę podobną do deklaracji zmiennych i składa się z ciągu identyfikatorów (będą to identyfikatory pól ), po których następuje dowolny typ określający typ tych pól.

 

 

Rekordy są bardzo elastyczną strukturą danych. Typ rekordowy jest używany do opisu obiektów złożonych o strukturze niejednorodnej tj. takich,  których części składowe zawierają dane różnych typów. Za przykład można podać strukturę informacji o książce w bibliotece. Zamiast deklarować kilka zmiennych opisujących element katalogu jak poniżej:

 

var  Tytul  :  array [1..50]  of char;

        Autor :  array [1..30] of char;

         Cena :  Real;

         Ilegz  :  0..100;

         Status : char;

 

rekordy umożliwiają przechowywanie związanych ze sobą danych w jednej strukturze która mogłaby być zapisana dla powyższego przykładu następująco :

 

 

TYPE   InfoBibl  =  RECORD

Tytul, Autor  :  Array[1..30] OF  CHAR;

Cena  :  Real;

IlEgz  :  0..100 ;

Status :  Char

                                 END;

 

VAR

        Ksiazka  :  InfoBibl ;

 

Z powyższego przykładu widać, że rekord jest strukturą danych, składającą się z ustalonej liczby składowych zwanych polami. Pola te mogą być różnych typów. Każde pole danych ma zwi_zany z nim typ danych. Pola Tytul, Autor i Status w powyższym przykładzie mają typ znakowy; pole Cena typ rzeczywisty a pole Ilegz typ okrojony  1..100. Rekord może mieć dwie części o różniących się strukturach : część stałą, która zawiera pola zawsze dostępne i część zmienną, grupującą kilka możliwych wariantów. Definicja typu rekordowego z częścią stałą  ma postać

 

 

TYPE  T  =  RECORD

                      Pierwsza lista identyfikatorów pól  :  T1  ;

Druga lista identyfikatorów pól      :  T2  ;

.

.

n-ta lista identyfikatorów pól         :  Tn

END;

 

gdzie T jest identyfikatorem nowego typu rekordowego, a T1, T2,.....,Tn są identyfikatorami typów danych lub opisami typów danych.

Zmienna ksiazka zadeklarowana w przykładzie jest typu rekordowego i ma pięę pól :


Tytul, autor, cena, ilegz i status. Każde z tych pól jest składową zmiennej książka która może przechowywać dane odpowiedniego typu, określonego w definicji typu rekordowego InfoBibl. Rekord jest strukturą danych o dostępie bezpośrednim. Oznacza to, że możliwy jest dostęp do każdego pola rekordu bez przeglądania pól poprzedzających. Odpowiednikiem zmiennej indeksowanej dla tablic jest w przypadku rekordów  deskryptor lub inaczej zwany desygnatorem pola  Deskryptor pola służy do wskazywania konkretnego pola  rekordu. Wskazuje on pole o podanym identyfikatorze w danej zmiennej rekordowej.  Pole rekordu jest identyfikowane przez desygnator (oznacznik) o postaci : NR.NP, gdzie NR jest nazwą rekordu, a NP - nazwą pola. Tak więc pola rekordu książka identyfikujemy (w instrukcjach czytania, przypisania, sprawdzania, wydruku, etc.) desygnatorami :

 

               ksiazka.tytul,   ksiazka.autor,   ksiazka.cena,   ksiazka.ilegz,   ksiazka.status.

 

Każde pole danego rekordu musi mieć unikatową nazwę, a te same nazwy pól mogą wystąpić w różnych definicjach typu rekordowego lub w różnych deklaracjach zmiennych rekordowych tego samego typu. Desygnatory pól są używane w programie podobnie jak zmienne.

Do pól rekordu ksiazka mozemy wpisywac wartosci instrukcjami przypisania :

 

ksiazka.tytul  :=  'Organizacja maszyn cyfrowych ' ;

ksiazka.autor :=  'Yaochan Chu                            ' ;

ksiazka.cena  :=  150.0  ;

ksiazka.ilegz  :=  10  ;

ksiazka.status :=  'C'  ;

 

lub instrukcjami czytania  :

 

Readln  ;  {nowa linia wejscia }

FOR  I  :=  1  TO  30  DO  IF  NOT  Eoln

                                         THEN  Read(ksiazka.tytul[I])

                                          ELSE   ksiazka.tytul[I]  :=  ' '  ;

Readln  ;  {nowa linia wejścia }

FOR  I  :=  1  TO  30  DO  IF  NOT  Eoln

                                        THEN  Read(ksiazka.autor[I])

                                         ELSE  ksiazka.autor[I]  :=  ' '  ;

Readln  ;  {nowa linia wejscia}

Read(ksiazka.cena,ksiazka.ilegz,ksiazka.status)  ;

 

Jeśeli zmienne rekordowe są tego samego typu,  np. ksiazka1, ksiazka2, ksiazka3 :  InfoBibl, to można kopiować całe rekordy  ; np :

ksiazka2  :=  ksiazka1

lub zamieniać miejscami zawartość rekordów  :

 

ksiazka2  :=  ksiazka1  ;  ksiazka1  :=  ksiazka3  ;  ksiazka3  :=  ksiazka2  ;

 

Uwaga  : Jeśeli zmienne są różnych typów rekordowych, ale zawierają pola tego samego typu, to można przepisać  ( kopiować ) zawartości pól.

 

 

                      

 

 


PRZYKłADY DEFINICJI TYPÓW REKORDOWYCH :

 

 

    TYPE

(a)          data              =          record

                                                    dzien :  1..31;

miesiac:  1..12;    

rok :  1900..1990   

end;

 

 

(b)         punkt      =     record

x, y :  real

end;

 

 

(c)          okrag      =     record

promien :  real;

srodek :  punkt

end;

 

 

(d)         student    =     record

nazwisko :  array [1..20]  of  char ;

nrid :  80000..120000;

grupa :  array [1..4]  of  char;

rokur :  1950..1970

end;

 

Przy powyższych definicjach typów oraz deklaracjach :

 

var    urodziny :  data;

P, Q :  punkt;

Circle:  okrag;

Kowalski :  student;

semestr ;  array [1..150]  of  student;

 

możliwe są przykładowe deskryptory pól :

 


urodziny.dzien

P.y

Circle.srodek.x

Kowalski.nazwisko

semestr[123].nrind

Kowalski.nrind   


          Przykłady stosowania rekordów :

 

(a)    wczytanie daty urodzin :

 

read(urodziny.dzien, urodziny.miesiac, urodziny.rok)

 

 

(b)   wydruk wspóórzędnych punktu

 

writeln('  x  =  ',P.x, 'y  =  ', P.y)

 

 

 

(c)    wybór studenta o najmniejszym numerze indeksu

 

min  :=  semestr[1].nrid;

for  i  :=  2  to  150  do

              if  min  <  semestr[i].nrind

              then  min  :=  semestr[i].nrid;

writeln('  indeks o najmniejszym numerze  :  ' , min)

 

 

INSTRUKCJA WIĄŻĄCA :

 

 


(a)   with  urodziny  do

             read(dzien, miesiac, rok)

 

 

 

(c)      with  Kowalski, Q  do

              begin

                   nrind  :=  87612;

                    rokur :=  1966;

                    writeln(x,'  ', y)

               end                          

 

 

 

            

 

(c)    with  Circle  do

           with  srodek  do

               read(x,y)  

 

(e)      with  Circle.srodek  do

              write(x,y)

 

 

(b)    with  Circle  do

             begin

                  read(promien);

                  srodek  :=  P

              end


Instrukcja wiążąca

 

Instrukcja wiążąca jest instrukcją pomocniczą, ułatwiającą zapis deskryptorów pól odnoszących się do tej samej zmiennej rekordowej albo do kilku zmiennych rekordowych różnych typów.

Instrukcja wiążąca  łączy (wiąże) identyfikatory pól występujące w instrukcji zapisanej po słowie kluczowym do ze zmiennymi wypisanymi po słowie kluczowym with (z). Oznacza to, że w instrukcji wewnętrznej można zastąpić deskryptory pól identyfikatorami pól, jeśli odpowiednie zmienne wymieniono wcześniej na liście instrukcji wiążącej. Zagnieżdżona instrukcja with jest szczególnie przydatna przy odwoływaniu się do pól zmiennych rekordowych zagnieżdżonych. Jako kolejne zmienne tej instrukcji występują wtedy rekordy kolejnych stopni zagnieżdżeń

 

Konflikty nazw

 

Może się zdarzyć  że nazwa pola w rekordzie jest taka sama jak nazwa jakiejś zmiennej w programie. Dopuszczalne jest również, że w dwu różnych typach rekordowych występują identyczne identyfikatory pól.  Dopóki  nie używa się instrukcji wiążącej sytuacja jest jednoznaczna. Pojedynczy identyfikator odnosi się zawsze do zmiennej, natomiast identyfikator pola może wystąpić  tylko po kropce, wewnątrz deskryptora pola. W tym jednak przypadku identyfikator zmiennej występujący w deskryptorze pola przed kropką jednoznacznie rozstrzyga, w której zmiennej rekordowej zawiera się wskazane pole. Sytuacja się komplikuje z chwilą zastosowania instrukcji wiążącej, gdyż w jej obrębie deskryptor pola redukuje się do identyfikatora pola,  który niczym nie różni się od identyfikatora zmiennej. Jedna nazwa oczywiście nie może jednocześnie oznaczać dwu różnych obiektów

 

Uwaga : Jeśli identyfikatory zmiennej i pola są takie same, to identyfikator występujący wewnątrz  instrukcji wiążącej odnosi się zawsze do pola rekordu, a nie do zmiennej. Mówimy, że identyfikatory pola wprowadzone przez instrukcję wiążącą  przesłaniają  inne identyfik.

         

Jeśli wewnątrz instrukcji wiążącej znajduje się inna instrukcja wiążąca, to identyfikatory        pól wprowadzone przez instrukcję wewnętrzną przesłaniaj_ także identyfikatory pól               wprowadzone przez instrukcję zewnętrzną (o ile wystąpi konflikt identyfikatorów pól)

 

Jeśli instrukcja wiążąca zawiera listę zmiennych rekordowych, to odpowiednie identyfikatory pól są wprowadzone w kolejności tych zmiennych, tzn. ostatnio wprowadzone przesłaniają w przypadku konfliktu wcześniejsze.

 

 

 

 

 

 

 

 

 

 

 

 


Instrukcja wiążąca  (WITH) - zagnieżdżona

 

TYPE

             Tstan   =   record

                                        Predkosc  :   Integer  ;

Punkt  :   record

X,Y   :   Real

                                                        end

                               end ;

 

var  Stan   :   Tstan  ;  {zmienna globalna }

 

procedure   InitA   ;

    begin

        with   Stan   do

            with   Punkt   do

                                      begin

        Predkosc  :=  0 ;

                     X  :=  1.0  ;

              Y  :=  1.0  ;

                end

     end ;  {InitA}

 

procedure   InitB  ;

    begin

        with  Stan,  Punkt  do

begin

Predkosc   :=  0  ;

X   :=  1.0  ;

Y   :=  1.0

end


end ;  {InitB}                                                                    Rekord z Wariantami

 

W zwykłym rekordzie liczba i typy pól są dla danego typu ustalone a pola zawsze dostępne poprzez deskryptory  pól. Rekord z wariantami zawiera część zmienną, grupującą kilka możliwych wariantów pól. Warianty te mogą różnić się liczbą składowych i ich typami Wybór wariantu potrzebnego w danym momencie oblicze_ odbywa się programowo, poprzez nadanie odpowiedniej wartości tzw. polu wyróżnikowemu.

Z praktyki wiadomo, że w formularzach występują specyficzne rubryki wypełniane w określonych sytuacjach. Np. rubryka 'nazwisko rodowe' wypełniana jest tylko przez zamężne kobiety. Część powierzchni druku bywa zatem nie w pełni wykorzystana. Opisanej sytuacji odpowiada odmiana typu rekordowego zwana rekordem z wariantami.

 

Definicja typu  rekordowego z częścią stałą  i zmienną ma postać :

 

T   =   RECORD

              definicje pól stałych  {część stała}

               CASE   pole znacznikowe    :  T1   OF

               Pierwsza lista stalych wyboru  : (Pierwsza lista pól);

                Druga lista stalych wyboru     : (Druga lista pól) ;

                .

                .

                .

                n-ta lista stalych wyboru  :  (n-ta lista pól)

             END  ;

 

gdzie  : pole znacznikowe  :  T1  OF  jest selektorem wariantu, ponieważ wartość  pola              znacznikowego, umieszczona na liście stałych wyboru, determinuje wybór wariantu.

 

 

Przykład :

 

type   Tdata   =   record

                              Rok,Mies,Dz   :   Longint;

                           end;

 

          Tosob   =   record

Nazw             :   string[30] ;

Imie                :   string[12] ;

ImRodz          :   string[20] ;

DataUr      :   Tdata ;

case  Plec   :  Char of

                                   'K'  :   (NazwRod  :  string[30]) ;

                                   'M'  :  ()

                 end;

 

const

             Liczba   =  100 ;

 var

              Osoby   :  array[1..Liczba]  of  Tosob ;


type wartoscdelty   =   (dodatnia, rownazeru, ujemna) ;

         zespolone   =   record

                                    re, im   :   real

                                 end;

          rownaniekwadratowe   =   record

   a,b,c   :   real  ;

                    delta  :   real  ;

 case  d  :  wartoscdelty  of

                   dodatnia  :  (x1,x2  :  real)  ;

    rownazeru  :  (x0  :  real )  ;

    ujemna  :  (z1,z2  :  zespolone)

                                                      end;

 

var  rk  :  rownaniekwadratowe ;                                                                                  

 

 

Zbiory:

Typ zbiorowy jest najprostszym typem strukturalnym języka. Zbiór pascalowy jest strukturą złożoną z elementów typu wskazanego przez programistę. Typ zbiorowy definiujemy w następujący sposób :

type t = set of T

gdzie :   t   -   nazwa typu zbiorowego,

T   -   identyfikator typu bazowego, który musi być typem prostym

Zmienną typu zbiorowego ( zbiór) definiujemy jako :

var   z   : t               lub         var   z   :   set   of T

Wartościami zmiennej z są wszystkie podzbiory zbioru T.

Przykłady definicji typów zbiorowych :

type

(a)                        kolor          =   (trefla, kara, kiery, pliki);
ręce
            =   set   of  kolor;

(b)                        litery          =   'a'..'z';

dobre         =   set   of litery;

(c)            dzielniki    =   set   of   1 ..20;

(d)            rumby        = set of (N,NE, E, SE, S, SW, W, NW);

(e)              kwiat           =   (lwiapaszcza, stokrotka, czubatka, nagietek, złocień,

bratek, dzwonek, chaber, mak, goździk, rezeda ); kwiatylet    =   set of kwiat;

Przykłady zmiennych typu zbiorowego :

var

ręka    :   ręce;

(d)                       dźwięczne   :   set   of 'a'..'z';

(e)                         trasa 1, trasa2   :   rumby;

(f)                         wspolnedzielniki   :   dzielniki;

(g)                          bukiet, wiązanka   :   kwiatylet;

Nadanie w programie wartości zmiennej typu zbiorowego polega na tym że zapisuje te zmienne jako listy elementów typu bazowego ujętych w nawiasy kwadratowe np. opierając się na wcześniejszych definicjach mazna zapisać :

bukiet := [stokrotka, czubatka, złocień];

ręka     := [kara, kiery];

         wspolnedzielniki := [1..2,5];

 

Operacje na zbiorach

Na typie zbiorowym określone są następujące operatory :

*    -       przecięcie (iloczyn zbioróe )

+    -       suma zbiorów;

różnica zbiorów;

in    -       należenie do zbioru;

=    -       równość zbiorów;

<>   -       nierówność zbiorów;

<=  -       zawieranie zbiorów;

Przykłady :

1)    - iloczyn dwóch zbiorów :

laka := [stokrotka, czubatka, nagietek]; bukiet := [nagietek, bratek, gozdzikj]; wiązanka := laka * bukiet;

Wartością zmiennej wiązanka jest [nagietek]

2)  - suma dwóch zbiorów :

bukiet := [stokrotka];

wiązanka := [czubatka, nagietek, mak, chaber ];

laka := bukiet + wiązanka

Wartością zmiennej laka jest: [stokrotka, czubatka, nagietek, mak, chaber ] 3)     -   operator in należenie do zbioru

Wyrażenie

mak in [chaber, mak, dzwonek]

przyjmuje wartość true (bo mak należy do zbioru [chaber, mak, dzwonek])

natomiast wyrażenie

goździk in [chaber, mak, dzwonek] przyjmuje wartość false

W pascalu można jawnie wypisać elementy danego zbioru, ujmując je w nawiasy kwadratowe. Otrzymujemy w ten sposób wartość zmiennej typu zbiorowego. Zakładając wcześniejsze definicje typów i deklaracje zmiennych możemy zapisać :

(a)         ręka   := [pliki, kara, trefle];

(b)        dźwięczne   :=   ['d', 'g', V];

if znak in dźwięczne then writeln(' OK ')

                                  else   writeln(' inna')

(c)    trasal   :=   [ ];

trasa2   :=   trasal   +   [N, W, S, E]

(d)        dzielnikil   :=   [1..2,7];
wspólnedzielniki   :=   dzielniki 1* [1, 7, 11]

(e)         read(k, 1);

if [k, 1] <= wspólnedzielniki

 then   writeln (' dobre dzielniki')

Przykład programu z zastosowaniem zmiennych typu zbiorowego :

Na dwóch kartkach narysowane jest po n figur o k bokach (3 <= k <= 10). Znaleźć figury o tej samej liczbie boków, które są na obu kartkach.

Program iloczynfigur (input, output);

const n = 5;

type figura = 3.. 10;

kartka = set of figura; var A, B, C : kartka;

i, k : integer;

Begin                                               

A:=[];B:=[];

writeln('Podaj ',n,' elementów zbioru A '); for i := 1 to n do

    begin     {wczytanie elementów do zbioru A }

read(k); A := A + [k] end;

writeln(' Podaj ',n,' elementów zbioru B1);

 for i :=  1  to n do

begin     {wczytanie elementów do zbioru B  }

read(k); B := B + [k]

 end;

C := A * B;    {znalezienie czesci wspólnej }

 write('Czesc wspólna zbioru to :');

for k := 3 to 10 do   {drukowanie elementów należących do C }

if k in C then write(k:3); 

  writeln

end.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

Ta strona internetowa została utworzona bezpłatnie pod adresem Stronygratis.pl. Czy chcesz też mieć własną stronę internetową?
Darmowa rejestracja