Vektorālā formā attēlots pašorganizējošs saraksts (1999)

Autors: Valdis Viesturs


1.Uzdevuma nostādne.


         Izveidot vektoriālā formā attēlotu pašorganizājošu sarakstu. Paredzēt procedūras: ListCurrentNpk, ListCurrentElement, FindNextElement, FindPriorElement, ListCreate, ListEmpty, ListTerminate, ListIsEmpty, ListIsFull,  ListSize, FindElementKey,  FindElementIth,  InsertElement, DeleteElement, UpdateElement, ListSaveToFile, ListLoadFromFile.


2.Teorētiskais pamatojums.

2.1 Ievads

Lai varētu sāk apskatīt sarakstu kā datu struktūru, ir jāiepazīstas ar pamatjēdzieniem:

Dati - ir aktuāla informācija, piemēram, statistika, mērījumi, u.tml., ko izmanto par pamatu aprēķinos, diskusijās un lēmumu pieņemšanas procesā. Šajā gadījumā dati ir informācija, ko apstrādājam kā vektoriālā formā attēlota pašorganizējoša saraksta elementus.
Programmas projektēšanas procesā tika precizēta datu struktūra, tās uzbūve, kā arī datu apstrādes algoritmi.

Datu struktūra  - ir cieši saistīta ar datu tipa jēdzienu. Datu tips ir termins, ko lieto, lai klasificētu datus. Datu tips ir tādu vērtību kopums, kuram ir kopīgas īpašības, kā arī operāciju kopums šo vērtību apstrādei. Programmā GDIVPSAR tiek izmantota datu struktūra - saraksts. Sarakstam kā vērtību kopumam ir kopīgas īpašības un ir arī noteikts vērtību apgabals. Ja pieņemam, ka šis saraksts ir veidots kā iedzīvotāju saraksts, tad ir divi ierakstu lauki - atslēglauks, kuru var uzskatīt arī par personas identifikācijas numuru, un datu lauki, kurus pieņem par noteiktās personas vārdu un uzvārdu.
Vispār datu struktūras var iedalīt:
operacionālas  struktūras;
failu  struktūras.
Šīs programmas realizēšanā tiek izmantotas operacionālās datu struktūras. Tas nozīmē, ka šīs datu struktūras tiek izveidotas, glabātas un apstrādātas datora pamatatmiņā. Tas ir samērā neracionāli,bet efektīvi pie nelieliem datu apjomiem, tāpēc lielāku datu apjoma glabāšanai vēlams izmantot failu struktūras. Tās plaši pielieto datu bāzēs.
          Šajā konkrētajā gadījumā sarakts tiek organizēts kā iepreikš noteikta izmēra masīvs. Lai optimizētu darbu ar sarakstu, saraksts tiek vaeidots kā pašorganizējošs saraksts. Pašaorganizējošā saraksta priekšrocība ir tā ka biežāk lietoto elementu meklēšanai tiek lietots mazāks laiks. Pašorganizācijai tiek izmantota 2. Metode – elements pie katras izmantošanas tiek pārvietots par vienu pozīciju uz priekšu, tādējādi pamazām virzoties uz saraksta sākumu. Lai nodrošinātu saraksta darbību ListInstance tiek paredzēti lauki – tekošā elementa npk, elementu skaits sarakstā un masīvs ar norādēm uz saraksta elementiem. Par vektoriālā formā attēlota saraksta trūkumiem jāuzskata tas, ka salīdzinot ar citiem sarakstiem tam uzreiz ir jāizdala lielāks atmiņas apjoms, bet kā priekšrocība – vienkārša un ātra elementa meklēšana pēc tā kārtas nummura, vienkāršāks apstrādes algoritms.

2.2 Vektoriālā formā attēlota saraksta struktūra

Vektorālā formā attēlota saraksts struktūras modeli var attēlot:
Atslēga
Dati
 
   ListInstance
Tekošais skaits
Tekošā elementa npk.
Norāde uz pirmo elementu
…..
Atslēga
Dati
 
Norāde uz pēdējo elementu
Brīvā vieta
ListInstance glabā tekošo elementu skaitu, un masīvu ar norādēm uz saraksta elementiem. ListInstance tiek attēlota šādi:

TSaraksts=record
 TekosaisSkaits:TElementuSkaits;
 TekosaisNpk:TElementuSkaits;
 M:array [1..cMaxSarIzmers] of PDatuElements;
end;

