Tablice.



Tablice (ang. ARRAYS) są to struktury złożone z ustalonej liczby elementów tego samego typu, który może być zarówno typem prostym lub łańcuchowym, jak i typem strukturalnym.
Za pomocą tablic są reprezentowane regularne układy danych, np. wektory i macierze. Dostęp do poszczególnych elementów tablic uzyskuje się za pomocą indeksowania. Indeksem może być dowolne wyrażenie, którego wartość jest zgodna w sensie przypisania z typem indeksowym. Dopuszczalny zakres indeksów jest podany w definicji tablicy.

Można tworzyć tablice o dowolnej liczbie wymiarów. Jednowymiarowa tablica to jedna kolumna o pewnej ilości wierszy (lub jak ktoś woli jeden wiersz o pewnej ilości kolumn), dwuwymiarowa posiada pewną ilość kolumn i pewną ilość wierszy, trójwymiarowa posiada jeszcze głębokość. Kolejnych wymiarów nie możemy sobie już niestety wyobrazić, ponieważ postrzegamy świat w trzech wymiarach, ale oczywiście można takie tablice tworzyć.



Deklarowanie tablic wygląda następująco :

1. Jednowymiarowe :
VAR x : ARRAY[1..n] OF Typ;
2. Wielowymiarowe (w przykładzie dwu-) :
VAR x : ARRAY[1..n, 1..m] OF Typ;
lub
VAR x : ARRAY[1..n] OF ARRAY[1..m] OF Typ;
Dla jednowymiarowej pierwszą zmienną jest x[1], drugą x[2], ostatnią x[n].

Dla dwuwymiarowej pierwszą zmienną z pierwszej kolumny jest x[1, 1], z drugiej kolumny x[1, 2], ostanią z ostatniej kolumny x[n, m]. Oczywiście pojęcie kolumny i wiersza jest tutaj umowne.

Pierwsza zmienna może posiadać także inny numer (np. 0 czy 12). Należy tylko odpowiednio ją zadeklarować. Dopuszczalne jest także numerowanie innymi typami porządkowymi, np. literami z tablicy ASCII :
VAR x : ARRAY['A'..'Z'];
ale oczywiście trzeba ujmować te znaki w apostrofy.



Przy okazji deklarowania tablic wynika pewien problem. Mianowicie dowolna Pascal'owa struktura danych musi mieścić się w ramach bloku pamięci o długości do 65 536 bajtów. Ponadto, ponieważ wszystkie zmienne statyczne Turbo Pascal'a umieszczane są w tym samym segmencie, ich sumaryczna wielkość również nie może przekroczyć wspomnianej liczby. Problem ten można ominąć stosując tablice wskażników i dynamiczne przydzielanie pamięci na dane.



Odwołanie się do elementu tablicy ma postać :

1. Jednowymiarowej :
Nazwa_tablicy[Indeks]
2. Dwuwymiarowej :
Nazwa_tablicy[Indeks_1][Indeks_2]


Gdy zamierzamy wykorzystywać tablice w programach, warto zdefiniować sobie typ tablicowy :
TYPE Tab = ARRAY [1..n] OF Typ;
umożliwi to nam działania na tablicach w procedurach i funkcjach.



Przykład :

{$R-,S-}
PROGRAM Porzadkowanie_Liczb_Rosnaco_Malejaco;

USES Crt;

TYPE Tab = ARRAY[1..2598] OF Integer;

VAR a    : Tab;
    n, i : Word;
    Zn   : Char;

PROCEDURE Losuj(Var x : Tab; l : Word);
Begin
  For i:=1 To l Do x[i]:=Random(100);
End;

PROCEDURE Wypisz(x : Tab; l : Word; t : String);
Begin
  WriteLn;
  WriteLn(t);
  For i:=1 To l Do Write(x[i]:0, ' ');
  WriteLn;
End;

PROCEDURE QuickSort(Var A: Tab; Lo, Hi: Integer); { Sortowanie QuickSort }

  Procedure Sort(l, r: Integer);
  Var i, j, x, y: Integer;
  Begin
    i:=l;
    j:=r;
    x:=a[(l+r) DIV 2];
    Repeat
      While a[i] < x Do i:=i+1;
      While x < a[j] Do j:=j-1;
      If i <= j Then
       Begin
         y:=a[i];
         a[i]:=a[j];
         a[j]:=y;
         i:=i+1;
         j:=j-1;
       End;
    Until i > j;
    If l < j Then Sort(l, j);
    If i < r Then Sort(i, r);
  End;

Begin; { QuickSort }
  Sort(Lo,Hi);
End;

PROCEDURE Sort_Mal(Var x : Tab; l : Word); { Sortowanie b_belkowe }
Var P : Boolean;
    B : Integer;
