Pole s otevřeným koncem (dynamická pole)

Námi používaná verse Pascalu nám umožňuje ještě lepší řešení:


program DynArrTest;

var Hodnoty : array of real;
    x : real;
    kam : integer;
begin
 Writeln('Zadejte libovolný počet kladných reálných čísel');
 Writeln('Zadávání ukončete záporným číslem nebo nulou.');
 
 ReadLn(x);  
 while x>0 do begin
   Kam:=High(hodnoty)+1; //Low(Hodnoty) je 0
   SetLength(Hodnoty,Kam+1);
   Hodnoty[Kam] := x;
   ReadLn(x);
 end;

 Writeln('Načetl jsem ', High(hodnoty)+1, ' čísel. Tady jsou jejich druhe mocniny:');

 for kam := 0 to High(hodnoty) do
   Writeln(Hodnoty[Kam],sqr(Hodnoty[Kam]));

 readln;
end.

Od předešlého se program hlavně liší tím, že pole Hodnoty má jako spodní mez intervalu indexů nulu. Počet prvků pole můžeme měnit procedurou SetLength(Pole,JakDlouhe). Aktuální horní mez zjistíme pomocí funkce High. Dolní mez si můžeme zjistit s pomocí funkce Low, ale bude to vždy nula a nelze ji měnit. Funkce Low a High můžeme použít i pro běžná pole, ale tam nám vrátí konstantu danou příslušnou mezí intervalu indexu, a může to být třeba i znak, když je má příslušné pole typ indexu char.

Následující program má být varováním, že při volání funkce SetLength mohou přestat platit odkazy na původní prvky pole.

program PozorNaNe;

type tCA = array of Char;
var A,B : tCA ;


Procedure UdelejDveVeci(var X : tCA; var c:char; N : integer);
begin
   SetLength(X,N);
   X[0]:='A';
   c:='X';  // tady je ten prusvih, c uz nemusi odkazovat na spravne misto.
end;

begin
   SetLength(A,10);
   SetLength(B,10);

   UdelejDveVeci(A,A[0],10); 
   Writeln(A[0]);            
  
   UdelejDveVeci(A,A[0],100); // Nejspis staci 13
   Writeln(A[0]);             // Uz to pise 'A'

   readln;
end.

Pokud bychom kromě SetLength(X,N) měnili ještě velikost jiných polí, mohlo by se stát, že paramtr c nebude odkazovat do prázdna jako nyní, ale přiřazení c:='X' naruší některé z těchto polí, které po změně velikosti skočilo na paměťovém místě původního pole A.

Pole s otevřeným koncem jako formální parametr

pokud deklarujeme formální parametr typu array of real tak jako v následujícím příkladu, můžeme při volání předat jako hodnotu

program test;

type tDP = array of real;
var    b : array[char] of real;
       c : tDP;

function Soucet(const V:array of real) :real;
var i : integer;
    s : real;
begin
  s:=0;
  for i := low(V) to high(V) do s:=s+V[i];
  Soucet:=s;
end;

begin
  Writeln(Soucet(b));       // vypíše 0 neboť statické pole je inicializováno na 0
  Writeln(Soucet(c));       // vypíše 0 neboť dynamické pole nemá na počátku ani jeden prvek
  Writeln(Soucet([0,1,2])); // vypíše 3
  Readln;
end.

Je třeba roszlišit jeden malý rozdíl mezi předchozími dvěma příklady. V prvním byl parametr typu tCA a šlo tak o dynamické pole. Pro něj je definována operace SetLength. Naproti tomu v druhém případě byl typ formálního parametru array of... . Z minula víme, že formální parametr typu array [interval] of NejakyTyp, není povolen, proto6e by nebyl komaptibilní s žádnou proměnnou a proceduru by nebylo možno vůbec použít. Formální parametr typu array of je tedy moderní konstrukcí určenou k tomu aby bylo možno funkci předat pole s nějakým základním typem ale libovolnými mezemi. S dynamickými poli se shoduje v tom, že Low vrací vždy 0, i když definiční interval byl třeba 1..3 nebo 'a'..'z'. High je tak rovno (délka_pole - 1).