Как сделать список в delphi
Программирование списков в среде Delphi
Цель: Ознакомить учащихся с основными свойствами и методами создания списков при составлении программ в среде Delphi
Сегодня на занятии мы познакомимся с созданием и программированием списков.
Как вы понимаете, что такое список?
Под списком будем понимать упорядоченную последовательность текстовых строк.
Вопрос учителя: Ребята, а где в повседневной жизни вы встречались с понятием “СПИСОК”?
Учащиеся: В журнале список учащихся, список дел на текущую неделю в еженедельнике.
Давайте познакомимся с различными видами списков, используемых при составлении программ в среде Delphi.
Откройте файл C:\МОИ ДОКУМЕНТЫ\ПРИМЕР1\пример1.exe.
Вашему вниманию представлена демонстрация трех, наиболее часто используемых видов списков.
Листинг программы представлен ниже.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
procedure ListBox1Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure ColorBox1Change(Sender: TObject);
procedure TForm1.ListBox1Click(Sender: TObject);
case ListBox1.itemindex of
procedure TForm1.ComboBox1Change(Sender: TObject);
case ComboBox1.itemindex of
procedure TForm1.ColorBox1Change(Sender: TObject);
Оформление программы представлено на рис. 1.
Учитель: В курсе БКП вы учились работать со многими готовыми программами. Вспомните, в каких программах вы встречались с рассмотренными видами списков.
Учащиеся: В Microsoft Word и Microsoft Excel – параметры шрифта.
Сегодня мы посмотрим, какие компоненты применяются для программирования списков, какими свойствами и методами они обладают.
На наших занятиях мы уже изучали компоненты, представляющие собой список текстовых строк. Это многострочный редактор Memo и группа зависимых переключателей RadioGroup.
Свойства указанных выше компонентов схожи со свойствами списков. Давайте вспомним их.
Для этого поиграем в игру “Домино”.
После выполнения данного задания поменяться карточками с ребятами, сидящими за компьютером справа, Проверить выполнение заданий, поставить оценку и написать фамилии проверявших на визитке (находится на лицевой стороне холста) и вложить в соответствующий конверт.
Правильные ответы зачитываются преподавателем
Время проверки 20 – 30 секунд
Вопросы и Ответы:
Вопрос | Предлагаемые варианты ответов | |
Правильные | Неправильные | |
Свойство, определяющее порядковый номер выбранного переключателя в радиогруппе | ItemIndex | ItemName |
Компонент, представляющий собой группу взаимозависимых переключателей | Radiogroup | Radiobutton |
Свойство радиогруппы, определяющее названия и количество переключателей | Items | Text |
Метод Memo для добавления строки текста в конец текста | Add | Load |
Метод Memo, позволяющий вставить строку текста перед заданной строкой | Insert | Insert |
Свойство Memo, определяющее количество строк текста и их содержание | Lines | MultiSelect |
Очистка Memo | Clear | Align |
Удаление строки текста из текста Memo | Delete | DeleteLines |
Метод, позволяющий загрузить данные из текстового файла в Memo | LoadFromFile | Visible |
Метод сохранения текста Memo в текстовый файл | SaveToFile | Save |
Вывод: мы повторили основные свойства и методы компонентов Memo и Radiogroup.
А теперь познакомимся со свойствами и методами простого списка ListBox.
Откройте файл C:\МОИ ДОКУМЕНТЫ\ПРИМЕР2\пример2.exe.
Внешний вид программы представлен на рис. 2.
Листинг программы представлен ниже:
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Списки
Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.
Указатели и динамические переменные позволяют создавать сложные динамические структуры данных, такие как списки и деревья.
Список можно изобразить графически (рис. 8.5).
Рис. 8.5. Графическое изображение списка
Для того чтобы программа могла использовать список, надо определить тип компонентов списка и переменную-указатель на первый элемент списка. Ниже приведен пример объявления компонента списка студентов:
type TPStudent = »»TStudent; // указатель на переменную типа TStudent
// описание типа элемента списка TStudent = record
surname: string[20]; // фамилия
name: string[20]; // имя
group: integer; // номер труппы
address: string[60]; // домашний адрес
var head: TPStudent; // указатель на первый элемент списка
Добавлять данные можно в начало, в конец или в нужное место списка. Во всех этих случаях необходимо корректировать указатели. На рис. 8.6 изображен процесс добавления элементов в начало списка.
Рис. 8.6. Добавление элементов в список
Следующая программа, ее текст приведен в листинге 8.4, формирует список студентов, добавляя фамилии в начало списка. Данные вводятся в поля редактирования диалогового окна программы (рис. 8.7) и добавляются в список нажатием кнопки Добавить (ви№оп1).
Рис. 8.7. Окно программы Динамический список 1
\ Листинг 8.4. Добавление элемента в начало динамического списка
Editl: TEdit; // фамилия
Buttonl: TButton; // кнопка Добавить
Button2: TButton; // кнопка Показать
<$R *.DFM>type TPStudent=/4TStudent; // указатель на тип TStudent
f_name:string[20]; // фамилия l_name: string[20]; // имя
next: TPStudent; // следующий элемент списка
var head: TPStudent; // начало (голова) списка
// добавить элемент в начало списка
procedure TForml.Button2Click(Sender: TObject); var curr: TPStudent; // текущий элемент списка n:integer; // длина (кол-во элементов) списка
st:string; // строковое представление списка
Добавление элемента в список выполняет процедура TFormi.Buttoniciick, которая создает динамическую переменную-запись, присваивает ее полям значения, соответствующие содержимому полей ввода диалогового окна, и корректирует значение указателя head.
Вывод списка выполняет процедура TForml. Button2ciick, которая запускается нажатием кнопки Показать. Для доступа к элементам списка используется указатель curr. Сначала он содержит адрес первого элемента списка. После того как первый элемент списка будет обработан, указателю curr присваивается значение поля next той записи, на которую указывает curr. В результате этого переменная curr содержит адрес второго элемента списка. Таким образом, указатель перемещается по списку. Процесс повторяется до тех пор, пока значение поля next текущего элемента списка (элемента, адрес которого содержит переменная curr) не равно nil.
Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.
Класс TList позволяет создать набор из произвольного количества элементов и организовать индексный способ доступа к ним, как это делается при работе с массивом. Списки отличаются от массивов двумя важными особенностями. Во-первых, их размер может динамически меняться в ходе работы программы, фактически ограничиваясь лишь доступной памятью. Во-вторых, в списках могут храниться элементы разных типов.
Далее перечислены наиболее важные свойства класса TList.
property Capacity: Integer;
Содержит количество элементов массива указателей списка. Всегда больше Count. Если при добавлении очередного элемента значение Count стало равно Capacity, происходит автоматическое расширение списка на 16 элементов.
property Count: Integer;
Количество элементов списка. Это свойство изменяется при добавлении или удалении элемента.
property Items(Index: Integer): Pointer;
Возвращает указатель на элемент списка по его индексу. Самый первый элемент списка имеет индекс 0.
property List: pPointerList;
Возвращает указатель на массив элементов списка.
Тип pPointerList определен следующим образом:
TPointerList « array [0..MaxListSize] of Pointer;
Константа MaxListSize для Delphi 1 ограничена значением 16 379 элементов. Для 32-разрядных версий Delphi она ограничивается доступной памятью.
Далее перечислены некоторые методы класса TList. function Add(Item: Pointer): Integer;
Добавляет элемент Item в конец списка и возвращает его индекс, procedure Clear;
Очищает список, удаляя из него все элементы. Не освобождает память, связанную с каждым удаленным элементом. Устанавливает в свойства Count и Capacity значение 0.
procedure Delete(Index: Integer);
Удаляет из списка элемент с индексом Index. Все элементы, расположенные за удаляемым, смещаются на одну позицию вверх.
procedure Exchange(Indexl, Index2: Integer);
Меняет местами элементы с индексами Indexl и Index2. function Expand: TList;
Расширяет массив элементов, увеличивая значение Capacity.
function First: Pointer;
Возвращает указатель на самый первый элемент списка, function IndexOf(Item: Pointer): Integer;
Отыскивает в списке элемент Item и возвращает его индекс.
procedure Insert(Index: Integer; Item: Pointer);
Вставляет элемент Item в позицию Index списка: новый элемент получает индекс Index, все элементы с индексами Index и больше увеличивают свой индекс на 1. При необходимости расширяет список.
function Last: Pointer;
Возвращает указатель на последний элемент списка.
procedure Move(Curlndex, Newlndex: Integer);
Упаковывает список: удаляет пустые элементы в конце массива индексов, function Remove(Item: Pointer): Integer;
Отыскивает в списке элемент Item и удаляет его.
procedure Sort(Compare: TListSortCompare);
Сортирует коллекцию с помощью функции Compare.
Методы Add и insert получают указатель на вставляемый элемент. Чтобы воспользоваться ими, программист должен сам разместить в куче данные и получить соответствующий указатель. Точно так же методы Delete, Remove и Clear не уничтожают распределенные в памяти данные, которые программист должен, если это необходимо, уничтожить сам. Пример:
List: TList; Item: Pointer; Value: AnyType; begin
List := TList.Create; // Создаем список
Item := New (Value); // Размещаем в куче данные
List.Remove(Item); // Удаляем элемент из списка
Dispose(Item); // Удаляем его из кучи
List.Free; // Удаляем ненужный список
Метод Sort сортирует список по критерию, устанавливаемому функцией Compary. Тип TListSortCompare определен следующим образом:
TListSortCompare = function(Iteml, Item2: Pointer): Integer;
Функция Compare получает указатели на два элемента списка. Результат сравнения:
• любое отрицательное число, если ItemlА Item2A.
Критерий сравнения данных устанавливается программистом и реализуется в функции Compare.
Function Compdteml, Item2: Pointer): Integer;
// С помощью этой функции реализуется сортировка чисел
if PDouble(Iteml)л PDouble(Item2)л then
procedure TfmExample.bbRunClick(Sender: TObject);
// Обработчик щелчков на кнопке bbRun выполняет основную работу
List := TList.Create; // Создаем список
for к := 1 to 20 do // Наполняем его begin
New(pD); // Резервируем память
pDA := Random; // Помещаем в нее случайное число
List.Add(pD); // Добавляем к списку end;
List.Sort(Comp); // Сортируем список по возрастанию
pD := List [к]; // Очередное число из списка
Применяем дженерики в RAD Studio Delphi. Создаем библиотеку сортировки списков однотипных объектов
Сегодня будем создавать в RAD Studio Delphi библиотеку классов, реализующих сортировку списков однотипных объектов.
Цель задачи
Прикладной разработчик должен получить инструмент для создания дочерних классов, в которых можно:
Приступаем
Сортировка по возрастанию — это перестановка элементов набора данных таким образом, чтобы в результате каждый последующий элемент набора был больше предыдущего. Сортировка по убыванию — то же самое, только обход результирующего набора данных нужно начинать с конца.
Сравнение объектов
Чтобы понять, какой элемент набора данных больше другого, для базовых типов необходимо применять оператор сравнения. А как быть с объектами? Базовый модуль System.Generics.Defaults включает в себя нужный нам интерфейс и реализацию класса
В интерфейсе видим единственный метод Compare вида
Для сравнения наших объектов будем использовать свои функции сравнения, которые описывают логику правил сравнения для каждого типа объектов. Заключим такие функции в отдельный класс TAllComparison. В нем и описываются все наши функции сравнения, они имеют тот же вид
А класс TComparer(T) как раз служит для сравнения двух объектов путем вызова метода Compare.
Можно использовать сравнение по умолчанию (Default), или создать свой метод сравнения Construct, чем мы и займемся.
Для удобства описание всех объектов будем хранить в отдельном модуле AllObjects. Здесь же будем хранить описание всех 100 созданных нами объектов.
Операции с объектами
Для осуществления операций с объектами списка в Delphi уже имеется нужный нам параметризированный класс, он же дженерик, с нужными нам методами
Вообще, универсальные параметризированные типы (дженерики) появились еще в Delphi 2009, но для нашего примера я использую RAD Studio Berlin 10.1 UPD1. Если у вас что-то не компилируется, нужно будет допилить пример для своей версии Delphi.
Пишем основной класс нашей библиотеки наследник TList(T)
Основной метод нашей задачи SortBy, опишем его использование далее.
Сортировка объектов
Пишем класс TAllSort, который содержит описание всех 100 методов сортировки вида:
На входе метод получает массив данных из списка, метод сравнения объектов, начальную позицию для сортировки, количество элементов в наборе. На выходе получаем количество произведенных в наборе данных перестановок.
Для удобства, все методы сортировки будем держать в отдельном модуле SortMethods.
Демонстрация
В качестве демонстрации решения представляю 2 механизма сортировки: «Быстрая» и «Пузырьком». Сортировать будем 2 типа объектов: список двумерных векторов (упорядоченные пары) типа Integer и список со строками.
Для начала отсортируем массив строк «пузырьками»:
А теперь «быстро» отсортируем массив двумерных векторов:
Вот такой результат получился с векторами:
Как сделать список в delphi
var StrList: TStringList;
begin
StrList:=TStringList.Create;
Теперь нужно описать способ хранения строк в списке. Список строк типа TStringList может сортировать добавляемые строки или хранить без сортировки, а также может игнорировать попытки добавления новой строки при наличии уже сохранённого дубликата:
StrList.Add(‘Новая строка’); | //Добавление в конец списка (или в порядке сортировки). Возвращается индекс строки |
//Строка добавляется на позицию с номером Index. Если список отсортирован, то возникает исключительная ситуация. |
Удалить строку:
StrList.Delete(Index); // Удаление строки с номером Index;
Количество строк в списке:
Доступ к строке с номером Index:
Index отсчитывается от 0, поэтому номер последней строки:
Очищаем список строк:
Если список отсортирован, есть метод для поиска:
StrList.Find(S, Index); | // В случае удачного поиска возвращает True, и индекс строки S в переменной Index |
Если список не отсортирован, то тоже есть функция поиска:
I:=StrList.IndexOf(Text); | // Возвращает индекс строки с заданным текстом Text, или -1, если поиск неудачен |
В конце работы со списком его необходимо удалить из памяти:
Эти методы работают в случае если список отсортирован. Однако есть задачи, где сортировка не нужна, а находить значение в списке всё равно необходимо. В этом случае нужно пользоваться функцией IndexOf.
Рассмотрим пример
Исходная таблица | Первый список | Второй список | Третий список | |||||||||||||||
| Анализ по росту 179 180 175 | Иванов, Сидоров Петров Ковалёв | 2 1 1 |
А вот процедура подсчёта:
procedure TForm1.Button1Click(Sender: TObject);
var i, k: Integer;
begin
Caption:=»;
List1.Clear; List2.Clear; List3.Clear;
Param:=ComboBox1.ItemIndex+1;
for i:=1 to StringGrid1.RowCount-1 do
begin
k:=List1.IndexOf(StringGrid1.Cells[Param, i]);
if k=-1 then
begin
List1.Add(StringGrid1.Cells[Param, i]);
List2.Add(StringGrid1.Cells[0, i]);
List3.Add(‘1’);
end else
begin
List2[k]:=List2[k]+’, ‘+StringGrid1.Cells[0, i];
List3[k]:=IntToStr(StrToInt(List3[k])+1);
end;
end;
k:=0;
for i:=0 to List3.Count-1 do
if StrToInt(List3[i])>k then
k:=StrToInt(List3[i]);
for i:=0 to List2.Count-1 do
if StrToInt(List3[i])=k then Caption:=Caption+List2[i]+’: ‘+List1[i]+’; ‘;
end;
Сортировка в StringList’е
procedure StringListForSort;
var S: TStringList;
i, max: Integer;
Taim: Int64;
begin
Taim:=GetTickCount;
max:=0;
S:=TStringList.Create;
for i:=1 to Form1.Grid.RowCount-1 do
begin
if Length(Form1.Grid.Cells[1, i])>max
then max:=Length(Form1.Grid.Cells[1, i]);
S.Add(Form1.Grid.Cells[1, i]);
end;
for i:=0 to S.Count-1 do
while Length(S[i])<>max do
S[i]:=’ ‘+S[i];
S.Sort;
Form1.Caption:=’Продолжительность сортировки ‘+IntToStr(GetTickCount-Taim)+’ мсек’;
for i:=1 to Form1.Grid.RowCount-1 do
Form1.Grid.Cells[1, i]:=Trim(S[i-1]);
S.Free;
end;
Обзор алгоритмов сортировки
Сортировка в StringList’е лишь в два раза медленнее так называемой «быстрой» сортировки. Для сравнения, рассмотрим и некоторые другие алгоритмы сортировки.