2.3 Datu elementu identifikācija



Parasti datu struktūras elementam piemīt pašidentificēšanās īpašība, tā kā daļa no datiem, kas atrodas datu elementā, var būt tikt izmantota kā pazīme, lai šādus struktūras elementus sameklētu sarakstā.
Taču vairumā gadījumu rīkojas tā, ka datu laukam pievieno vēl vienu lauku, ko sauc par atslēgas lauku. Katrs struktūras elements struktūras ziņā ir pieraksts ar datu un atslēgas lauku.
Datu laukam var būt sarežģīta struktūra, vairākos līmeņos, ja tas ir paredzēts. Atslēgas lauks satur skalāra - ordināra tipa datus, kuri katrā datu elementā ir unikāli un neatkārtojas.
data      key
 
Datu elementa uzbūve - 
                                   
Mūsu gadījumā šie lauki tiek aprakstīti sekojoši:
TAtslega=string[10]; { Atslēgas tips }
TElDati=string[80]; { Datu tips }
Pats datu elements:
TDatuElements=record
 Atslega:TAtslega;
 Teksts:TElDati;
end;

3.Instrukcija lietotājam.


Lai varētu sākt strādāt ar programmu GDIVPSAR, ir jāizveido jauns tukšs saraksts, ko var izdarīt ar procedūras <CREATE> palīdzību. Ja saraksts nebūs izveidots, pārējās procedūras nebūs pieejamas.
Kad saraksts ir izveidots, var ievietot tajā jaunus elementus izsaucot procedūru <INSERT>. Nedrīkst aizmirst, ka elements sastāv no diviem laukiem. Atslēglaukā ir jāievada STRING tipa izteiksme. Atslēglaukā jābūt unikālai izteiksmei, t.i., tās nedrīkst atkārtoties. Ja tiek ievadīta izteiksme, kas atkārtojas, tad tiek izvadīts paziņojums < Nevaru ievietot šo elemenentu >.
Meklēt var pēc atslēgas - <FIND  KEY>, pēc kārtas numura - <FIND  Ith>, kā arī atrast saraksta pirmo <FIND FIRST>, pēdējo elementu <FIND LAST> un tekošā elementa priekšteci  <FIND PRIOR> un pēcteci <FIND NEXT>.  Ja, strādājot ar procedūru <FIND Ith>, vai tiek ievadīti neatbilstoša tipa dati (nav integer tips),saņemsiet paziņojumu <”jūsu ievadītā vērtība” is not a valid integer value” >. No šī loga var atteikties ar pogas aizverot logu ar krustiņu augšējā labā stūrī palīdzību. Ja, turpretī sarakstā tāds elements nav atrodams, tad tiek izvadīts paziņojums - < Nav elementa ar šādu nummuru>, vai arī meklējot pēc atslēgas < Nav elementa ar šādu atslēgu >. Tekošais elements tiek attēlots citā (zilā) krāsā.
Lai labotu kādu vai dzēstu ierakstu, tas ir jāpadara par tekošu. To var izdarīt ar jau iepriekšminētajām meklēšanas procedūrām. Jāizsauc procedūra <UPDATE> un jāievada dati. Nedrīkst ievadīt jaunajā atslēgas layka vēr’tiba jau eksistējošu atslēgu. Pie mēģinājuma to darīt saņemsiet paziņijumu < Nevaru izlabot šo elemenentu >
Dzēšanai izmanto procedūru <DELETE>. Dzēšot elementu, par tekošo kļūst tā pēctecis, izņemot gadījumu ja dzēšat pēdējo elementu, tad par tekošo kļust iepriekšējais elements. Lai iznīcinātu sarakstu, izmanot procedūru <TERMINATE>.
- var uzzināt vai saraksts ir pilns.
< IsEmpty > - var uzzināt vai saraksts ir tukšs.
- par tkošo kļūst pirmais saraksta elements
 >  - par tkošo kļūst pēdējais saraksta elements
Lai izietu no programmas, izmanto Windows standarta loga aizvēršanu : Alt+F4 vai krustiņu augšējā labajā stūrī.

4. Programmas apraksts

Programma sastāv no vairākām procedūrām, kuras ir  apgūtas gan studiju laikā, gan pašmācības ceļā. Turpmāk detalizētākā  izklāstā būs iespējams saprast programmas galveno algoritmu un darbības principus.

4.1. Procedūru apraksts

