Pole záznamů a úspora paměti

Často se nám stává, že v poli záznamů potřebujeme zaznamenávat proměnné, nadeklarované pomocí klíčového slova record. Klasický příklad představuje seznam zaměstnanců, ale vlastně i každá jiná malá databáze, kvůli které by nestálo za to nutit uživatele, aby si spolu s programem instaloval nějaké dll moduly. Například pole pro evidenci 100 zaměstnanců (max.) by pak mohlo vypadat následovně:

type
  os = record
    jmeno : string[30];
    prijmeni : string[39];
    adresa_ulice : string[59];
    adresa_mesto : string[59];
    psc : string[5];
    telefon : string[15];
  end;

var
  lide : array[0..99] of os;

Při dnešních cenách pamětí to nehraje velkou roli, ale velký rozsah dat se nám vrátí znovu, pokud budeme potřebovat s daty jakkoli manipulovat (například je setřídit). Proto je někdy výhodnější použít dynamicky alokované paměti a v poli držet jen ukazatele na data. Připravíme si obdobný datový typ (os) a ukazatel na něj (uos). V části deklarace proměnných (kapitola var) pak nadefinujeme pole pouze s ukazateli, nikoli s daty (jeden ukazatel má velikost 4 byty).

type
  uos = ^os;    {vyjímka - zde je použití před deklarací přípustné, protože je předem
                 známa velikost v paměti; později u struktur by to jinak ani nešlo napsat}
  os = record
    jmeno : string[30];
    prijmeni : string[39];
    adresa_ulice : string[59];
    adresa_mesto : string[59];
    psc : string[5];
    telefon : string[15];
  end;

var
  lide : array[0..99] of uos;

V následujících příkladech je ukázka programu, který si můžete sami vyzkoušet. Struktura je zde zjednodušena na samotné jméno, a pro vyplnění cvičných dat je pak použita funkce "loadfromfile" - v tomto případě u komponenty Memo, kde je nejsnáze dostupná (také bychom si mohli vytvořit novou proměnnou typu TStrings, což by asi bylo rozumnější). (pro ladění programů je memo výhodnější, protože vidíme, co děláme).

Důležité! Program nejprve načte obsah mema, ale při následném kopírování do struktury (cyklem) buď doplní počet řetězců na 25 řetězcem "zzz" (opakovaně), nebo při delším souboru vezme jen prvních 25 řádek. Projeví se v datech, nikoli v Memu! (Použijte tlačítko Button1).

Tlačítko Button2 strukturu setřídí. Tlačítka lze přejmenovat (Caption).

Bez použití ukazatelů - pole v datové paměti:

unit Unit17;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  te = record
      name : string[50];
    end;

var
  Form1: TForm1;
  e1,e2 : te;
  e : array[1..25] of te;
  i : integer;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
  if opendialog1.execute
    then memo1.lines.loadfromfile(opendialog1.filename);
  if memo1.lines.count <25 then begin
    for i:=1 to memo1.lines.count do e[i].name:=memo1.lines[i-1];
    for i:= memo1.lines.count+1 to 25 do e[i].name:='zzz';
  end else for i:=1 to 25 do e[i].name:=memo1.lines[i-1];
  form1.caption := 'File has been load';
end;

procedure TForm1.Button2Click(Sender: TObject);
var i,j:integer;
  e3:te;   
begin
  for j:= 1 to 24 do
    for i:= 1 to j do
      if e[i].name > e[i+1].name then       
        begin
          e3 := e[i];
          e[i] := e[i+1];
          e[i+1] := e3;
        end;
  memo1.lines.clear;
  for i:= 1 to 25 do memo1.lines.add(e[i].name);
end;

end.

Následně byl program upraven na použití pointerů (vyznačeno červeně a zeleně):

unit Unit17;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  te = record
      name : string[50];
    end;
  tep = ^te;  

var
  Form1: TForm1;
  e1,e2 : te;
  e : array[1..25] of tep;
  i : integer;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
  if opendialog1.execute
    then memo1.lines.loadfromfile(opendialog1.filename);
  if memo1.lines.count <25 then begin
    for i:=1 to memo1.lines.count do e[i]^.name:=memo1.lines[i-1];
    for i:= memo1.lines.count+1 to 25 do e[i]^.name:='zzz';
  end else for i:=1 to 25 do e[i]^.name:=memo1.lines[i-1];
  form1.caption := 'File has been load';
end;

procedure TForm1.Button2Click(Sender: TObject);
var i,j:integer;
  e3:tep;
begin
  for j:= 1 to 24 do
    for i:= 1 to j do
      if e[i]^.name > e[i+1]^.name then    
        begin
          e3 := e[i];
          e[i] := e[i+1];
          e[i+1] := e3;
        end;
  memo1.lines.clear;
  for i:= 1 to 25 do memo1.lines.add(e[i]^.name);
end;

initialization                  
  for i:=1 to 25 do
    new(e[i]);
end.

Zeleně označené symboly stříšky nejsou nezbytné, pokud je nenapíšete, Delphi si je domyslí.