Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TStringList. Статья. 
:(
    Опции темы
THandle
Дата 28.4.2008, 17:39 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 65
Всего: 372



                                                                     TStringList. 


Для чего нужен класс TStringList?


Этот класс нужен для работы с наборами строк и объектов. Класс происходит от абстрактного класса TStrings.

  Напомним, что абстрактным является тот класс, который содержит в себе хоть один абстрактный метод. Все такие методы должны быть перекрыты в классе-потомке.

Например:
Код


type
TSomeClass = class
  public
    procedure SomeMethod1; virtual; abstract;
    procedure SomeMethod2;
end;

TSomeChildClass = class(TSomeClass)
  public
    procedure SomeMethod1; override;
end;

procedure TSomeClass.SomeMethod2;
begin
  //реализация
end;

procedure TSomeChildClass.SomeMethod1;
begin
  //реализация
end;


Код


var
  sc : TSomeClass;
  scc : TSomeChildClass;
begin
  sc := TSomeClass.Create;//всё нормально
  scc := TSomeChildClass.Create;//всё нормально
  sc.SomeMethod2;//тоже все ОК
  scc.SomeMethod1;//ОК
  sc.SomeMethod1;//А тут ошибка EAbstractError
end;



В общем виде иерархия TStringList такова:


                                          TObject
                                                |
                                        TPersistent
                                                |
                                          TStrings
                                                |
                                        TStringList


Как Вы, наверное, уже заметили, потомки класса TStrings используются во многих VCL компонентах – TlistBox, TMemo, TRichEdit…
Хранит в себе класс TStringList массив указателей на объекты и строки.


А теперь рассмотрим свойства, методы и события класса TstringList.




Метод Create.


Создаёт объект класса TStringList. Конструктор у TStringList остался еще от TObject, в котором он, кстати, является пустым.

Пример создания объекта класса TStringList:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    //Делаем что-то
  finally
    s.Free;
  end;
end;




Метод Add.

Объявлен как:

Код

function Add(const S: string): Integer; override;



Добавляет в конец набора новую строку, переданную в s. Возвращает индекс элемента в наборе.

Пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    ShowMessage(IntToStr(s.Add('SomeString')));
  finally
    s.Free;
  end;
end;


В сообщение будет показан ноль, так как мы добавили лишь первую строку в набор (почему 0, читать далее).



Свойство Strings.


Объявлено как:

Код

property Strings[Index: Integer]: string read Get write Put; default;


В свойстве, при обращении, содержится строка с переданным индексом Index из набора строк, находящихся в данный момент в созданном объекте.

Например:
Код


procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Add('String1');
    ShowMessage(s.Strings[0]);
  finally
    s.Free;
  end;
end;


Будет показано сообщение “String1”.
Индексы начинаются с нуля.
Если Index не существует, то возникнет ошибка, и будет показано сообщение:
            
Цитата

List index out of bounds (№ не существующего индекса)


Чтобы подобного не происходило, у класса TStringList существует свойство Count, которое содержит в себе количество загруженных в наш набор строк.
Так как свойство Count содержит количество строк, а свойство Strings начинается с 0, то индекс последней существующей строки будет равен не числу, содержащемуся в Count, а числу Count – 1.

Пример:

Нам нужно обратиться к последнему элементу нашего набора.

Верно:


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    //..
    ShowMessage(s.Strings[s.Count - 1]);
  finally
    s.Free;
  end;
end;



Неверно, List Index Out Of Bounds:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    //..
    ShowMessage(s.Strings[s.Count]);
  finally
    s.Free;
  end;
end;



По индексу к набору строк можно обращаться не только через свойство Strings, но и напрямую, как к массиву. 
Это связано с тем, что свойство Strings в классе-родителе объявлено с директивой default.

1:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    //..
    ShowMessage(s.Strings[s.Count - 1]);
  finally
    s.Free;
  end;
end;



2:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    //..
    ShowMessage(s[s.Count - 1]);
  finally
    s.Free;
  end;
end;




Метод AddObject.

Объявлен как:

Код

function AddObject(const S: string; AObject: TObject): Integer; override;


Добавляет в конец набора строку и ссылку на объект. Для получения ссылки на добавленный объект существует свойство Objects, очень похожее на Strings.
Объявлено это свойство так:

Код

property Objects[Index: Integer]: TObject;


Методом AddObject можно добавить абсолютно любой объект, так как параметр AObject имеет тип TObject, наследниками которого являются все классы Delphi.

Пример:

Есть у нас некий класс:

Код

 type
  TSomeClass = class
    procedure Show;
  end;



Его метод Show реализован следующим образом:

Код

procedure TSomeClass.Show;
begin
  ShowMessage('SomeClass arbaiten!!!');
end;


А теперь сам пример работы с AddObject:


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  sc : TSomeClass;
begin
  s := TStringList.Create;
  sc := TSomeClass.Create;
  try
    s.AddObject('SomeString', sc);
    (s.Objects[0] as TSomeClass).Show;
    ShowMessage(s[0]);
  finally
    s.Free;
    sc.Free;
  end;
end;


Будут показаны два сообщения. Сначала:
Цитата

              'SomeClass arbaiten!!!'

Потом:
Цитата

              'SomeString'



С методом Objects нельзя работать так же как с массивом. Всегда необходима запись вида:

Код

s.Objects[…];



Примечание:  В действительности метод Add вызывает в своём теле метод AddObject с параметром Aobject равным nil.



Метод AddStrings.

Объявлен как:

Код

    procedure AddStrings(Strings: TStrings); virtual;


Добавляет в конец нашего набора строк еще один набор в виде любого потомка TStrings, переданного в Strings.

Пример:

Добавим в Memo1, расположенный на форме, сформированный нами TstringList.

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 9 do
      s.Add('String #' + IntToStr(i));
    Memo1.Lines.AddStrings(s);
  finally
    s.free;
  end;
end;


Допустим, в Memo1 был текст:

Цитата

Memo1.SomeText.


Тогда результатом выполнения примера будет следующий текст в Memo:

Цитата

Memo1.SomeText.
String #0
String #1
String #2
String #3
String #4
String #5
String #6
String #7
String #8
String #9





Свойство Capacity.


Объявлено как:

Код

property Capacity: Integer read GetCapacity write SetCapacity;


Напомним, что набор строк реализуется с помощью массива указателей. Свойство Capacity содержит в себе текущую длину этого массива. Значение свойства Capacity зависит от значения Count.

Если при добавлении нового элемента Capacity окажется меньше Count, то будет выполнен следующий код:

Код

procedure TStringList.Grow;
var
  Delta: Integer;
begin
  if FCapacity > 64 then Delta := FCapacity div 4 else
    if FCapacity > 8 then Delta := 16 else
      Delta := 4;
  SetCapacity(FCapacity + Delta);
end;


Delta — тут является значением, на которое нужно увеличить Capacity.

То есть, если старое значение Capacity меньше 8, то Delta равна 4, соответственно Capacity увеличится на 4, будет выполнена резервация динамической памяти еще на 4 элемента.
Дальше: если старое значение Capacity больше 8, но меньше 64, то Delta составляет 16 элементов, на которые будет выделена память. Если же старое значение Capacity будет больше 64, то тогда Delta будет рассчитываться по следующей формуле:
  
                   
Цитата

Delta = старое_значение_capacity целочисленно делим(div) на четыре.


Память резервируется с помощью функции ReallocMem.
Поэтому стоит призадуматься — может быть лучше заранее установить Capacity в нужное положение, если набор будет очень большим, и если известно заранее количество элементов? Думаю, что стоит. Ведь таким образом можно сэкономить время, которое занимает постоянные расширения массива указателей.

Еще раз напоминаю, что все вышеописанные действия будут происходить только в случае того, если при добавлении нового элемента в набор, значение свойства Capacity окажется меньшим значения свойства Count.

На всякий случай приведу небольшой пример. В наш StringList добавим в цикле 200 строк, и на каждой итерации будем выводить в Memo значения свойств Count и Capacity.


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 1 to 200 do
      begin
        s.Add('String #' + IntToStr(i));
        Memo1.Lines.Add('Count :' + IntToStr(s.Count) + '   Capacity: ' + IntToStr(s.Capacity));
      end;
  finally
    s.free;
  end;
end;





Метод Delete.

Объявлен как:

Код

procedure Delete(Index: Integer); override;


Удаляет элемент набора с индексом Index.



Пример:

В примере опять фигурирует компонент Tmemo, расположенный на главной форме.

Код


procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 4 do
      s.Add('String #' + IntToStr(i));
    s.Delete(3);
    Memo1.Lines.AddStrings(s);
  finally
    s.free;
  end;
end;



В результате получаем такой список:

Цитата

String #0
String #1
String #2
String #4


Строка 'String #3' удалена, так как после формирования набора s, индекс у нее равнялся 3.
А строка:

Код

s.Delete(3);


Взяла да удалила элемент с этим индексом. Жалко, однако.




Свойства Delimiter, QuoteChar .

Объявлены как:

Код

property Delimiter: Char read GetDelimiter write SetDelimiter;


Код


property QuoteChar: Char read GetQuoteChar write SetQuoteChar;


Оба свойства служат для разделения строк в свойствах DelimetedText и CommaText.
О них далее.

По умолчанию свойство Delimiter = ','. А свойство QuoteChar = '"'.




Свойства DelimitedText, CommaText.

Объявлены как:

Код

property DelimitedText: string read GetDelimitedText write SetDelimitedText;


Код

property CommaText: string read GetCommaText write SetCommaText;


Код

property Text: string read GetTextStr write SetTextStr;


Свойство DelimitedText объединяет все строки(Strings) нашего набора в одну. После каждой строчки добавляется знак, который содержится в свойстве Delimiter.(см. Пример, 1 случай)

Если в какой-нибудь из строк есть знак, который равен значению, содержащемуся в свойстве Delimiter, то в начало и конец этой строки добавляется знак, содержащийся в свойстве QuoteChar. То же самое будет наблюдаться если в одной из строк присутствует пробел. (см. Пример, 2 случай)

Если же в какой либо строке обнаружен символ QuoteChar, строка делится на участки, которые обрамляются спереди и сзади знаком QuoteChar.(см. Пример, 3 случай)


Свойство CommaText аналогично свойству DelimitedText, но в нем не учитывается свойство Delimiter, оно всегда установлено в нем по умолчанию.(см. Пример, 4 случай)

В остальном эти два свойства схожи.


Рассмотрим примеры:


1 случай:

  Даны две строки:

Цитата

  SomeText1
  SomeText2


Свойства Delimiter и QuoteChar установлены по умолчанию.

Код добавления строк в набор s:
Код


      s.Add('SomeText1');
      s.Add('SomeText2');



Значение DelemitedText:  

Цитата

     SomeText1,SomeText2


Значение CommaText:  

Цитата

   SomeText1,SomeText2



Полный код примера:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Add('SomeText1');
    s.Add('SomeText2');
    ShowMessage(s.DelimitedText);
    ShowMessage(s.CommaText);
  finally
    s.Free;
  end;
end;






2 случай:

Даны две строки:
Цитата


  SomeText1, SomeText2
  SomeText3



Свойства Delimiter и QuoteChar установлены по умолчанию.

Код добавления строк в набор s:

Код

      s.Add('SomeText1,SomeText2');
      s.Add('SomeText3');



Значение DelemitedText:

Цитата

  "SomeText1,SomeText2",SomeText3


Значение CommaText:

Цитата

  "SomeText1,SomeText2",SomeText3


Как видно из примера, свойство Delimiter установленное по умолчанию не игнорируется в CommaText.

Полный код примера:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Add('SomeText1,SomeText2');
    s.Add('SomeText3');
    ShowMessage(s.DelimitedText);
    ShowMessage(s.CommaText);
  finally
    s.Free;
  end;
end;





3 случай:

Даны две строки:

Цитата

  SomeText1"SomeText2
  SomeText3



Свойства Delimiter и QuoteChar установлены по умолчанию.

Код добавления строк в набор s:
Код


    s.Add('SomeText1"SomeText2');
    s.Add('SomeText3');


Значение DelemitedText:

Цитата

  "SomeText1 "" SomeText2",SomeText3


Значение CommaText:

Цитата

  "SomeText1 "" SomeText2",SomeText3


В данном случае Delimiter тоже не игнорируется.

Поный код примера:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Add('SomeText1"SomeText2');
    s.Add('SomeText3');
    ShowMessage(s.DelimitedText);
    ShowMessage(s.CommaText);
  finally
    s.Free;
  end;
end;





4 Случай:

Даны 4 строки:

Цитата

  SomeText1,SomeText2
  SomeText3:SomeText4
  SomeText5"SomeText6
  Some Text 7


Свойства Delimiter = ':'(двоеточие), а свойство QuoteChar установлено по умолчанию.


Код добавления строк в набор s:

Код

      s.Add('SomeText1,SomeText2');
      s.Add('SomeText3:SomeText4');
      s.Add('SomeText5"SomeText6');
      s.Add('Some Text 7');


Значение DelemitedText:  

Цитата

SomeText1,SomeText2:"SomeText3:SomeText4":"SomeText5""SomeText6":"Some Text 7"


Давайте попробуем понять, почему именно так.

1 строка не заключена в знаки QuoteChar, так как в ней нет пробелов, хотя присутствует запятая, но свойство Delimiter было установлено нами в знак двоеточия.

2 строка заключена в знаки QuoteChar, так как в ней присутствует текущее значение свойства Delimiter, то есть двоеточие.

3 строка разделена знаками QuoteChar на две строки:
SomeText5  и   SomeText6
Разделены они были потому, что между ними содержался знак QuoteChar.

4 строка заключена в знаки QuoteChar, так как в ней присутствуют пробелы.


Значение CommaText: 

Цитата

"SomeText1,SomeText2",SomeText3:SomeText4,"SomeText5""SomeText6","Some Text 7"


Тут 1 строка заключена в знаки QuoteChar потому, что любое значение свойства Delimiter, кроме значения по умолчанию, игнорируется в CommaText, но тут-то как раз в этой строке и находится это самое значение по умолчанию — запятая.

2 строка не заключена в знаки QuoteChar по той же причине — для CommaText двоеточие не является значением свойства Delimiter, даже если оно и установлено.

Оставшиеся две строки без изменений по сравнению с DelimitedText.

Полный код примера:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Delimiter := ':';
    s.Add('SomeText1,SomeText2');
    s.Add('SomeText3:SomeText4');
    s.Add(' SomeText5"SomeText6');
    s.Add(' Some Text 7');
    ShowMessage(s.DelimitedText);
    ShowMessage(s.CommaText);
  finally
    s.Free;
  end;
end;



Примечания:
В действительности нет никаких значений "по умолчанию". Просто при чтении и записи CommaText значение QuoteChar = '"', а значение Delimiter = ','.

Вот, например процедура записи CommaText:

Код

procedure TStrings.SetCommaText(const Value: string);
begin
  Delimiter := ',';
  QuoteChar := '"';
  SetDelimitedText(Value);
end;


Из нее видно, что вся установка значения CommaText сводится к установке нужных значений свойств Delimiter и QuoteChar и вызове процедуры установки значения DelimitedText.






Свойство Text.


Объявлено как:

Код

property Text: string read GetTextStr write SetTextStr;



Свойство Text хранит в себе все строки, какие были добавлены в набор, разделенные знаками #13#10.



Пример:

На форме расположены два компонента Tmemo.

Код


procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 9 do
      s.Add('SomeString' + IntToStr(i));
    Memo1.Lines.Add(s.Text);
    Memo2.Lines.AddStrings(s);
  finally
    s.Free;
  end;
end;


Как видите, в Memo1 и Memo2 одинаковый текст.


Записать какую то определенную строку в s.Text можно двумя способами:

Код

s.Text := 'SomeString';


и
Код


s.SetText('SomeString');


Заметьте, что в виде параметра SetText принимает не тип string, а тип PansiChar, что требует явного приведения типов:

Код

procedure TForm1.Button2Click(Sender: TObject);
var
  s : TStringList;
  str : string;
begin
  s := TStringList.Create;
  try
    str := 'SomeString';
    s.SetText(PChar(str));
  finally
    s.Free;
  end;
end;


Так же у TstringList есть метод GetText. С ним я думаю все понятно — он возвращает значение Text.




Метод Append.

Объявлен как:

Код

procedure Append(const S: string);


Выполняет те же действия, что и метод Add, только не возвращает никаких значений, так как сам по себе является не функцией, а процедурой. (Напомним, что метод Add возвращал индекс добавленного элемента).  Реализован так:

Код

procedure TStrings.Append(const S: string);
begin
  Add(S);
end;


Думаю, в дальнейших комментариях не нуждается.



Это сообщение отредактировал(а) THandle - 28.4.2008, 18:03

Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  Examples.rar 404,42 Kb
PM   Вверх
THandle
Дата 28.4.2008, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 65
Всего: 372



Метод Exchange.


Объявлен как:

Код

procedure Exchange(Index1, Index2: Integer); override;


Меняет местами строки с индексами Index1 и Index2.


Пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
begin
  s := TStringList.Create;
  try
    s.Add('FirstString');
    s.Add('SecondString');
    ShowMessage(s.Text);
    s.Exchange(0, 1);
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


Сначала будет показано сообщение:

Цитата


                                  FirstString
                                  SecondString


После вызова s.Exchange будет показано уже другое сообщение:
Цитата


                                 SecondString
                                 FirstString


Первая и вторая строки поменялись местами.




Метод Clear.

Объявлен как:

Код

procedure Clear; override;


Удаляет все строки из набора.

Пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 1 to 5 do
      s.Add('SomeString' + IntToStr(i));
    s.Clear;
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;



Перед вызовом деструктора набор очищать методом Clear не надо, сам очистится, ни куда не убежит.
Будет показано пустое сообщение, так как набор был очищен от строк.




Свойство Sorted.

Объявлено как:

Код

property Sorted: Boolean read FSorted write SetSorted;


Если это свойство равняется true, то все строки в наборе будут сортироваться в алфавитном порядке.
Пример:

Напишем функцию, генерирующую случайные строки задаваемой длины из строчных латинских букв:
Код


function GetRandomString(Len : integer) : string;
var
  i : integer;
begin
  result := '';
  for i := 1 to len do
    result := result + chr(random(26) + 97);
end;



А теперь сам пример использования свойства Sorted:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    randomize;
    for i := 1 to 5 do
      s.Add(GetRandomString(10));
    ShowMessage(s.Text);
    s.Sorted := true;
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


Заметьте, что при показе первого сообщения строки идут в хаотичном порядке, а после - упорядоченные по алфавиту. Сортировка в TstringList реализована с помощью метода быстрой сортировки.

У класса TstringList так же есть метод эквивалентный по своему действию присвоению значения true свойству Sorted — это метод Sort. Метод Sort будет сортировать набор только в том случае, если Sorted = false, что вполне  логично.

То есть вышепредставленный и нижеперечисленный код делают одно и тоже:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    randomize;
    for i := 1 to 5 do
      s.Add(GetRandomString(10));
    ShowMessage(s.Text);
    s.Sort;
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;





Свойство Duplicates.


Объявлено как:

Код

property Duplicates: TDuplicates read FDuplicates write Fduplicates;


Управляет возможностью размещения в наборе идентичных строк. Учитывается только тогда, когда свойство Sorted = true.

Может принимать следующие значения:

dupAccept — в наборе может находиться неограниченное количество одинаковых строк.
dupIgnore — добавлять одинаковые строки нельзя, они будут игнорироваться.
dupError — при попытке добавить в набор строку, которая в нем уже есть, будет возбуждено исключение типа ElistError.

Изначально свойство равно dupIgnore.

Рассмотрим пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    s.Sorted := true;

    //dupIgnore
    for i := 1 to 5 do
      s.Add('SomeText');
    ShowMessage(s.Text);
    s.Clear;

    //dupAccept
    s.Duplicates := dupAccept;
    for i := 1 to 5 do
      s.Add('SomeText');
    ShowMessage(s.Text);
    s.Clear;

    //duError
    s.Duplicates := dupError;
    for i := 1 to 5 do
      s.Add('SomeText');
    ShowMessage(s.Text);

  finally
    s.Free;
  end;
end;


В первом случае будет показано сообщение:
  
Цитата

                                        SomeText






Во втором:
 
Цитата


                                        SomeText
                                        SomeText
                                        SomeText
                                        SomeText
                                        SomeText


В третьем же случае дело до сообщения не дойдет, так как на втором проходе цикла будет поднято исключение и показано сообщение об ошибке.




Метод Find.

Объявлен как:
Код


function Find(const S: string; var Index: Integer): Boolean; virtual;


Ищет строку, переданную в S, возвращает true если строка найдена, и false иначе.
В параметр Index будет записан индекс строки в наборе, если она найдена, иначе index будет равен 1 и использовать его не следует.

Пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 1 to 5 do
      s.Add('SomeString' + IntToStr(i));
    if s.Find('SomeString3', i) then
      s.Delete(i);
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


В этом примере мы сначала добавляем в набор следующие строки:

Цитата

                                         SomeString1
                                         SomeString2
                                         SomeString3
                                         SomeString4
                                         SomeString5


После этого мы ищем в наборе строку 'SomeString3'. Если она найдена, то мы её удаляем.
После чего будет показано сообщение, содержащее следующие строки:

Цитата

                                         SomeString1
                                         SomeString2
                                         SomeString4
                                         SomeString5



Как видите, строка 'SomeString3' была успешно найдена и удалена.





Метод Insert.


Объявлен как:

Код

procedure Insert(Index: Integer; const S: string); override;


Увеличивает  размер набора на 1, после чего сдвигает все элементы находящиеся после индекса Index, в том числе и сам элемент с этим индексом, в конец набора, и на освободившуюся позицию вставляет строку S.

Выглядит это так:

Есть у нас некий набор S(элементы разделены чертой):
                                
Цитата

                                   S0|S1|S2|S3|S4


После чего в набор добавляем новый элемент методом Insert:

Код

  S.Insert(2, S5);

  
Получается следующий набор строк:
Цитата


                                  S0|S1|S5|S2|S3|S4


Теперь рассмотрим этот пример в виде кода:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 4 do
      s.Add('S' + IntToStr(i));
    s.Insert(2, 'S5');
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


Добавлено @ 17:55
Метод InsertObject.

Объявлен как:

Код

procedure InsertObject(Index: Integer; const S: string; AObject: TObject); override;


Аналогичен методу Insert, только вставляет не только строку, но и некоторый объект. Думаю с этим методом и так все понятно, и пример можно не приводить.




Метод Move.

Объявлен как:

Код

procedure Move(CurIndex, NewIndex: Integer); virtual;


Перемещает элемент с индексом CurIndex, на место с индексом NewIndex.
Происходит это так:

Значения строки и объекта, которые надо переместить  заносятся во временные переменные, после чего элемент с индексом  CurIndex удаляется методом Delete.
После чего происходит вызов InsertObject, в параметрах которого передаются временные переменные, со значениями, взятыми из уже удаленного элемента CurIndex.
Вот так выглядит код перемещения:

Код

procedure TStrings.Move(CurIndex, NewIndex: Integer);
var
  TempObject: TObject;
  TempString: string;
begin
  if CurIndex <> NewIndex then
  begin
    BeginUpdate;
    try
      TempString := Get(CurIndex);
      TempObject := GetObject(CurIndex);
      Delete(CurIndex);
      InsertObject(NewIndex, TempString, TempObject);
    finally
      EndUpdate;
    end;
  end;
end;



А теперь рассмотрим пример использования метода Move:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 1 to 5 do
      s.Add('SomeString' + IntToStr(i));
    s.Move(1,4);
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


В этом примере мы сначала добавляем в массив 5 строк, после чего мы перемещаем строку с индексом 1(там будет находиться строка 'SomeString2') на место с индексом 4.




Методы SaveToStream, LoadFromStream.


Объявлены как:

Код

procedure SaveToStream(Stream: TStream); virtual;


Код

procedure LoadFromStream(Stream: TStream); virtual;


Процедура SaveToStream сохраняет набор строк в поток Stream.
Поток должен быть создан, перед тем как будет произведено сохранение в него.

Процедура LoadFromStream загружает набор строк из потока Stream.

Пример:

Допустим, у нас есть некая глобальная переменная:

Код

var
  Stream : Tstream;


В OnCreate формы он создается:

Код

procedure TForm1.FormCreate(Sender: TObject);
begin
  Stream := TMemoryStream.Create;
end;


Так как класс Tstream — абстрактный, создаем объект класса TmemoryStream.

Текст мы будем брать не из какого-нибудь объекта класса TstringList, а из компонента Memo лежащего на форме. Так, по-моему, будет более наглядно.

Запись(заодно после неё мы очистим Memo от текста):

Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.SaveToStream(Stream);
  Memo1.Clear;
end;


Чтение:

Код

procedure TForm1.Button2Click(Sender: TObject);
begin
  Stream.Position := 0;
  Memo1.Lines.LoadFromStream(Stream);
end;


Полный пример находится в архиве, прикреплённом в конце статьи, в папке №1.





Методы SaveToFile,  LoadFromFile.

Объявлены как:
Код


procedure SaveToFile(const FileName: string); virtual;


Код

procedure LoadFromFile(const FileName: string); virtual;



Процедура SaveToFile сохраняет все строки набора в файл, а процедура LoadFromFile соответственно загружает текст из файла.
На самом же деле в обеих процедурах вызываются методы SaveToStream, LoadToStream с переданными в них заранее созданными объектами класса TfileStream(файловый поток). 

Для наглядности процедура сохранения выглядит так:
Код


procedure TStrings.SaveToFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(Stream);
  finally
    Stream.Free;
  end;
end;



А процедура загрузки из файла так:


Код

procedure TStrings.LoadFromFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;


Пример:

На форме в этот раз будет очень много компонентовsmile
А точнее:

  TopenDialog, TsaveDialog, Tmemo, 2xTButton.

Обработчики кнопок выглядят следующим образом:

Кнопка сохранения текста в файл:

Код

procedure TForm1.Button1Click(Sender: TObject);
begin
  if SaveDialog1.Execute then
    Memo1.Lines.SaveToFile(SaveDialog1.FileName + '.txt');
end;


Кнопка загрузки из файла текста:
Код


procedure TForm1.Button2Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
end;


Полный пример находится в прикрепленном архиве в папке №2.





Метод Equals.

Объявлен как:

Код

 function Equals(Strings: TStrings): Boolean;


Сравнивает наборы строк(тот в котором вызывается метод и тот который передан в параметре Strings). Возвращает true если наборы содержат одинаковое количество строк, длина которых в обоих наборах равна, возвращает false если наборы различаются по длине, либо содержат различные наборы строк, либо порядок строк в наборах отличается друг от друга. Сравнивает только строки. Игнорирует все объекты(Objects). Так же при сравнении учитывается регистр символов.

Рассмотрим примеры:

1.    Пример в котором вызов Equals возвращает true.

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s1, s2 : TStringList;
  i : integer;
begin
  s1 := TStringList.Create;
  s2 := TStringList.Create;
  try
    for i := 0 to 9 do
      begin
        s1.Add('SomeText' + IntToStr(i));
        s2.Add('SomeText' + IntToStr(i));
      end;
    if s1.Equals(s2) then
      ShowMessage('Вызов Equals дал true:)');
  finally
    s2.Free;
    s1.Free;
  end;
end;

   

2.    Пример, в котором вызов Equals возвращает true.


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  s1, s2 : TStringList;
  i : integer;
begin
  randomize;
  s1 := TStringList.Create;
  s2 := TStringList.Create;
  try
    for i := 0 to 9 do
      begin
        s1.Add('SomeText' + IntToStr(i));
        s2.Add('SomeText' + IntToStr(Random(i)));
      end;
    if s1.Equals(s2) then
      ShowMessage('Вызов Equals дал true:)');
  finally
    s2.Free;
    s1.Free;
  end;
end;







События OnChange, OnChanging.

Объявлены как:

Код

    property OnChange: TNotifyEvent read FOnChange write FOnChange;


Код

    property OnChanging: TNotifyEvent read FOnChanging write FonChanging;



Событие OnChanging возникает при вызове одного из методов добавления(Add, Insert...), но когда строка еще не добавлена в набор.

Событие OnChange возникает при завершении операции добавления.




Метод IndexOf.

Объявлен как:

Код

function IndexOf(const S: string): Integer; override;



Ищет в наборе строку S, если она найдена, то возвращает её индекс, иначе возвращает -1.

Пример:


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  S : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 1 to 5 do
      s.Add('SomeText' + IntToStr(i));
    s.Delete(s.IndexOf('SomeText3'));
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


В этом примере строка 'SomeText3' была успешно найдена и удалена.





Метод IndexOfObject.


Объявлен как:

Код

 function IndexOfObject(AObject: TObject): Integer; virtual;


Полностью аналогичен методу IndexOf, только ищет не строку, а объект. Если ничего не найдено, то возвращает -1. Думаю, в примере не этот метод не нуждается, так как все показано в примере к IndexOf.




Свойство NameValueSeparator.



Объявлено как:

Код


property NameValueSeparator: Char read GetNameValueSeparator write SetNameValueSeparator;


В наборе TstringList могут находиться строки, которые состоят из имени и значения, разделенных некоторым знаком, которым и является свойство NameValueSeparator.
Например, если это свойство равно знаку '='(это значение свойства по умолчанию), то строки в TstringList будут выглядеть так:

Цитата

           Имя = Значение


Например, с помощью этого механизма имен-значений реализованы Ini-файлы(класс TiniFile).




Свойства Names, Values.

Объявлены как:
Код


property Names[Index: Integer]: string read GetName;


Код

property Values[const Name: string]: string read GetValue write SetValue;


В свойстве Names хранятся все "имена" строк, а в свойстве Values соответственно "значения".(В кавычках потому, что хранятся то те же самые обычные строки, просто представление другое)

Обращаться к "именам" нужно по индексу строки, а к "значениям" по "имени".

Рассмотрим пример:
На форме находятся два компонента Tmemo. В один из них мы выведем список "имен" сформированного набора, а во второй список "значений".

Значение NameValueSeparator установлено по умолчанию и является знаком '='(равно).


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  S : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 4 do
      s.Add('Name' + IntToStr(i) + s.NameValueSeparator + 'Value' + IntToStr(random(100)));
    for i := 0 to 4 do
      begin
        Memo1.Lines.Add(s.Names[i]);
        Memo2.Lines.Add(s.Values[s.Names[i]]);
      end;
  finally
    s.Free;
  end;
end;






Метод IndexOfName.

Объявлен как:
Код


function IndexOfName(const Name: string): Integer; virtual;


Возвращает индекс переданного в Name "имени". Если "имя" не найдено, 
то возвращает -1.

Пример:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  S : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 4 do
      s.Add('Name' + IntToStr(i) + s.NameValueSeparator + 'Value' + IntToStr(random(100)));
    i := s.IndexOfName('Name2');
    if i <> -1 then
      s.Delete(i);
    ShowMessage(s.Text);
  finally
    s.Free;
  end;
end;


Строка, в которой содержалось "имя" 'Name2' была успешно найдена и удалена. Удалена была вся строка — и "имя" и "значение".





Свойство ValueFromIndex.

Объявлено как:

Код

property ValueFromIndex[Index: Integer]: string read GetValueFromIndex write SetValueFromIndex;


Тоже самое, что и Values, только обращаться к "значениям" с помощью этого свойства надо не по "имени", а по индексу.

То есть с использованием этого свойства, пример, данный в описании свойств Names и Values, выглядел бы так:


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  S : TStringList;
  i : integer;
begin
  s := TStringList.Create;
  try
    for i := 0 to 4 do
      s.Add('Name' + IntToStr(i) + s.NameValueSeparator + 'Value' + IntToStr(random(100)));
    for i := 0 to 4 do
      begin
        Memo1.Lines.Add(s.Names[i]);
        Memo2.Lines.Add(s.ValueFromIndex[i]);
      end;
  finally
    s.Free;
  end;
end;





Статья была написана при поддержке модуля Classes.pas









Хочу выразить ОГРОМНУЮ благодарность Rrader'у за полезные замечания по статье. smile 

Это сообщение отредактировал(а) THandle - 28.4.2008, 17:58

Присоединённый файл ( Кол-во скачиваний: 31 )
Присоединённый файл  Examples.rar 404,42 Kb
PM   Вверх
Arch1S
Дата 28.4.2008, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 14.1.2008
Где: Беларусь, Гомель

Репутация: 1
Всего: 3



отличная статья THandle smile 
PM MAIL   Вверх
Ofer
Дата 28.4.2008, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 293
Регистрация: 15.10.2006
Где: КривбаСС

Репутация: 1
Всего: 5



Статья что надо!! Стараешся! Полезный ты человек smile 
PM MAIL ICQ   Вверх
Rohoss
Дата 28.4.2008, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начальник интернета
***


Профиль
Группа: Завсегдатай
Сообщений: 1308
Регистрация: 9.10.2006
Где: Matrix

Репутация: 4
Всего: 18



Спасибо за статью! smile  Было бы не плохо, если бы она была ещё и в формате .doc, так удобней распечатывать.  smile

Добавлено через 9 минут и 44 секунды
Между прочим у меня Антивирус Касперского 7 находит в ехе вот такого зверя Virus.Win32.Hidrag.a 


--------------------
Файловый менеджер Explorer.Net скачать  video
PM ICQ   Вверх
Rrader
  Дата 29.4.2008, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 70
Всего: 191



Продолжай в том же духе!  smile  smile 


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
THandle
Дата 29.4.2008, 07:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 65
Всего: 372



Arch1SOferRohossRrader, спасибо!!! smile  

 
Цитата(Rohoss @  29.4.2008,  00:42 Найти цитируемый пост)
Было бы не плохо, если бы она была ещё и в формате .doc, так удобней распечатывать.



Элементарно smile  Прикрепил к этому сообщению.

Цитата(Rohoss @  29.4.2008,  00:42 Найти цитируемый пост)
Между прочим у меня Антивирус Касперского 7 находит в ехе вот такого зверя Virus.Win32.Hidrag.a  


Понятия не имею почему. В екзешниках только тот код который лежит в соседних исходниках. Я бы никогда не стал бы вирусы выкладывать намеренно. Может какой внешний вирус залез...

Rohoss, попробуй у себя скомпилировать в отдельной папочке эти проектики и проверь получившиеся exe на вирусы. Если в моих действительно вирус есть, то их надо удалить из архива. У меня просто нет антивируса.

Присоединённый файл ( Кол-во скачиваний: 32 )
Присоединённый файл  TStringList.doc 186,00 Kb
PM   Вверх
Poseidon
Дата 29.4.2008, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Не плохо!

Не большео дополнение:

Про Find необходимо добавить что этот метод подходит только для сортированных списков (Sort = True). Для не сортированных нужно использовать IndexOf.

Ну и про Delete нужно бы отдельно "тыкнуть носом" в тот факт, что после удаление количество строк в списке (Count) уменшается. В связи с этом код:
Код
procedure TForm1.Button1Click(Sender: TObject);
var
s: TStringList;
i: integer;
begin
s:= TStringList.Create;
for i:= 1 to 10 do
s.Add('String #' + IntToStr(i));

for i:= 0 to s.Count-1 do // <--- Не верно!!!
if какое-то_условие then s.Delete(i);

s.Free;
end;
Может вызвать ошибку, потому как изначально s.Count-1 равно 10, а после удаления будет уже 9 или менше. В итоге мы можем попытаться удалить строку с индексом, которого уже нет. Правильно будет так:
Код
procedure TForm1.Button1Click(Sender: TObject);
var
s: TStringList;
i: integer;
begin
s:= TStringList.Create;
for i:= 1 to 10 do
s.Add('String #' + IntToStr(i));

for i:= s.Count-1 downto 0 do // <--- Верно.
if какое-то_условие then s.Delete(i);

s.Free;
end;


Обращаю на это особое внимание, т.к. это очень распространенная ошибка у новичков.



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
THandle
Дата 29.4.2008, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 65
Всего: 372



Poseidon, спасибо smile 

В ближайшие дни добавлю вместе с другими дополнениями. smile 
PM   Вверх
Akella
Дата 11.12.2008, 21:08 (ссылка)  | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 36
Всего: 329



В новых версиях Delphi появился THashedStringList.
В некоторых случаях он работает на много быстрее.
PM MAIL   Вверх
Romikgy
Дата 12.12.2008, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7325
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 26
Всего: 146



про метод Assign имхо забыли упомянуть !


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Kbl4AH
Дата 12.1.2009, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 741
Регистрация: 1.4.2008
Где: Вятка

Репутация: 1
Всего: 15



THandle, пиши еще и побольше. Очень понра. Спасибо!!!
PM MAIL ICQ   Вверх
SergeyLS
Дата 28.2.2009, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 20.2.2009
Где: Москва

Репутация: нет
Всего: нет



Пишите еще, мне очень помогло!
Спасибо!

Это сообщение отредактировал(а) SergeyLS - 28.2.2009, 19:06
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2713 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.