function ListCurrentNpk(ASaraksts:PSaraksts):TElementuSkaits;
Atgriež tekošā elementa kārtas nummuru.
function ListCurrentElement(ASaraksts:PSaraksts):PDatuElements;
Atgriež norādi uz tekošo elementu.
function FindNextElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
Pāreja pie nākošā elementa.
function FindPriorElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
Pāreja pie iepriekšējā elementa.
function ListCreate:PSaraksts;
Izveido jaunu tukšu sarakstu.
procedure ListEmpty(ASaraksts:PSaraksts);
Iznīcina saraksta saturu.
procedure ListTerminate(ASaraksts:PSaraksts);
Iznīcina sarakstu.
function ListIsEmpty(ASaraksts:PSaraksts):boolean;
Pārbauda vai saraksts ir tukšs
function ListIsFull(ASaraksts:PSaraksts):boolean;
Pārbauda vai saraksts ir pilns
function ListSize(ASaraksts:PSaraksts):TElementuSkaits;
Noskaidro cik elementu ir sarakstā
function FindElementKey(ASaraksts:PSaraksts;AAtslega:TAtslega;var Atrastais:PDatuElements):TElementuSkaits;
Meklē elementu pēc atslēgas
function FindElementIth (ASaraksts:PSaraksts;KursPk:TElementuSkaits;var Atrastais:PDatuElements):TElementuSkaits;
Meklē elementu pēc kārtas nummura
function InsertElement(ASaraksts:PSaraksts;ADatuElements:TDatuElements):TElementuSkaits;
Ievieto jaunu elementu
function DeleteElement(ASaraksts:PSaraksts):boolean;
Nodzēš tekošo elementu elementu
function UpdateElement (ASaraksts:PSaraksts;ADatuElements:TDatuElements):boolean;
Izmaina tekošā elementa vērtības
procedure ListSaveToFile(ASaraksts:PSaraksts;FileName:String);
Saglabā saraksta saturu datnē.
function ListLoadFromFile (FileName:String; var ASaraksts:PSaraksts) :boolean;
Nolasa saraksta saturu no datnes.

4.2. Ievades un izvades informācija.

Sākot darbu,  programma piedāvā  izvēlni, kurā ir   nepieciešamās saraksta apstrādes operācijas. Vēlamo operāciju var realizēt, aktivizējot  operācijai  atbilstošo izvēlnes punktu.
<INSTERT> , ,  ievades informācija ir personas identifikācijas numurs, vārds un uzvārds.
<FIND KEY> ievades informācija ir elementa atslēga.
<FIND i-th> ievades informācija ir elementa kārtas nummurs. Tam jābūt integer tipa lielumam.

4.3 Kontrolpiemēra analīze.

Vispirms jāizveido saraksts ar <Create>
Pēc tam ievietosim trīs ierakstus ar sekojošām vērtībām:
Key
Data
1
Aldis
2
Gatis
3
Agnis
No izvēlenes izvēloties <insert> nokļuūstam sekojošā logā

Kur jāievada atslēgas un datu vērtības.
Iegūstam sekojošu aizpildīto sarakstu:




Lai pārbaudītu funkciju FindIth meklēsim otro (pēs kārtas) saraksta elementu:

Rezultātā:
Atradām otro elementu, un par cik šis ir pašorganizējošš saraksts otrais elements pērvietojās uz priekšu un kļuva par pirmo un tekošo.



Tagad pārbaudām funkciju FindKey:

Rezultātā:



Tekošais elements ir ar atslēgu “3” un parvietojās otrajā pazīcijā pašorganizēšanās dēļ. Tgad izmēģināsim funkciju Update










Ja mēģināsim apmainīt elementam atslēgu uz vērtību kura ir jau piešķirta citam elementam:

5. Secinājumi.


               Veidojot programmu, tika iegūtas papildzināšanas priekšmetā DATU PAMATSTRUKTŪRAS. Programmā GDIVPSAR nevajadzētu būt kļūdās, jo programmu testējot, un kontrolpiemēra izpildes laikā tās netika atrastas. Programmas uzlabojums varētu būt - labāks programmas vizuālais izskats, kā arī dažādas citas procedūras, kuras ne tikai atvieglotu darbu ar šo programmu, bet arī dotu dažādas papildus iespējas.

6. PIELIKUMI

6.1 Programmas pirmteksts.

6.1.1 program gdivpsar


