Difference between revisions of "TStringList-TStrings Tutorial/pl"
(→Rozszerzony przykład: tłumaczenie na j. polski) |
|||
Line 95: | Line 95: | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
− | // | + | // Działa to doskonale, bez podwójnego tworzenia listy ciągów |
function theStringList: TStringList; | function theStringList: TStringList; | ||
var | var | ||
Line 118: | Line 118: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Aby iterować po liście, lepiej jest użyć pętli '''while-do''' zamiast pętli '''for-to'''. Powodem jest to, że lista może być pusta, więc pętla for-to nie działa poprawnie. | |
− | + | ||
+ | W tym przykładzie procedura SubscriberDel jest wywoływana dla każdego identyfikatora ID na liście, a lista identyfikatorów ID jest przekazywana do procedury jako ciąg znaków (string). | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> |
Revision as of 12:57, 26 August 2020
│
Deutsch (de) │
English (en) │
español (es) │
suomi (fi) │
français (fr) │
polski (pl) │
русский (ru) │
TStringList
TStringList (lub jego rodzic TStrings) jest bardzo podobna do fantazyjnej tablicy dynamicznej lub zbiór ciągów typu string (zbiór ciągów nie jest możliwy w FPC). Ten typ danych jest bardzo przydatny podczas programowania i mam zamiar nauczyć Cię podstaw obsługi TStringList!
Prosty przykład
program StrList;
{$mode objfpc}
uses
Classes, SysUtils;
var
Str: TStringList;
begin
Str := TStringList.Create; // Jest to potrzebne podczas korzystania z tej klasy (lub większości klas)
Str.Add('Jakiś ciąg znaków!');
writeln('Lista ciągów ma teraz ' + IntToStr(Str.Count) + ' ciąg(ów).');
Readln;
Str.Free; //Zwolnij pamięć używaną przez tę instancję stringlist
end.
Jest to prosty program konsolowy, który utworzy i doda jeden ciąg (string) do listy ciągów (stringlist). Oto kilka rzeczy, które powinieneś wiedzieć:
Create - Stworzy listę ciągów, którą potem możesz modyfikować. Jeśli używasz konstruktora constructor
Create, musisz później zwolnić jego pamięć za pomocą Free. Wywołanie free
skutkuje wywołaniem destruktora destructor
Destroy
, który niszczy listę i uwalnia zajmowaną przez nią pamięć. Jeśli tego nie zrobisz, to program nie ulegnie awarii, ale też nie zwolni całej zajmowanej pamięci i nastąpi tzw. wyciek pamięci.
Count - Ta właściwość jest licznikiem liczby ciągów na liście.
Add - Ta metoda umożliwia dodanie jednego ciągu do listy ciągów. Jest to funkcja, która zwraca indeks ciągu. Tutaj z pomocą przychodzi licznik.
Delete - Usuwa ciąg (string) z listy ciągów (stringlist). Musisz wiedzieć, że nie podajesz ciągu znaków, które chcesz usunąć, ale musisz wprowadzić indeks tego ciągu. Jak powiedziałem: to jak fantazyjna tablica dynamiczna.
IndexOf - Zwróci indeks ciągu na liście. Jeśli nie zostanie on znaleziony, to zwraca -1.
Clear - Czyści całą listę.
Rozszerzony przykład
A może bardziej soczysty przykład, co?
program StrList2;
{$mode ObjFPC}
uses
Classes, SysUtils;
var
Str: TStringList;
S: String;
Counter: Integer;
begin
Str := TStringList.Create;
Writeln('String List Test');
repeat
Writeln('Wpisz ciąg do dodania (wpisz KONIEC, aby zatrzymać dodawanie ciągów)');
Readln(S);
if (S = 'KONIEC') then
Break; // wyjście z pętli
if (S <> '') then
begin
Counter := Str.Add(S);
Writeln('Ciąg: ' + S + ' został dodany!');
Writeln('Jego index to: ' + IntToStr(Counter)); // Licznik zawsze będzie indeksem ostatnio dodanej rzeczy
end
else
begin
Writeln('Nie wprowadzono żadnych danych...');
end;
until (S = 'KONIEC');
writeln('Zawartość TStringList: '+ Str.CommaText);
Str.Free; //zwolnij pamięć
end.
Jednak, aby uniknąć możliwych wycieków pamięci, zawsze powinieneś używać bloku Try - Finally wszędzie, gdzie to możliwe, aby uzyskać coś takiego:
var
slist: TStringList;
...
slist := TStringList.Create;
try
...
// rób różne rzeczy z twoją listą stringów (stringlist)
...
finally
if Assigned(slist) then
FreeAndNil(slist);
end;
// Działa to doskonale, bez podwójnego tworzenia listy ciągów
function theStringList: TStringList;
var
J: integer;
begin
result := TStringList.Create;
for J:=0 to 10 do
result.add(intToStr(J));
end;
procedure Caller;
var
SL: TStringList;
K: integer;
begin
SL := theStringList;
for K:=0 to pred(SL.Count) do
writeln(SL[K]);
if assigned(SL) then
SL.Free;
end;
Aby iterować po liście, lepiej jest użyć pętli while-do zamiast pętli for-to. Powodem jest to, że lista może być pusta, więc pętla for-to nie działa poprawnie.
W tym przykładzie procedura SubscriberDel jest wywoływana dla każdego identyfikatora ID na liście, a lista identyfikatorów ID jest przekazywana do procedury jako ciąg znaków (string).
procedure SubscribersDelete(const Subscriber_ID: string);
var
List : TStringList;
i : Integer;
begin
List := TStringList.Create;
List.Text := Subscriber_ID;
i := 0;
while i < List.Count do
begin
SubscriberDel(List.Strings[i]);
inc(i);
end;
List.Free;
end;
Conversion to and from delimited strings
Code below will result in a stringlist, containing 4 elements ('1', '2', '3' and '4');
procedure Sample;
var
MyStringList: TStringList=nil;
begin
MyStringList:= TStringList.create;
MyStringList.Delimiter := ';';
MyStringList.DelimitedText:='1;2;3;4';
MyStringList.free;
end;
Respectively next code will assemble a stringlist into a delimited string ('1;2;3;4'):
function Sample2 : string;
var
MyStringList: TStringList=nil;
begin
MyStringList:= TStringList.create;
MyStringList.Delimiter := ';';
MyStringList.Add('1');
MyStringList.Add('2');
MyStringList.Add('3');
MyStringList.Add('4');
Result :=MyStringList.DelimitedText;
MyStringList.free;
end;
Note that Delimter is a character, not a string!
If your separator is a string (for example „\n‟), you could use code below, to get a stringlist, containing 4 elements ('1', '2', '3' and '4'):
procedure Sample;
var
MyStringList: TStringList=nil;
begin
MyStringList:= TStringList.create;
MyStringList.text:=StringReplace('1\n2\n3\n4','\n',Lineending,[rfReplaceAll, rfIgnoreCase]);
MyStringList.free;
end;
Vice versa, next function will return „1\n2\n3‟:
Function Sample : string;
var
MyStringList: TStringList=nil;
begin
MyStringList:= TStringList.create;
MyStringList.SkipLastLineBreak := True;
MyStringList.add('1');
MyStringList.add('2');
MyStringList.add('3');
result := StringReplace(MyStringList.Text,Lineending,'\n', [rfReplaceAll, rfIgnoreCase]);
MyStringList.free;
end;
File Handling
When using the TStringList you have 2 file handling procedures: SaveToFile and LoadFromFile. SavetoFile will save all strings in the list to a file. LoadFromFile will open the file and add the file data to the list string by string.
program StrListFile;
{$mode objfpc}
uses
Classes, SysUtils;
var
Str: TStringList;
begin
Str := TStringList.Create;
try
Str.LoadFromFile('SomeFile.txt');
Str.Add('Hello');
Str.SaveToFile('SomeFile.txt');
finally
Str.Free;
end;
end.
You just opened a file, edited it and saved it right back to were it was!
Sorting
The Find procedure requires that the list be sorted. The easiest approach is to set its Sorted property to True, then new items added to the list will be inserted in the correct position. This has a few extra side effects, firstly, you cannot use the Insert() procedure, use only Add(). Secondly, it sets the Duplicates property, its default setting is "dupIgnore" which means attempts to Add identical entries will be ignored. However, calls to AddObject() that have an identical string and a new Object, the new Object replaces the existing one.
Dynamic string array comparison
TStringList is simply an object-oriented version of a dynamic string array. Some methods have analogs:
Operation | array of string | TStringList |
---|---|---|
Variable declaration | StringList: array of string; | StringList: TStringList; |
Initialization | implicit constructor | StringList := TStringList.Create |
Set size | SetLength(StringList, X); | StringList.Size := X; |
Get size | X := Length(StringList); | X := StringList.Count; |
Add item | SetLength(StringList, Length(StringList) + 1); StringList[Length(StringList) - 1] := X; | StringList.Add(X); |
Delete item | for I := Index to Length(StringList) - 2 do StringList[I] := StringList[I + 1]; SetLength(StringList, Length(StringList) - 1); | StringList.Delete(Index); |
Remove all items | SetLength(StringList, 0); | StringList.Clear; |
Finalization | implicit destructor | StringList.Free; |
However, TStringList offers much more functionality than a basic structure such as a dynamic array.
Keep Learning
TStringList has many other interesting features:
- It allows you to sort the strings
- It allows you to limit the list to only unique strings
- You can get the text of all strings as a single string using the Text property.
- You can store an object or other data next to the string
You can learn all the different procedures, functions and properties. See TStringList documentation... or the help in Lazarus.
... and you might like to extend this tutorial if you feel like it.