Масиви символів. Рядки символів у мові Паскаль використовуються як масиви. Рядки, що містять один символ, є константами стандартного типу char. Рядок, що містить п (п > 1) символів, вважається константою типу, який означається як упакований масив:
PACKED ARRAY [1..n] OF char
При цьому кожен символ є компонентом масиву. Службове слово PACKED вказує на те, що при розміщенні компонентів масиву в пам'яті ЕОМ більш економічно використовується пам'ять. Компоненти масиву запам'ятовуються в послідовно розміщених комірках пам'яті, причому для звичайних (неупакованих) масивів кожен з них займає поле в одне слово. Кількість байтів, які відводяться під слово, залежить від типу ЕОМ. Так, в деяких ЕОМ під слово відводиться чотири байти. В упакованих масивах в одному слові міститься кілька символів. Зокрема, під один символ може відводиться один байт пам'яті.
Рядкова змінна — це упакований масив символів.
Приклади опису рядкових змінних:
VAR line : PACKED ARRAY [k..l] OF char;
x: PACKED ARRAY [1..12] OF char;
У програмі таким змінним можна присвоїти значення — рядок символів. Наприклад,
х:= 'мова Паскаль'
Довжина рядка не може змінюватися в процесі виконання програми. Тому будь-яке значення, яке присвоюється рядковій змінній, повинно містити ту кількість символів, яка вказана при опису змінної. Інакше виконання програми переривається i видається повідомлення про помилку. Наприклад, щоб помістити в х більш короткий рядок, треба доповнити рядок пропусками до 12 символів:
х:= 'Мова Бейсік ‘
Дозволяється використовувати i неупакованi масиви символів.
Наприклад,
VAR у : ARRAY [1..12] OF char;
Проте неупакований масив у в оперативній пам'яті займатиме більше місця, ніж упакований масив х.
Властивості рядків випливають з властивостей масивів. Рядки одного того самого типу можуть фігурувати в операторах присвоювання. До них можна застосовувати операції відношення =,<>,<,< =. >. > = (тут рядки розглядаються як масиви літер і тому компоненти операцій відношення повинні мати однакову довжину).
Результати операцій відношення залежать від того, як впорядковані символи. Правила впорядкування різні для різних ЕОМ. Проте в усіх випадках справедливі такі співвідношення:
‘A’ < ‘B’ <...< ‘Y’ < ‘Z’
‘0’ < ‘1’ < … < ‘8’ < '9’
Порівняння рядків відбувається так: спочатку порівнюються перші зліва символи; якщо вони однакові, то порівнюються наступні символи і т. д. Наприклад, відношення 'BASIC’ < ‘PASCAL’, '25' > '200’, — істинні, а відношення ‘ ABC’= ‘ABC’ — хибне.
Зауважимо, що стандартна процедура read не дає змоги автоматично читати рядки з вхідного файла. Якщо треба читати символьні рядки, то це виконується в циклі, посимвольно. Виводити ж на друк символьні змінні можна цілком (а не лише покомпонентно).
Наприклад,
writeln (line);
writeln (x)
Упаковані масиви можна використовувати в програмі так само, як і неупаковані, але їх іноді не дозволяється передавати процедурі чи функції як параметри-змінні. Програма з упакованими масивами працює повільніше (плата за економію пам'яті). Це пояснюється тим, що компоненти упакованого масиву вибираються повільніше, ніж компоненти неупакованого масиву. В деяких випадках швидкодію програми можна збільшити, скопіювавши упакований масив в неупакований перед його використанням. Якщо, наприклад, описано два масиви
VAR а: ARRAY [m..n] OF char;
pa : PACKED ARRAY [k..l] OF char;
j: k..l;
де n – m >= l—k, то розпаковку масиву pa можна було б виконати так:
FOR j:= k ТО l DO a[j —k+ m]:= pa [j];
Після виконання цього оператора масив ра буде розпакований:
a [m]:= ра [k]; а [т + 1]:= pa [k + 1]; .... a [l — k + m]: = pa [l].
У мові Паскаль є стандартна процедура unpack для розпаковки масиву.
unpack (pa, а, i)
Ця процедура рівносильна
FOR j:= k ТО l DO а[j — k + i]:=ра [j]
Для упаковки масиву е також стандартна процедура — раск:
раск (а, і, pa).
Ця процедура рівносильна
FOR j:= k ТО l DO ра [j]:= a[j – k + i].
Зазначимо, що упаковка і розпаковка масивів, компоненти яких належать до будь-якого іншого типу, відмінного від char, виконується так само.
Тип даних string. Масиви символів мають один недолік — їх довжина не може змінюватися під час виконання програми. Під час роботи з літерними величинами доводиться в основному мати справу з рядками, довжина яких наперед невідома. Для запису таких алгоритмів в мові Паскаль передбачений тип даних string (рядок) (в стандартному Паскалі використання цього типу не передбачено). Змінні типу string на відміну від звичайного масиву символів можуть набувати значень змінної довжини.
Описуючи змінні типу string, вказують максимальну довжину (атрибут довжини), яка не повинна перевищувати 255. Наприклад,
VAR line, line 1 : string [150];
line2 : string [40];
Тут описано три змінні типу string. Перші дві змінні можуть мати будь-яку довжину від 0 до 150, змінна line 2 — довільну довжину від 0 до 40. Зауважимо, що довжину 0 має порожній рядок (рядок, який не містить жодного символу). Наприклад, після оператора присвоювання line 2 :=‘’ змінна line 2 є порожнім рядком.
Для вводу значень змінних типу string використовується оператор readln, а не read. Одним оператором можна ввести тільки один рядок.
Два рядки, як і масиви символів, можна порівнювати, використовуючи операції відношення. Порівнювання виконується так, як і порівнювання масивів символів. Єдина відмінність тільки в тому, що рядки можуть мати різну довжину. Якщо перший рядок коротший, ніж другий, і всі його символи збігаються з відповідними символами другого рядка, то більшим вважається другий, довший, рядок. Отже, наступні логічні вирази матимуть значення true:
'DELTA' > 'ALPHA', 'APPLE' < 'PEAR', 'fir' < 'fire', 'ELEPHANT' < 'MOUSE';
вирази матимуть значення false:
'MOUSE' < 'ELEPHANT', 'DELTA' < > 'DELTA',’fir’ > 'fire'.
Операції, стандартні функції і процедури для роботи з рядками.
У мові Паскаль можна використовувати операцію з'єднання (склеювання, конкатенації) рядків, яка позначається знаком +.
Наприклад, після виконання оператора присвоєння
x:= 'ТРАНС' + 'ФОРМА' + 'ТОР'
рядкова змінна х матиме значення ‘ТРАНСФОРМАТОР’. Для роботи з рядками у мові Паскаль є ряд стандартних (вбудованих) функцій.
Функція length— для заданого значення типу string видає ціле число, яке дорівнює кількості символів в значенні рядка.
Наприклад, після виконання операторів (u, v — рядкові змінні)
u:= ‘’; v:= 'ALPHA';
write (length (v), length (u));
v:= 'КОНСТРУКТОР';
write (length ('АВТО') + length (v));
буде видано три числа: 5, 0, 15.
Функція concatвиконує операцію з'єднання рядків, які є аргументами функції. Наприклад, результатом функції concat ('ТРАНС', 'ФОРМА', 'ТОР') буде рядок 'ТРАНСФОРМАТОР'. Цього ж результату можна досягти, якщо використати знак +.
Функція pos (u, v) (u, v — рядки) визначає, чи міститься перший рядок у другому. Результатом функції – є ціле число, яке дорівнює номеру першої зліва позиції, починаючи з якої рядок u входить у рядок v. Якщо перший рядок не міститься в другому, то функція видає значення 0.
Наприклад,
значення pos ('ФОРМА', 'ТРАНСФОРМАТОР') дорівнює 6,
значення pos ('ІН', 'ФОРМА') дорівнює 0,
значення pos('IH', 'ІНФОРМАТИКА') дорівнює 1.
Функція copy (s, i, j) формує символьний рядок довжиною в j символів, починаючи з позиції i початкового рядка s.
Так, оператор
write (copy ('ТРАНСФОРМАТОР', 6, 5) видає слово 'ФОРМА', а оператор
write (copy (s, length (s) — 1, 2) — два останніх символи рядкової змінної s.
Операції вирізання алгоритмічної мови а [р : q] відповідає в мові Паскаль функція
copy (а, р, m), де m = q — р + 1.
Для роботи з рядками можна використовувати також вбудовані процедури.
Процедура delete (s, і, j) вилучає з рядка s j символів, починаючи з позиції і. Так, після виконання операторів
х:= 'трансформатор';
delete (x, 6, 5);
writein (x)
буде виведено рядок 'транстор'.
Процедура insert (s1, s2, i) вставляє рядок s1 в рядок s2 перед символом s2[i].
Процедура str(x,s)перетворює чисельне значення х у відповідний символьний рядок, значення якого присвоюється рядковій змінній s. Якщо, наприклад, значення цілої змінної z дорівнює 1988, то після виконання оператора процедури ster(z, line) значення рядкової змінної line дорівнюватиме '1988'.
Процедура val (s, v, с) перетворює рядковий вираз s у ціле чи дійсне значення (залежно від типу змінної v) і присвоює це значення змінній v; с — це ціла змінна. Якщо при перетворенні помилку не виявлено, то с набуває значення 0, інакше ціла змінна с набуває значення позиції першого помилкового символу; значення v у цьому випадку не визначене. Якщо, наприклад, s має значення '125', то val (s, х, і) присвоїть х значення 125, а i — значення 0.
Якщо s має значення '3R5', то
val (s, х, с) присвоїть с значення 2, а х буде невизначеним.
2.10. Множини
У мові Паскаль використовується такий складений (структурований) тип, як множина (тип SET). Поняття множини у мові Паскаль дещо вужче, ніж традиційне математичне поняття. Множина може складатися з довільної кількості, включаючи нуль, компонент одного типу.
Означення типу множина має таку форму:
TYPE ім'я типу = SET OF тип компонент
Тип компонент (його ще називають базовим) — це довільний простий тип, крім real. Для цілого типу можна задавати лише діапазони. Множина (тип SET) містить елементи базового типу, всі підмножини початкової множини і порожню множину.
Нехай, наприклад, задано такі означення і описи:
TYPE numbers = SET OF 1..3;
charset = SET OF 'A'.. ‘Z';
primarycolor = (red, green, blue);
color = SET OF primarycolor;
VAR nsl, ns2 : numbers;
chars : charset;
colorl, color2, соlогЗ : color;
Тут numbers, charset, color — імена типу множина. Значеннями змінних типу SET є конкретні множини. Тоді значеннями змінних nsl і ns2 може бути одна з множин [ ] (порожня множина), [І], [2], [З], [1, 2], [1, З], [2, З], [1, 2, З]. Зауважимо, що для позначення множини замість фігурних дужок у мові Паскаль використовуються квадратні. Змінна chars має тип множини, ім'я якого charset. Значеннями цієї змінної може бути будь-яка з множин [ ], [‘A’], [‘B’],…,[‘Z’], [‘A’,’B’],…, [‘A’, ‘Z’],…, [‘A’..’Z’].
Змінні colorl, color2, соїогЗ можуть мати значеннями одну з множин [ ], [red], [green], [blue], [red, green], [red, blue], [red, green, blue]. Кожна з множин є комбінацією основних кольорів (червоного, зеленого, синього; primary color — основний колір); порожня множина означає відсутність кольору взагалі.
Для вище описаних змінних можна записати, наприклад, такі оператори присвоювання:
ns1:= [2, 3]; ns2:=[];
chars:= ['A'..'H', 'P'];
color1 := [red, blue];
Як бачимо, в програмі множина задається у вигляді списку елементів, які взято в квадратні дужки. У дужках може не бути елементів, може стояти один або кілька елементів, які відокремлюються один від одного комами. Елементом може бути константа, змінна, вираз, значення якого належать базовому типу, а також інтервал значень (пара елементів, які відокремлені двома крапками).
Множина, яка описується за допомогою інтервалa, в якого перше граничне значення більше другого, трактується як порожня. Наприклад, множини [3..1], ['С’..'А'], [blue..red] трактуються як порожні множини.
Змінні, які належать до типу множина, можуть бути описані безпосередньо в розділі VAR, без попереднього означення імені типу в розділі TYPE. Наприклад,
VAR nsl, ns2: SET OF 1..3;
При роботі з множинами можна використовувати операції об'єднання (+), перетину (*), різниці (—) множин.
Наприклад,
[1, 2]+ [2, 3] ® [1, 2, 3]
[1, 2] * [2, 3] ® [2]
[1, 2, 3] - [1] ® [2, 3]
['A'..'H', 'P'] — ['D'..’H'] ® ['A', 'В', 'С', 'P']
За допомогою таких операцій можна будувати вирази, значення яких належать даному типу. В операторах присвоювання для змінних типу множина права частина в загальному випадку є виразом того самого типу.
Множини можна порівнювати за допомогою операцій відношень =,<>,<=,>=. Логічний вираз S1 = S2, де S1 і S2 однотипні множини, має значення true, якщо S1 і S2 містять одні й ті самі елементи. Якщо множини 51 і S2 відрізняються хоча б одним елементом, то значення виразу S1 < > S2 є true. Значення true мають також вирази:
S1 < = S2, якщо множина S1 є підмножиною множини S2;
SI > = S2, якщо множини S2 є підмножиною множини S1.
Наприклад, значення true мають вирази:
[2, 3] = [2, 3];
['A'...'Z'] - ['С', ‘К'] < = ['A'..'Z']
[1, 2, 3] = [1..3]
[2]<>[1..3]
[ ] < = [red, blue]
Значення виразів
[2] < = [3]
[1,2]*[ ]<>[ ]
[3..1] >=[2] є false.
Є спеціальна операція IN, яка дає змогу перевірити, чи належить елемент даній множині. Загальний вигляд операції входження такий:
вираз базового типу IN вираз типу множина Результатом операції е значення типу boolean : true — якщо значення виразу зліва є елементом множини, яка є значенням виразу справа; false — якщо не є елементом множини.
Використання операції входження дає змогу в деяких випадках записувати логічні вирази значно простіше.
Наприклад, оператор
IF (х = 2) OR (x = 4) OR (x = 5) OR (x = 6) OR (x = 7) THEN... можна записати так:
IF x IN [2, 4...7] THEN...
2.11. Записи
У мові Паскаль для подання сукупності даних різних типів є структурований тип запису. Запис (тип RECORD) — це структура даних, яка складається з фіксованого числа компонентів, які називаються полями. При цьому поля можуть бути різних типів.
Записи зручно використовувати тоді, коли необхідно об'єднати різні дані, які належать до одного об'єкта.
Наприклад, інформація про книгу в бібліотеці може бути подана у формі запису, який містить такі дані:
Шифр
Автор
Назва
Видавництво
Рік видання
Анотація
Ціна
Прапорець, який показує, чи видано книгу, чи ні. Анкетні відомості про учня можуть містити, зокрема, такі поля:
Прізвище
Ім'я
Стать
Рік народження
Клас
Оцінки
Отже, записи, як і масиви, використовуються для опису впорядкованої сукупності величин. Проте між ними є суттєві відмінності.
Так, компоненти масиву повинні бути одного типу, а компоненти запису можуть мати різні типи. Іншим є й механізм вибору компонентів масиву і запису. Для масивів використовується обчислювальний вибір компонентів, при якому змінна з індексами однозначно вказує на потрібний компонент. У записах кожному компоненту присвоюється власне ім'я, яке й використовується для вибору поля.
Означення типу запис у мові Паскаль має вигляд:
TYPE ім'я типу =
RECORD
ім'я m1, ім'я n1, …: тип 1;
ім'я m2, ім'я n2, …: тип 2;
………………………….
ім'я mk, ім'я nk, …: тип k
END;
Тут імена mj, nj, …, j = 1,2, …, k, — це імена полів, які є окремими компонентами запису.
Приклади означення структур типу запис:
1. TYPE complex = RECORD
re : real;