uses
  Forms,
  VPSarMainU in 'VPSarMainU.pas' {VPSarMain},
  VPSarakstsU in 'VPSarakstsU.pas',
  ElemEditU in 'ElemEditU.pas' {ElemEdit},
  HelpAboutU in 'HelpAboutU.pas' {AboutBox},
  ElemKartasNumU in 'ElemKartasNumU.pas' {ElemKartasNum},
  ElemKeyU in 'ElemKeyU.pas' {ElemKey};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TVPSarMain, VPSarMain);
  Application.CreateForm(TElemEdit, ElemEdit);
  Application.CreateForm(TAboutBox, AboutBox);
  Application.CreateForm(TElemKartasNum, ElemKartasNum);
  Application.CreateForm(TElemKey, ElemKey);
  Application.Run;
end.

6.1.2 unit ElemEditU

unit ElemEditU;

interface

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

type
  TElemEdit = class(TForm)
    Label1: TLabel;
    Atslega: TEdit;
    Label2: TLabel;
    Dati: TEdit;
    BitBtn1: TBitBtn;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ElemEdit: TElemEdit;

implementation

{$R *.DFM}

procedure TElemEdit.FormShow(Sender: TObject);
begin
 FocusControl(Atslega);
end;

end.

6.1.3 unit ElemKartasNumU


unit ElemKartasNumU;

interface

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

type
  TElemKartasNum = class(TForm)
    npk: TEdit;
    Label1: TLabel;
    BitBtn1: TBitBtn;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ElemKartasNum: TElemKartasNum;

implementation

{$R *.DFM}

end.

6.1.4 unit ElemKeyU;

unit ElemKeyU;

interface

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

type
  TElemKey = class(TForm)
    Label1: TLabel;
    Atslega: TEdit;
    BitBtn1: TBitBtn;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ElemKey: TElemKey;

implementation

{$R *.DFM}

end.

6.1.5 unit HelpAboutU

unit HelpAboutU;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
  Buttons, ExtCtrls;

type
  TAboutBox = class(TForm)
    Panel1: TPanel;
    ProgramIcon: TImage;
    ProductName: TLabel;
    Copyright: TLabel;
    OKButton: TButton;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  AboutBox: TAboutBox;

implementation

{$R *.DFM}

procedure TAboutBox.FormCreate(Sender: TObject);
begin
 ProductName.Caption:=Application.MainForm.Caption;
end;

end.

6.1.6 unit VPSarakstsU


unit VPSarakstsU;

interface

uses SysUtils;

const cMaxSarIzmers=120;

type

TElementuSkaits=0..cMaxSarIzmers;
TAtslega=string[10]; { Atslēgas tips }
TElDati=string[80];
PDatuElements=^TDatuElements;
TDatuElements=record
 Atslega:TAtslega;
 Teksts:TElDati;
end;

TElemFile=file of TDatuElements;

PSaraksts=^TSaraksts;
TSaraksts=record
 TekosaisSkaits:TElementuSkaits;
 TekosaisNpk:TElementuSkaits;
 M:array [1..cMaxSarIzmers] of PDatuElements;
end;

function ListCurrentNpk(ASaraksts:PSaraksts):TElementuSkaits;
function ListCurrentElement(ASaraksts:PSaraksts):PDatuElements;
function FindNextElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
function FindPriorElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
function ListCreate:PSaraksts;
procedure ListEmpty(ASaraksts:PSaraksts);
procedure ListTerminate(ASaraksts:PSaraksts);
function ListIsEmpty(ASaraksts:PSaraksts):boolean;
function ListIsFull(ASaraksts:PSaraksts):boolean;
function ListSize(ASaraksts:PSaraksts):TElementuSkaits;
function FindElementKey(ASaraksts:PSaraksts;AAtslega:TAtslega;var Atrastais:PDatuElements):TElementuSkaits;
function FindElementIth(ASaraksts:PSaraksts;KursPk:TElementuSkaits;var Atrastais:PDatuElements):TElementuSkaits;
function InsertElement(ASaraksts:PSaraksts;ADatuElements:TDatuElements):TElementuSkaits;
function DeleteElement(ASaraksts:PSaraksts):boolean;
function UpdateElement(ASaraksts:PSaraksts;ADatuElements:TDatuElements):boolean;
procedure ListSaveToFile(ASaraksts:PSaraksts;FileName:String);
function ListLoadFromFile(FileName:String; var ASaraksts:PSaraksts):boolean;

implementation

