От Delphi 4 к Delphi 5 часть 30

От Delphi 4 к Delphi 5
Типы данных. Множества.
В повседневной жизни и практической деятельности часто приходится говорить о некоторых совокупностях различных объектов: предметов, понятий, чисел, символов и т.д. Например, совокупность деталей механизмов, аксиом геометрии, чисел натурального ряда, букв русского алфавита. На основе интуитивных представлений о подобных совокупностях сформировалось математическое понятие множества как объединения объектов в единое целое. Именно такой точки зрения придерживался основатель теории множеств немецкий математик Георг Кантор.
Множество — это структурированные типы данных, состоящие из упорядоченного набора значений, называемых элементами множества. Причем эти элементы не могут дублироваться, так как каждый элемент или представлен во множестве, или нет. Другими словами, элемент или принадлежит множеству, или нет. Операции с множествами основаны именно на принадлежности элементов, а не на порядке их расположения или частоте появления.
Элементы объединены по какому-либо признаку (множество компьютеров, множество учащихся и т.д.).
Применение множеств состоит в создании набора независимых признаков ("флагов"), которые могут описывать различные состояния не обязательно взаимоисключающие.
Задать значения множества можно следующим образом: необходимо указать набор элементов, которые заключены в квадратные скобки.
Например: первое множество [3, 4, 5,]; второе множество ['Q', 'R', 'S'].
Множественный тип описывается указанием пары ключевых слов set of после знака = (равно) в описании типа.
type
Имя типа = set of ТипЭлемента;
Например:
type
ABCDE = set of Char;
Numb = set of Byte;
За ключевыми словами set of следует тип элемента множества, который называется базовым. Все элементы множества должны быть порядкового типа.
Всего может содержаться не более 256 элементов типа перечисления, причем номер младшего элемента не должен быть меньше нуля, а порядковый номер старшего элемента не должен быть больше 255.
Использование типа перечисления в качестве базового типа позволит сделать ваши программы читабельными.
В зависимости от способа описания элементов существует несколько вариантов синтаксиса выражения для задания значения множества.
Итак, синтаксис описания множества с перечислением всех элементов выглядит следующим образом:
[Элемент1, Элемент2, …, ЭлементК]
Можно задавать интервалы значений, т.е. перечисление диапазонов величин базового типа:
[Интервал1, Интервал2,…, Интервал N]
Допускается совместное использование явно указанных величин и диапазонов изменения значений.
Пример:
[-23..-2]
[1..10, 15, 99]
['C'.. 'G']
Множество — это группа элементов, которая ассоциируется с ее именем.
С множеством можно сравнивать другие величины, чтобы определить, принадлежат ли они ему. Один и тот же элемент не может входить во множество более одного раза. Как частный случай, множество может быть пустым.
Пустым называется такое множество, которое не содержит ни одного элемента. Например, множество действительных корней уравнения Х*X + 1 = 0.
Так как множество определяется перечислением его элементов, заключенным в прямоугольные скобки, то такая форма определения называется конструктором множества.
Область значений конкретного множества – это набор всех возможных подмножеств, включая пустое множество.
Например, если множество возможных единичных символов, которые могут быть получены в ответ на вопрос программы "False/True", содержит символы "F", "T", "f" и "t", то это множество можно описать таким конструктором:
['F','T','f','t'].
Для определения, принадлежит ли переменная множеству, служит операция in. В предыдущем примере проверить, дал ли пользователь один из допустимых ответов, можно оператором:
if (key in ['F','T','f','t'])
then <оператор, выполняемый при допустимом ответе>
Множества могут содержать не только отдельные значения, но и ограниченные типы. Например, если вы хотите контролировать символы, вводимые пользователем при вводе целого положительного или отрицательного числа, вы можете определить множество ['0'..'9', '+', '-'] и использовать его, например, при обработке события OnKeyPress какого-то окна редактирования.
Вы уже использовали этот прием для ограничения ввода символов в текстовый редактор (Занятие 2).
If not(Key in ['0'..'9', '+', '-']) then Key:=#0;
Но в данном примере множество заранее не объявлялось в виде типа. Если в вашем приложении будет несколько таких проверок, то целесообразнее объявить переменную или типизированную константу типа множества или тип множества и несколько переменных этого типа.
Объявление глобальной переменной с инициализацией осуществляется следующим образом:
var K: set of Char = ['0'..'9','+','-']

