Програмування на мові Delphi. Глава 2. Основи мови Delphi. Частина 3, Різне, Програмування, статті

попередня стаття серії


Зміст



Програмні модулі


Структура модуля


Логічно відокремлені групи процедур та функцій надзвичайно зручно поєднувати в спеціалізовані бібліотеки – модулі. Для цього мова Delphi пропонує спеціальні засоби і доступну кожному технологію. Наведемо загальну структуру програмного модуля:

 Заголовок модуля unit <ім'я модуля>;
Директиви компілятора {$ <директиви>}

Інтерфейсна частина interface
Підключення модулів uses <ім'я>, …, <ім'я>;
Константи const … ;
Типи даних type … ;
Змінні var … ;
Заголовки процедур procedure <ім'я> (<параметри>);
Заголовки функцій function <ім'я> (<параметри>): <тип>;

Частина реалізації implementation
Підключення модулів uses <ім'я>, …, <ім'я>;
Константи const … ;
Типи даних type … ;
Змінні var … ;
Реалізація процедур procedure <ім'я>; begin … end;
Реалізація функцій function <ім'я>; begin … end;

Код ініціалізації initialization <оператори>
Код завершення finalization <оператори>
end.


Після слова unit записується ім'я модуля. Воно повинно співпадати з ім'ям файлу, в якому знаходиться вихідний текст модуля. Наприклад, якщо файл називається MathLib.pas, то модуль повинен мати ім'я MathLib. Заголовок модуля формується автоматично при збереженні файлу на диску, тому його не слід змінювати вручну. Щоб дати модулю інший заголовок, просто збережіть його на диску під іншим ім'ям.

У розділі interface описуються глобальні дані, Процедури та функції, доступні для використання в основній програмі і інших модулях.

У розділі implementation реалізується програмний код глобальних процедур і функцій і описуються локальні дані, Процедури та функції, недоступні основній програмі й іншим модулям.

Блок initialization є необов'язковим. Він складається з операторів і виконується автоматично безпосередньо перед запуском основної програми. Блоки ініціалізації підключених до програми модулів виконуються в тому порядку, в якому вони згадуються в секції uses.

Блок finalization теж є необов'язковим. Він складається з операторів і виконується автоматично безпосередньо після завершення основної програми. Блоки завершення підключених до програми модулів виконуються в порядку, зворотному порядку підключення модулів у секції uses.

Якщо модуль не потребує ініціалізації та завершення, блоки initialization і finalization можна опустити.

У якості вправи давайте створимо модуль і підключимо його до основної програми (для цього спочатку запустіть середу Delphi):


  1. Виберіть в головному меню команду File / New…, В діалоговому вікні активізуйте значок з підписом Unit і клацніть на кнопці OK (малюнок 6).

    Малюнок 6. Вікно середовища Delphi для створення нового модуля


  2. Ви побачите, що середовище Delphi створить в редакторі коду нову сторінку з текстом нового модуля Unit1 (Малюнок 7):

    Малюнок 7. Текст нового модуля в редакторі коду


  3. Збережіть модуль під ім'ям MathLib, вибравши в меню команду File / Save (Малюнок 8):

Малюнок 8. Вікно збереження модуля



  1. Зауважте, що основна програма Console змінилася: у списку модулів з'явилося ім'я модуля MathLib (малюнок 9). Після слова in середовище Delphi автоматично поміщає ім'я файлу, в якому знаходиться модуль. Для стандартних модулів, таких як SysUtils, це не потрібно, оскільки їх місцезнаходження добре відомо.

    Малюнок 9. Текст програми Console у вікні редактора


Тепер перейдемо до вмісту модуля. Давайте оголосимо в ньому константу Pi і дві функції: Power – обчислення ступеня числа, і Average – обчислення середнього арифметичного двох чисел:

unit MathLib;

interface

const
Pi = 3.14;

function Power(X, Y: Double): Double;
function Average(X, Y: Double): Double;

implementation

function Power(X, Y: Double): Double;
begin
Result := Exp(Y * Ln(X));
end;

