Чудесата на TStringList

Object Pascal, комбиниран с асемблер в неговата съвременна форма Delphi 5/6/7, предоставя неограничени възможности за летене на мислите на програмиста и с тази статия ще отворим поредица, в която последователно ще демонстрираме това.

Ще започнем с един прост, изключително полезен, но малко известен, поне за начинаещи, стандартен Delphi TStringList клас. Сега ще видим колко красиво се решават типични задачи с този клас.

Като начало, накратко, какви прекрасни свойства имат обектите от този клас. TStringList е клас, предназначен да съхранява списък от низове и списък от обекти с текстово представяне (точно както в 1C - това е списък със стойности). Освен това този списък може да бъде сортиран по азбучен ред или чрез функция за сравнение, написана от програмиста. Освен това този списък може да се интерпретира като списък със стойности (Име=низ). Освен това този списък може да бъде записан във файл или поток, преобразуван в непрекъснат низ или низ, разделен със запетая. Физически полученият ред или поток е обикновен текст, в който редовете са разделени със знаци CR / LF (стандартен текстов файл на Windows) или запетаи (CommaText, Excel). Е, разбира се, възможно е да се зареди списък с низове от файл, поток, низ и низ, разделен със запетая. Специално внимание заслужава забележителното свойство на опаковане в низ, разделен със запетая: при обратно разопаковане низовете винаги се възстановяват в оригиналната си форма. Това означава, че е разрешено многократно влагане на низове, разделени със запетая, което дава огромна печалба при пакетиране/разопаковане на многомерни структурни данни в текстов формат, което ще демонстрираме.във втората задача.

Така че, като начало, нека разгледаме списък от низове като списък от обекти с текстово представяне, тъй като това е начинът, по който списъкът от низове трябва да се използва в реални приложения. Какво е обект за представяне на текст? Това може да бъде например списък с продукти, които освен името имат и допълнителни параметри като мерна единица, количество в опаковката и цена. И така, имаме предварително определение на типа:

Наборът от обекти TTovar е класическа директория на хомогенни продукти, като например хлебни изделия. Полето Тегло в класа TedIzm е необходимо за преобразуване на една единица в друга. Да се ​​върнем на нашите хлебчета. Да предположим, че доставчикът „Karyakinsky Khlebozavod“ ни предостави текстов файл, съдържащ информация за неговите нови продукти и продажни цени в текстов формат:

Ако решите този проблем директно (като четене ред по ред и анализиране на текстов файл), както и директно добавяне към ListBox, това ще доведе до неефективна работа на компютъра, забавяне (на слаби машини) и като цяло за по-нататъшни промени в програмния код това решение не е най-доброто. Много по-ефективно е да направите трик с ушите си, а именно да създадете TStringList, да заредите изходния файл в него, да създадете втори TStringList, да заредите продуктите в него, да ги сортирате и накрая да присвоите свойството ListBox.Items:

Имайте предвид, че ако напишем функция от типа TStringListSortCompare, тогава ще бъде възможно да сортирате не само по представянето на текста, но и по всякакви други критерии, например по цена:

Е, накрая ще демонстрираме реакцията при двойно щракване върху получения списък с продукти. С двойно щракване ще покажем продажната цена на артикула:

Между другото, не забравяйте да освободите системните ресурси на обектите преди товаизтриване на низове с помощта на методите ListBox1.Items.Delete()/Clear() или str.Delete()/Clear() (str:TStringList), ако е необходимо, както и при затваряне на приложението:

Сега нека усложним малко задачата. Да предположим, че имаме не един файл, а десет - от десет различни доставчика. Трябва да изтеглим общо 20 000 заглавия и след това да ги сортираме. Ако направим точно това, сортирането на толкова голям списък от обекти ще отнеме значително време и това е проблемът. Такава задача обаче се решава много просто - след създаването на обекта TStringList е достатъчно веднага да присвоите свойството му Sorted на true. След това вмъкването на нови редове ще се извърши с помощта на бърз алгоритъм, но възможността за сортиране по параметрите на прикачените обекти ще бъде загубена, т.к. в случай на Sorted=true, сортирането се извършва автоматично само чрез текстово представяне (вижте източниците на TStringList). Когато Sorted=true, обработката на дубликати се определя от свойството Duplicates. Можете да пропускате, активирате и деактивирате дублирани обекти с едно и също представяне на текст. В същото време, ако дубликатите са пропуснати или забранени, е необходимо да се следи освобождаването на ресурси на обекти, които не са добавени в списъка. По подразбиране свойството Duplicates е настроено на dupIgnore, което означава, че дубликатите се пропускат, така че по подразбиране се следи за освобождаване на ресурси.

Струва си да се отбележи, че когато записвате или зареждате списък с низове, обектите, прикачени към низове, не се записват или възстановяват в стандартния TStringList, но можете много добре да разрешите този проблем - да напишете наследник на TStringList с отменени GetTextStr и SetTextStr процедури, в които да измислите и реализирате свой собствен формат за съхраняване на обекти и тяхното текстово представяне като непрекъснато текстово представянетекст.

И така, видяхме, че TStringList ви позволява да решавате голямо разнообразие от задачи от групиране на обекти с текстово представяне до просто обработване на списък от стойности на променливи. Сега нека видим как този клас ви позволява да решавате проблемите с опаковането / разопаковането на сложно структурирани данни в текстова форма и обратно. Такава задача много често възниква при комуникационни задачи, например при прехвърляне на данни по мрежа или между софтуерни модули.