if (Key in K) then …
Объявление типизированной константы производится таким образом:
const K: set of Char = ['0'..'9','+','-'];
Объявление типа множества и переменных этого типа производится следующим образом:
type TDigit = set of '0'..'9';
var D1, D2: TDigit;
...
D1:=['0','1'];
D2:=['2'..'9'];
Определение элементов множества можно провести следующим образом:
type
CharSet = set of Char;
Производится описание множества, к элементам которого относятся все величины типа Char.
После определения области значений отдельных элементов множества, т.е. объявления множественного типа, вы можете определять переменные множественного типа.
Например:
var
Chars: CharSet;
Определяет переменную множественного типа CharSet, к возможным элементам которого относятся все 255 символов.
Рассмотрим пример определения множеств.
1. type
2. CharSet = set of Char;
3. NumbSet = set of Byte;
4. var
5. ABCD: CharSet;
6. Numb: NumbSet;
7. begin
8. ABCD := [];
9. ABCD := ['e','k','l','m','n'];
10. ABCD := ['a'..'d','h'..'l'];
11. ABCD := [#10,#13,'A'..'E'];
12. ABCD := ['7'];
13. Numb := [];
14. Numb := [8];
15. Numb := [1..20];
16. Numb := [1,2,3,4,5];
17. Numb := [0..255];
18. end.
Проведем анализ операторов.
Блок type в строках с 1 по 3 объявляет два множественных типа: CharSet, который является множеством всех символов в диапазоне от #0 до #255, и NumbSet, который является множеством чисел размером в байт, со значениями от 0 до 255.
Строки 4, 5 и 6 образуют блок описания переменных, определяющий две переменные множественного типа: ABCD и Numb, принадлежащие к типам CharSet и NumbSet, соответственно.
Блок исполняемых операторов begin-end в строках с 7 по 18 содержит операторы присваивания различных значений переменным множественного типа.
В строках 8 и 13 присваивается значение пустого множества, обозначенного [], переменным ABCD и Numb. Обратите внимание, что пустое множество совместимо с любым множественным типом. Другими словами, значение [] может быть присвоено любой переменной множественного типа, независимо от ее базового типа.
Строка 9 присваивает набор из трех символов 'e', 'k', 'l,' 'm', 'n' переменной ABCD.
Строка 10 иллюстрирует использование диапазонов указанных членов множества. Вместо непосредственного перечисления значений в виде ['а','b','с','d','h','i','j','k,'l' ] использовано обычное обозначение диапазона изменения для двух непрерывных последовательностей элементов.
Присваивание в строке 11 использует смесь из определения диапазона и перечисления для указания членов множества. Обратите внимание на то, что численное представление обозначает символы, которые не могут быть выведены на печать.
Строка 12 иллюстрирует множество только с одним элементом. Надо подчеркнуть тот факт, что запись '9' обозначает символ, а не число, поэтому элемент '9' относится к множеству символов. Множество, состоящее из единственного элемента-числа, показано в строке 14. Здесь оно присваивается переменной Numb.
В строке 15 иллюстрируется множество, определенное диапазоном значений. После присваивания переменная Numb содержит множество из 20 элементов: все натуральные числа от 1 до 20 включительно.
Строка 16 — пример непосредственного перечисления набора чисел.
Строка 17 интересна тем, что выражение, стоящее справа от знака присваивания, обозначает множество, состоящее из всех чисел базового типа. Можно отметить, что указанное множество не является диапазоном в собственном смысле этого слова, а перекрывает все возможные значения базового типа. Этот набор "полон" в том смысле, что в него входят все возможные элементы.

Операции над множествами.
При работе над множествами допускается использование операций отношения (=, <>, > =, <=), объединения, пересечения, разности множеств и операции in.
Одной из основных операций является проверка того, является ли конкретное значение элементом данного множества. Для этих целей используется оператор in.
Операция in для проверки принадлежности к множеству берет один элемент и проверяет одно множество. Результат применения операции in к элементу и множеству равен Тгuе, если элемент принадлежит множеству и Fаlsе — в противном случае.
Обычно применяется в условных операторах:
6 in [4..8] результат True;
6 in [1..3, 7..9] результат False.
Операция in позволяет эффективно и наглядно выполнять сложные проверки условий, заменяя иногда десятки других операций. Например, оператор
if (X=1) or (X=2) or (X=3) or (X=5) or (X=7) then
можно заменить более коротким
if X in [1..3, 5,7] then
Операции сравнения (=, <> ).
Два множества считаются равными, если они состоят из одних и тех же элементов. Порядок следования в сравниваемых множествах значения не имеет. Два множества считаются не равными, если они отличаются по количеству элементов (по мощности) или по значению хотя бы одного элемента. Например:
[4, 5] <> [4, 5, 6] результат False (разные мощности множеств);
[6, 7] = [6, 7, 8] результат False (разные мощности множеств);
[7, 8, 9] = [9, 8, 7] результат True (порядок следования элементов не имеет значения);
[7, 8, 9] = [7..9] результат True.
Операции принадлежности (> =, <=). Выражение A > = B (больше или равно) равно True в том случае, если все элементы множества В содержатся во множестве А. Выражение A <= B (меньше или равно) равно True в том случае, если выполняется обратное условие, т.е. все элементы множества А содержатся в множестве В.
Например:
[6, 7] <= [6, 7, 8] равно True, так как все элементы первого множества содержатся во втором множестве;
[6, 7, 8] > = [6, 7] равно True, так как все элементы второго множества содержатся в первом множестве.
[6, 7] <= [5, 7] равно False, так как элементы первого множества не входят во второе множество.
Объединением двух множеств (+) является третье множество, содержащее элементы обоих множеств.
Например:
[5, 6, 7] + [6, 7, 8] результат третье множество [5, 6, 7, 8];
[] + [6, 7] результат [6, 7].
Пересечением двух множеств (*) является третье множество, которое содержит элементы, входящие в оба множества одновременно.
Например:
[6, 7] * [5, 6] результат [6]
[6,7] * [] результат [].
Разностью двух множеств (-) является третье множество, которое содержит элементы первого множества, не входящие одновременно в оба множества.
[6, 7, 8] – [6, 7] результат [8];
[6,7] – [] результат [6, 7].
В Object Pascal введены две стандартные процедуры Include и Exclude, которые предназначены для работы с множествами.
Процедура Include(S,I) включает во множество S элемент I. Она дублирует операцию объединения множеств, с той лишь разницей, что при каждом обращении включает только один элемент и делает это более эффективно.
procedure Include(var S: set of T; I:T);
результат S = S + [I].
Процедура Exclude(S,I) исключает из множества S элемент I. Она дублирует операцию разности множеств, с той лишь разницей, что при каждом обращении исключает только один элемент и делает это более эффективно.
procedure Exclude(var S: set of T;I:T);
результат S = S — [I].
Использование в программе множеств дает возможность упростить операторы If, улучшает наглядность программы и понимание алгоритма решения задачи, экономится время разработки программы.

Компонент CheckListBox.
Этот компонент очень похож на ListBox, выглядит он так же, но около каждой строки имеется индикатор, который вы можете переключать.
Список можно использовать для вывода данных с необходимостью отметки какой-либо характеристики.
Компонент CheckListBox позволяет группировать независимые переключатели, позволяя обратиться к любому из них по индексу.
Для того чтобы вставить в компонент группу независимых переключателей, необходимо открыть редактор его свойства Items и ввести одну или несколько текстовых строк. Эти надписи будут соответствовать поясняющей надписи справа от переключателя (рисунок 1).
Рассмотрим некоторые свойства компонента CheckListBox.
Свойство AllowGrayed разрешает или запрещает использовать в переключателях третье состояние cbGrayed.
Если AllowGrayed устанавливается в True, то каждый пункт имеет три возможных состояния: помеченное, непомеченное и помеченное затененное серым цветом. Если это свойство устанавливается в False, то каждый пункт имеет только два возможных состояния: помеченное и непомеченное.
Свойство BorderStyle определяет тип рамки, которая очерчивает компонент: если установлено bsNone, то рамка отсутствует, bsSingle определяет толщину рамки в один пиксель.
Свойство Canvas используется для программной прорисовки опций.
Свойство Checked определяет выбор Да или Нет для переключателя с индексом Index. В этом случае состояния cbUnchecked и cbGrayed отражаются как False.
Следующий оператор использует свойство Checked:
CheckListBox1.Checked[2]:=True;
что позволяет пометить переключатель.
Свойство Columns определяет количество колонок опций.
Свойство IntegralHeight определяет автоматическое изменение высоты компонента, чтобы в нем полностью отображались опции, если установлено значение True. Если установлено значение False, то последняя опция не полностью отображается в окне компонента.
Свойство ItemHeight совместно с установленным значением lsOwnerDrawFixed для Style определяет высоту каждой опции компонента. При других значениях Style это свойство игнорируется, например:
CheckListBox1.ItemHeight:= 55;.
На рисунке 3 показаны свойства Columns и ItemHeight.
Свойство ItemIndex содержит индекс выбранной опции (индексация начинается с нуля).
Следующий пример использует CheckListBox, содержащий список строк, кнопку Button и компонент редактирования Edit на форме. Когда вы выполняете приложение и нажимаете кнопку, третий пункт в списке становится первым и индексная величина этого пункта появляется в элементе редактирования. Отображаемая индексная величина — 2, указывает на третий пункт в списке (первый пункт в списке имеет индексную величину 0):
procedure TForm1.FormCreate(Sender: TObject);
var
Number: Integer;
begin
for Number := 1 to 20 do
CheckListBox1.Items.Add('Строка ' + IntToStr(Number));
end;
procedure TForm1.Button1 Click(Sender: TObject);
begin
CheckListBox1.TopIndex := 2;
Edit1.Text := IntToStr(CheckListBox1.TopIndex);
end;
end.
Свойство Items содержит опции компонента.
Свойство MultiSelect, установленное в True, позволяет выбирать несколько опций.
Свойство SelCount содержит количество выбранных опций компонента, если свойство MultiSelect установлено в True.
Свойство Selected содержит True, если опция с индексом Index выбрана.
Свойство Sorted сортирует по алфавиту надписи на переключателях.
Свойство State содержит состояние переключателя с индексом Index: cbUnchecked – нет; cbChecked – да; cbGrayed – промежуточное состояние.
Свойство TListBoxStyle = (lbStandard, lbOwnerDrawFixed, lbOwnerDrawVariable);
property Style: TListBoxStyle; определяет способ прорисовки опций компонента:
lbStandard – опции прорисовывает Windows;
lbOwnerDrawFixed – компонент использует программный метод прорисовки опций, каждый из которых имеет одинаковую высоту ItemHeight;
lbOwnerDrawVariable – опции прорисовываются программно и могут иметь разную высоту.
Свойство TopIndex содержит индекс первой отображаемой опции.
В компоненте CheckListBox имеется событие OnClickCheck, возникающее при каждом изменении пользователем состояния индикатора. В этом случае его можно использовать для обработки результатов изменения.
Этот компонент находит широкое применение в приложениях, например можно его использовать для выбора опций при настройке параметров в документах Word (рисунок 4).
Рассмотрим пример использования компонента CheckListBox.
Основная идея примера состоит в том, что приложение будет производить расчет значений для двух чисел по формулам сокращенного умножения. Вначале производится ввод значений чисел A и B, щелчок по кнопке позволит провести расчет квадрата суммы двух чисел. В это же время произойдет появление на форме компонента CheckListBox и кнопки Bitbtn. В CheckListBox1 введены независимые переключатели, позволяющие выбирать формулы сокращенного умножения. Выбор отдельных переключателей или всех предложенных приведет к выдаче результатов.
1. Запустите Delphi.
2. Сохраните файл модуля под именем FSM_pas. — сокращенное название от (Formulas of shorten multiplying), а файл проекта под именем FSM.dpr.
3. Поместите на форму четыре компонента Edit, в которые будете вводить значения А и В и выводить значения полученных результатов.
4. Поместите на форму кнопку Button, BitBtn, CheckListBox. Для Button1 введите заголовок "Квадрат суммы двух величин", для BitBtn введите заголовок "Другие возможности".
5. Для компонента CheckListBox1, используя свойство Items на странице Properties инспектора объекта, произведите щелчок по кнопке с тремя точками справа от слова (TStrings). В раскрывшемся диалоговом окне Strihg List editor введите три строки: "Квадрат разности двух величин", "Разность квадратов двух величин", "Куб суммы двух величин". Нажмите кнопку Ok. В компоненте CheckListBox1 вы увидите три независимых переключателя.
6. Размещение компонентов на форме показано на рисунке 5.
7. Напишите программный код, представленный ниже, для отклика на событие щелчок по кнопкам.
implementation

{$R *.DFM}
var
A, B, C: Real;

procedure TForm1.Button1 Click(Sender: TObject);
begin
A:=StrToFloat(Edit1.Text);
B:=StrToFloat(Edit2.Text);
C:= A*A + 2*A*B +B*B;
Edit3.Text:=FloatToStr(C);
Canvas.TextOut(20,150, 'Квадрат суммы двух чисел равен');
CheckListBox1.Visible:=True;
Bitbtn1.Visible:=True;
end;

procedure TForm1.BitBtn1 Click(Sender: TObject);
begin
if CheckListBox1.Checked [0]=False then
ShowMessage('Необходимо пометить опцию, иначе результат будет неверен');
if CheckListBox1.Checked [0]=True then
A:=StrToFloat(Edit1.Text);
B:=StrToFloat(Edit2.Text);
C:= A*A — 2*A*B +B*B;
Canvas.TextOut (20,200, 'Квадрат разности двух чисел равен');
Edit4.Text:=FloatToStr(C);
end;
end.
Здесь приведен программный код только для квадрата разности и суммы двух чисел.
На рисунке 6 представлен результат работы программы.

Владимир Скуратов


(c) компьютерная газета


Компьютерная газета. Статья была опубликована в номере 42 за 2001 год в рубрике программирование :: delphi

©1997-2024 Компьютерная газета