16.3.2. TStringList

TStringList представляет собой полнофункциональный класс общего назначения и является прямым потомкам TStrings. Помимо перекрытых абстрактных методов своего родителя класс включает в себя такие дополнительные методы и свойства:

property Duplicates: TDu-plicates; | Свойство, позволяющее управлять возможностью размещения в наборе двух и более идентичных строк
property Sorted: Boolean; | Признак необходимости сортировки строк в алфавитном порядке
property OnChange: TNotifyEvent;; | Определяет реакцию на изменение набора строк. Возникает после последнего изменения
property OnChanging: TNotifyEvent | Определяет реакцию на изменение набора строк. Возникает до очередного изменения
function Find(const S:String; var Index: Integer) : Boolean; | Ищет в наборе строку S и в случае успеха в параметре index возвращает ее индекс

При sorted = True строки набора автоматически сортируются в алфавитном порядке. При этом свойство Duplicates разрешает коллизию, связанную с добавлением в набор строки, идентичной одной из ранее вставленных. Если Duplicates = dulgnore, идентичная строка отвергается и программе ничего об этом не сообщается; если Duplicates = duError, возбуждается исключение EListError; значение Duplicates = duAccept разрешает вставлять в набор сколько угодно идентичных строк.

Следует заметить, что сортировка строк в Windows 32 осуществляется не совсем так, как это происходит в MS-DOS или Windows 3-х. Чтобы убедиться в этом, советую прогнать следующий вариант учебной программы (см. рис. 16.1). В ней обработчик события OnClick кнопки bbRun создает два списка строк - List1и List2. Список List1 первоначально способен сортировать строки (в его свойство sorted устанавливается значение True). Затем в цикле от 32 до 255 (О...31 - это коды служебных символов) происходит наполнение обоих списков: в List1 помещается строка, содержащая символ и его код, а в List2 - наоборот, сначала код, а затем сам символ. Поскольку символьное представление кода дополняется до трех символов (в двузначных числах слева добавляется ведущий ноль), строки в списке List1 окажутся отсортированными по символу, а в списке List2 - по коду символа. Затем оба списка для наглядности объединяются и помещаются в редактор mmOutput.

procedure TfmExample.bbRunClick (Sender: TObject);

var

k: Byte;

Listi, List2: TStringList;

S: String;

begin

// Создаем два списка

List1 := TStringList.Create;

Listi.Sorted := True;

List2 := TStringList.Create;

// Цикл наполнения списков монотонно возрастающими кодами

for k := 32 to 255 do

begin

S := IntToStr(k); // Код символа

if k<100 then

S := '0' + S;// Двузначное число дополняем ведущим нулем

// Формируем строку Listi из символа + табуляция + код символа Listi.Add(Char(k) + #9 + S) ;

// Формируем строку List2 из кода + табуляция + символ

List2.Add(S + #9 + Char(k));

end;

// Объединяем оба списка

Listi.Sorted := False; // Отключаем сортировку List1

for k := 0 to List1.Count-1 do

List1[k] := List1[k] + #9 + List2[k];

// Переносим результат в mmOutput mmOutput.Lines.Assign(List1);

// Уничтожаем List1 и List2 Listi.Free;

List2. Free;

end;

Следует прокомментировать два момента. Во-первых, с помощью единственного оператора

mmOutput.Lines.Assign(List1);

все строки List1 помещаются в свойство Lines редактора mmOutput. Это возможно из-за того, что mmOutput. Lines и Listi имеют общего родителя TStrings, который умеет копировать родственные наборы строк с помощью своего метода Assign. Во-вторых, перед объединением строк мы отключили свойство Sorted списка Listi. если этого не сделать, любое изменение строк в отсортированном списке привело бы к исключентю EStringListError.

Рис. 16.1. Окно прогона программы сравнения сортировки строк для Windows 32 и Windows З.х

Как видим, строки в 32-разрядных Windows сортируются не с учетом внутреннего кода символа, а с учетом “смысла”: в начале располагаются все знаки препинания и разного рода “мусор”, затем идут цифры, буквы латинского алфавита и символы кириллицы. Буквы упорядочены парами - сначала заглавная, за ней строчная - и не идут сплошным массивом. “Виновником” такой сортировки является API-функция AnsiCompareText, К который обращается метод TStringList. Quicksort. Если вам понадобится отсортировать так, как это принято в MS-DOS или Windows З.х, т. е. по коду символа, проделайте следующее.

1. Разыщите в каталоге source | Rtl | common исходный файл classes . pas и скопируйте его в ваш рабочий каталог (в предыдущих версиях этот файл располагался в каталоге Source | vci). Если вы не найдете этого файла, вы не сможете изменить сортировку, т. к. в классе TStringList метод Quicksort, отвечающий за сортировку, определен в секции private и, следовательно, недоступен наследникам.
2. В раздел implementation этого модуля сразу после предложения Uses поместите такое описание функции AnsiCompareText:

Function AnsiCompareText(SI, S2 : String): Integer;

begin

if S1 < S2 then Result := -1

else if SI == S2 then Result := 0

else Result := 1

end;

3. С помощью опции Project | Add To Project добавьте измененный модуль classes к вашему проекту и сделайте новый прогон программы. Теперь оба столбца будут идентичны.