Классы TStrings и TStringList – наборы строк и объектов
Класс TStrings.Абстрактный класс TStrings инкапсулирует поля и методы для работы с наборами строк. От него порождены многочисленные специализированные потомки, обслуживающие наборы строк в таких компонентах, как TComboBox, TListBox, TRichEdit и др. Эти классы (TComboBoxStrings, TListBoxStrings, TRichEditStringsи др.) объявляются в разделах Implementation соответствующих модулей (StdCtrls, СomCtrls и др.) и поэтому скрыты от браузера Delphi и не включены в справочную службу. Единственным доступным наследником TStrings является TStringList - полнофункциональный класс общего назначения.
Замечательной особенностью TStrings и его потомков является то обстоятельство, что элементами наборов служат пары строка-объект, в которых строка - собственно строка символов, а объект - объект любого класса Delphi. Такая двойственность позволяет сохранять в TStrings объекты с текстовыми примечаниями, сортировать объекты, отыскивать нужный объект по его описанию и т.д. Кроме того, в качестве объекта может использоваться потомок от TStrings, что позволяет создавать многомерные наборы строк.
Набор строк технически реализуется подобно TList - в виде массива указателей. Свойство Capacity показывает текущую длину этого массива, а свойство Count - количество элементов, занятых в нем. Свойство CommaText интерпретирует содержимое набора строк в виде одной длинной строки с элементами вида "первая строка", "вторая строка", "третья строка" и т. д. (каждая строка набора заключается в двойные кавычки и отделяется от соседней строки запятой; если в строке встречается символ “"”, он удваивается). Свойство Text интерпретирует содержимое набора в виде одной длинной строки с элементами, разделенными стандартным признаком Eoln (#13#10). Методы Add, Append, Insert, Clear и т.п. в классе TStrings - абстрактные. Связано это с тем, что класс инкапсулирует их и таким образом делает доступными во всех потомках, но он при этом не накладывает никаких ограничений на то, как располагаются в памяти строки и объекты. Каждый потомок решает эту задачу наиболее удобным для него способом.
Класс TStringList.TStringList представляет собой полнофункциональный класс общего назначения и является прямым потомкам TStrings. Помимо перекрытых абстрактных методов своего родителя класс включает в себя такие дополнительные методы и свойства (табл. 21):
Таблица 21
property Duplicates: TDuplicates; | Свойство, позволяющее управлять возможностью размещения в наборе двух и более идентичных строк |
property Sort: Boolean; | Признак необходимости сортировки строк в алфавитном порядке |
property OnChange: TNotifyEvent;; | Определяет реакцию на изменение набора строк. Возникает после последнего изменения |
property OnChanging: TNotifyEvent | Определяет реакцию на изменение набора строк. Возникает до очередного изменения |
function Find(const S:String; var Index: Integer) : Boolean; | Ищет в наборе строку S и в случае успеха в параметре Index возвращает ее индекс |
При Sort = True строки набора автоматически сортируются в алфавитном порядке. При этом свойство Duplicates разрешает коллизию, связанную с добавлением в набор строки, идентичной одной из ранее вставленных. Если Duplicates = DuIgnore, идентичная строка отвергается и программе ничего об этом не сообщается; если Duplicates = DuError, возбуждается исключение EListError; значение Duplicates = DuAccept разрешает вставлять в набор сколько угодно идентичных строк.
Строки в 32-разрядных Windows сортируются не с учетом внутреннего кода символа, а с учетом «смысла»: в начале располагаются все знаки препинания и разного рода «мусор», затем идут цифры, буквы латинского алфавита и символы кириллицы. Буквы упорядочены парами - сначала заглавная, за ней строчная. «Виновником» такой сортировки является API-функция AnsiCompareText, к которой обращается метод TStringList.Quicksort.
Отсортировать строки в поле Memo1 можно следующим образом:
…
Var str:TSTringList; i:integer;
Begin
str:=TStringList.Create;
For i:=0 to Memo1.Lines.Count-1 do
str.Add(Memo1.Lines[i]);
str.Sort;
Memo1.Lines.Clear;
For i:=0 to str.Count-1 do Memo1.LineS.Add(str[i]);
str.Free;
End;