function Average(X, Y: Double): Double;
begin
Result := (X + Y) / 2;
end;

end.


Ось як могла б виглядати програма, що використовує модуль Math:

program Console;

{$APPTYPE CONSOLE}

uses
SysUtils,
MathLib in MathLib.Pas;

begin
Writeln(Pi);
Writeln(Power(2, 4));
Writeln(Average(2, 4));
Writeln(Press Enter to exit…);
Readln;
end.


Після компіляції і запуску програми ви побачите на екрані три числа (малюнок 10):

Малюнок 10. Результат роботи програми Console

Стандартні модулі мови Delphi


До складу середовища Delphi входить чудовий набір модулів, можливості яких задовольнять навіть самого вибагливого програміста. Всі модулі можна розбити на дві групи: системні модулі та модулі візуальних компонентів.

До системним модулям відносяться System, SysUtils, ShareMem, Math. У них містяться найбільш часто використовувані в програмах типи даних, константи, змінні, процедури і функції. Модуль System – це серце середовища Delphi; містяться в ньому підпрограми забезпечують роботу всіх інших модулів системи. Модуль System приєднується автоматично до кожної програми і його не треба вказувати в операторі uses.

Модулі візуальних компонентів (VCL – Visual Component Library) використовуються для візуальної розробки повнофункціональних GUI-додатків – додатків з графічним інтерфейсом (Graphical User Interface). Ці модулі в сукупності є високорівневу об'єктно-орієнтовану бібліотеку зі всілякими елементами інтерфейсу: кнопками, написами, меню, панелями і т.д. Крім того, модулі цієї бібліотеки містять прості та ефективні засоби доступу до баз даних. Дані модулі підключаються автоматично при приміщенні компонентів на форму, тому вам про це дбати не треба. Їх список занадто великий, тому ми його не наводимо.

Всі основні модулі середовища Delphi, включаючи модулі візуальних компонентів, поставляються разом з вихідними текстами на мові Delphi. У міру зростання вашого професійного досвіду ми рекомендуємо частіше звертатися до цих початкових текстів. По-перше, в них ви знайдете відповіді на багато питань про внутрішній устрій середовища Delphi, а по-друге, вони послужать зразковим прикладом професійного підходу у вирішенні широкого кола завдань. І, по-третє, що не менш важливо, це допоможе навчитися красиво і правильно (в рамках усталеного стилю) оформляти тексти Ваших власних програм так, щоб їх з легкістю читали і розуміли інші програмісти.

Вихідні тексти стандартних модулів середовища Delphi знаходяться в каталозі Delphi / Source.

Область дії ідентифікаторів


При програмуванні необхідно дотримуватися ряду правил, що регламентують використання ідентифікаторів:


Рядки


Рядкові значення


Рядок – Це послідовність символів. При програмуванні рядкові значення полягають в апострофи, наприклад:

 Writeln (Я тебе люблю);

Так як апостроф є службовим символом, для його записи в рядку як значущого символу застосовуються два апострофа, наступних безпосередньо один за одним:

Writeln(Object Pascal is Delphis and Kylixs language);

Для запису відсутніх на клавіатурі символів використовується символ #, За яким слід десятковий номер символу в кодовій таблиці ASCII, наприклад:

 Writeln (Copyright # 169 А. Вальвачев, К. Сурков, Д. Сурков, Ю. Четирько);

Рядок, яка не містить символів, називається порожньою:

Writeln();

Тепер, коли відомо, що представляють собою рядкові значення, займемося рядковими змінними.

Строкові змінні


Строкова мінлива оголошується за допомогою зарезервованого слова string або за допомогою ідентифікатора типу даних AnsiString, наприклад:

var
FileName: string;
EditText: AnsiString;

Рядок можна вважати нескінченною, хоча насправді її довжина обмежена 2 ГБ. Залежно від присвоюється значення рядок збільшується і скорочується динамічно. Це зручність забезпечується тим, що фізично строкою мінлива зберігає не самі символи, а адреса символів рядка в області динамічно розподіляє пам'яті (о динамічно розподіляє пам'яті ми розповімо нижче). При створенні рядка завжди ініціалізувалися порожнім значенням (). Управління динамічної пам'яттю при операціях з рядками виконується автоматично за допомогою стандартних бібліотек мови Delphi.

