Typy strukturalne w Pascalu.doc

(164 KB) Pobierz
Typy strukturalne, czyli jak przechować więcej danych

TYPY STRUKTURALNE W PASCALU

Typy strukturalne w Pascalu reprezentują 4 rodzaje struktur: tablice, rekordy, zbiory i pliki. Ograniczeniem rozmiaru jest ok. 64 kB pamięci (65520 B).

              Typ tablicowy składa się z ustalonej liczby elementów tego samego typu składowego (prosty lub łańcuchowy) albo strukturalny. Za pomocą tablic przedstawia się regularne struktury danych np. wektory czy macierze. Dostęp do elementów uzyskuje się za pomocą indeksowania, wyrażeniem zgodnym i będącym w zakresie zdefiniowanego typu tablicowego. Np.:

 

Type wektor  =Array [0..100] Of Integer;

macierz2=Array [1..20] Of Array [1..50] Of Real;

macierz3=Array [1..10,1..20,1..30] Of Real;

tablica =Array [Boolean, 1..20,znak] Of Char; {=Array [Boolean] Of Array[1..20] Of Array [znak] Of Char;}

 

Typ rekordowy - rekordem w Pascalu nazywamy złożoną strukturę danych, której składowe, nazywane polami, mogą być różnych typów. Poszczególne pola mogą same być strukturami złożonymi. Definicja typu rekordowego określa dla każdego pola jego typ i identyfikator. Rozpoczyna się słowem kluczowym record, po którym następują deklaracje pól, kończy się słowem kluczowym end; Kolejne deklaracje oddziela się średnikami. Ostatnia z nich może być wariantowa (składa się z kluczowego słowa case wyróżnik of wykaz-wariantów). Przykłady zmiennych rekordowych:

Type data=Record

rok     : Integer;

miesiac : 1..12; {9typy okrojone}

dzien   : 1..31

end;{data}

posiadanie={posiada,nie_posiada};{typ porządkowy}

