Dynamické zoznamy reťazcov
V programoch je často potrebné uchovávať zoznamy dát. Pascal pre túto úlohu ponúka typ pole, ktoré však má jednu veľkú nevýhodu, a to, že počet prvkov poľa musíte určiť už pri deklarácii poľa. Ponúka aj možnosť vytvárania dynamických polí, ale moderný objektový Pascal ponúka možností oveľa viac.
Obsah článku
Free Pascal poskytuje prostriedky na vytváranie dynamických zoznamov pomocou ukazovateľov, ale kto to skúšal vie, že to nie je triviálny záležitosť a je potrebné ošetriť celú prácu so zoznamom. Inými slovami je to kopmlexná úloha. Free Pascal na to zavádza triedu, ktorá celý proces zapúzdruje.
Na spravovanie zoznamov reťazcov zavádza Free Pascal vo svojej
behovej knižnici triedu TStringList, ktorá je definovaná v
jednotke Classes. TStringList
je potomkom abstraktnej
triedy TStrings, preto najprv popíšem obe triedy. Potom sa
pokúsim ukázať využitie TStringList pomocou príkladov.
V knižnici vizuálnych komponentov Lazara môžme triedu TStringList
(respektíve jej predka TStrings
) nájsť napríklad v komponentoch
ako TMemo
, TComboBox
, či TListBox
. Takže prácu s
dynamickými zoznammi reťazcov pomocou triedy TStringList
možno
využiť aj pri používaní vizuálnych komponentov a nie len pri používaní
programov príkazového riadku.
TStrings
TStrings
implementuje abstraktnú triedu na spravovanie poľa
reťazcov. Zavádza metódy na vkladanie a získavanie reťazcov v poli,
hľadanie reťazcov, ich spájanie a podobne. Umožňuje tiež každému
reťazcu priradiť dodatočný objekt. Zavádza aj metódy pre spravovanie
nastavení v podobe dvojíc meno=hodnota
, ktoré sú bežné v rôznych
konfiguračných súboroch.
Inštancia triedy TStrings
nemá byť nikdy priamo vytváraná, namiesto
toho vytvárajte jej potomkov (napr. TStringList
), pretože
TStrings
je abstraktná trieda, ktorá neimplementuje všetky metódy.
TStrings
tiež neuchováva žiadne reťazce, táto vlastnosť je funkčná
až v potomkoch (TStringList
).
Metódy triedy TStrings
Add
– pridáva do zoznamu reťazec;AddObject
– pridáva do zoznamu reťazec a priradený objekt;AddStrings
– pridáva k tomuto zoznamu obsah iného zoznamu reťazcov;Append
– pridáva do zoznamu reťazec;Assign
– priraďuje k tomuto zoznamu obsah iného zoznamu reťazcov;BeginUpdate
– označuje začiatok aktualizačnej dávky;Clear
– odstraňuje zo zoznamu všetky reťazce a priradené objekty;Delete
– odstraňuje zo zoznamu reťazec;Destroy
– uvoľňuje všetky reťazce a objekty, a odstraňuje zoznam z pamäte;EndUpdate
– označuje koniec aktualizačnej dávky;Equals
– porovnáva obsah dvoch zoznamov reťazcov;Exchange
– vymieňa dva reťazce v zozname medzi sebou;GetNameValue
– vracia meno aj hodnotu, pár meno-hodnota podľa jeho indexu;GetText
– vracia obsah akoPChar
;IndexOf
– nájde v zozname reťazec a vráti jeho pozíciu;IndexOfName
– hľadá index mena v páre meno-hodnota;IndexOfObject
– hľadá v zozname objekt a vracia jeho index;Insert
– vkladá do zoznamu reťazec;InsertObject
– vkladá do zoznamu reťazec a priradený objekt;LoadFromFile
– načíta obsah zoznamu zo súboru, ako postupnosť reťazcov;LoadFromStream
– načíta obsah zoznamu zo streamu, ako postupnosť reťazcov;Move
– presúva reťazec z jedného miesta zoznamu na iné;SaveToFile
– ukladá obsah zoznamu do súboru;SaveToStream
– ukladá obsah zoznamu do streamu;SetText
– nastavuje obsah zoznamu zPChar
.
Vlastnosti triedy TStrings
Capacity
(rw) – kapacita zoznamu, teda počet reťazcov, ktoré môže zoznam obsahovať pred jeho rozšírením;CommaText
(rw) – obsah zoznamu ako čiarkou oddelený reťazec;Count
(ro) – počet reťazcov v zozname;DelimitedText
(rw) – vracia alebo nastavuje všetky reťazce v zozname odedelené oddeľovačom;Delimiter
(rw) – znak oddeľovača použitý v DelimitedText;Names
(ro) – časť meno z páru meno-hodnota v zozname;NameValueSeparator
(rw) – hodnota znaku použitá na oddelenie na oddelenie mena a hodnoty v páre;Objects
(rw) – indexovaný prístup k objektom priradeným k reťazcom v zozname;QuoteChar
(rw) – znak úvodzovky použý v DelimitedText;Strings
(rw) – indexovaný prístup k reťazcom v zozname;StringsAdapter
(rw) – neimplementované vo Free Pascal.Text
(rw) – obsahuje zoznam ako jeden veľký reťazec;ValueFromIndex
(rw) – vracia časť hodnoty na základe jeho indexu;Values
(rw) – časť hodnota z páru meno-hodnota v zozname.
TStringList
TStringList
je potomkom triedy TStrings
, ktorá implementuje
všetky abstraktné metódy zavedené v TStrings
. Okrem toho zavádza
aj nové metódy:
- zoradenie zoznamu alebo udržiavanie zoznamu stále zoradeného
- špeciálnu obsluhu duplikátov v zoradených zoznamoch
- informovanie o zmenách v zozname
Metódy triedy TStringList
CustomSort
– umožňuje priradiť vlastnú implementáciu algoritmu radenia;Find
– vyhľadáva index daného reťazca v zoradenom zozname;Sort
– triedi reťazce v zozname.
Vlastnosti triedy TStringList
CaseSensitive
(rw) – udáva, či hľadanie reťazcov má byť citlivé na veľkosť;Duplicates
(rw) – popisuje správanie zoradeného zoznamu s ohľadom na duplikáty reťazcov;Sorted
(rw) – určuje, či je zoznam zoradený alebo nie.
Udalosti triedy TStringList
OnChange
– udalosť vyvolaná po zmene zoznamu;OnChanging
– udalosť vyvolaná ke je zoznam menený.
Používanie TStringList
S triedou TStringList
, alebo teda presnejšie s jej predkom
TStrings
, sa stretnete v komponentoch ako TMemo
,
TComboBox
, či TListBox
. Práve na komponente TMemo
sa
pokúsim ukázať ako využiť možnosti tejto triedy. Komponent TMemo
má vlastnosť Lines
, ktorá je typu TStrings
. Áno TStrings
,
nie je to preklep, a to napriek tomu, že som skôr písal o TStrings
ako o abstraktnej triede, ktorá nemá byť priamo používaná. Táto
trieda je použitá ako predok tried, a tak je možné vlastnosti
Lines
priradiť akéhokoľvek potomka TStrings
, čiže aj
TStringList
.
Pre našu ukážku si vytvorte nový projekt s jednym formulárom, do ktorého vložte komponenty podľa priloženého kódu.
Definícia formulára
type
{ TfrmSort }
TfrmSort = class(TForm)
btnSort: TButton;
btnClose: TButton;
memText: TMemo;
private
{ private declarations }
public
{ public declarations }
end;
var
frmSort: TfrmSort;
implementation
{ TfrmSort }
procedure TfrmSort.btnCloseClick(Sender: TObject);
begin
Application.MainForm.Close;
end;
Ako môžete v kóde vidieť, formulár má meno frmSort
a obsahuje dve
tlačidlá (btnSort
a btnClose
), jedno textové pole
(memText
). Priradená je aj udalosť OnClick
tlačidlo
btnClose
, ktorá má za úlohu zatvoriť aplikáciu.
Zoradenie položiek
Ako prvé si môžeme vyskúšať zoradenie položiek. Do udalosti OnClick, tlačidla btnSort priradíme obsluhu, ktorá sa o zoradenie postará:
Aplikácia triedenia zoznamu:
procedure TfrmSort.btnSortClick(Sender: TObject);
var
lStrList: TStringList;
begin
try
lStrList := TStringList.Create;
lStrList.Assign(memText.Lines);
lStrList.Sort;
memText.Lines := lStrList;
finally
FreeAndNil(lStrList);
end;
end;
Vzhľadom na to, že vlastnosť Lines
, komponenty memText
je typu
TString
, a táto trieda nemá triedenie implementované, potrebujeme
použiť lokálnu premennú typu TStringList
. Najprv vytvoríme
inštanciu triedy lStrList
, do ktorej následne pomocou metódy
Assign
priradíme obsah vlastnosti Lines
komponentu
memText
. Inštancia triedy TStringList
už metódu Sort
implementovanú má, takže môžeme zoznam zoradiť a potom priradiť naspäť
do komponentu - v tomto prípade už jednoduchým priradením.
Za pozornosť stojí, že celá táto operácia je implementovaná pomocou
ošetrenia výnimiek (chýb), teda bloku try - finally - end
.
Významom tejto konštrukcie je, že či už sa v bloku medzi try
a
finally
vyskytne výnimka alebo nie, vždy je nakoniec vykonaný kód
medzi finally
a end
, inými slovami aj keď sa vyskytne niečo
neplánované, je objekt lStrList
vždy uvoľnený.
Na obrázkoch môžete vidieť náhodne zadaný text a výsledok jeho zoradenia:
Pridanie položky
Pre príklad pridávania položky do TStringList
rozšírime náš
program o ďalšie ovládacie prvky, a to o jedno editačné pole edtText
a tlačidlo btnAdd
. Pridanie položky umožňuje metóda Add
,
ktorá je implementovaná aj v triede TStrings
, takže pri práci s
komponentom TMemo
nemusíme používať pomocnú premennú, ale môžeme
položku pridať priamo. Do obsluhy udalosti OnClick
tlačidla
btnAdd
pridáme tento kód:
Pridanie záznamu:
procedure TfrmSort.btnAddClick(Sender: TObject);begin
if edtText.Text <> '' then
begin
memText.Lines.Add(edtText.Text);
edtText.Clear;
end
else
ShowMessage('Textové pole je prázdne!!!');
end;
V tejto obsluhe najprv testujeme, či editačné pole vôbec obsahuje
nejaký text. Ak nie, program vypíše hlásenie, ak pole nie je prázdne,
pridá metóda Add
jeho obsah na koniec textu ako posledný riadok.
Po pridaní textu je obsah editačného prvku zmazaný metódou Clear
.
Nasledujúce obrázky ukazujú stav aplikácie pred a po pridaní položky:
Keďže sme nemenili obsluhu udalosti tlačidla btnSort
, stále ho
môžete použiť na zoradenie obsahu TMemo
.
Vloženie položky
Niekedy nie je postačujúce pridávanie položky na koniec zoznamu, ale
je potrebné vložiť novú položku na začiatok, či iné vopred určené
miesto. Na toto poslúži metóda Insert
, ktorá má dva parametre.
Prvý je celé číslo a udáva číslo riadku, na ktorý bude položka vložená
(prvý riadok je nula), za ním nasleduje samotný text položky. Do
formulára pridáme ďalšie tlačidlo btnIns
a do obsluhy jeho
udalosti OnClick
tento kód:
Vloženie položky:
procedure TfrmSort.btnInsClick(Sender: TObject);
begin
if edtText.Text <> '' then
begin
memText.Lines.Insert(0, edtText.Text);
edtText.Clear;
end
else
ShowMessage('Textové pole je prázdne!!!');
end;
Princíp vloženia je rovnaký ako vpredchádzajúcom príklade, vrátane ošetrenia obsahu editačného poľa, či jeho vymazania po vložení. Výsledok potom môže vyzerať takto:
Na rozdiel od komponenta TListBox
, TMemo
neposkytuje
jednoduchý spôsob ako zistiť, na ktorom riadku sa nachádza kurzor,
takže pridanie položky na určitú pozíciu môže byť netriviálna úloha.