Ви звичайно ж можете описувати рядкові типи даних і використовувати їх при оголошенні змінних і типізованих констант, наприклад:

type
TName = string;
var
Name: TName;
const
FriendName: TName = Alexander;

Символи рядка індексуються від 1 до N +1, де N – реальна довжина рядка. Символ з індексом N +1 завжди дорівнює нулю (# 0). Для отримання довжини слід використовувати функцію Length, А для зміни довжини – процедуру SetLength (Див. нижче).

Для того щоб у програмі звернутися до окремого символу рядка, потрібно відразу за ідентифікатором строкової змінної або константи в квадратних дужках записати його номер. Наприклад, FriendName [1] повертає значення 'A', а FriendName [4] – 'x'. Символи, одержувані в результаті індексування рядки, належать типу Char.

Гідність рядка мови Delphi полягає в тому, що вона об'єднує в собі властивості рядки самої мови Delphi і рядки мови C. Оперуючи рядком, ви оперуєте значенням рядка, а не адресою в оперативній пам'яті. У той же час рядок не обмежена по довжині і може передаватися замість C-рядка (як адресу першого символу рядка) в параметрах процедур і функцій. Щоб компілятор дозволив це зробити, потрібно, записуючи рядок як параметр, перетворити її до типу PChar (тип даних, який використовується в мові Delphi для опису нуль-терминировать рядків мови C). Таке приведення типу допустимо з тієї причини, що рядок завжди завершується нульовим символом (# 0), який хоч і не є її частиною, проте завжди дописується відразу за останнім символом рядка. У результаті формат рядка задовольняє формату C-строки. Про роботу з нуль-терминировать рядками ми поговоримо трохи пізніше.

Рядки у форматі Unicode


Для підтримки роботи з рядками формату Unicode в мову Delphi є рядковий тип даних WideString. Робота з рядками типу WideString майже не відрізняється від роботи з рядками типу AnsiString; існують лише дві відмінності.

Перша відмінність полягає в поданні символів. У рядках типу WideString кожен символ кодується не одним байтом, а двома. Відповідно елементи рядка WideString – це символи типу WideChar, тоді як елементи рядка AnsiString – це символи типу AnsiChar.

Друга відмінність полягає в тому, що відбувається при присвоєнні строкових змінних. Про це ви дізнаєтесь трохи пізніше, прочитавши параграф "Подання рядків в пам'яті".

Короткі рядки


Короткий рядок оголошується за допомогою ідентифікатора типу ShortString або зарезервованого слова string, За яким слід укладену в квадратні дужки значення максимально допустимої довжини, наприклад:

var
Address: ShortString;
Person: string[30];

Коротка рядок може мати довжину від 1 до 255 символів. Зумовлений тип даних ShortString еквівалентний оголошенню string[255].

Реальна довжина рядка може бути менше або дорівнює тій, що вказана при її оголошенні. Наприклад, максимальна довжина рядка Friend у прикладі вище складає 30 символів, а її реальна довжина – 9 символів. Реальну довжину рядка можна дізнатися за допомогою вбудованої функції Length. Наприклад, значення Length (Friend) дорівнюватиме 9 (кількість літер у слові Alexander).

Усі символи в рядку типу ShortString пронумеровані від 0 до N, де N – максимальна довжина, зазначена при оголошенні. Символ з номером 0 – це службовий байт, в ньому міститься реальна довжина короткого рядка. Значущі символи нумеруються від 1. Очевидно, що в пам'яті рядок займає на 1 байт більше, ніж її максимальна довжина. Тому значення SizeOf (Friend) дорівнюватиме 31.

type
TName = string[30];
var
Name: TName;
const
FriendName: TName = Alexander;

Звернутися до окремого символу можна так само, як і до символу звичайної рядка. Наприклад, вирази FriendName [1] і FriendName [9] повертають відповідно символи A і r. Значення FriendName [10] .. FriendName [30] будуть випадковими, так як при оголошенні типізований константи FriendName символи з номерами від 10 до 30 не були ініціалізований. Символи, одержувані в результаті індексування короткого рядка, належать типу Char.

Оскільки існує два типи рядків: звичайні (довгі) рядки і короткі рядки, виникає закономірне питання, чи можна їх поєднувати. Так, можна! Короткі і довгі рядки можуть одночасно використовуватися в одному вираженні, оскільки компілятор мови Delphi автоматично генерує код, що перетворює їх тип. Більше того, можна виконувати явні перетворення рядків за допомогою конструкцій виду ShortString (S) і AnsiString (S).

Операції над рядками


Вирази, в яких операндами служать рядкові дані, називаються рядковими. Вони складаються з рядкових констант, змінних, імен функцій і строкових операцій. Над рядковими даними допустимі операції зчеплення і відносини.

Операція зчеплення (+) Застосовується для зчеплення декількох рядків в один рядок.










Вираз


Результат

Object + Pascal Object Pascal

Операції відносини (=, <>,>, <,> =, <=) Проводять порівняння двох рядкових операндів. Порівняння рядків проводиться зліва направо до першого неспівпадаючі символу, і той рядок вважається більше, в якій перший неспівпадаючі символ має більший номер в кодової таблиці. Рядки вважаються рівними, якщо вони повністю збігаються по довжині і містять одні й ті ж символи. Якщо рядки мають різну довжину, але у загальній частині символи збігаються, вважається, що більш короткий рядок менше, ніж довша.



















Вираз


Результат

USA < USIS True { A < I }
abcde > ABCDE True
Office = Office True
USIS > US True

Якщо короткою рядку присвоюється значення, довжина якого перевищує максимально допустиму величину, то всі зайві символи справа відкидаються.












Оголошення рядки


Вираз


Значення рядка

Name: string[6]; Name := Mark Twain; Mark T

Допускається змішання в одному виразі операндів строкового і символьного типу, наприклад при зчепленні рядка та символу.

Строкові ресурси


У мові Delphi існує спеціальний вид строкових даних – рядкові ресурси. Строкові ресурси дуже схожі на рядкові константи, але відрізняються від них тим, що розміщуються не в області даних програми, а в спеціальній області виконуваного файлу, званої ресурсами. Якщо дані завжди завантажуються разом з кодом програми і залишаються в оперативній пам'яті аж до завершення програми, то ресурси підвантажуються в оперативну пам'ять лише у міру потреби.

У програмі рядкові ресурси описуються як звичайні рядкові константи, з тією лише різницею що розділ їх опису починається не словом const, А словом resourcestring:

resourcestring
SCreateFileError = Cannot create file: ;
SOpenFileError = Cannot open file: ;

Використання строкових ресурсів нічим не відрізняється від використання рядкових констант:

var
S: string;
begin
S := SCreateFileError + MyFile.txt;

end;

На роль строкових ресурсів відмінно підходять повідомлення про помилки, які займають багато місця в пам'яті і залишаються не потрібні до тих пір, поки в програмі не виникне помилка. Використання ресурсів спрощує переклад інтерфейсу на інші мови, оскільки заміна текстових повідомлень може здійснюватися безпосередньо в виконуваному файлі, тобто без перекомпіляції програми.

Формати кодування символів


Існують різні формати кодування символів. Окремий символ рядка може бути представлений в пам'яті одним байтом (стандарт Ansi), двома байтам (стандарт Unicode) і навіть чотирма байтами (стандарт UCS-4 – Unicode). Рядок "Wirth" (прізвище автора мови Pascal – прародителя мови Delphi) буде представлена ​​в зазначених форматах наступним чином (малюнок 11):

Малюнок 11. Формати кодування символів

Існує також формат кодування MBCS (Multibyte Character Set), згідно з яким символи одного рядка кодуються різною кількістю байт (одним або двома байтами в залежності від алфавіту). Наприклад, букви латинського алфавіту кодуються одним байтом, а ієрогліфи японської алфавіту – двома. При цьому латинські букви і японські ієрогліфи можуть зустрічатися в одній і тій же рядку.

Стандартні процедури та функції для роботи з рядками


Так як обробка рядків виконується практично в кожної серйозної програмі, стандартно підключається модуль System має набір процедур і функцій, що значно полегшують цей процес. Всі наступні процедури і функції застосовні і до коротким, і до довгих рядках.


Приклади:



















Вираз


Значення S

S := Concat(Object , Pascal); Object Pascal
S:= Copy(Debugger, 3, 3); bug
S := Compile; Delete(S, 1, 3); pile
S := Faction; Insert(r, S, 2) Fraction














Вираз


Результат

Pos(rat, grated’) 2
Pos(sh, champagne) 0

















Вираз


Значення S

Str(-200, S); -200
Str(200 : 4, S); 200
Str(1.5E+02 : 4, S); 150





















Вираз


Значення V


Значення Code

Val(100, V, Code); 100 0
Val(2.5E+01, V, Code); 25.0 0
Val(2.5A+01, V, Code); <Не визначено> 4

Описані процедури і функції є базовими для всіх інших підпрограм обробки рядків з модуля SysUtils.


Масиви


Оголошення масиву


Масив – Це складовий тип даних, що складається з фіксованого числа елементів одного і того ж типу. Для опису масиву призначено словосполучення array of. Після слова array в квадратних дужках записуються межі масиву, а після слова of – Тип елементів масиву, наприклад:


type
TStates = array[1..50] of string;
TCoordinates = array[1..3] of Integer;

Після опису типу можна переходити до визначення змінних і типізованих констант:

var
States: TStates; { 50 strings }
const
Coordinates: TCoordinates = (10, 20, 5); { 3 integers }

Зверніть увагу, що ініціалізація елементів масиву відбувається в круглих дужках через кому.

Масив може бути визначений і без опису типу:

var
Symbols: array[0..80] of Char; { 81 characters }

Щоб отримати доступ до окремого елементу масиву, потрібно у квадратних дужках вказати його індекс, наприклад

Symbols[0]

Оголошені вище масиви є одновимірними, оскільки мають тільки один індекс. Одномірні масиви зазвичай використовуються для представлення лінійної послідовності елементів. Якщо при описі масиву задано два індекси, масив називається двовимірним, Якщо n індексів – n-мірним. Двовимірні масиви використовуються для подання таблиці, а n-мірні – для подання просторів. Ось приклад оголошення таблиці, що складається з 5 колонок і 20 рядків:

var
Table: array[1..5] of array[1..20] of Double;

Те ж саме можна записати в більш компактному вигляді:

var
Table: array[1..5, 1..20] of Double;

Щоб отримати доступ до окремого елементу багатовимірного масиву, потрібно вказати значення кожного індексу, наприклад

Table[2][10]

або в більш компактній записи

Table[2, 10]

Ці два способи індексації еквівалентні.

Робота з масивами


Масиви в цілому беруть участь тільки в операціях присвоєння. При цьому всі елементи одного масиву копіюються в іншій. Наприклад, якщо оголошені два масиви A і B,

var
A, B: array[1..10] of Integer;

то допустимо наступний оператор:

A := B;

Обидва масиву-операнда в лівій і правій частині оператора присвоювання повинні бути не просто ідентичні за структурою, а описані з одним і тим же типом, інакше компілятор повідомить про помилку. Саме тому всі масиви рекомендується описувати в секції type.

З елементами масиву можна працювати, як із звичайними змінними. У наступній програмі елементи чисельного масиву послідовно вводяться з клавіатури, а потім сумуються. Результат виводиться на екран.

program Console;

{$APPTYPE CONSOLE}

uses
SysUtils;

var
A: array[1..5] of Double;
Sum: Double;
I: Integer;

begin
for I := 1 to 5 do Readln(A[I]);
Sum := 0;
for I := 1 to 5 do Sum := Sum + A[I];
Writeln(Sum);
Writeln(Press Enter to exit…);
Readln;
end.


Для масивів визначені дві вбудовані функції – Low і High. Вони отримують в якості свого аргументу ім'я масиву. Функція Low повертає нижню, а High – верхню межу цього масиву. Наприклад, Low (A) поверне значення 1, а High (A) – 5. Опції Low і High найчастіше використовуються для вказівки початкового і кінцевого значень в операторі циклу for. Тому обчислення суми елементів масиву A краще переписати так:

for I := Low(A) to High(A) do Sum := Sum + A[I];

В операціях з багатовимірними масивами цикли for вкладаються один в одного. Наприклад, для ініціалізації елементів таблиці, оголошеної як

var
Table: array[1..5, 1..20] of Double;

потрібні два вкладених циклу for і дві цілі змінні Col і Row для параметрів цих циклів:

for Col := 1 to 5 do
for Row := 1 to 20 do
Table[Col, Row] := 0;

Масиви в параметрах процедур і функцій


Масиви, як і інші типи даних, можуть виступати в якості параметрів процедур та функцій. Ось як може виглядати функція, що обчислює середнє значення в масиві дійсних чисел:

const
Max = 63;
type
TStatistics = array [0..Max] of Double;

function Average(const A: TStatistics): Double;
var
I: Integer;
begin
Result := 0;
for I := Low(A) to High(A) do Result := Result + A[I];
Result := Result / (High(A) – Low(A) + 1);
end;


Функція Average приймає як параметр масив відомої розмірності. Вимога фіксованого розміру для масиву-параметра часто є надмірно стримуючим фактором. Процедура для знаходження середнього значення має бути здатна працювати з масивами довільної довжини. Для цієї мети в мову Delphi введені відкриті масиви-параметри. Такі масиви були запозичені розробниками мови Delphi з мови Modula-2. Відкритий масив-параметр описується за допомогою словосполучення array of, При цьому межі масиву опускаються:

function Average(const A: array of Double): Double;
var
I: Integer;
begin
Result := 0;
for I := Low(A) to High(A) do Result := Result + A[I];
Result := Result / (High(A) – Low(A) + 1);
end;

Усередині підпрограми Average нижня межа відкритого масиву A дорівнює нулю (Low (A) = 0), а от значення верхньої межі (High (A)) невідомо і з'ясовується тільки на етапі виконання програми.

Існує тільки два способи використання відкритих масивів: звернення до елементів масиву і передача масиву іншої підпрограмі, що приймає відкритий масив. Не можна присвоювати один відкритий масив іншому, тому що їх розміри заздалегідь невідомі.

Ось приклад використання функції Average:

var
Statistics: array[1..10] of Double;
Mean: Double;
begin

Mean := Average(Statistics);
Mean := Average([0, Random, 1]);

end;

Зауважте, що в другому операторі відкритий масив конструюється в момент виклику функції Average. Конструктор відкритого масиву є укладений у квадратні дужки список виразів. У виразах можуть використовуватися константи, змінні і функції. Тип виразів повинен бути сумісний з типом елементів масиву. Конструювання відкритого масиву рівносильно створенню та ініціалізації тимчасової змінної.

І ще одне важливе зауваження з приводу відкритих масивів. Деякі бібліотечні підпрограми мови Delphi приймають параметри типу array of constвідкриті масиви констант. Масив, переданий в якості такого параметра, обов'язково конструюється в момент виклику підпрограми і може складатися з елементів різних типів (!). Фізично він складається із записів типу TVarRec, Що кодують тип і значення елементів масиву (записи розглядаються нижче). Відкритий масив констант дозволяє емулювати підпрограми з перемінним кількістю різнотипних параметрів і використовується, наприклад, у функції Format для форматування рядка (див. вище).

Ущільнення структурних даних у пам'яті


З метою економії пам'яті, займаної масивами та іншими структурними даними, ви можете випереджати опис типу зарезервованим словом packed, Наприклад:

var
A: packed array[1..10] of Byte;

Ключове слово packed вказує компілятору, що елементи структурного типу повинні зберігатися щільно притиснутими один до одного, навіть якщо це уповільнює до них доступ. Якщо структурний тип даних описаний без ключового слова packed, Компілятор вирівнює його елементи на 2 – і 4-байтових кордонах, щоб прискорити до них доступ.

Зауважимо, що ключове слово packed застосовно до будь-структурному типу даних, тобто масиву, безлічі, записи, файлу, класу, заслання на клас.

Безлічі


Оголошення безлічі


Безліч – Це складовий тип даних для представлення набору деяких елементів як єдиного цілого. Область значень множини – набір всіляких підмножин, складених з його елементів. Всі елементи множини повинні належати однобайтове порядковому типу. Цей тип називається базовим типом безлічі.

Для опису множини типу використовується словосполучення set of, Після якого записується базовий тип множини:

type
TLetters = set of A..Z;

Тепер можна оголосити змінну множинного типу:

var
Letters: TLetters;

Можна оголосити безліч і без попереднього опису типу:

var
Symbols: set of Char;

У виразах значення елементів безлічі вказуються в квадратних дужках: [2, 3, 5, 7], [1 .. 9], [A, B, C]. Якщо безліч не має елементів, воно називається порожнім і позначається як []. Приклад ініціалізації множин:

const
Vowels: TLetters = [A, E, I, O, U];
begin
Letters := [A, B, C];
Symbols: = []; {пусте безліч}
end;

Кількість елементів множини називається потужністю. Потужність множини в мові Delphi не може перевищувати 256.

Операції над множинами


При роботі з множинами допускається використання операцій відносини (=, <>,> =, <=), об'єднання, перетину, різниці множин і операції in.

Операції порівняння (=, <>). Два безлічі вважаються рівними, якщо вони складаються з одних і тих самих елементів. Порядок проходження елементів в порівнюваних множинах значення не має. Два безлічі A і B вважаються не рівними, якщо вони відрізняються по потужності або за значенням хоча б одного елемента.



















Вираз


Результат

[1, 2] <> [1, 2, 3] True
[1, 2] = [1, 2, 2] True
[1, 2, 3] = [3, 2, 1] True
[1, 2, 3] = [1..3] True

Операції приналежності (> =, <=). Вираз A> = B одно True, якщо всі елементи множини B містяться в множині A. Вираз A <= B одно True, якщо виконується зворотне умова, тобто всі елементи множини A містяться в множині B.
















Вираз


Результат

[1, 2] <= [1, 2, 3] True
[1, 2, 3] >= [1, 2] True
[1, 2] <= [1, 3] False

Операція in. Використовується для перевірки належності елемента вказаною безлічі. Зазвичай застосовується в умовних операторах.













Вираз


Результат

5 in [1..9] True
5 in [1..4, 6..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

Операцію in іноді намагаються записати з запереченням: X not in S. Такий запис є помилковою, тому що дві операції ідуть підряд. Правильний запис має вигляд: not (X in S).

Об'єднання множин (+). Об'єднанням двох множин є третя безліч, що містить елементи обох множин.













Вираз


Результат

[ ] + [1, 2] [1, 2]
[1, 2] + [2, 3, 4] [1, 2, 3, 4]

Перетин множин (*). Перетин двох множин – це третє безліч, яке містить елементи, що входять одночасно в обидва множини.













Вираз


Результат

[ ] * [1, 2] [ ]
[1, 2] * [2, 3, 4] [2]

Різниця множин (-). Різницею двох множин є третя безліч, яке містить елементи першого безлічі, що не входять у другу безліч.













Вираз


Результат

[1, 2, 3] – [2, 3] [1]
[1, 2, 3] – [ ] [1, 2, 3]

У мову Delphi введено дві стандартні процедури Include і Exclude, які призначені для роботи з множинами.

Процедура Include(S, I) включає в безліч S елемент I. Вона дублює операцію + (плюс) з тією лише різницею, що при кожному зверненні включає тільки один елемент і робить це більш ефективно.

Процедура Exclude(S, I) виключає з безлічі S елемент I. Вона дублює операцію – (мінус) з тією лише різницею, що при кожному зверненні виключає тільки один елемент і робить це більш ефективно.
















Вираз


Результат

S := [1, 3]; [1, 3]
Include(S, 2); [1, 2, 3]
Exclude(S, 3) [1, 2]

Використання в програмі множин дає ряд переваг: значно спрощуються складні оператори if, Поліпшується наочність програми і розуміння алгоритму розв'язання задачі, економиться час розробки програми. Тому безлічі широко використовуються в бібліотеці компонентів середовища Delphi.

Записи


Оголошення записи


Запис – Це складовий тип даних, що складається з фіксованого числа елементів одного або декількох типів. Опис типу запису починається словом record і закінчується словом end. Між ними укладено список елементів, званих полями, Із зазначенням ідентифікаторів полів і типу кожного поля:

type
TPerson = record
FirstName: string [20]; / / ім'я
LastName: string [20]; / / прізвище
BirthYear: Integer; / / рік народження
end;

Ідентифікатори полів повинні бути унікальними тільки в межах записи. Допускається вкладення записів один в одного, тобто поле запису може бути в свою чергу теж записом.

Щоб отримати в програмі реальну запис, потрібно створити змінну відповідного типу:

var
Friend: TPerson;

Записи можна створювати і без попереднього опису типу, але це робиться рідко, так як мало відрізняється від опису полів у вигляді окремих змінних.

Доступ до вмісту запису здійснюється за допомогою ідентифікаторів змінної і поля, розділених крапкою. Така комбінація називається складовим ім'ям. Наприклад, щоб отримати доступ до полів запису Friend, потрібно записати:

Friend.FirstName := Alexander;
Friend.LastName := Ivanov;
Friend.BirthYear := 1991;

Звернення до полів запису має кілька громіздкий вигляд, що особливо незручно при використанні мнемонічних ідентифікаторів довжиною більше 5 символів. Для вирішення цієї проблеми в мові Delphi призначений оператор with, який має формат:

 with <запис> do
<Оператор>;

Одного разу вказавши ім'я запису в операторі with, можна працювати з іменами її полів як зі звичайними змінними, тобто без вказівки ідентифікатора запису перед ідентифікатором поля:

with Friend do
begin
FirstName := Alexander;
LastName := Ivanov;
BirthYear := 1991;
end;

Допускається застосування оператора присвоювання і до записів в цілому, якщо вони мають один і той же тип. Наприклад,

Friend := BestFriend;

Після виконання цього оператора значення полів запису Friend стануть рівними значенням відповідних полів запису BestFriend.

Записи з варіантами


Строго фіксована структура запису обмежує можливість її застосування. Тому в мові Delphi є можливість задати для запису кілька варіантів структури. Такі записи називаються записами з варіантами. Вони складаються з необов'язковою фіксованого та варіантної частин.

Варіантна частина нагадує умовний оператор case. Між словами case і of записується особливе поле запису – поле ознаки. Воно визначає, який з варіантів в даний момент буде активізований. Поле ознаки має дорівнювати одному з розташованих слідом значень. Кожному значенню зіставляється варіант запису. Він полягає в круглі дужки і відокремлюється від свого значення двокрапкою. Приклад опису записи з варіантами:

type
TFigure = record
X, Y: Integer;
case Kind: Integer of
0: (Width, Height: Integer); / / прямокутник
1: (Radius: Integer); / / окружність
end;

Зверніть увагу, що у варіантної частини немає окремого end, Як цього можна було б очікувати за аналогією з оператором case. Одне слово end завершує і варіантну частину, і весь запис.

На цьому ми поки закінчимо розповідь про записи, але хочемо сподіватися, що читач вже догодался про їх потенційної користі при організації даних з більш складною структурою.

наступна стаття серії


Посилання по темі



Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*