procedure ListSaveToFile(ASaraksts:PSaraksts;FileName:String);
var f:TElemFile;
    i:TElementuSkaits;
begin
 Assign(f,FileName);
 ReWrite(f);
 with ASaraksts^ do begin
  for i:=1 to TekosaisSkaits do Write(f,m[i]^);
 end;
 Close(F);
end;

function ListLoadFromFile(FileName:String; var ASaraksts:PSaraksts):boolean;
var f:TElemFile;
    e:TDatuElements;
begin
 ListLoadFromFile:=false;
 Assign(f,FileName);
 {$I-}
 Reset(f);
 {$I+}
 if IOResult=0 then begin
  ASaraksts:=ListCreate;
  while not(eof(f)) do begin
   read(f,e);
   InsertElement(ASaraksts,e);
  end;
  ListLoadFromFile:=true;
  Close(f);
 end;
end;

function ListSize(ASaraksts:PSaraksts):TElementuSkaits;
begin
 ListSize:=ASaraksts^.TekosaisSkaits;
end;
// Meklē nākošo elementu sarakstā
function ListCurrentNpk(ASaraksts:PSaraksts):TElementuSkaits;
begin
 ListCurrentNpk:=ASaraksts^.TekosaisNpk;
end;

function ListCurrentElement(ASaraksts:PSaraksts):PDatuElements;
begin
 with ASaraksts^ do begin
  if TekosaisNpk>0
  then ListCurrentElement:=M[TekosaisNpk]
  else ListCurrentElement:=nil;
 end;
end;

function FindNextElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
begin
with ASaraksts^ do begin
 if TekosaisNpk
  TekosaisNpk:=TekosaisNpk+1;
  Atrastais:=M[TekosaisNpk];
  FindNextElement:=TekosaisNpk;
 end else FindNextElement:=0;
end;
end;

// Meklē iepriekšējo elementu sarakstā
function FindPriorElement(ASaraksts:PSaraksts;var Atrastais:PDatuElements):TElementuSkaits;
begin
with ASaraksts^ do begin
 if TekosaisNpk>1 then begin
  TekosaisNpk:=TekosaisNpk-1;
  Atrastais:=M[TekosaisNpk];
  FindPriorElement:=TekosaisNpk;
 end else FindPriorElement:=0;
end;
end;
// Pārvieto elementu uz priekšu un atgriež tā jauno npk;
function MoveElement(ASaraksts:PSaraksts;kuru:TElementuSkaits):TElementuSkaits;
var Darba:PDatuElements;
begin
 MoveElement:=kuru;
 if kuru>1 then begin
  Darba:=ASaraksts^.M[kuru-1];
  ASaraksts^.M[kuru-1]:=ASaraksts^.M[kuru];
  ASaraksts^.M[kuru]:=Darba;
  MoveElement:=kuru-1;
 end;
end;

//Izveido tukšu sarakstu
function ListCreate:PSaraksts;
var rez:PSaraksts;
begin
 new(rez);
 rez^.TekosaisSkaits:=0;
 rez^.TekosaisNpk:=0;
 ListCreate:=rez;
end;

// Iztīra elementus no saraksta
procedure ListEmpty(ASaraksts:PSaraksts);
var i:TElementuSkaits;
begin
 for i:=1 to ASaraksts^.TekosaisSkaits do Dispose(ASaraksts^.m[i]);
 ASaraksts^.TekosaisSkaits:=0;
 ASaraksts^.TekosaisNpk:=0;
end;

// Iznīcina sarakstu
procedure ListTerminate(ASaraksts:PSaraksts);
begin
 ListEmpty(ASaraksts);
 Dispose(ASaraksts);
end;

// Meklē elementu pāc atslēgas taču nemaina ne tā npk, ne tekošā npk.
// Paredzēts lai meklēšanas kodu izmantotu kan FindKey, gan Update;
function InternalFindElementKey(ASaraksts:PSaraksts;AAtslega:TAtslega;
var Atrastais:PDatuElements):TElementuSkaits;
var i:TElementuSkaits;
begin
i:=1;Atrastais:=nil;
while (i<=ASaraksts^.TekosaisSkaits)
      and (ASaraksts^.m[i].Atslega<>AAtslega) do begin
 i:=i+1;
end;
if (i<=ASaraksts^.TekosaisSkaits) and (ASaraksts^.m[i].Atslega=AAtslega) then begin
  Atrastais:=ASaraksts^.m[i];
  InternalFindElementKey:=i;
