MFF UK / Ústav teoretické fyziky / Tomáš Ledvinka
Přednášky
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
  Úvod
  Programy a algoritmy
  Píšeme program
  Píšeme program II
  Procedury a funkce
  Malujeme funkce
  Chyby. Typy I.
  Typy II. Pole a Záznamy
  Pole II.Řetězce.Soubory.
    With a Case
    Pole, zarážky etc.
    Dynamická pole
    Řetězce
    Text a spol
  Gnuplot.Interpolace...
  Matice. Velké O...
  Fronta,Zásobník. Postscript
  Bin. soubory, ...
  Ukazatele,Objekty, ...
Počítačová algebra
Klasická elektrodynamika (2.r)
Vybrané partie OTR

Cvičení
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
Teoretická mechanika (2.r)
Klasická elektrodynamika (2.r)


Věda
. . . . . . . . . . . . . . . . . . . . . . . . . .
Diskové zdroje v OTR
Hyperbolické systémy v OTR


Kontakt
. . . . . . . . . . . . . . . . . . . . . . . . . .
Email
Konzultační hodiny


Ostatní
. . . . . . . . . . . . . . . . . . . . . . . . .
Mallorca
Ze společnosti

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.

  • První položka pole s volným koncem má index nula.
  • Na počátku je High(Pole) = -1, takže ani ta není k dispozici
  • Po provedení SetLength(Pole,N) je poslední prvek pole Pole[N-1]
  • Protože SetLength musí najít dostatčně velký kus volné paměti na souvislé uložení pole, může se při změně délky provádět kopírování starých hodnot na nové místo.
  • Nové prvky vzniklé po SetLength mají obecně nedefinované hodnoty, výjimkou jsou pole řetězců.
  • Původní místo zůstává nevyužito až dokud se pro něj nenajde použití při nějaké další operaci SetLength

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

  • libovolné pole reálných čísel
  • dynamické pole reálných čísel
  • pole zkonstruované přímo na místě aktuálního parametru a zapsané jako [Vyraz,Vyraz,...,Vyraz]
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).

.