Begin
  Repeat
    P:=True;
    For i:=l DownTo 2 Do
      If x[i] > x[i-1] Then
        Begin
          B:=x[i];
          x[i]:=x[i-1];
          x[i-1]:=B;
          P:=False;
        End;
  Until P=True;
End;

BEGIN
  ClrScr;
  WriteLn('                                  PROGRAM : ');
  WriteLn('                            Porzadkowanie Liczb. ');
  WriteLn;
  Write('Podaj ile liczb losowac : ');
  ReadLn(n);
  Randomize;
  Losuj(a, n);
  Wypisz(a, n, 'Wylosowane liczby :');
  QuickSort(a, 1, n);
  Wypisz(a, n, 'Liczby uporzadkowane rosnaco :');
  Sort_Mal(a, n);
  Wypisz(a, n, 'Liczby uporzadkowane malejaco :');
  Zn:=ReadKey;
END.





Rekord jest to połączenie danych różnych (niekoniecznie) typów w pewną całość. Pozwala na wygodne posługiwanie się takim kompletem jak jedną daną.

Deklaracja rekordu ma postać :
Var Kolega : RECORD
               Imie, Nazwisko     : String;
               Wiek, Waga, Wzrost : Byte;
             END;
Podobnie jak w wypadku tablic lepiej jest zadeklarować nowy typ :
TYPE Rek : RECORD
             Imie, Nazwisko     : String;
             Wiek, Waga, Wzrost : Byte;
           END;
VAR Kolega : Rek;
Teraz w zmiennej Kolega mamy zmienne jego dotyczace. Aby sie do nich odwolac trzeba wpisac :
Kolega.Nazwa_zmiennej:=Cos_tam;
lub
WITH Kolega DO
  BEGIN
    Imie:=Jakies_imie;
    Nazwisko:=Jakies_nazwisko;
    ...
    Wzrost:=Jakis_wzrost;
  END.
w drugim przypadku operujemy na wszystkich polach danego rekordu jednocześnie.



Obie te struktury danych (tablice i rekordy) można połączyć. Można więc zbudować zarówno tablicę, której elementami są rekordy, jak i rekord, którego polami są tablice. Np. :
VAR Magazyn : ARRAY[1..100] OF RECORD
                                 Nazwa : String;
                                 Ilość : Word;
                                 Cena  : Real;
                               END;

VAR Sklad : RECORD
              Nazwa : ARRAY[1..100] OF String;
              Ilość : ARRAY[1..100] OF Word;
              Cena  : ARRAY[1..100] OF Real;
            END;
W zasadzie obie powyżej zdefiniowane zmienne pozwalają opisać to samo : 100 różnych towarów w magazynie, jednak bardziej naturalna jest pierwsza. Bowiem opisuje ona tablicę stu towarów, każdy z tych towarów można czasem potraktować jako niezależną jednostkę. Rozwiązanie drugie jest sztuczne. Poszczególne właściwości towarów są ze sobą powiązane jedynie indeksem w tablicy. Zamiast 100 towarów mamy 100 nazw, 100 cen i 100 informacji o ilości. W pierwszym przypadkku raz wybieramy pozycję w tablicy i wiemy wszystko o danym towarze, w drugim - wybieramy trzy razy i musimy pamiętać, jaka jest zależność miedzy indeksami kolejnych danych.



Przykład :


PROGRAM Rekordy;

USES Crt;

TYPE Osoba = RECORD
               Imie, Nazw : String[15];
               Adres      : String[50];
               Tel        : String[10];
             END;
     Tab  = ARRAY[1..35] OF Osoba;

Var x  : Tab;
    n  : Byte;
    i  : Integer;
    Zn : Char;
	
PROCEDURE Wpisz(Var a : Tab; n : Byte);
Begin
  ClrScr;
  WriteLn('Dane osoby nr ', n:3);
  Write('Podaj imie     : ');
  ReadLn(a[n].Imie);
  Write('Podaj nazwisko : ');
  ReadLn(a[n].Nazw);
  Write('Podaj adres    : ');
  ReadLn(a[n].Adres);
  Write('Podaj telefon  : ');
  ReadLn(a[n].Tel);
End;

PROCEDURE Wypisz(a : Tab; n : Integer);
Begin
 ClrScr;
 Write('Osoba nr ', n:3);
 WriteLn;
 With a[n] Do
  Begin
   WriteLn;
   WriteLn('NAZWISKO : ', Nazw);
   WriteLn('IMIE     : ', Imie);
   WriteLn('ADRES    : ', Adres);
   WriteLn('TELEFON  : ', Tel);
  End;
 WriteLn;
 Zn:=ReadKey;
End;

BEGIN
  ClrScr;
  Write('Podaj liczbe obsob : ');
  ReadLn(n);
  For i:=1 To n Do Wpisz(x, i);
  For i:=1 To n Do Wypisz(x, i);
END.