Object Pascal
1. Основи мови Object Pascal
1.1. Алфавіт мови
Основними символами мови Object Pascal є:
символи _ + --
26 великих і 26 малих латинських букв A, B, ... Y, Z, a, b, ..., y, z
10 арабських цифр 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
спеціальні символи */= ^ <> () [] (). ,:; '# $ @
Літери російського алфавіту не входять до складу алфавіту мови. Їх використання можливе лише у строкових і символьних значеннях.
Ні відмінностей при використанні великих і малих букв в записі імен змінних, процедур, функцій і ярликів. Їх максимальна довжина обмежена 126 символами.
1.2. Короткі відомості про структуру програми
Програма, написана в середовищі Delphi за допомогою мови Object Pascal, завжди складається з декількох модулів. Як мінімум таких модулів має бути два. Один модуль завжди є головною програмою і має назву program. Інші модулі відіграють допоміжну і залежну від головного програми або від інших модулів роль і називаються unit. Мінімально структурована програма має один модуль program і один модуль unit. Серйозні програми крім модуля program можуть містити до декількох десятків авторських модулів unit і велика кількість посилань на фірмові або розроблені як самим автором, так і іншими розробниками модулі unit.
Програма завжди починає роботу з модуля program, активізуючи функціонування одного або декількох залежних модулів unit. Ті в свою чергу можуть активізувати інші модулі unit і т.д.
Вихідний програмний текст кожного модуля складається мовою Object Pascal і поміщається в окремий файл, який завжди має розширення. pas. Текст модуля program має розширення. Dpr.
Повний програмний текст будь-якого модуля також має свою структуру, яка може включати блоки визначення констант, внутрішніх структур опису типів, тексти процедур, функцій та ін
1.3. Лексична структура мови
Будівельним матеріалом для конструювання програмного тексту модуля є лексеми - особливі мовні конструкції, що мають самостійний сенс. Лексеми будуються за допомогою символів алфавіту мови. У Object Pascal розрізняють наступні основні класи лексем:
Зарезервовані (службові) слова. Цей клас складається з слів, побудованих тільки за допомогою букв алфавіту. Службові слова можна використовувати тільки за прямим призначенням, тобто так, як їх призначення визначив розробник мови. Ні в якому іншому вигляді, наприклад як імена змінних, їх використовувати не можна.
Нижче представлений список таких слів:
And
asm
class
destructor
do
end
file
for
if
inherited
interface
library
not
or
procedure
raise
resource
shl
then
try
until
while
with
array
begin
const
dispose
downto
except
finalization
function
implementation
initialization
in
interface
is
mod
object
out
program
record
string
shr
threadvar
type
uses
as
case
constructor
div
else
exports
finally
goto
in
line
label
nil
of
packed
property
repeat
set
string
to
unit
var
xor
Крім того, не можна використовувати такі слова, які не належать до цього класу: private, protected, public, published, automated, directives, on, virtual b>.
Ідентифікатори (імена). Ідентифікатори або імена призначені-чени для позначення констант, змінних, типів, процедур, функцій, позначок. Вони формуються з літер, цифр та символу "_" (підкреслення). Довжина імені може бути довільною, проте компілятор враховує име-на на його перших 63 символів. Всередині імені не повинно бути пробілів.
Object Pascal в іменах не розрізняє великих і малих букв. Так наступні імена будуть ідентичні:
SaveToFile, SAVETOFILE, savetofile, sAVEtOfILE.
Серед програмістів встановилося гарне правило, відповідно до якого імена формуються таким чином, щоб одночасно вико-няти роль коментаря, пояснюючого призначення імені. Так, у наведеному прикладі ім'я перекладається з англійської як "зберегти у файлі". Крім того, з урахуванням неможливості вставки всередину такого імені прогалин, перші букви слів зазвичай пишуть великими, а інші малими. З наведеного прикладу добре видно, що саме такий спосіб запису найбільш наочний для візуального сприйняття імені. Нерідко як замінник пробілу використовують символ "_". Однак це подовжує і без того довгі імена. Переваги довгих імен зовсім не означають, що не можна застосовувати короткі імена. Зрозуміло, що простіше набрати з клавіатури і використовувати оператор
a: = a + 1,
ніж ідентичний йому оператор
Disk_C_DirctoryCounter: = Disk_C_DirctoryCounter 1.
Слід, однак, з великою обережністю використовувати короткі імена, тому що це нерідко призводить до плутанини між глобальними і локальними змінними, позначеними однаковими іменами, і, як наслідок, до помилок у роботі програми. Найбільш зручним, безпечним і бажаним можна вважати локальне використання коротких імен, коли вони описані і використані всередині якої-небудь порівняно невеликий за обсягом тексту процедури або функції та їх дія обмежена межами тільки цієї алгоритмічної одиниці. При підозрі на плутанину, дія такої змінної легко проконтролювати візуально.
Зображення. До їх числа відносяться константи, символьні рядки і деякі інші значення.
Знаки операцій формуються з одного або декількох символів з визначення дій, пов'язаних з перетворенням даних.
Роздільники використовуються з метою більшого структурування модуля, з тим щоб підвищити візуальне сприйняття довгих текстів. До їхнього числа можна віднести;: = (.
Коментарі. Ці лексеми використовують для пояснення окремих фрагментів тексту програми. Вони являють собою послідовність символів, укладену в фігурні дужки () або в роздільники (* і *), а також послідовність символів, розташованих у рядку праворуч від двох наступних один за одним символів /.
Приклади коментарів:
(Функція обчислення кількості днів між двома датами)
(* Функція обчислення кількості днів між двома датами *)
// Неправильна відповідь
Пробіл. Цей символ не має видимого зображення і служить для відділення лексем один від одного в тих випадках, коли це необхідно. Зазвичай використання одного або декількох поруч стоять прогалин не спотворює сенс програми.
1.4. Деякі важливі поняття
Зупинимося на цих поняттях для того, щоб коротко визначити їх для розуміння більшості прикладів, якими супроводжується матеріал. Ці компоненти мови мають виняткову важливість, у наступних розділах вони будуть описані більш докладно.
Осередок. Цей дещо застарілий, але дуже зручний термін позначає фрагмент пам'яті, який можна представити як якийсь контейнер для зберігання даних певної структури. Осередок завжди має своє унікальне ім'я, яке служить адресою, по якому розташовані що знаходяться в ній дані. Прикладом комірки можуть служити будь-які дозволені імена, наприклад a1, Imk12, Count і т.д. Термін "осередок" не є мовними терміном Object Pascal і використовується тут тільки для більшої наочності при описі основ мови.
Значення - це постійна величина або структурний комплекс постійних величин, виражених в явному вигляді. Значення не має імені.
Приклади значень:
-55.455051 (звичайне дійсне число),
'Розрахунок посадки з натягом' (рядок символів).
Константа - це клітинка, в якій завжди зберігається одне значення. Константи не можуть бути змінені в ході виконання програми. У цьому сенсі константа відповідає загальноприйнятому визначенню постійною (незмінною) величини. Будь-яка константа повинна бути описана, тобто має бути явно вказано її значення. Значення константи неявно визначає її тип.
Необхідно відзначити, що в мові існують так звані тіпізованние константи, які під час проходження програми можуть бути змінені. Тип константи вказується в спеціальної мовної конструкції, що починається словом Type (тип).
Змінна - це клітинка, в якій в кожний момент часу зберігається одне значення або не зберігається нічого. Змінна в будь-який момент часу може бути змінена програмою. Будь-яка змінна повинна бути описана. т. е. повинен бути явно вказаний її тип. Тип змінної вказується в спеціальної мовної конструкції, що починається словом Var (від англійського variable - постійна).
Тип - це структура та опис безлічі значень, які можуть бути присвоєні змінній.
Оператор присвоювання - це команда, призначена для зміни вмісту комірки. З його допомогою відбувається зміна значення змінної (або тіпізованной константи).
Синтаксис оператора присвоєння:
x: = y; (читається "x привласнити y")
Тут x - змінна, y - вираз. Виявом можуть бути, зокрема, змінна, константа або значення. Послідовність символів ": =" означає операцію привласнення, відповідно до якої спочатку обчислюється вираз y, потім отриманий результат у вигляді значення записується в змінну x (див. докладніше гол. 9).
Приклади:
d: = 5; (значення 5 записується в змінну D),
h: = d + 12.5; (вич. 5 +12.5, рез. 17.5 записується в змінну h).
2. Система типів
У мові Object Pascal всі змінні, тобто елементу пам'яті, призначені для запису, читання та зберігання значень, повинні бути попередньо описані. Це означає, що будь-яка змінна повинна бути явно віднесена до будь-якого типу.
Тип - це одночасно структура та опис безлічі значень, які можуть бути присвоєні такої змінної.
Мова Object Pascal має безліч різноманітних типів. Більш того він дозволяє самому користувачеві конструювати найрізноманітніші типи, які можуть бути йому необхідні. Конструювання таких типів проводиться з порівняно обмеженої кількості стандартних типів.
Типи мають свою ієрархію. На верхньому поверсі ієрархії розташовані такі типи: прості, складові, посилальні і процедурні.
3. Стандартні прості типи
Основними типами мови є стандартні прості типи і стандартні структурні типи.
Прості типи поділяються на скалярні та обмежені типи. Cкалярние типи поділяються на стандартні і перечіслімие. Стандартні скалярні типи поділяються на такі групи:
цілі [Integer],
речові [Real],
логічний (булевський) [Boolean],
символьні [Char],
рядкові [String].
До них примикає особливий варіантний тип [Variant].
3.1. Цілі типи
Ця група типів охоплює безліч цілочисельних значень. Вони відрізняються один від одного діапазоном допустимих значень і кількістю займаної пам'яті.
Цілими типами є ShortInt, SmallInt, LongInt, Int64, Byte, Word і LongWord, характеристики яких наведено в табл. 1.
Таблиця 1
№
Тип
Діапазон значень
Об'єм пам'яті
1.
2.
3.
4.
5.
6.
7.
ShortInt
SmallInt
LongInt
Int64
Byte
Word
LongWord
-128 .. 127
-32768 .. 32767
-2147483648 .. 2147483647
-2 ^ 63 .. 2 ^ 63-1
0 ... 255
0 ... 65535
0 .. 4294967295
1 байт
2 байти
4 байти
8 байтів
1 байт
2 байти
4 байти
При призначенні типу змінної слід виходити з оцінки діапазону можливих значень, які вона може приймати в ході виконання програми.
Так якщо значення змінній будуть тільки позитивними, то можна її віднести до одного з типів Byte, Word, LongWord. Якщо відомо також, що її значення ніколи не вийдуть за 255 (наприклад, якщо мінлива призначена для зберігання номера місяця поточного року), то краще використовувати тип Byte. При цьому пам'ять буде витрачатися найбільш економно.
Не слід, однак, прагнути до зайвої економії пам'яті на змінних. Нерідко економно описана змінна може призвести до ситуації, коли програма спробує записати в неї таку константу, яка перевищує допустимий діапазон значень. Це приведе до негайного аварійного завершення програми з повідомленням "Range check error" (вихід за допустимі межі діапазону). Повідомлення такого роду можуть генеруватися самими різними операціями і в різних місцях програми. З цієї причини шукати помилки в програмі, особливо якщо вона багатомодульним і складна, може надовго затягтися.
Не слід також зловживати многооб'емнимі типами, тому що це може призвести до зайвого перевитрати, а іноді і нестачі пам'яті, з одного боку, та уповільнення роботи програми - з іншого.
Приклади:
Var
A, A_Par: Integer;
T1, T2, T3: LongInt;
CircleCounter: byte;
Значення цілих типів зображаються в звичайному десятковому або в шістнадцятковому видах. Вони відрізняються тим, що при зображенні шістнадцятиричних значень на його початку ставиться символ $ і самі значення формуються з шістнадцятиричних цифр 0 .. 9, A ... F.
Максимально допустимий діапазон значень визначається їх типом.
Приклади:
0 9877 -56 $ F1 (те ж, що 241)
Над цілими значеннями можна виконувати чотири звичайних арифметичних дії: додавання (+), віднімання (-), множення (*), ділення (/) і два додаткові дії: розподіл без остачі (div) і взяття залишку від ділення (mod) . При виконанні поділу результатом буде дійсне значення, у всіх інших операціях - ціле.
3.2. Речові типи
Ця група типів охоплює речові значення.
Речові типи не можуть бути використані:
як індексів масивів;
в операторах For і Case;
в якості базисного типу при визначенні множин;
при визначенні підтипів.
При описі замість Real48 можна вказувати Real.
Нижче в табл. 2 наведено список типів та їх характеристики.
Таблиця 2
№
Тип
Діапазон значень
значущих цифр у мантиса
Об'єм пам'яті
1.
2.
3.
4.
5.
6.
Real48
Single
Double
Extended
Comp
Currency
2.9 x 10 ^ -39 ... 1.7 x 10 ^ 38
1.5 x 10 ^ -45 ... 3.4 x 10 ^ 38
5.0 x 10 ^ -324 ... 1.7 x 10 ^ 30
3.6 x 10 ^ -4951 ... 1.1 x 10 ^ 4932
-2 ^ 63 +1 ... 2 ^ 63 -1
-922337203685477.5808 ... 922337203685477.5807
11 - 12
7 - 8
15 - 16
19 - 20
19 - 20
19 - 20
6 байтів
4 байти
8 байтів
10 байтів
8 байтів
8 байтів
Приклади:
Var
rA, rA_Par: Real;
T: Integer;
Речові значення можна зобразити:
у формі з фіксованою десяткового точкою;
у формі з плаваючою точкою десяткового.
Перша форма подання речового значення представляє звичне число, в якому ціла і дробова частини розділені десяткового крапкою, наприклад
12.455
-988.45
-8.0
Друга форма призначена для запису дуже великих або дуже маленьких за абсолютною величиною значень, коли їх подання у формі з фіксованою точкою важко або неможливо. Таке значення зображують у вигляді
E
Приклади:
-45.2E6 (те ж, що -45,2 106)
5.245E-12 (те саме, що 5,24 10-12)
Порядок таких чисел повинен бути завжди цілим числом.
3.3. Логічний (булевський) тип
Логічні змінні мають тип boolean. Така мінлива займає один байт пам'яті і може мати одне з двох можливих значень - True (істина) або False (неправда).
Приклади:
Var
b: boolean;
b1, Ti: boolean;
3.4. Символьний тип
Типи AnsiChar і WideChar описують безліч окремих символів мови, включаючи літери російського алфавіту. AnsiChar описує безліч з 256 ASCII-кодів і займає один байт пам'яті, WideChar описує безліч Unicode - універсальна безліч кодів і займає два байти пам'я-ти. Тип AnsiChar еквівалентний базового типу Char колишніх версій мови.
Приклади:
Var
Ch, k: AnsiChar;
Char_Massivr: array [1 .. 100] of Char;
символьне значення представляють у вигляді символу, укладеного з обох сторін у апострофи. Для зображення самого апострофа його подвоюють (останній приклад), наприклад:
'h' 'X' '#' '$'''''
3.5. Рядкові типи
Цей тип багато в чому схожий з типом Array of Char, тобто масивом символів. Відмінність полягає в тому, що мінлива цього типу може мати динамічне кількість символів (від нуля до верхньої межі), у той час як масив символів завжди статичний і має однакову кількість символів.
Таблиця 3
№
Тип
Фраза
Займана пам'ять
1.
2.
3.
ShortString
AnsiString
WideString
0 - 256 символів
0 - 2 Гб символів
0 - 2 Гб символів
(Кількість символів) х 1 байт
(Кількість символів) х 1 байт
(Кількість символів) х 2 байти
Максимальна довжина рядковий змінної повинна бути вказана явно. Розмір рядка на одиницю більше її оголошеної довжини, тому що в її нульовому байті міститься фактична довжина рядка. Довжину в нульовому байті можна примусово змінювати.
Особливо слід виділити тип String. Якщо довжина String-рядки не оголошена, то при дії директиви компілятора ( $ H + b>) або без її вказівки таке оголошення рівносильно AnsiStrig. Якщо встановлена директива ( $ H- b>), то тип String рівносильний типу ShortString.
строкове значення зображують у вигляді послідовності символів, укладеної в апострофи. Порожню рядок зображують подвійним апострофом.
Приклади значень строкових типів:
'Іванов І.І.' '' 'Газета "ИЗВЕСТИЯ"' 'Рядок символів'
Приклади опису змінних строкових типів:
Var
b>
s1, s2: ShortString [12];
st1, st2: AnsiString [580];
ChMassiv: array [1 .. 15] of String;
3.6. Рядок PChar
Для зв'язку з функціями Windows в мову Object Pascal введено новий тип рядків - PChar-рядки з завершальним нулем. У звичайній і звичної для попередніх версій мови String-рядку нульовий байт відведена для зберігання реальної кількості символів цієїрядки, а самі символи послідовно розташовуються починаючи з першого байта. У PChar-рядку, навпаки, символи розташовуються починаючи з нульового байта, а їх послідовність закінчується завершальним нулем.
Строки PChar можна оголошувати як звичайні символьні масиви. Наприклад, рядок довжини 3000 плюс один байт, зарезервований під завершальний нуль, можна визначити наступним чином:
Var b>
s: array [1 .. 3000] of Char;
П р и м і т к а і е. Без потреби не використовуйте PChar-рядка. Рядкові String-типи і функції для обробки таких рядків добре налагоджені, вони легше у використанні, і, як правило, надійніше PChar-рядків.
3.7. Динамічні PString-рядки
Цей тип рядків так само, як PChar, введений в мову для звернення до функцій Windows. Подробнее PString-рядки описані далі.
3.8. Перечіслімие типи
Цей тип змінних може бути сформований самим користувачем. Він створюється простим перерахуванням можливих значень змінної.
Приклади перечіслімих типів:
Type
b>
MaleNames = (Ivan, Peter, Serge);
SwithOpts = (On, Off);
SostTypes = (Active, Passive, Waiting);
Sides = (Left, Right, Top, Down);
У першому прикладі мінлива оголошеного типу може приймати значення одного з трьох чоловічих імен. У другому - одне з двох значень - On (включено) або Off (вимкнено) і т. д.
Імена зі списку перечіслімого типу вважаються константами відповідного перечіслімого типу і в межах блоку не повинні повторюватися.
Наприклад, описи виду
Type
Days1 = (Monday, Wednesday, Friday);
Days2 = (Tuesday, Wednesday, Saturday, Sunday);
містять помилку, тому що константа Wednesday використовується двічі.
3.9. Обмежені типи
Цей тип формується самим користувачем за допомогою звуження значень раніше визначеного або стандартного типів.
Приклади:
Type
Diapason = 1 .. 30;
Letters = 'a' .. 'v';
TList = (t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
TlistSmall = (t2 .. t8);
3.10. Варіантний тип (Variant)
Тип Variant - особливий тип мови Object Pascal. Значення цього типу наперед невідомо, однак може бути визначено через присвоюється значення одним з таких типів: всі цілі, дійсні, рядкові, символьні і логічні типи, за винятком Int64.
Наступні приклади демонструють використання типу Variant і механізм конверсії типів при змішуванні його з іншими типами. Супровідних коментарі пояснюють правила, за допомогою яких оператори присвоювання змінюють тип Variant-змінних в залежності від прийнятого ними значення.
Var
V1, V2, V3, V4, V5: Variant; (опис Variant-змінних)
I: Integer;
D: Double;
S: string;
...
begin
b>
V1: = 1; (integer-значення)
V2: = 1234.5678; (real-значення)
V3: = 'Іванов'; (string-значення)
V4: = '1000 '; (string-значення)
V5: = V1 + V2 + V4; (real-значення 2235.5678)
I: = V1; (I = 1 (integer-значення))
D: = V2; (D = 1234.5678 (real-значення))
S: = V3; (S = 'Іванов' (string-значення))
I: = V4; (I = 1000 (integer-значення))
S: = V5; (S = '2235 .5678 '(string-значення))
end;
b>
3.11. Тип "дата - час"
У мові є кілька типів, призначених для роботи з датами і часом. Вони мають вигляд
Type
b>
TDateTime = Double;
TDate = TDateTime;
TTimeStamp = Record
b>
Time: Integer; (час в мілісекундах від півночі)
Date: Integer; (одиниця + число днів з 01.01.0001 р.)
end;
b>
Тип TDateTime призначений для збереження дати і часу.
Змінна відрізняється від константи або значення тим, що в процесі роботи програми вона може змінювати вміст своєї пам'яті. Проте в кожен момент часу вона зберігає тільки одне значення. Всяка змін-ва має ім'я, тип і свою область видимості. По суті, мінлива є-ється контейнером для зберігання значення ідентичного типу. Всяка змін-ва в блоці опису повинна бути представлена тільки один раз.
Опис змінної або групи змінних починається словом Var. Область видимості змінної буде детально описано далі.
Загальний вигляд опису змінних одного типу:
:;
Приклад:
Var
t_s1, t_q1: String [255];
rt1, rt2: (Opened, Closed, Unknown);
Re1, Re2, Re3: Real;
i: Integer;
У цьому прикладі змінні t_s1 і t_q1 описані як рядкові змінні типу String [255]. При роботі програма виділить під кожну з них з урахуванням нульового байта по 256 байтів пам'яті для зберігання символьних значень. Змінні rt1, rt2 оголошені як змінні, які можуть приймати в певний момент часу одне з перерахованих значень: Opened, Closed, Unknown. Змінні Re1, Re2, Re3 оголошені речовими, а змінна i - цілочисельний типу Integer.
змінних можуть бути оголошені не тільки змінні простих типів. Нижче будуть розглянуті змінні більш складних - структурних - типів. Більш того, перемінними можуть бути оголошені структури структур, прикладом яких є класи. Наприклад:
type
TKdnClass = class (TObject)
...
End;
Var
Ts: Record
A, N: Integer;
End;
Cl: TKdnClass;
5. Опис констант
У Object Pascal розрізняється два види констант - звичайні і тіпізованние. Опис констант слід після слова Const.
5.1. Звичайні константи
Опис константи будується за правилом
=;
Приклади:
Const
T_Par = 12899;
M_ArrayCount = 16;
Middle_M_Array = M_ArrayCount div 2;
RealMax = 1.7e38;
StarString = '* * * * * * * * * * * * *';
Log10 = 2.302585;
Log10_Invert = 1/Log10;
LeftArrayBound =-M_ArrayCount;
Тип константи визначається автоматично за видом її значення.
Існує кілька констант, які заздалегідь визначені і не вимагають опису:
Pi = 3.1415926536E +00 (тип Real)
False, True (Boolean)
MaxInt = 32767 (Integer)
MaxLongInt = 2147483647 (LongInt)
Nil (Pointer).
Часто константи використовують для визначення динамічних масивів, динамічних рядків і інших динамічних структур. Наступні опису демонструють приклад такого визначення.
Const
b>
ArrMax = 100;
nSt = 46;
Var
b>
IntArr: Array [1 .. ArrMax] of Integer;
StrArrr: Array [1 .. ArrMax] of String [nSt];
Такий спосіб опису дозволяє при необхідності легко змінити розмір масивів, змінивши всього лише значення константи (у даному випадку константи ArrMax). При цьому відбудуться автоматичні зміни визначень як в поточному, так і в інших модулях, якщо вони містять визначення, що спираються на цю константу. Явне визначення масивів через значення 100 зажадало б відповідних явних змін значення на інше всюди, де такі описи мали б місце. Для великих програм це могло б стати причиною помилок, якщо частина змін не була б виконана через недогляд.
Тіпізованние константи
Це спеціальний тип констант, які відрізняються від звичайних констант тим, що при їх описі необхідно вказувати тип.
Прості тіпізованние константи. Загальний вигляд константи:
: =;
Приклади:
Const
CurrentPosition: Word = 11000;
LastLetter: Char = 'z';
HeadOfModule: String [26] = 'Початок програмного модуля';
Тіпізованние константи не можна використовувати для опису динамічних структур. Наступний приклад демонструє неприпустиме опис динамічного масиву Arr через тіпізованную константу ArrMax:
Const
ArrMax: Integer = 100;
Var
IntArr: Array [1 .. ArrMax] of Integer; (Помилка)
Значення тіпізованних констант можна змінювати в ході виконання програми, і вони можуть бути використані в якості Var-параметра процедури або функції. У зв'язку з цим тіпізованние константи по суті є змінними з початковим значенням.
Тіпізованние константи типу "масив". Цей тип констант дозволяє позначити постійною величиною цілий масив однотипних значень, наприклад:
Type
tVotes = (Yes, No, UnDef);
tVoteArr = array [tVotes] of String [7];
Const
Votes: tVoteArr = ( 'Так', 'Ні', 'Не знаю');
Var
V: tVoteArr;
S: String [20];
...
V: = Votes;
S: = V [UnDef];
...
Тут в секції Type спочатку описаний перечіслімий тип tVote з трьох значень Yes, No, Undef. Потім через цей тип визначений новий тип tVoteArr як тип-масив з трьох елементів, кожен з яких є рядком довжини 7. Далі в секції Const визначена тіпізованная константа Votes, яка визначена як масив трьох строкових значень ( 'Так', 'Ні', 'Не знаю'). Потім в секції Var описані змінні V і S різних типів. Передостання і остання рядки є виконуваними операторами присвоювання. Спочатку змінній V присвоєно початкове значення - константа Votes. Потім змінної S присвоєно значення третього елемента масиву V. У результаті значенням рядковий змінної S буде 'Не знаю'.
Тіпізованние константи типу "запис". Це комбінований тип констант, заснований на конструкціях типу Record (див. параграф 7.1), які складаються з полів. Константи такого типу визначаються за правилом "ім'я поля: значення поля".
Приклад:
Type
tDayOfYear = Record (день року)
Week: (Mon, Tue, Wed, Thu, Fri, Sat, Sun); (день тижня)
Num: 1 .. 31; (день місяця)
Month: 1 .. 12; (місяць)
Year: 1951 .. 2050; (рік)
End;
Const
D1: (Week: Sun; Num: 26; Month: 10; Year: 2001 D1, яка представляє конкретну дату "Неділя, 26, жовтень);
Тут в секції Type описана запис, що складається з чотирьох полів і характеризує день року. Призначення цих полів зрозуміло з супровідних коментарів. Потім в секції Const описана тіпізованная константа (Sun, 26; 12; 2001), тобто "неділею, 26 жовтня 2001".
Тіпізованние константи типу "безліч". Ці константи можуть бути побудовані як підмножини базових або похідних від них типів.
Приклади:
Type
tChildNameSet = set of [ 'Таня', 'Валя', 'Володя', 'Гена'];
Const
Girls2Set: tGirlsNamesSet = [ 'Валя', 'Гена'];
Indexes: set of integer = [300 .. 500, 1777,3700];
Тут в секції Type описано безліч з чотирьох імен дітей. Нижче в секції Const описано дві константи, кожна з яких представляє підмножини. Перша - підмножина імен, оголошених раніше в tChildNameSet, другий - підмножина цілих чисел типу Integer.
6. Опис типів
Раніше вже наводилися приклади опису змінних, в яких їх тип вимірювався в Var-секції явно або на основі раніше оголошеного користувацького типу.
Опис секції типів починається словом Type.
У табл. 4 дан приклад двох ідентичних способів опису змінних t, u, n.
Таблиця 4
Явний спосіб опису
змінних
Опис змінних з попереднім описом їх типу
Var
t, u, n: (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
Type
DaysOfWeek = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
Var t, u, n: DaysOfWeek;
У тих випадках, коли явний і тіпізованний способи опису змінних конкурують, варто завжди віддавати перевагу способу опису змінних з попереднім оголошенням їх типу в секції Type. Такий спосіб дозволяє:
а) конкретизувати тип;
б) чітко виділити безліч змінних цього типу;/P>
в) підвищити рівень структурованості програми;
г) знизити ймовірність плутанини в типах, коли змінні фактично того ж типу оголошені різними способами;
д) зменшити обсяг тексту за рахунок можливості швидкого посилання на раніше певний тип, особливо в тих ситуаціях, коли цей тип використовується для породження нових типів, змінних, функцій і пр. в інших секціях або модулях.
У зв'язку з цим важливо підкреслити, що навіть при збігу базових типів різниця у користувацьких типах може призвести до непередбачуваного поведінки програми. Наприклад, в нижченаведеної секції Type два похідних типу t1 і t2 мають однаковий базовий тип byte. Однак оголошені нижче в Var-секції змінні p1 і p2 будуть розцінені системою як змінні різних типів. Ця обставина може послужити причиною непорозумінь під час складання та/або виконання програми.
Type
t1 = byte;
t2 = byte;
Var
p1: t1;
p2: t2;
Коректним можна вважати наступний аналог:
Type
t1 = byte;
Var
p1, p2: t1;
7. Структурні типи
Структурні типи представляють собою сукупність значень одного чи декількох різних типів. Їх наявність дозволяє програмісту конструювати похідні типи практично будь-якої складності, що різко розширює можливості мови.
До числа структурних відносяться наступні типи:
множинні типи [Set],
регулярні типи (масиви) [Array],
комбіновані типи (записи) [Record],
файлові типи [File],
класи [Class],
класові посилання [Class reference],
інтерфейси [Interface].
Нижче будуть докладно описані перші чотири структурних типу - регулярний, комбінований, множинний і файловий.
Три останніх типи будуть описані окремо у розділах, присвячених об'єктно-орієнтованого програмування.
7.1. Регулярні типи (масиви)
Масив - це структура мови Object Pascal, що представляє собою упорядковану сукупність елементів одного типу.
Слід розрізняти два види масивів: масив-тип і масив-змінну.
Масив-тип. Синтаксис маcсіва-типу:
= Array [,, ...,]
Of;
Кожен масив має розмірність. Розмірність визначається кількістю типів індексів, які поміщені в квадратні дужки [.. ].
Масив-тип призначений для опису:
структури масиву як типу;
розмірності масиву;
типів індексів масиву;
типу кожного елемента масиву.
Так, у наступному прикладі
Type
tA1: array [1 .. 10] of Real;
описана структура одновимірного масиву речових елементів (Real), у якому індекс може змінюватися в діапазоні цілих значень від 1 до 10. Його елементами є речові типи tA1 [1], tA1 [2], tA1 [3], ..., tA1 [9], tA1 [10].
Інший приклад:
Type
Color: (Red, Green); (перечіслімий тип)
Z: array [1 .. 3, Color] of Boolean; (масив)
У ньому спочатку описаний простий перечіслімий тип Color. Нижче на його основі описаний двовимірний масив Z логічних (Boolean) елементів. Перший індекс масиву має цілий тип, а другий - тип Color. Таким чином, масив складається з шести елементів - логічних типів:
Z [1, Red], Z [1, Green], Z [2, Red], Z [2, Green], Z [3, Red], Z [3, Green].
Масив-змінна. Синтаксис маcсіва-змінної:
: Array b> [,, ...,]
Of b>;
Масив-мінлива відрізняється від масиву-типу тим, що всі його елементи - це окремі незалежні змінні, які можуть містити різні значення одного типу.
Масив-змінна може бути описаний явно або за допомогою раніше визначеного в секції Type типу.
У наступному прикладі масиви y, Z описані ідентично, причому y - явно, Z - на основі раніше визначеного типу в секції Type, тобто неявно.
Type
tA1: array [1 .. 10] of Real;
Var
y: array [1 .. 10] of Real; (масив)
Z: tA1; (масив)
Цей приклад демонструє різні способи опису однакових за структурою, але різних за типом масивів. З точки зору коректного програмування він одночасно є прикладом того, як не варто описувати ідентичні змінні. Причина цього полягає в тому, що ідентичні структури щоб уникнути непередбачуваної поведінки програми слід описувати одним типом.
У зв'язку з цим коректним буде будь-який з варіантів, наведених у табл. 5.
Таблиця 5
Коректний неявний спосіб
Коректний явний спосіб
Type tA1: array [1 .. 10] of Real;
Var Y, Z: tA1;
Var y, Z: array [1 .. 10] of Real;
Багатовимірні масиви містять два і більше індексів, наприклад:
Var h: array [1 .. 3, boolean, -7 .. 7] of Word;
що еквівалентно
Var h: array [1 .. 3] of array [boolean] of array [-7 .. 7] of Word;
Для упакованих масивів
Var packed array [Boolean, 1 .. 10, TShoeSize] of Char;
що еквівалентно
Var
packed array b> [Boolean] of packed array b> [1 .. 10]
of packed array b> [TShoeSize] of b> Char;
Маніпуляції з окремими елементами масивів. Звернення до окремого елементу масиву можливо через його індекси. У наступному прикладі в секції Var описані проста мінлива i і два одновимірних масиву A і V як цілі змінні типу Integer. Потім у блоці begin ... end розташовані три обчислювальних оператора.
Var
i: Integer;
A, V: array [1 .. 100] of Integer;
...
begin
i: = 5;
V [8]: = i 9;
A [45]: = V [i +3] * 2;
end;
При виконанні першого з них мінлива i прийме значення 5. При виконанні другий - восьмий елемент масиву V прийме значення 14. У третьому операторі спочатку буде обчислено індекс i + 3 = 8, потім значення восьмого елемента масиву V (значення 14) буде помножена на 2 і отриманий результат - значення 28 - буде присвоєно 45-му елементу масиву A.
Маніпуляції з масивами. Мова допускає за допомогою одного оператора присвоєння виконати операцію над масивом в цілому. Нехай, наприклад, масиви A, V оголошені як квадратні матриці. Тоді оператор
V: = A;
виконає копіювання значень всіх елементів масиву A в масив V, а після виконання оператора
V: = A * V;
буде виконано множення матриці А на матрицю V і результат буде поміщений в матрицю V з попередніми затиранням старих значень.
Упаковані масиви. Елементи упакованого масиву зберігаються в пам'яті максимально щільно. Під час запису він попередньо упаковується з метою економії пам'яті. При читанні, навпаки, розпаковується. Операції упакування і розпакування вимагають додаткового часу. Тому використання упакованих масивів трохи сповільнює роботу програми. Від звичайного масиву Array опис упакованого масиву відрізняється тим, що перед цим словом додається слово Pаcked, наприклад:
Var W: packed array [1 .. 100] of Integer;
7.2. Комбіновані типи (записи)
Запис - це об'єднання елементів різних типів. Як і в масивах, слід розрізняти запис-тип і запис-змінну. Один елемент запису називається полем.
Запис-тип. Синтаксис запису-типу:
= Record b>
:;
:;
...
:;
End b>;
Записи дуже зручні для опису і зберігання різнотипних даних про будь-які однотипних структурах.
Прикладом можуть служити відомості про студентів. Відомості про будь-якому з них можуть мати поля: Прізвище, Ім'я, По батькові, Рік народження, Група, Рік вступу до вузу, Курс. Такі структури є однотипними і можуть бути описані таким типом:
Type
TStud = Record (Відомості про студента як запис)
Fio: String [40]; (ПІБ як рядокз 40 символів)
Name: String [20]; (Назва як рядок з 20 символів)
Otch: String [30]; (батькові як рядок з 30 символів)
BirthYear: Word; (Рік народження як ціле типу Word)
Group: String [8]; (Група як рядок з 8 символів)
ElectYear: Word; (Рік вступу як ціле типу Word)
Curs: Byte; (Курс як ціле типу Byte)
End;
b>
У цьому прикладі типи полів запису типу tStud призначені з урахуванням максимально можливих значень цих полів. Так, структура може зберігати прізвище з не більше ніж 40 символів. Полю Curs призначений тип Byte, який має діапазон значень 0 .. 255, т. к. значенням цього поля може бути одне з значень 1 .. 6, які повністю охоплюються діапазоном типу Byte. Цьому полю можна було б призначити будь-який інший цілий тип, наприклад Word. Однак, з метою економії пам'яті, підвищення швидкості читання і запису даних, слід призначити саме тип Byte, який займає всього 1 байт пам'яті, а не тип Word, який вимагає 2 байти пам'яті. У той же час, наприклад, для поля ElectYear (рік вступу) тип Byte непридатний, адже має недостатній діапазон значень.
Записи з варіантами. Синтаксис запису допускає варіантність опису полів. Варіантна частина містить кілька альтернатив, в кожній з яких у круглих дужках задається список полів, властивих свого варіанту. Прикладом можуть служити запису про пенсіонерів:
Type
tPensioner = Record b> (пенсіонер)
FioIO: String [100]; (Прізвище, ім'я, по батькові одним рядком)
Age: Byte; (Вік)
Case b> Citizen: boolean of b> (Горожанин чи?)
TRUE: (Town: String [30];) (Місто, в якому проживає)
FALSE: (Address: String [100]; (Повна адреса одним рядком)
Transport: String [200];) (Транспорт, яким можна дістатися до міста)
End;
У цьому прикладі запис tPensioner містить зрозумілі поля FioIO і Age, а також поле нового виду - логічне поле Citizen варіантного типу. Від значення цього поля залежить поява і непоявленіе деяких потенційних полів запису. Так якщо значення цього поля TRUE (істина), то в записі з'являється (стає доступним) поле Town (місто), при значенні FALSE (неправда) - поля Address і Transport.
При використанні варіантних полів в записах слід підкорятися наступним правилам синтаксису:
варіантна частина повинна починатися з рядка, на початку якої розташовується слово Case, а в її кінці - слово Of. Між ними розташовується поле-ознака.
Запис повинен містити тільки один варіант, який має розташовуватися в кінці всіх описаних полів безпосередній перед словом End.
Імена полів у всіх варіантах повинні бути різними. Вони повинні також відрізнятися від імен полів фіксованої частини.
Для деяких можливих значень поля-ознаки варіант може бути відсутнім. У цьому випадку після двокрапки, що відповідає значенню варіанту, слід поставити порожній список () або не вказувати цей варіант взагалі (включаючи значення, двокрапка і порожнє поле).
Запис-змінна. Синтаксис запису-змінної:
: Record
b>
:;
:;
...
:;
End;
b>
тобто синтаксис змінної і типу відрізняються одним символом ( ":" і "=").
Приклад:
Type
tMass: Array [1 .. 2, 1 .. 50] of Real;
tRec: Record
b>
Name: String [10];
Mass2: tMass;
End;
b>
Var
J: Integer;
S: String [70];
F, Gri: Record
a, b, c: Integer;
k: Array [1 .. 10] of String