end else InternalFindElementKey:=0;
end;

// Meklē elementu pēc atslēgas, ar pašorganizēšanos
function FindElementKey(ASaraksts:PSaraksts;AAtslega:TAtslega;var Atrastais:PDatuElements):TElementuSkaits;
var rez:TElementuSkaits;
begin
rez:=InternalFindElementKey(ASaraksts,AAtslega,Atrastais);
if rez>0 then begin
  ASaraksts^.TekosaisNpk:=MoveElement(ASaraksts,rez);
  FindElementKey:=ASaraksts^.TekosaisNpk;
 end else FindElementKey:=0;
end;

// Meklē elementu pēc kārtas #
function FindElementIth(ASaraksts:PSaraksts;KursPk:TElementuSkaits;var Atrastais:PDatuElements):TElementuSkaits;
begin
 with ASaraksts^ do begin
 if TekosaisSkaits>=KursPk then begin
  Atrastais:=M[KursPk];
  TekosaisNpk:=MoveElement(ASaraksts,KursPk);
  FindElementIth:=TekosaisNpk;
 end else FindElementIth:=0;
 end;
end;

// Pārbauda vai saraksts ir tukšs
function ListIsEmpty(ASaraksts:PSaraksts):boolean;
begin
 ListIsEmpty:=ASaraksts^.TekosaisSkaits=0;
end;

// Pārbauda vai saraksts ir pilns
function ListIsFull(ASaraksts:PSaraksts):boolean;
begin
 ListIsFull:=ASaraksts^.TekosaisSkaits>=cMaxSarIzmers;
end;

// Ievieto jaunu elementu sarakstā
function InsertElement(ASaraksts:PSaraksts;ADatuElements:TDatuElements):TElementuSkaits;
var Atrastais:PDatuElements;
begin
 if ListIsFull(ASaraksts)
    or (InternalFindElementKey(ASaraksts,ADatuElements.Atslega,Atrastais)>0)
 then begin InsertElement:=0;
 end else with ASaraksts^ do begin
  new(Atrastais);
  TekosaisSkaits:=TekosaisSkaits+1;
  m[TekosaisSkaits]:=Atrastais;
  Atrastais^:=ADatuElements;
  TekosaisNpk:=TekosaisSkaits;
  InsertElement:=TekosaisSkaits;
 end;
end;

// Nodzēš tekošo elementu
function DeleteElement(ASaraksts:PSaraksts):boolean;
var i:TElementuSkaits;
begin
 with ASaraksts^ do begin
 if (TekosaisNpk>0) and (TekosaisNpk<=TekosaisSkaits) then begin
  Dispose(ASaraksts^.m[TekosaisNpk]);
  ASaraksts^.TekosaisSkaits:=ASaraksts^.TekosaisSkaits-1;
  for i:=TekosaisNpk to ASaraksts^.TekosaisSkaits do
  ASaraksts^.M[i]:=ASaraksts^.M[i+1];
  if TekosaisNpk>TekosaisSkaits then TekosaisNpk:=TekosaisSkaits;
  DeleteElement:=true;
 end else DeleteElement:=false;
 end;
end;

// Izmaina tekošā elementa vērtības
function UpdateElement(ASaraksts:PSaraksts;ADatuElements:TDatuElements):boolean;
var Atrastais:PDatuElements;
    AtrNpk:TElementuSkaits;
begin
 UpdateElement:=false;
 with ASaraksts^ do begin
 AtrNpk:=InternalFindElementKey(ASaraksts,ADatuElements.Atslega,Atrastais);
 if (AtrNpk=TekosaisNpk) or (AtrNpk<1) then begin
  m[TekosaisNpk]^:=ADatuElements;
  UpdateElement:=true;
 end;
 end;
end;

end.

6.1.7 unit VPSarMainU


unit VPSarMainU;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, ActnList,VPSarakstsU, Grids;