dana=Record

              nazwisko:String [20];

              imie    :String [15];

              data_ur :data;

              adres   :String[30];

              Case dzieci:posiadanie Of

              posiada    :(data_ur_dziecka:Array[1..10] Of data;

              nie_posiada:(znak:Char)

End;{dana}

 

              Typ zbiorowy jest zbiorem potęgowym danego typu rzeczywistego, tzn. jest zbiorem wszystkich podzbiorów tego typu w tym także typu pustego. Definicja ma postać: type identyfikator-typu = Set Of typ-porządkowy;  Liczba elementów typu porządkowego, będącego typem bazowym w takiej definicji nie może przekraczać 256, przy czym ich liczby porządkowe  muszą należeć do przedziału 0..255. Wartości typu zbiorowego podaje się przez wypisanie listy elementów danego zbioru oddzielonych przecinkami w nawiasach kwadratowych. Zapis [] oznacza zbiór pusty. Np.:

type             

dzien_pracy=Set Of [poniedzialek, wtorek, sroda, czwartek, piatek];

znaki      =Set Of Char;

male_litery=Set Of 'a'..'z';

miesiac    =[sty, lut, mar, kwi, maj, cze, lip, sie, wrz,

              paz, lis, gru];

              z_mies     =Set Of miesiac;

Var              nazwa_mies : miesiac;

              z_nazw     : z_mies;

 

              Typ plikowy jest ciągiem elementów tego samego typu, liczba jego składowych jest zmienna. Reprezentuje fizyczny zbiór danych o dostępie sekwencyjnym. Oznacza to, że aktualnie mamy dostęp do 1 elementu, a do innych można dotrzeć po wykonaniu odpowiednich operacji. Zależy od przebiegu programu, skojarzenia pliku z fizycznym zbiorem danych (na dysku, wyprowadzanych na drukarkę itp). Definicja:

type id_pliku = File Of typ-elementow; id_pliku = File;

typ-elementów oznacza identyfikator dowolnego typu prostego, opis typu porządkowego, strukturalnego lub wskaźnikowego. Istnieje predefiniowany plik tekstowy o nazwie Text, którego elementami są wiersze podzielone na znaki. Na końcu wiersza wstawiona jest para znaków CR/LF (carriage return, line feed = powrót karetki, zmiana linii), koniec pliku znaczy znak ^Z.  Pliki tekstowe służą do obsługi dostępnych zbiorów fizycznych przy pomocy klawiatury, monitora, drukarki. Np.:

type dane   =File Of Integer;

              wyniki =File Of Real;

              complex=Record

                       re, im : Real

                      End;

var daty : File Of data; 

    zesp : File Of complex;

Z punktu widzenia każdego użytkownika tablica jest po prostu ciągiem jednolitych "szufladek" przechowujących dane tego samego typu. Każda szufladka jest identyfikowana numerem - tzw. indeksem - który musi być typu porządkowego (trudno bowiem wyobrazić sobie element tablicy o numerze półtora). Tablice deklarowane są za pomocą słowa kluczowego array (tablica), zaś składnia deklaracji jest następująca:

nazwa_tablicy : array[indeks_dolny..indeks_górny] of typ;

W nawiasach kwadratowych musimy umieścić dwie stałe określające najmniejszy i największy dopuszczalny indeks tablicy. Pamiętajmy, że wartości użyte w deklaracji muszą być znane w momencie kompilacji programu (najczęściej podawane są jawnie, ewentualnie w postaci prostych wyrażeń dopuszczalnych w definicjach stałych). Pascal wymaga określenia rozmiaru tablicy w chwili kompilacji i nie dopuszcza użycia tzw. tablic dynamicznych (o rozmiarze określanym podczas wykonania) Obydwa indeksy mogą mieć dowolne wartości, ale muszą być tego samego typu porządkowego, a górny indeks nie może być mniejszy od dolnego. Zwykle tablice indeksuje się od 1, jak np. tablicę autorów książek:

 

var

 

 

Autorzy : array[1..1000] of string[30];

ale całkowicie normalne są również deklaracje:

 

 

 

var

 

 

Sinusy : array[0..359] of real;

 

 

Odchylka : array[-10..10] of real;

Tablice wcale nie muszą być indeksowane liczbami. Jeśli np. chcemy zliczyć częstość występowania w tekście poszczególnych znaków alfabetu, możemy użyć efektownej konstrukcji

 

var

 

 

Liczniki : array['a'..'z'] of word;

Każdy z elementów takiej tablicy jest licznikiem o pojemności około 65 tysięcy "impulsów", adresowanym za pomocą odpowiedniego znaku alfabetu.

Aby odwołać się do elementu tablicy o danym numerze, musimy użyć składni

nazwa_tablicy[indeks]

gdzie indeks jest numerem żądanego elementu (stałą lub zmienną typu porządkowego o wartości zawartej pomiędzy dolnym a górnym zadeklarowanym indeksem). Aby zatem wyświetlić trzecią z kolei pozycję tablicy autorów, wystarczy użyć instrukcji

writeln(Autorzy[3]);

zaś instrukcja

Autorzy[5] := 'Ernest Hemingway';

ustali nazwisko autora piątej książki w katalogu. W przypadku tablicy liczników znaków odwołania będą wyglądały następująco:

 

{ zwiększy licznik dla znaku o 1 }

{ zwiększy licznik dla znaku o 1 }

 

writeln(Liczniki['a'];

{ wyświetli wartość}

 

 

{ licznika znaków 'a' }

Próba użycia indeksu leżącego poza zadeklarowanym zakresem kończy się na ogół błędem wykonania, o ile opcja kontroli zakresów (Options-Compiler-Range checking) nie została wyłączona (uwaga: domyślnie opcja ta jest wyłączona!). W tym ostatnim przypadku odczyt z tablicy zwróci bezsensowną wartość, zaś zapis może mieć złe skutki (z zawieszeniem komputera włącznie), gdyż wartość zostanie wstawiona w miejsce przeznaczone na coś zupełnie innego.

Dwa główne obszary zastosowania tablic to bazy danych (czyli programy służące do przechowywania i zarządzania informacją opisującą rzeczywiste obiekty, np. książki w bibliotece, towary w hurtowni itp.) oraz oprogramowanie inżynierskie i naukowe, wykorzystujące tzw. wektory i macierze, czyli liniowe i prostokątne tablice liczb. Jak zapisać wektor (czyli liniową lub jednowymiarową tablicę liczb), już wiemy. Przykładowemu wektorowi złożonemu z dziesięciu liczb rzeczywistych

będzie odpowiadała tablica

Wektor : array[1..10] of real

zaś dla prostokątnej tablicy (macierzy) o wymiarach m na n:

 



 

użyjemy deklaracji

Macierz : array[1..M, 1..N] of real

Jak widać, tworzenie tablic odpowiadających dwu- i więcejwymiarowym strukturom danych nie stanowi w Pascalu trudnego zadania. Ogólna składnia deklaracji tablicy wielowymiarowej wygląda tak:

nazwa_tablicy : array[zakres_1, zakres_2, ... zakres_n] of typ

gdzie zakres_k opisuje zakres indeksów dla k-tego wymiaru i ma formę początek..koniec. Dla tablic dwuwymiarowych pierwszy indeks oznacza numer wiersza, zaś drugi - numer kolumny (w pamięci komputera dane przechowywane są wierszami ułożonymi jeden za drugim). Chociaż Pascal nie narzuca ograniczenia na liczbę wymiarów tablicy (jedynymi ograniczeniami są łączny rozmiar elementów, nie mogący przekraczać 65520 bajtów, oraz zakres indeksów, nie mogący wykraczać poza zakres liczb całkowitych), tablic więcej niż dwuwymiarowych używa się bardzo rzadko. Tablice dwuwymiarowe stosowane są przede wszystkim w programach obliczeniowych (realizujących obliczenia tzw. rachunku macierzowego). Aby jednak nie poprzestawać na samym opisie, zademonstruję krótki przykład: oto program pozwalający na wprowadzenie z klawiatury wartości elementów macierzy o wymiarach 3 na 3 i wyświetlający największy wprowadzony element oraz sumę wszystkich elementów leżących na przekątnej i powyżej niej.

 

program Macierz3x3;

 

{ program demonstruje elementarne obliczenia macierzowe }

 

var

 

 

t : array[1..3, 1..3] of real;

{ macierz 3x3 }

 

 

max, sum : real;

{ tymczasowe maksimum i suma elementów }

 

 

i, j : integer;

{ liczniki wierszy i kolumn }

 

 

 

begin

 

{ wczytanie zawartości macierzy }

 

 

for i := 1 to 3 do

 

 

 

for j := 1 to 3 do

 

 

 

 

begin

 

 

 

 

 

write('Podaj element macierzy x[',i,',',j,']: ');

 

 

...
Zgłoś jeśli naruszono regulamin