type
  TVPSarMain = class(TForm)
    ActionList1: TActionList;
    sCreate: TAction;
    sTerminate: TAction;
    eInsert: TAction;
    eDelete: TAction;
    eUpdate: TAction;
    eLast: TAction;
    eFirst: TAction;
    sIsEmpty: TAction;
    sIsFull: TAction;
    eFindPrior: TAction;
    eFindNext: TAction;
    eFindIth: TAction;
    MainMenu1: TMainMenu;
    Saraksts1: TMenuItem;
    Elements1: TMenuItem;
    Create1: TMenuItem;
    Terminate1: TMenuItem;
    IsFull1: TMenuItem;
    IsEmpty1: TMenuItem;
    Update1: TMenuItem;
    Insert1: TMenuItem;
    FindIth1: TMenuItem;
    FindKey1: TMenuItem;
    FindPrior1: TMenuItem;
    FindNext1: TMenuItem;
    Delete1: TMenuItem;
    eFindKey: TAction;
    sg: TStringGrid;
    HelpAbout: TAction;
    N1: TMenuItem;
    Parprogrammu1: TMenuItem;
    First1: TMenuItem;
    Last1: TMenuItem;
    procedure sCreateExecute(Sender: TObject);
    procedure sTerminateExecute(Sender: TObject);
    procedure HelpAboutExecute(Sender: TObject);
    procedure sIsEmptyExecute(Sender: TObject);
    procedure sIsFullExecute(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure eInsertExecute(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure eDeleteExecute(Sender: TObject);
    procedure eUpdateExecute(Sender: TObject);
    procedure eLastExecute(Sender: TObject);
    procedure eFirstExecute(Sender: TObject);
    procedure eFindPriorExecute(Sender: TObject);
    procedure eFindNextExecute(Sender: TObject);
    procedure eFindIthExecute(Sender: TObject);
    procedure eFindKeyExecute(Sender: TObject);
  private
    { Private declarations }
  public
    ASaraksts:PSaraksts;
    { Public declarations }
    procedure FillGrid;
  end;

var
  VPSarMain: TVPSarMain;

implementation

uses HelpAboutU, ElemEditU, ElemKartasNumU, ElemKeyU;

{$R *.DFM}

procedure TVPSarMain.sCreateExecute(Sender: TObject);
begin
 ASaraksts:=ListCreate;
 sCreate.Enabled:=false;
 sTerminate.Enabled:=true;
 eInsert.Enabled:=true;
 eDelete.Enabled:=true;
 eUpdate.Enabled:=true;
 eLast.Enabled:=true;
 eFirst.Enabled:=true;
 sIsEmpty.Enabled:=true;
 sIsFull.Enabled:=true;
 eFindPrior.Enabled:=true;
 eFindNext.Enabled:=true;
 eFindIth.Enabled:=true;
 eFindKey.Enabled:=true;
end;

procedure TVPSarMain.sTerminateExecute(Sender: TObject);
var row:TStrings;
begin
 ListTerminate(ASaraksts);ASaraksts:=nil;
 sCreate.Enabled:=true;
 sTerminate.Enabled:=false;
 eInsert.Enabled:=false;
 eDelete.Enabled:=false;
 eUpdate.Enabled:=false;
 eLast.Enabled:=false;
 eFirst.Enabled:=false;
 sIsEmpty.Enabled:=false;
 sIsFull.Enabled:=false;
 eFindPrior.Enabled:=false;
 eFindNext.Enabled:=false;
 eFindIth.Enabled:=false;
 eFindKey.Enabled:=false;
 sg.RowCount:=2;
 row:=sg.rows[1];
 row.Strings[0]:='';
 row.Strings[1]:='';
end;

procedure TVPSarMain.HelpAboutExecute(Sender: TObject);
begin
 AboutBox.ShowModal;
end;

procedure TVPSarMain.sIsEmptyExecute(Sender: TObject);
var txt:String;
begin
 if ListIsEmpty(ASaraksts) then txt:='Saraksts ir tukšs' else txt:='Saraksts nav tukšs';
 MessageDlg(txt,mtInformation,[mbOK],0);
end;

procedure TVPSarMain.sIsFullExecute(Sender: TObject);
var txt:String;
begin
 if ListIsFull(ASaraksts) then txt:='Saraksts ir pilns' else txt:='Saraksts nav pilns';
 MessageDlg(txt,mtInformation,[mbOK],0);
end;

procedure TVPSarMain.FormDestroy(Sender: TObject);
begin
 if Assigned(ASaraksts) then begin
  ListTerminate(ASaraksts);ASaraksts:=nil;
 end;
end;

procedure TVPSarMain.eInsertExecute(Sender: TObject);
var elm:TDatuElements;
begin
 ElemEdit.Caption:='Ievietot elementu';
 ElemEdit.Atslega.Text:='';
 ElemEdit.Dati.Text:='';
 if ElemEdit.ShowModal=mrOK then begin
  elm.Atslega:=ElemEdit.Atslega.Text;
  elm.Teksts:=ElemEdit.Dati.Text;
  if InsertElement(ASaraksts,elm)<=0 then
  MessageDlg('Nevaru ievietot šo elemenentu',mtInformation,[mbOK],0);
 end;
 FillGrid;
end;

procedure TVPSarMain.FillGrid;
var
    row:TStrings;
    i:TElementuSkaits;
    sel:TGridRect;
    rowc:integer;
begin
  rowc:=ListSize(ASaraksts)+1;  { +1 virsrakstam}
  if rowc=1 then rowc:=2;
  sg.RowCount:=rowc;
  row:=sg.rows[1];
  row.Strings[0]:='';
  row.Strings[1]:='';
  for i:=1 to ListSize(ASaraksts) do begin
   row:=sg.rows[i];
   row.Strings[0]:=ASaraksts^.m[i]^.Atslega;
   row.Strings[1]:=ASaraksts^.m[i]^.Teksts;
  end;
  sel.Top:=ListCurrentNpk(ASaraksts);
  sel.Bottom:=sel.Top;
  sel.Left:=0;
  sel.Right:=1;
  sg.Selection:=sel;
end;

procedure TVPSarMain.FormCreate(Sender: TObject);
var row:TStrings;
begin
 row:=sg.rows[0];
 row.Strings[0]:='Atslēga';
 row.Strings[1]:='Teksts';
end;

procedure TVPSarMain.eDeleteExecute(Sender: TObject);
begin
 DeleteElement(ASaraksts);
 FillGrid;
end;

procedure TVPSarMain.eUpdateExecute(Sender: TObject);
var elm:PDatuElements;
    jaun:TDatuElements;
begin
 elm:=ListCurrentElement(ASaraksts);
 if Assigned(elm) then begin
  ElemEdit.Caption:='Labot elementu';
  ElemEdit.Atslega.Text:=elm.Atslega;
  ElemEdit.Dati.Text:=elm.Teksts;
  if ElemEdit.ShowModal=mrOK then begin
   jaun.Atslega:=ElemEdit.Atslega.Text;
   jaun.Teksts:=ElemEdit.Dati.Text;
   if not(UpdateElement(ASaraksts,jaun)) then
   MessageDlg('Nevaru izlabot šo elemenentu',mtInformation,[mbOK],0);
   FillGrid;
  end;
 end else MessageDlg('Nav tekošā elementa',mtInformation,[mbOK],0);
end;

procedure TVPSarMain.eLastExecute(Sender: TObject);
var elm:PDatuElements;
begin
 // Nevar tasit ar findIth(izmers), jo tad pedejais klus par priekspedejo
 while FindNextElement(ASaraksts,elm)>0 do;
 FillGrid;
end;

procedure TVPSarMain.eFirstExecute(Sender: TObject);
var elm:PDatuElements;
begin
 FindElementIth(ASaraksts,1,elm);
 FillGrid;
end;

procedure TVPSarMain.eFindPriorExecute(Sender: TObject);
var elm:PDatuElements;
begin
 if FindPriorElement(ASaraksts,elm)<=0 then
 MessageDlg('Nav iepriekšējā elementa',mtInformation,[mbOK],0);
 FillGrid;
end;

procedure TVPSarMain.eFindNextExecute(Sender: TObject);
var elm:PDatuElements;
begin
 if FindNextElement(ASaraksts,elm)<=0 then
 MessageDlg('Nav nākošā elementa',mtInformation,[mbOK],0);
 FillGrid;
end;

procedure TVPSarMain.eFindIthExecute(Sender: TObject);
var elm:PDatuElements;
begin
 if ElemKartasNum.ShowModal=mrOk then begin
  if FindElementIth(ASaraksts,StrToInt(ElemKartasNum.npk.Text),elm)<=0 then
  MessageDlg('Nav elementa ar šādu nummuru',mtInformation,[mbOK],0);
  FillGrid;
 end;
end;

procedure TVPSarMain.eFindKeyExecute(Sender: TObject);
var elm:PDatuElements;
begin
 if ElemKey.ShowModal=mrOk then begin
  if FindElementKey(ASaraksts,ElemKey.Atslega.Text,elm)<=0 then
  MessageDlg('Nav elementa ar šādu atslēgu',mtInformation,[mbOK],0);
  FillGrid;
 end;
end;

end.

Nav komentāru:

Ierakstīt komentāru