Елементи програмування мовою PASCAL

 ·             Повернутись в головне меню

        

·        Структура програми

·        Ідентифікатори і службові слова

·        Вирази і операторації

·        Опис змінних та констант

·        Опис типів

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

·        Ввід та вивід.Формати виводу

·        Оператори

·        Типи даних

·        Процедури і функції

·        Стандартні процедури і функції

·      Процедури і функції роботи із графікою

·        Класи і об’єкти

·        Модулі

 

 

 


 



Ідентифікатори і службові слова

 

Ідентифікатори служать як імена програм, модулів, процедур, функцій, типів, змінних і констант. Ідентифікатором вважається будь-яка послідовність латинських букв або цифр, що починається з букви. Буквою вважається також символ підкреслення "_".

Наприклад, a1 _h, b123 - ідентифікатори, а 1a, ф2 - ні.

 

Зарезервовані слова Borland Pascal   Табліця 1.1

----------------------------------------------------------------

                                                                                     

and

array

as

begin

break

case

class

const

constructor

continue

destructor

div

do

downto

else

end

exit

external

externalsync

file

finalization

for

forward

function

if

in

inherited

initialization

is

mod

not

of

or

private

procedure

program

property

protected

public

 

record

repeat

set

shl

shr

sizeof

string

 

then

to

type

unit

until

uses

var

while

with

xor

 

 

                                    

                                                               

                                                        

                                  

                                

                                                 

                                  

                                                   

                        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Структура програми

Програма на мові Pascal має наступний вигляд:

program ім'я програми;
розділ підключення модулів

розділ описів

begin  

 оператори

end.

Перший рядок називається заголовком програми і є необов'язковою.

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

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

Розділ підключення модулів і розділ описів можуть бути відсутній.

Операторі відділяються один від одного символом "крапка з комою".

 

Вирази і операції

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

В Pascal є наступні операції: @, not ^ * /, div, mod, and, shl, shr +, -, or, xor = > < <> <= і >=.

Арифметичні операції

До арифметичних відносяться бінарні операції + - * / для дійсних і цілих чисел, бінарні операції div і mod для цілих чисел і унарні операції + і - для дійсних і цілих чисел. Вираз, що має числовий тип, називається арифметичним. Тип арифметичного виразу визначається за наступним правилом: якщо всі операнди цілі і у виразі відсутня операція розподілу /, той вираз має тип integer, в осоружному випадку вираз має тип real. Наприклад, якщо b має тип byte, з має тип 1..9, то b+c і -b мають тип integer, а 2.0+b і 1/2 - тип real.

Логічні операції

До логічних відносяться бінарні операції and, or і xor, а також унарна операція not, операнди типу boolean, що мають, і повертаючі значення типу boolean. Вираз, що має тип boolean, називається логічним.

Операції відношення

 Операції відношення < > <= >= = <> повертають значення типу boolean і застосовуються до операндів цілого, речовинного, символьного, логічного і рядкового типів, а також до покажчиків, що типізуються. Операції = і <> також застосовуються до операндів типу роinter, до операндів, є об'єктами класів і до константи nil. При порівнянні символу і рядка символ перетвориться в рядок довжини 1.

Побітові операції

Побітові операції and, or, not, xor, shl, shr проводять побітові маніпуляції з операндами цілого типу. Для унарної операції not результат має той же тип, що і операнд. Для решти операцій результат має тип integer. Наприклад, якщо b має тип byte і b=1, то b shl 10=1024, а not b=254.

Рядкові операції

Крім операцій відношення < > <= >= = <>, до рядкових і символьних операндів застосовна операція конкатенації (злиття) +. Її результат має рядковий тип. Наприклад, 'a'+'b'='ab'. Оскільки рядки можуть містити максимум 255 символів, то якщо зливаються рядки сумарної довжини більше 255, то програма завершується повідомленням про помилку

» Помилка: відбулося переповнювання рядка при виконанні операції "+".

Операція @

Операція @ застосовується до змінної і повертає її адресу.

Операції з покажчиками

До покажчиків, що типізуються, застосовна операція разыменования ^: якщо p є покажчиком на тип T, то p^ - елемент типа T, на якого указує p.

Крім операцій відношення < > <= >= = <>, до покажчиків, що типізуються, застосовні арифметичні операції + і -.

Операція + застосовується до покажчика і цілого числа, що типізується: якщо p має тип ^T і указує на елемент а[k] одновимірного масиву елементів типу T, i - ціле, то p+i повертає адресу елемента а[k+i]. Операція - застосовується до двох покажчиків одного типу, що типізуються: якщо p1 і p2 указують на елементи одновимірного масиву елементів типу T, то p2-p1 повертає кількість елементів між цими покажчиками (узяте із знаком -, якщо адреса в p2 менше адреси в p1). Наприклад:

var
   а:
array [1..10] integer;  

   p: ^integer;

begin   p:=@a[1];
 
 for i:=1 to 10 do   begin     

 p^:=i;
            p:=p+1
;
 
 end;
   ...

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

 До множин застосовні операції + (об'єднання), - (різниця) і * (перетин):

var
        
s1,s2,s: set byte;

begin  

s1:=[1..4];  

s2:=[2..5];  

s:=s1+s2; // s=[1..5] 

s:=s1-s2; // s=[1]
s:=s1*s2; // s=[2..4]

До множин застосовні також операції відношення:

= (рівність)

<> (нерівність)

<= (вкладено) 

>= (містить):

var
   s1,s2,s: set byte;  

b: boolean;

begin  

s1:=[1..4];  

s2:=[2..5]; 

s:=[1,2];     

b:=s1=s2; // b=False  

b:=s2<>s; // b=True  

b:=s<=s2; // b=False
b:=s1>=s; // b=True

Нарешті, операція in визначає, чи належить елемент множині:

1 in [2..5] // False
3 in [2..5] // True

Пріоритет операцій

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

Таблиця пріоритетів операцій

@, not ^

1 (щонайвищий)

* /, div, mod, and, shl, shr

2

+, -, or, xor

3

= <> < > <= >=, in

4 (низький)

 

 

Опис змінних і констант

Розділ описів змінних починається із службового слова var, після якого слідують рядки вигляду

 список імен змінних: тип;

Імена в списку перераховуються через кому. Наприклад:

var
        
а,b,c: integer;  

d: real;  

e,f: integer;  

s,s1: string;  

ch: char;

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

 ім'я константи = значення;

або

ім'я константи : тип = значення;

Наприклад:

const
  Pi = 3.14;
  Count = 10;
  Name = 'Mike';
  DigitsSet = ['0'..'9'];
  Arr: array [1..5] of integer = (1,3,5,7,9);
  Rec: record name: string; age: integer end = (name: 'Иванов'; age: 23);
  Arr2: array [1..2,1..2] of real = ((1,2),(3,4));

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

 

Опис типів

Розділ опису типів починається із службового слова type, після якого слідують рядки вигляду

 ім'я типу = тип;

 

Наприклад:

type
  myint = integer;
  arr10 = array [1..10] of integer;
  pinteger = ^integer;
  A = class
    i: integer;
    constructor Create(ii: integer);
    begin
      i:=ii;
    end;
  end;

 При описі рекурсивних структур даних, вказівник на тип може фігурувати раніше опису самого типу у визначенні іншого типу:

type
  PNode = ^TNode;
  TNode = record
    data: integer;
    next: PNode;
  end;

 При цьому важливо, щоб визначення обох типів знаходилися в одному розділі type.

Наступний опис буде помилковим:

type
  TNode = record
    data: integer;
    next: ^TNode;
  end;

 (повідомлення про помилку: "Тип TNode повністю не визначений").

 

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

Основна програма, процедура і функція складаються із заголовка і блоку. Блоком називається розділ описів, після якого слідують оператори, укладені в операторні дужки begin/end.

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

В блоці, проте, може бути описано декілька процедур або функцій з одним ім'ям, але з різним набором параметрів (це називається перевантаженням).

Область дії ідентифікатора (тобто місце, де він може бути використаний) простягається від моменту опису до кінця блоку, в якому він описаний. Область дії глобальноого ідентифікатора, описаного в модулі, простягається на весь модуль, а також на основну програму, до якої даний модуль підключений в розділі uses.

Ідентифікатор з тим же ім'ям, визначений у вкладеному блоці, приховує ідентифікатор, визначений в зовнішньому блоці. Наприклад, в коді

var i: integer;

procedure p;
var i: integer;

begin  

i:=5;

end;

значення 5 буде присвоєно змінній i, описаній в процедурі p; усередині ж процедури p послатися на глобальну змінну i неможливо.

Аналогічна ситуація має місце і в похідних класах: в них можна визначати поля з тими ж іменами, що і в базових класах, але тоді посилатися на полі базового класу з методу похідного класу не можна. Проте, можна посилатися на метод базового класу з методу похідного класу, використовуючи службове слово inherited:

type
  A=class
    i: integer;
    procedure p;
    begin
      i:=5;
    end;
  end;
  B=class(A)
    i: integer;
    procedure p;
    begin
      i:=5;
      inherited p;
    end;
  end;

 Ввід і вивід. Формати виводу

 Для виводу у вікно виведення використовуються стандартні процедури write і writeln. Вони можуть викликатися як без параметрів, так і із списком параметрів. Параметри в списку перераховуються через кому і повинні мати простий тип (окрім перечислимого типу і інтервального типу, побудованого на базі перечислюваного), або тип string, або тип вказівника. Процедура writeln після виведення своїх параметрів здійснює перехід на наступний рядок.

В процедурах виводу write і writeln після кожного значення типу, що виводиться, може указуватися формат виведення, що є двокрапкою, після якої слідує ціле число або вираз. Це число або вираз задає ширину поля виведення, тобто кількість позицій, що відводяться під значення, що виводяться. Якщо довжина значення, що виводиться, менше ширини поля виводу, то текст, що виводиться, доповнюється зліва пропусками до потрібної ширини; значення, що в результаті виводиться, вирівнюється по правому краю. Якщо довжина значення, що виводиться, більше ширини поля виведення, то формат виведення ігнорується. Речовинні і комплексні значення з форматом виведення вигляду :m завжди виводяться в експоненціальній формі.

Наприклад, якщо а, b - цілі змінні, то при виконанні операторів

а:=-2437;

b:=13555;

writeln(а:6,'Привет!':9);
writeln(b:1);

у вікно виведення буде виведений наступний текст:

-2437   Привіт!
13555

Для речовинних і комплексних значень можна також використовувати формат :m:n, де m і n - цілі значення. Значення m задає ширину поля виведення, а значення n   кількість знаків після десяткової крапки. Наприклад:

writeln(-14.859:10:3);  //  ___-14.859

writeln(-14.859:10:5);  // _-14.85900

writeln(-14.859:10:2);  //  ____-14.86

writeln(-14.859:10:0);  //  _______-15

writeln(-14.859:10:7);  // -14.8590000

writeln((0,1):10:1);     // _(0.0,1.0)

(тут символом “ зображені пропуски).

Для введення з клавіатури використовуються стандартні процедури read і readln. Вони можуть викликатися як без параметрів, так і з списком параметрів. Параметри в списку перераховуються через кому і повинні бути змінними простого типу (окрім перечислюваного типу, а також інтервального типу, побудованого на базі перечислюваного), або типу string. Процедура readln після введення пропускає дані до кінця поточного рядка введення.

Процедури write, writeln, read, readln - єдині, для яких можна вказувати список параметрів довільної довжини.

Для уведення-виведення в текстовий файл використовуються ті ж процедури, але як перший параметр вказується файлова змінна:

writeln(f,'abc',1,True,2.4);

 

 

Оператори

 

·        Оператор присвоєння

·        Умовний оператор

·        Оператор вибору

·        Оператор циклу for

·        Оператор циклу while

·        Оператор циклу repeat

·        Оператори break, continue і exit

·        Оператор with

Оператор присвоєння

Оператор присвоєння має вигляд:

змінна:= вираз

Як змінна може бути проста змінна, розіменований вказівник, змінна з індексами або компонент змінної типу запис. Вираз повинен мати тип, або співпадаючий з типом змінної, або такий, що неявно до нього приводиться (див.  Неявне приведення типів).

Умовний оператор

Умовний оператор має повну і коротку форми.

Повна форма умовного оператора виглядає таким чином:

 

if <умова> then <оператор1>
else <оператор2> ;

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

Коротка форма умовного оператора має вигляд:

if <умова> then <оператор>;

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

У разі конструкції вигляду

 if < умова > then   

       if < умова2 > then <оператор1>
       else <оператор2> ;

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

if умова1 then
begin   

if умова2 then оператор1;

end

else оператор2

Єднальний і порожній оператори

Єднальний оператор призначений для об'єднання декількох операторів в один. Він має вигляд:

begin
  операторы
end

 Оператори відділяються один від одного символом ";". Службові слова begin і end, оздоблюючі оператори, називаються операторними дужками.

Наприклад:

s:=0; p:=1;
for i:=1 to 10 do
begin
  p:=p*i;
  s:=s+p
end

 Перед end також може ставитися ";". В цьому випадку вважається, що останнім оператором перед end є порожнім оператором, що не виконує жодних дій.

Оператор вибору

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

case перемикач of
  список вибору 1: оператор1;
  ...
  список вибору N: операторN;
  else оператор0
end;

 Перемикач є виразом порядкового типу (цілого, символьного, перечислимого або інтервального), а списки вибору містять константи сумісного типу. Як і в операторі if, вітка else може бути відсутньою.

Оператор case працює таким чином: якщо в одному із списків вибору знайдено поточне значення перемикача, то виконується оператор, відповідний даному списку. Якщо ж значення перемикача не знайдено ні в одному списку, то виконується оператор по вітці else або, якщо вітка else відсутня, оператор case не виконує жодних дій.

Список вибору складається або з однієї константи, або з діапазону значень вигляду а..b (константа а повинна бути менше константи b); можна також перерахувати декілька констант або діапазонів через кому:

case DayOfWeek of
  1..5: writeln('Будній день');
  6,7: writeln('Вихідний день');
end;

 Списки вибору не повинні перетинатися. Наприклад, наступний фрагмент

case i of
  2,5: write(1);
  4..6: write(2);
end;

 приведе до помилки компіляції "Перетин діапазонів міток в операторі case".

 

Оператор циклу for

Оператор циклу for має одну з двох форм:

for змінна:=початкове значення to кінцеве значення do
   оператор

або

for змінна:= початкове значення downto кінцеве значення do
   оператор

Текст від слова for до слова do включно називається заголовком циклу, а оператор після do - тілом циклу. Змінна після слова for називається параметром циклу. Для першої форми циклу з ключовим словом to параметр циклу міняється від початкового значення до кінцевого значення, збільшуючись всякий раз на одиницю, а для другої форми ключовим словом downto - зменшуючись на одиницю. Для кожного значення змінної-параметра виконується тіло циклу. Однократне повторення тіла циклу називається ітерацією циклу.

Значення параметра циклу після завершення циклу вважається невизначеним.

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

Якщо цикл використовується в процедурі або функції, то змінна-параметр циклу повинна бути описаний як локальна.

Крапка з комою, наступна відразу після do, в Pascal вважається синтаксичною помилкою.

Зміна змінної-параметра циклу усередині циклу є логічною помилкою. Наприклад, наступний фрагмент з вкладеним оператором for є помилковим:

for i:=1 to 10 do
   for i:=1 to 5 do      

write(i);

Змінна-параметр циклу може мати будь-який порядковий тип (цілий, символьний, перечислюваний або інтервальний). При цьому типи початкового і кінцевого значення повинні відповідати типу параметра циклу. Наприклад:

var
  en: (red,green,blue,white);
  c: char;
...
for en:=red to blue do
  write(Ord(en):2);
for c:='a' to 'z' do
  write(c);
 

 

  Оператор циклу while

Оператор циклу while має наступну форму:

while <умова> do
   оператор

<Умова> є виразом логічного типу, а оператор після do називається тілом циклу. Перед кожною ітерацією циклу умова обчислюється, і якщо вона істинна, то виконується тіло циклу, в протилежнлму випадку відбувається вихід з циклу.

Якщо <умова> завжди виявляється істинною, то може відбутися зациклювання:

while 2>1 do
   write(1);

Щоб перервати програму, що зациклилася, слід використовувати комбінацію клавіш Ctrl-F2 .

Оператор циклу repeat

Оператор циклу repeat має наступну форму:

repeat
   оператори

until умова

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

Якщо умова завжди виявляється помилковою, то може відбутися зациклювання:

repeat
   write(1);

until 2=1;

Щоб перервати програму, що зациклилася, слід використовувати комбінацію клавіш Ctrl-F2.

  Оператор виклику процедури

Оператор виклику процедури має вигляд:

ім'я процедури

або

ім'я процедури(список фактичних параметрів)

Кількість фактичних параметрів повинна співпадати з кількістю формальних, а типи фактичних параметрів повинні відповідати типам відповідних формальних.

Оператори break, continue і exit

Оператори break і continue використовуються тільки усередині циклів.

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

flag:=False;
for i:=1 to 10 do
begin
  read(x);
  if x<0 then continue; // пропуск поточної ітерації цикла
  if x=5 then
  begin
    flag:=True;
    break; // вихід з цикла
  end
end;

 Використовування операторів break і continue зовні тіла циклу помилково.

Оператор exit призначений для дострокового завершення процедури або функції. Наприклад

function Analyze(x: integer): boolean;
begin
  if x<0 then
  begin
    Result:=False;
    exit
  end;
  ...
end;

 Виклик exit в розділі операторів основної програми приводить до її негайного завершення.

Оператор with

Оператор with дозволяє скоротити звернення до полів запису, а також до полів, методів і властивостей об'єкту. Він має вигляд:

with ім'я запису або об'єкту do оператор

або

with список імен do оператор

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

var
  DateOfBirthday=record
    Day: Integer;
    Month: Integer;
    Year: Integer;
  end;

 Тоді присвоєння значень її полям без використання оператора with має вигляд:

DateOfBirthday.Day:=23;

DateOfBirthday.Month:=2;

DateOfBirthday.Year:=1965;

Використовування оператора with дозволяє скоротити попередній запис:

with DateOfBirthday do
begin
  Day:=23;
  Month:=2;
  Year:=1965; 
end;

 Якщо зовнішня змінна має те ж ім'я, що і поле (метод, властивість), то перевага віддається полю (методу, властивості). За наявності вкладених операторів with спочатку робиться спроба розглядати змінну як поле запису або об'єкту самого внутрішнього оператора with, потім безпосередньо охоплюючого його оператора with і т.д. Якщо оператор with   містить список об'єктів, то вони розглядається справа наліво. Наприклад, якщо є опису

var
  x,y,z: integer;
  a: record
    x,y: integer;
  end;
  b: record
    x: integer;
  end;

 то фрагмент програми

with a,b do
begin
  x:=1;
  y:=2;
  z:=3; 
end;

еквівалентний фрагменту

with a do
 with b do
 begin
   x:=1;
   y:=2;
   z:=3; 
 end;

а також фрагменту

b.x:=1;
a.y:=2;
z:=3;

 

Типи даних

 

Огляд типів

В Pascal є наступні типи:

integer (цілий)
byte (байтовий)
char (символьний)
перечислюваний
діапазонний
boolean (логичний)
real (дійсний)
complex (комплексний)
string (рядковий)
array(тип "массив")
record(тип "запис")
pointer(тип "вказівник")
процедурний
файловий
классовий

Типи integer, byte, char, перечислимый і діапазонний називаються порядковыми. Тільки значення цих типів можуть бути індексами масивів і фігурувати як вираз-перемикача в операторі case. Змінна-параметр циклу for також повинна мати перечислимый тип.

До всіх значень порядкового типу застосовні наступні функції:

Pred(x) повертає значення, передуюче x (до якнайменшого значення не застосовується);
Succ(x) повертає значення, наступне за x
(до найбільшого значення не застосовується);
Ord(x)
повертає порядкове ціле значення, відповідне x. Для цілих x повертає саме значення x, для символів char повертає їх код, а для елементів перечислимого типу - їх номер (нумерація починається з нуля).

Всі порядкові типи, а також типи boolean, real і complex називаються простими типами.


Порядкові типи

Тип integer (цілий). Значення цього типу займають 4 байти і знаходяться в діапазоні від -2147483648 до 2147483647. Константа MaxInt береже значення 2147483647.

Тип byte (беззнаковий цілий). Значення цього типу займають 1 байт і знаходяться в діапазоні від 0 до 255.

Тип char (символьний). Значення цього типу займають 1 байт і є символами в кодуванні Windows. Стандартна функція Chr(x) повертає символ з кодом x. Константи цього типу можуть бути записаний у вигляді #x, де x - ціле число від 0 до 255.

Перечислімий тип визначається впорядкованим набором ідентифікаторів:

type
   Season = (Winter,Spring,Summer,Autumn);   DayOfWeek = (Mon,Tue,Wed,Thi,Thr,Sat,Sun);

Значення перечислимого типу займають 4 байти.

Інтервальний тип є підмножиною значень цілого, символьного або перечислимого типу і описується у вигляді а..b, де а - нижня, b - верхня межа інтервального типу:

var
   а: 0..10;   з: 'a'..'z';   d: Mon..Thr;  

Тип, на основі якого будується інтервальний тип, називається базовим

Типи boolean, real і complex

Тип boolean (логічний). Змінні і константи логічного типу займають 1 байт і приймають одне з двох значень, що задаються приреченими константами True (істина) і False (брехня).

Тип real (речовинний). Значення речовинного типу займають 8 байт, містять 15-16 значущих цифр і по модулю не можуть перевершувати величини 1.7•10308. Найменше позитивне число речовинного типу рівно 5.0•10-324. Константи типу real можна записувати як у формі з плаваючою крапкою, так і в експоненціальній формі: 1.7, 0.013, 2.5e3 (2500), 1.4e-1 (0.14).

Тип complex (комплексний). Значення комплексного типу займають 16 байт. Константи цього типу записуються у вигляді (x,y), де x і у - вирази речовинного типу, речовинну і уявну частини комплексного числа, що є. Якщо змінна з має тип complex, то звернутися до її речовинної і уявної частин можна як до полів запису: c.re і c.im. Наприклад:

const ci=(0,1);
var з: complex;...c.re:=2*c.im;з:=ci*c+(c.im,c.re);

До змінних типу complex застосовні стандартні числові функції: abs, sin, cos, exp, ln, sqrt, а також функція conj(c), що повертає комплексно зв'язане до з, і функція carg(c), що повертає головне значення аргументу комплексного числа з. При обчисленні багатозначних функцій ln, sqrt, carg повертається головне значення і передбачається, що розріз зроблений по негативній речовинній осі, причому, верхній берег належить розрізу. Так, carg(c) повертає значення в діапазоні (-Pi,Pi].

  Рядковий тип( STRING )

Рядки мають тип string і складаються з не більше ніж з 255 символів. При описі

var s: string;

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

Для економії пам'яті передбачений опис вигляду

 var s1: string[40];

В цьому випадку під рядок відводиться 41 байт (нульовий байт - під довжину рядка). У разі присвоєння змінного s1 рядка із понад 40 символів зайві символи відсікаються, і довжина рядка s1 вважається рівною 40.

При виконанні операції конкатенації вигляду s1+s1 результат вважається рядком типу string, тобто займає 256 байт. Проте, якщо при конкатенації результат займатиме більше 255 символів, то програма завершиться з помилкою.

До символів в рядку можна звертатися, використовуючи індекс: s[i] позначає i-тий символ в рядку. Звернення до нульового символу s[0] вважається помилковим. Щоб змінити довжину рядка, слід скористатися процедурою SetLength(). Якщо індекс i виходить за межі пам'яті, що відводиться під рядок, то видається повідомлення про помилку. Проте, якщо індекс i виходить лише за межі довжини рядка, то повідомлення про помилку не видається.

  Масиви

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

array [тип индекса1 ..., тип индексаN] базовий тип

Тип індексу обов'язково є інтервальним типом і обов'язково повинен задаватися у вигляді а..b, де а і b - константні вирази цілого, символьного або перечислюваного типу. Наприклад:

type enum=(w1,w2,w3,w4,w5);
var    a1,a2: array [1..10] integer;
 
 b: array ['a'..'z',w2..w4] string;
  
з: array [1..10] array [1..5] real;

Базовий тип може бути будь-яким (зокрема, він може бути типом масиву, як для змінної з).

Змінні-масиви одного типу можна присвоювати один одному, при цьому проводитиметься копіювання вмісту одного масиву в іншій:

a1:=a2;

При передачі по значенню параметра типу масив в підпрограму також проводиться копіювання вмісту массива-фактического параметра в массив-формальный параметр:

procedure p(arr: array [1..10] integer);
...p(a1);

Як правило, в цій ситуації копіювання вмісту масиву не потрібне, тому масив рекомендується передавати по посиланню:

procedure r(var arr: array [1..10] integer);
...r(a1);

До елементів масиву звертаються за допомогою змінних з індексами:

a1[3]:=a2[5];
b['f',w3]:='Hello';
з[3]
[4]:=3.14;

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

Записи( RECORD )

Запис є набором елементів різних типів, кожний з яких має своє ім'я і називається полем запису. Тип запису конструюється таким чином:

record

список полів1: тип1;

...

 список полівN: типN;

end

Останній символ ";" не є обов'язковим. Наприклад:

type
   Date=record      

Day: 1..31;      

Month: (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Осt, Nov, Dec);      

Year: Integer; 

 end;

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

var d1,d2: Date;

Щоб отримати доступ до полів запису, слід скористатися точковою нотацією, вказавши ім'я змінної-запису і поле, розділене крапкою:

d1.Day:=9;
d1.Month:=Sep;d1.Year:=2004;

Як і для масивів, можна скопіювати вміст полів однієї змінної-запису в іншу:

d2:=d1;
 

Множини

 Множина є набором елементів одного порядкового типу. Елементи множини вважаються неврегульованими; кожний елемент може входити в множину не більше одного разу. Тип множини описується таким чином:

set of базовий тип

Як базове може бути будь-який порядковий тип з елементами, для яких функція Ord повертає значення в діапазоні від 0 до 255. Наприклад:

type
  ByteSet = set of byte;
  CharSet = set of char;
  Digits = set of '0'..'9';
  SeasonSet = set of (Winter,Spring,Summer,Autumn);

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

 [список значень]

де в списку можуть перераховуватися через кому або вирази базового типу, або їх діапазони у вигляді а..b, де а і b - вирази базового типу. Наприклад:

var
  bs: ByteSet;
  bestdays: (Mon,Tue,Wed,Thi,Thr,Sat,Sun);
...
bs:=[1,3,5,20..25];
bestdays:=[Wed,Thr..Sun];

Значення в списку можуть бути відсутній, тоді множина є порожньою:

bs:=[];

Операція in перевіряє приналежність елемента множині:

if Wed in bestdays then ...

Для множин визначені операції:     + (об'єднання),   - (різниця), * (перетин), = (рівність), <> (нерівність), <= (вкладено), >= (містить). Приклади цих операцій приведені в пункті Вирази і операції.

Множини з сумісними базовими типами неявно перетворяться одне до іншого (див. пункт Неявне приведення типів). При присвоєнні множині за необхідності відбувається усікання його елементів до значень базового типу. Наприклад:

var st: set 3..9;...
st:=[1..5,8,10,12]; // в st потраплять значення [3..5,8]

Щоб вивести значення елементів множини, необхідно перебрати всілякі значення в циклі і перевірити їх на приналежність множині за допомогою операції in:

for i:=0 to 255 do
   if i in st then write(i,' ');

Вказівники

Вказівник зберігає адресу комірки пам'яті.

Тип вказівника на тип T має форму ^T, наприклад:

type pinteger=^integer;
var p: ^record

r,i: real

       end;

Нетипізовані вказівники описується за допомогою слова роinter.

Для доступу до елемента пам'яті, адресу якого зберігає вказівник, що типізується, використовується операція розіменування ^:

var
     i: integer;  

     pi: ^integer;

     ...

     pi:=@i; // вказівнику присвоїли адресу змінної i

     pi^:=5; // змінній i присвоїли 5

Операція розіменування не може бути застосованою до нетипізованого вказівника.

Вказівник, що типізується, може бути неявно перетворений до нетипізованого:

type preal=^real;
var    p: роinter;   pr: ^real;...p:=pr;

Зворотне перетворення може бути виконано тільки явно:

pr:=preal(p);
pr^:=3.14;

Вказівник можна порівнювати на рівність (=) і нерівність (<>). На додаток до цього вказівники, що типізуються, можна порівнювати, використовуючи операції < > <= >=.

Для вказівників, що типізуються, доступні також операції p+i, p-i і p2-p1, де i ціле.

Для того, щоб відзначити той факт, що вказівник нікуди не вказує використовують стандартну константу  nil (нульовий вказівник)

 Файли

Текстові файли бережуть символи, розділені на рядки символами #13#10.

Для опису текстового файлу використовується стандартне ім'я типу text, а для опису файлу, що типізується, - конструкція file тип елементів:

var
   f1: file real;  

   f2: text;

Файлові процедури і функції описуються в пункті Процедури і функції для роботи з файлами.

Процедурний тип

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

procedure (список параметрів)

або

function (список параметрів): тип значення, що повертається

При цьому список параметрів разом з круглими дужками можуть бути відсутній. Наприклад:

type proc=procedure(i: integer);
var
  p1: proc;
  p2: procedure;
  f1: function: integer;

Процедурній змінній можна привласнити процедуру або функцію з сумісним типом:

procedure my(i: integer);
begin
  ...
end;
function f: integer;
begin

end;
...
p1:=my;
f1:=f;

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

p1(5);
write(f1);

procedure foreach(var a: array [1..100] of real; n: integer; p: procedure(var r: real));
var i: integer;
begin
  for i:=1 to n do
    p(a[i]);
end;

procedure mult2(var r: real);
begin
  r:=2*r
end;

procedure print(var r: real);
begin
  write(r,' ');
end;
...
foreach(a,10,mult2); // множення елементів масиву на 2
foreach(a,10,print); // вивід елементів масиву

 

 

Еквівалентність типів

Два типи вважаються еквівалентними (рівними), якщо співпадають їх описи. Наприклад, після описів

type Arr=array [1..100] of integer;
var
  a: Arr;
  b: array [1..100] of integer;

 можна присвоювати масиви один одному:

а:=b;

В типах записів, крім типів полів, повинні співпадати імена:

type
  rec1 = record i,j: integer end;
  rec2 = record x,y: integer end;
...
var r1: rec1; r2: rec2;
...
r1:=r2; // ошибка!

 В типах формальних параметрів процедур і функцій імена можуть не співпадати:

type
  proc1 = procedure (i: integer); 
  proc2 = procedure (x: integer);
...
var p1: proc1; p2: proc2;
...
p1:=p2; // все правильно

Подібне розширене трактування еквівалентності (в порівнянні з Borland Pascal і Borland Delphi) дозволяє передавати параметри складового типу (масиви, записи, процедурний і вказівний) в процедури і функції, не визначаючи для цих параметрів новий тип:

procedure foreach(var a: array [1..100] of real; n: integer; f: function(r: real): real);
var i: integer;
begin
  for i:=1 to n do
    a[i]:=f(a[i]);
end;

 

 Неявне приведення типів

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

Типи byte і integer неявно перетворяться один до одного, а також до типів real і complex.

Тип real неявно перетвориться до типу complex.

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

Символ неявно перетвориться в рядок. Рядки різної довжини неявно перетворяться один до одного.

Покажчик на будь-який тип неявно перетвориться до вказівника роinter.

Похідний клас неявно перетвориться до базового.

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

Ім'я процедури або функції неявно перетвориться до вказівника на процедуру або функцію з параметрами тих же типів (у функції повинен також співпадати тип значення, що повертається).

В процесі виконання програми після неявного перетворення числових типів може відбутися переповнювання. Наприклад, це можливо при перетворенні типу integer в тип byte. Проте, якщо s1 і s2 - рядки і при привласненні s1:=s2 дані рядки s2 не уміщаються в рядок s1, то залишок рядка усікається без виникнення помилки.

Операнди у виразах також можуть мати різні типи. В цьому випадку звичайно менший тип неявно приводиться до більшого або обидва типи приводяться до більшого. Наприклад, якщо r має тип real, а i - тип integer, то у виразі r+i значення i спочатку приводиться до типу real, після чого виконується операція складання над двома речовинними значеннями. Якщо рядок s1 має тип string[30], а s2 - тип string[40], то у виразі s1+s2 обидва рядки приводяться до типу string і тільки потім виконується операція складання.

Вирази "менший тип" і "більший тип" в попередньому абзаці використовуються в значенні діапазону значень. Наприклад, тип set 1..9 менше типу set byte, але жоден з типів set 1..9 і set 5..15 не менше іншого.

Явне приведення типів

Деякі типи не приводяться до інших неявно, проте таке перетворення має сенс. Наприклад, змінну типу char можна перетворити до значення типу byte, що є кодом символу. Змінну типу integer, що містить ненегативне значення, можна перетворити до інтервального типу, причому, це значення виступатиме номером елемента в порядковому типі.

Для перетворення виразу до нового типу використовується конструкція

ім'я нового типу(вираз)

Наприклад:

type
  pinteger=^integer;
  days=(mon,tue,wed,thi,fri,sat,sun);
var
  p: pointer;
  i: integer;
  en: days;
...
p:=pinteger(@i);
i:=integer(en):
en:=days(3);

 Слід звернути увагу на те, що для явного приведення типів необхідно використовувати ідентифікатор імені типу (тобто тип повинен визначатися одним словом). Наприклад, наступний запис є помилковим:

p:=^integer(@i);

Явні перетворення типів містять всі неявні. Крім того, всі порядкові типи можна явно перетворювати один до одного, всі порядкові типи можна явно перетворювати до типів real і complex, базовий клас можна явно перетворити до похідного і покажчик роinter можна явно перетворити до покажчика на будь-який тип.

 

Процедури і функції

 

Опис процедур і функцій

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

Будь-яка, що використовується в програмі, процедура або функція повинна бути заздалегідь описаною в розділі описів.

Опис процедури має вигляд:

procedure ім'я(список формальних параметрів);

розділ описів
begin

   оператори

end;

Опис функції має вигляд:

function ім'я(список формальних параметрів): тип значення, що повертається;
розділ описів

begin  

оператори

end;

Оператори підпрограми, облямовані операторними дужками begin/end, називаються тілом цієї підпрограми.

Список формальних параметрів разом з оточуючими дужками може бути відсутній. Він складається з однієї або декількох секцій, розділених символом ";". Кожна секція складається із списку змінних, перераховуваних через кому, після якого слідують двокрапка і тип. Кожна секція може передувати службовим словом var, що указує на те, що параметри передаються по посиланню (Параметри процедур і функцій).

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

Приклад опису процедури наводиться нижче:

procedure Reverse(var a: array [1..100] of integer; n: integer);
var i,v: integer;
begin
  for i:=1 to n div 2 do
  begin
    v:=a[i];
    a[i]:=a[n-i+1];
    a[n-i+1]:=v;   
  end;
end;

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

function Add(a,b: real): real;
begin
  Add:=a+b;
end;

Ім'я функції може бути використано з метою повернення значення тільки в лівій частині оператора присвоєння. Якщо ім'я функції зустрічається у виразі, то це трактується як рекурсивний виклик цієї функції.

Замість імені функції, усередині тіла функції можна використовувати іншу спеціальну змінну з ім'ям Result. На відміну від імені функції, змінну Result можна використовувати і у виразах:

function MinElement(var a: array [1..100] of real; n: integer): real;
var i: integer;
begin
  Result:=a[1];
  for i:=1 to n do
    if a[i]<Result then Result:=a[i];
end;

Якщо усередині функції не присвоїти імені функції або змінної Result деяке значення, то функція поверне в результаті свого виклику непередбачуване значення.

Параметри процедур і функцій

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

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

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

procedure PrintSquare(i: integer);
begin
  writeln(i*i);
end;

Тоді при виклику PrintSquare(5*a-b) значення 5*a-b буде обчислено і привласнено змінній i, після чого виконається тіло процедури.

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

procedure Mult2(var a: integer);
begin
  a:=a*2;
end;

то після виклику Mult(d) значення d збільшиться в 2 рази.

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

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

procedure Print(var a: array [1..10] of integer; n: integer);
var i: integer;
begin
  for i:=1 to n do
    write(a[i],' ');
  writeln;
end;

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

procedure PrintSquare1(i: integer);
begin
  i:=i*i; // правильно
  writeln(i);
end;
procedure PrintSquare2(const i: integer);
begin
  i:=i*i; // помилково!!!
  writeln(i);
end;

 

Локальні і глобальні змінні

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

Параметри підпрограми вважаються її локальними змінними.

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

var i: real;

procedure p;

var i: integer;

begin

  // до глобальної змінної i усередині процедури не можна звернутися

  i:=5; // присвоєння локальної змінної i; ...

end;

 

Випереджаюче оголошення

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

procedure B(i: integer); forward;

procedure A(i: integer);

begin

  ...

  B(i-1);

end;

procedure B(i: integer);

begin

  ...

  A(i div 2);

end;

Forward-оголошення можливо тільки для зовнішніх підпрограм. Заборонено також робити forward-оголошення для вже описаної підпрограми.

 

Перевантаження імен

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

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

procedure p(b: byte);
begin

end;
procedure
p(r: real);
begin

end;

то при виклику p(1.0) буде вибрана переобтяжена версія з параметром типу real (точна відповідність), а при виклику p(1) буде вибрана переобтяжена версія з параметром типу byte (при цьому відбудеться перетворення фактичного параметра типу integer до типу byte).

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

procedure p(i: integer; r: real);
begin

end;
procedure
p(r: real; i: integer);
begin

end;

то при виклику p(1,2) обидва вони однаково підходять, що приводить до неоднозначності.

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

 

 

Стандартні процедури і функції

 

Загальні стандартні процедури і функції

Ім'я і параметри

Процедура або функція

Типи параметрів

Тип значення, що повертається

Дія

Read(а,b...)

процедура

а,b,c - змінні простого типу або типу string

 

вводить значення з клавіатури в змінні а, b ...

Write(а,b...)

процедура

а,b,c - вирази простого типу, типа string або покажчики

 

виводить значення а, b ... у вікно висновку

 

Readln(а,b...)

процедура

 а,b,c - змінні простого типу або типу string

 

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

Writeln(а,b...)

процедура

а,b,c - вирази простого типу, типа string або покажчики

 

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

Abs(x)

функція

x - integer, real, complex

співпадає з типом параметра

повертає абсолютне значення (модуль) x

Sqr(x)

функція

x - integer, real, complex

співпадає з типом параметра

повертає квадрат x

Sqrt(x)

функція

x - real, complex

співпадає з типом параметра

повертає квадратний корінь з x

Sin(x)

функція

x - real, complex

співпадає з типом параметра

повертає синус x

Cos(x)

функція

x - real, complex

співпадає з типом параметра

повертає косинус x

Ln(x)

функція

x - real, complex

співпадає з типом параметра

повертає натуральний логарифм x

Exp(x)

функція

x - real, complex

співпадає з типом параметра

повертає e в ступені x (e=2.718281...)

Arctan(x)

функція

x - real, complex

співпадає з типом параметра

повертає арктангенс x

Power(x,y)

функція

x, у - real

real

повертає x в ступені у

Conj(z)

функція

z - complex

complex

повертає число, комплексно зв'язане до z

Carg(z)

функція

z - complex

real

повертає аргумент комплексного числа z (в діапазоні (-Pi, Pi])

Round(x)

функція

x - real

integer

повертає результат округлення x до найближчого цілого

Trunc(x)

функція

x - real

integer

повертає цілу частину х

Int(x)

функція

x - real

real

повертає цілу частину х

Frac(x)

функція

x - real

real

повертає дробову частину х

Ord(x)

функція

x - порядкового типу

integer

повертає номер значення порядкового типу

Chr(x)

функція

x - integer

char

повертає символ з кодом х

Odd(x)

функція

x - integer

boolean

повертає True, якщо х - непарне, і False в осоружному випадку

Inc(x)

процедура

x - порядкового типу

 

Збільшує x на 1

Dec(x)

процедура

x - порядкового типу

 

Зменшує x на 1

Inc(x,n)

процедура

x - порядкового типу, n - цілого типу

 

Збільшує x на n

Dec(x,n)

процедура

x - порядкового типу, n - цілого типу

 

Зменшує x на n

Pred(x)

функція

x - порядкового типу

співпадає з типом параметра

повертає попереднє значення порядкового типу

Succ(x)

функція

x - порядкового типу

співпадає з типом параметра

повертає наступне значення порядкового типу

Random(x)

функція

x - integer

integer

повертає випадкове ціле в діапазоні від 0 до x-1

Random

функція

 

real

повертає випадкове речовинне в діапазоні [0..1)

Include(s,x)

процедура

s - множина, x - елемент, тип якого сумісний з базовим типом множини

  

включає елемент x в безліч s

Exclude(s,x)

процедура

s - множина, x - елемент, тип якого сумісний з базовим типом множини

  

виключає елемент x з безлічі s

FillChar(v,count,x)

процедура

v - змінна будь-якого типу, count - integer,
x - byte

 

заповнює count значеннями x область пам'яті, займану змінній v. Контроль виходу за межі не проводиться

 

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

Ім'я і параметри

Процедура або функція

Типи параметрів

Тип значення, що повертається

Дія

Length(s)

функція

s - string

integer

повертає довжину рядка s

Сміттю(s,index,count)

функція

s - string, index і count - integer

string

повертає підрядок рядка s довжини count, починаючи з позицією index

Delete(s,index,count)

процедура

s - string, index і count - integer

 

видаляє в рядку s count символів починаючи з позицією index

Insert(subs,s,index)

процедура

s, subs - string, index - integer

 

вставляє підрядок subs в рядок s з позиції index

Pos(subs,s)

функція

s, subs - string

integer

повертає позицію першого підрядка subs в рядку s (або 0 якщо підрядок не знайдений)

SetLength(s,n)

процедура

s - string, n - integer

 

встановлює довжину рядка s рівної n

Str(x,s)
Str(x:n,s)
Str(x:n:m,s)

процедура

s - string, x - integer, real і n, m - integer

 

перетворить x до рядкового уявлення (в другому і третьому випадках згідно формату висновку, встановлюваному n і m) і записує результат в рядок s

Val(s,v,code)

процедура

s - string, v - integer, real, і code - integer

 

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

IntToStr(i)

функція

i - integer

string

перетворить ціле число до рядка

StrToInt(s)

функція

s - string

integer

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

FloatToStr(r)

функція

r - real

string

перетворить дійсне число до рядка

StrToFloat(s)

функція

s - string

real

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

UpCase(c)

функція

з - char

char

повертає символ з, перетворений до верхнього регістра

 

LowCase(c)

функція

з - char

char

повертає символ з, перетворений до нижнього регістра

 

UpperCase(s)

функція

s - string

string

повертає рядок s, перетворений до верхнього регістра

 

LowerCase(s)

функція

s - string

string

повертає рядок s, перетворений до нижнього регістра

 


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

 

Ім'я і параметри

Процедура або функція

Типи параметрів

Тип значення, що повертається

Дія

Assign(f,name)

процедура

f - змінна файлового типу, name - string

 

зв'язує файлову змінну f з файлом з ім'ям name

Reset(f)

процедура

f - змінна файлового типу

 

відкриває файл, раніше пов'язаний з файловою змінною f за допомогою процедури Assign. Файл повинен існувати на диску, в осоружному випадку відбувається помилка часу виконання. Текстові файли відкриваються тільки на читання, файли, що типізуються, - на читання і запис

Rewrite(f)

процедура

f - змінна файлового типу

 

створює і відкриває новий файл, раніше пов'язаний з файловою змінною f за допомогою процедури Assign. Якщо файл з вказаним ім'ям вже існує, то він віддаляється, і замість нього створюється новий файл. Текстові файли відкриваються тільки на запис, файли, що типізуються, - на читання і запис

Append(f)

процедура

f - змінна типу Text

 

відкриває текстовий файл на запис для додавання. Файловий покажчик встановлюється в кінець файлу.

Close(f)

процедура

f - змінна файлового типу

 

закриває файл

FileExists(name)

функція

name - string

boolean

повертає True, якщо на диску є файл з ім'ям name, в осоружному випадку повертає False

CanCreateFile(name)

функція

name - string

boolean

повертає True, якщо можна створити файл з ім'ям name, в осоружному випадку повертає False

Read(f,a,b...)

процедура

f - змінна файлового типу, а,b - змінні простого типу, типа string або покажчики

 

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

Write(f,a,b...)

процедура

f - змінна файлового типу, а,b - вирази простого типу, типа string або покажчики

 

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

 

Readln(f,a,b...)

процедура

 f - змінна типу Text, а,b - змінні простого типу, типа string або покажчики

 

прочитує значення з текстового файлу f в змінні а, b ..., після чого пропускає символи до кінця рядка. Виклик readln(f) просто пропускає символи до кінця рядка

Writeln(f,a,b...)

процедура

f - змінна типу Text, а,b - вирази простого типу, типа string або покажчики

 

записує значення а, b ... в текстовий файл f, після чого записує в нього символ кінця рядка. Значення а, b ... записуються у файл в текстовому вигляді, при цьому можуть бути використаний формати висновку. Виклик writeln(f) просто записує у файл символ кінця рядка

Eof(f)

функція

f - змінна файлового типу

boolean

повертає True, якщо файловий покажчик стоїть на кінці файлу, і False в осоружному випадку

Eoln(f)

функція

f - змінна типу Text

boolean

повертає True, якщо файловий покажчик стоїть на кінці рядка, і False в осоружному випадку

SeekEof(f)

функція

f - змінна типу Text

boolean

пропускає пропуски, символи табуляції і переходу на новий рядок, після чого повертає True, якщо файловий покажчик стоїть на кінці файлу, і False в осоружному випадку

SeekEoln(f)

функція

f - змінна типу Text

boolean

пропускає пропуски, символи табуляції, після чого повертає True, якщо файловий покажчик стоїть на кінці рядка, і False в осоружному випадку

FileSize(f)  

функція

f - змінна типу file

integer

повертає кількість елементів у файлі, що типізується

FilePos(f)

функція

f - змінна типу file

integer

повертає позицію файлового покажчика у файлі, що типізується (нумерація елементів у файлі, що типізується, починається з нуля)

Seek(f,n)

процедура

f - змінна типу file

 

переміщає файловий покажчик у файлі, що типізується, на n-тый елемент (нумерація починається з нуля)

Truncate(f)

процедура

f - змінна типу file

 

видаляє всі елементи файлу, що типізується, з поточної позиції файлового покажчика до кінця файлу

Rename(f,name)

процедура

f - змінна файлового типу, name - string

 

перейменовує файл, пов'язаний з файловою змінною f. Файл повинен бути закритий

 

Erase(f)

процедура

 f - змінна файлового типу

 

видаляє файл, пов'язаний з файловою змінною f. Файл повинен бути закритий

 

 

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

 

Ім'я і параметри

Процедура або функція

Типи параметрів

Дія

New(p)

процедура

p - вказівник, що типізується

виділяє динамічну пам'ять розміру, рівного розміру типа, на якого указує p, і повертає покажчик на неї в змінній p

Dispose(p)

процедура

p - вказівник, що типізується

звільняє динамічну пам'ять по покажчику p, раніше виділену процедурою New

GetMem(p,n)

процедура

p - вказівник будь-якого типу, n - integer

виділяє динамічну пам'ять розміру n байт і повертає покажчик на неї в змінній p

FreeMem(p)

процедура

p - вказівник будь-якого типу

звільняє динамічну пам'ять по покажчику p, раніше виділену процедурою GetMem

 

Системні процедури і функції

Ім'я і параметри

Процедура або функція

Типи параметрів

Тип значення, що повертається

Дія

Sleep(ms)

процедура

ms - integer

 

Здійснює паузу у виконанні програми на ms мілісекунд

Cls

процедура

 

 

Очищає вікно висновку

 

Halt(n)

процедура

 n - integer

 

Завершує програму. Виводить у вікно висновку попередження "Програма завершена викликом Halt(n)"

 



Процедури та функції робои із графікою

Procedure arc(x, y,stAngle, endAngle, radius:integer);

Procedure arc(x, y,stAngle, endAngle, radius:integer; color:COLORS);

Procedure arc(x, y,stAngle, endAngle, radius, color:integer);

Procedure bar( x, y, x1, y1:integer);

Procedure bar(x, y, x1, y1, color : integer);

Procedure bar(x, y, x1, y1:integer; color:COLORS);

Procedure bar3d(x, y, x1, y1, z:integer; top:boolean);

Procedure circle(x, y, radius:integer);

Procedure circle(x, y, radius :integer; color :COLORS);

Procedure circle(x, y, radius, color :integer);

Procedure close();

Procedure cleardevice();

Procedure closegraph();

Procedure ellipse(x, y, rWidth, rHeight:integer);

Procedure ellipse(x, y, rWidth, rHeight:integer; color:integer);

Procedure ellipse(x, y, rWidth, rHeight:integer; color:COLORS);

Procedure fillellipse(x, y, rWidth, rHeight:integer);

Procedure fillellipse(x, y, rWidth, rHeight, color:integer);

Procedure fillellipse(x, y, rWidth, rHeight:integer; color:COLORS);

Function getmaxx():integer;

Function getmaxy():integer;

Procedure image(x, y :integer; path:string);

Procedure initgraph();

Procedure initgraph(setWidth, setHeight:integer);

Procedure initgraph(drv, drm:integer; text:string);

Procedure line(x, y, x1, y1:integer);

Procedure line(x, y, x1, y1:integer; color :COLORS);

Procedure line(x, y, x1, y1:integer; color :integer);

Procedure lineto(x, y:integer);

Procedure lineto(x, y, color:integer);

Procedure lineto(x, y:integer; color:COLORS);

Procedure moveto(x, y:integer);

Procedure outtext(text:string);

Procedure outtext(text:string; color:integer);

Procedure outtext(text:string; color:COLORS);

Procedure outtextxy(x, y:integer; text:string);

Procedure outtextxy(x, y:integer; text:string; color:integer);

Procedure outtextxy(x, y:integer; text:string; color:COLORS);

Procedure pieslice(x, y, stAngle, endAngle, radius:integer);

Procedure pieslice(x, y, stAngle, endAngle, radius, color:integer);

Procedure pieslice(x, y, stAngle, endAngle, radius:integer; color:COLORS);

Procedure putpixel(x, y:integer);

Procedure putpixel(x, y:integer; color:COLORS);

Procedure putpixel(x, y:integer; color:integer);

Procedure rectangle(x, y, x1, y1 :integer);

Procedure rectangle(x, y, x1, y1 :integer; color :COLORS);

Procedure rectangle(x, y, x1, y1 :integer; color :integer);

Procedure save(path: string);

Procedure setbkcolor(color:COLORS);

Procedure setbkcolor(color:integer);

Procedure setcolor(color:COLORS);

Procedure setcolor(color:integer);

Procedure setfillcolor(color:COLORS);

Procedure setfillcolor(color:integer);

Procedure setfillstyle(patern:PATERN; color:COLORS);

Procedure setfillstyle(patern:integer; color:COLORS);

Procedure setfillstyle(patern:PATERN; color:integer);

Procedure setfillstyle(patern:integer; color:integer);

Procedure setlinestyle(style:LINESTYLE; upattern, thickness:integer);

Procedure setlinestyle(style, upattern, thickness:integer);

Procedure settextstyle(font:string; mydirection:DIRECTION; size:integer);

Procedure settextstyle(font:string; mydirection, size:integer);

Класи і об’єкти

 

Огляд класів і об'єктів

Клас є складовим типом, що складається з полів (змінних), методів (процедур і функцій) і властивостей.

Опис класу має вигляд:

type
   ім'я класу=class      

               опису полів                 

               оголошення або опису методів і опису властивостей  

   end;

Після слова class в дужках може бути вказано ім'я класу-предка (див. п. Наслідування).

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

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

Наприклад:

type
  Student=class
    name: string;
    course, group: integer;
    constructor Create(nm: string; c,gr: integer);
    procedure Print;
    begin
      writeln('Имя:',name,' курс:',course,' группа:');
    end;
    procedure NextCourse;
    begin
      Inc(course);
    end;
  end;

  constructor Student.Create(nm: string; c,gr: integer);
  begin
    name:=nm;
    course:=c;
    group:=g;
  end;

Тут конструктор Create оголошений в класі, а визначений зовні класу, а методи Print і NextCourse визначені усередині класу. При визначенні методу зовні класу його імені передує ім'я класу з подальшою крапкою.

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

Оголошення методу не може слідувати за визначенням цього ж методу.

Екземпляри класів називаються об'єктами. Кожний об'єкт містить копії всіх полів, визначених в його класі, і може користуватися всіма його методами. Змінна типу клас зберігає насправді вказівник на об'єкт. Проте, при зверненні до полів, методам або властивостям об'єкту розіменування такого вказівника не потрібне; указується ім'я об'єкту і потім, після роздільника-крапки, указується ім'я поля, методу або властивості:

var s: Student;
...
s.name:='Иванов'; s.course:=1; s.group:=3;
s.Print;
s.GotoNextCourse;
s.Print;

 Як і інші вказівники, змінна типу клас може містити значення nil:

s:=nil;
...
if s=
nil then ...

Декількох змінних типу клас можуть посилатися на один об'єкт:

var s1,s2: Student;
...
s1.name:=' Петров';
s2:=s1;
writeln(s2.name); // s2.name='Петров'

Локальні визначення класів (тобто визначення в процедурах і функціях) заборонені.

В методах, описаних усередині класу заборонені вкладені описи процедур.

 


  
Конструктори і деструктори

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

Конструктор є функцією, що створює об'єкт в динамічній пам'яті, що ініціалізовує його поля і повертає вказівник на створений об'єкт. Цей вказівник звичайно відразу присвоюється змінній типу клас. При описі конструктора замість службового слова function використовується службове слово constructor. Крім того, для конструктора не вказується тип значення, що повертається. Для виклику конструктора слід вказати ім'я класу, за яким слідує крапка-роздільник, ім'я конструктора і список параметрів. Наприклад:

var s: Student;
...
s:=Student.Create('Иванов',1,3);

 При створенні об'єкту поля не ініціалізувалися автоматично, тому рекомендується всі поля ініціалізувати в конструкторі явно.

Деструктор є процедурою, що знищує об'єкт,  звільняючу динамічну пам'ять, яку цей об'єкт займав. При описі деструктора замість службового слова procedure використовується службове слово destructor. Деструктор об'єкту викликається як звичайний метод:

s.Destroy;

Після виклику деструктора користуватися об'єктом (тобто звертатися до його полів і викликати його методи) не можна. Щоб це підкреслити, корисно відразу після виклику деструктора присвоїти змінній, що представляє об'єкт, значення nil:

s:=nil;

В Borland Delphi, прийнято використовувати ім'я Create для конструктора і ім'я Destroy - для деструкції.

 

Властивості

Властивості дозволяють здійснювати доступ до полів класу, попутно виконуючи деякі дії. Властивість описується в класі таким чином:

property <Prop>: тип read <ім'я функції читання> write <ім'я процедури запису>;  

Як правило, кожна властивість пов'язана з деяким полем класу і повертає значення цього поля за допомогою функції читання, а міняє - за допомогою процедури запису. Функція читання і процедура запису повинна бути методами цього класу і мати наступний вигляд:

function getProp: тип;
procedure setProp(v: тип);

Секція write може бути опущений, тоді доступ до поля через властивість можна здійснювати тільки на читання (властивості тільки для читання).

Наприклад, розглянемо тип Person (персона), що має поле _age (вік). Доступ до поля _age здійснюватимемо через властивість Age:

type Person=class
  _age: integer;
  procedure setAge(a: integer);
  begin
    if a>0 then _age:=a
    else writeln('Помилка в Person.setAge: вік не може бути від’ємним');
  end;
  function getAge: integer;
  begin
    writeln('Здійснено доступ до поля _age на зчитування');
    Result:=_age;
  end;
  property Age: integer read getAge write setAge;
end;
var
  p: Person;
  a: integer;
...
p:=Person.Create;
p.Age:=-3; // помилка!!!
i:=p.Age; // зчитування поля _age 

 Кожного разу, коли ми присвоюємо властивості Age нове значення, викликається процедура setAge з відповідним параметром. Всякий раз, коли ми прочитуємо значення властивості Age, викликається функція getAge.

З прикладу видно, що властивості поводяться аналогічно полям. При цьому вони можуть проводити додаткові дії, наприклад, перевірку на допустимість присвоюваного значення. Доступ же до полів класів напряму зв'язаний з помилками:

p._age:=-3;

Присвоєння полю _age негативного значення помилково, але подібна помилка не буде оброблена.

Замість імені функції читання або імені процедури запису можна використовувати ім'я поля, наприклад:

property Age: integer read _age write setAge;

В цьому випадку рядок i:=p.Age еквівалентна рядку i:=p._age.

Звичайно для доступу до поля на читання в секції read властивості указується саме поле, оскільки звичайно при читанні поля ніяких додаткових дій проводити не вимагається.

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

Inc(p.Age); // помилка!

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

a:=p.Age;
Inc(a);
p.Age:=a;

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

b1.Width:=100;

Процедура для запису цієї властивості в приватне поле _width виглядатиме приблизно так:

procedure SetWidth(w: integer);
begin
  if (w>0) and (w<>_width) then
  begin
    _width:=w;
    <перемалювання кнопки>
  end
end;

 Слід звернути увагу на другу частину умови в операторі if: w<>_width. Додавання цієї перевірки дозволяє уникнути зайвого перемальовування кнопки у випадку, якщо її ширина не міняється.

 

Індексні властивості

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

Індексна властивість описується в класі таким чином:

property Prop[ім'я: тип індексу]: тип read ім'я функції читання write ім'я процедури запису;  

Функція читання і процедура запису повинна бути методами цього класу і мати наступний вигляд:

function getProp(ind: тип індексу): тип;
procedure setProp(ind: тип індексу; v: тип);

Кожного разу, коли ми виконуємо присвоєння Prop[ind]:=value, викликається процедура setProp(ind,value), а коли прочитуємо значення Prop[ind], викликається функція getProp(ind).

Перша індексна властивість, описана в класі, називається індексною властивістю по замовчуванню і дозволяє користуватися об'єктами класу як масивами, тобто використовувати запис а[i], де а - об'єкт класу.

Принципова відмінність індексних властивостей від полів-масивів полягає в тому, що тип індексу може бути довільним (зокрема, рядковим).   Це дозволяє легко реалізувати так звані асоціативні масиви, елементи яких індексуються рядками. Наведемо приклад реалізації класу AssocArray. Цей клас можна використовувати, наприклад, для підрахунку   кількості появ кожного слова в тексті:

type AssocArray=class
private
  words: StringArray; // слова
  nums: IntArray; // к-сть появ слов
public
  constructor Create;
  begin
    words:=StringArray.Create;
    nums:=IntArray.Create;
  end;
  procedure setProp(ind: string; value: integer);
  function getProp(ind: string): integer;
  property Items[ind: string]: integer read getProp write setProp;
  property Keys: StringArray read words;
  property Values: IntArray read nums;
end;

procedure AssocArray.setProp(ind: string; value: integer);
var i: integer;
begin
  i:=words.IndexOf(ind); // пошук слова
  if i<>0 then           // якщо знайдено, то
    nums[i]:=value       // встановлення к-сті появ слова
  else                   // якщо не знайдено, то
  begin                   
    words.add(ind);      // добавлення слова в массив слов
    nums.add(value);     // установка к-сті появ слова
  end;
end;

function AssocArray.getProp(ind: string): integer;
var i: integer;
begin
  i:=words.IndexOf(ind);  // пошук слова
  if i<>0 then            // якщо знайдено, то
    Result:=nums[i]       // повернення к-сті появ слова
  else                    // якщо не знайдено, то
  begin
    words.add(ind);       // добавлення слова в массив слов
    nums.add(0);          // установка к-сті появ слова рівними нулю
    Result:=0;
  end;
end;
 

var CountNames: AssocArray;
...
CountNames.Items['крокодил']:=3;
CountNames['бегемот']:=5; // індексна властивість по замовчуванню
CountNames['бегемот']:=CountNames['бегемот']+2;

 

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

Inc(CountNames['бегемот'],2);

 

Змінна Self

Усередині кожного методу неявно визначається змінна Self, що посилається на об'єкт, цей метод, що викликав. Наприклад:

type
  A=class
    i: integer;
    constructor Create(i: integer);
    begin
      Self.i:=i;
    end;
  end;

 У момент виклику конструктора Create об'єкт буде вже створений. Конструкція Self.i посилається на поле i цього об'єкту, а не на параметр i функції Create.

Наслідування

Клас може бути успадковуваний від іншого класу. Наприклад, при оголошенні

type MyClass=class(BaseClass)
...
end;

 клас MyClass успадковується від класу BaseClass.

Клас-нащадок називається також похідним класом або підкласом, а клас-предок - базовим класом або надклассом. Нащадок автоматично успадковує всі поля і методи свого предка. Він може також визначати нові поля і методи, а також перевизначати (заміщати) методи предка.

Імена полів і методів, оголошені в класі, доступні до кінця оголошення класу, а також у всіх його нащадках.

Всі класи неявно успадковуються від класу Object. Цей клас оголошений таким чином:

type Object=class
  constructor Create;
  destructor Destroy;
  function TypeName: string;
  function ToString: string;
end;

 Таким чином, будь-який клас може створювати свої об'єкти, викликаючи конструктор Create без параметрів, і знищувати їх, викликаючи деструктор Destroy, навіть якщо ці методи не приведені в його описі:

var m: MyClass;
...
m:=MyClass.Create;
...
m.Destroy;

 В кінці роботи програми всі створені об'єкти повинні бути зруйнований. Тому для кожного створеного об'єкту рекомендується явно викликати деструктор.

Метод TypeName повертає ім'я класу об'єкту, а метод ToString - рядкове представлення об'єкту. В класі Object метод ToString також повертає ім'я класу об'єкту, але ця поведінка може бути перевизначений в нащадках. Наприклад:

type MyClass=class
  i: integer;
  constructor Create(i: integer);
  begin
    Self.i:=i;
  end;
  function ToString: string;
  begin
    Result:=IntToStr(i);
  end;
end;
var a: MyClass;
...
a:=MyClass.Create(3);
writeln(a.TypeName); // MyClass
writeln(a.ToString); // 3 

 Видимість членів класу

Кожне поле, метод або властивість класу має атрибут, званий видимістю. В Pascal існують три типи атрибутів видимості: public (відкритий), private (закритий) і protected (захищений). До члена класу, що має атрибут public, можна звернутися з будь-якого місця програми, члени класу з атрибутом private доступні тільки усередині методів цього класу, члени класу з атрибутом protected доступні усередині методів цього класу і всіх його підкласів. Атрибути видимості можуть знаходитися усередині класу, при цьому всі подальші члени придбавають цей атрибут. Наприклад:

type
  A=class
  private
    x: integer;
  protected
    a: integer;
  public
    constructor Create(xx: integer);
    begin
      x:=xx; //  вірно, оскільки ми усередині методу класу, якому належить закрите поле
      a:=0; // вірно
    end;
    procedure print;
  end;
  B=class(A)
    procedure print;
    begin
      writeln(a); // вірно, оскільки а - захищене поле
      writeln(x); // невірно, оскільки х - закрите поле
    end;
  end;
...
var a1: A;
...
writeln(a1.x); //
невірно, оскільки х - закрите поле
writeln(a1.a); //
невірно, оскільки а - захищене поле
a1.print; //
вірно, оскільки print - відкритий метод

 

За умовчанням всі члени є відкритими. Зокрема, метод print класу B - відкритий.

Якщо x - закритий або захищений член класу, то доступ до нього з використанням явної вказівки об'єкту неможливий: запис a.x викличе помилку при компіляції "поле x недоступне". Виключення складає запис Self.x, що використовується в методі класу, містить x.

Перевизначення методів

Метод базового класу може бути перевизначений (заміщений) в підкласах. Якщо при цьому вимагається викликати метод базового класу, то використовується службове слово inherited (англ.- успадковуваний). Наприклад:

type
  Person=class
    name: string;
    age: integer;
    constructor Create(nm: string; ag: integer);
    begin
      name:=nm; age:=ag;
    end;
    procedure Print;
    begin
      writeln('Ім’я: ',name,'  Вік: ',age);
    end;
  end;
  Student=class(Person)
    course, group: integer;
    constructor Create(nm: string; ag,c,gr: integer);
    begin
      inherited Create(nm,ag);
      course:=c; group:=gr;
      name:=nm; age:=ag;
    end;
    procedure Print;
    begin
      inherited Print;
      writeln('Курс: ',course,'  Група: ',group);
    end;
  end;

 Тут метод Print похідного класу Student викликає спочатку метод Print, успадковуваний від базового класу Person, за допомогою конструкції inherited Print. Аналогічно конструктор Create класу Student викликає спочатку конструктор Create базового класу Person, також використовуючи службове слово inherited. Слід звернути увагу, що конструктор базового класу викликається в цьому випадку як процедура, а не як функція, при цьому створення нового об'єкту не відбувається.

Приведення типів об'єктів

Об'єкт похідного класу неявно приводиться до типу базового класу. Наприклад, якщо у нас є клас

type MyClass=class
  procedure print;
end;

 то можна ініціалізувати змінну класу Object об'єктом класу MyClass:

var o: Object;
...
o:=MyClass.Create;

 Тепер в змінній типу Object зберігається адреса об'єкту MyClass. Це можна перевірити, викликавши функцію TypeName класу Object:

writeln(о.TypeName); // буде виведений 'MyClass'

Тип класової змінної, оголошений при описі, прийнято називати її статичним типом, а тип об'єкту, на який посилається класова змінна в процесі виконання програми - її динамічним типом. Динамічний тип може або співпадати із статичним, або бути його спадкоємцем. Об'ект базового класу можна явно перетворити до типу похідного класу. Так, в приведеному вище прикладі, хоча змінна о посилається на об'єкт типу MyClass, користується методом print, визначеним в класі MyClass, через змінну о не можна. Щоб це здійснити, об'єкт базового класу повинен бути явно приведений до об'єкту похідного класу:

var m: MyClass;
...
m=MyClass(o);

 Після цього, зрозуміло, можна викликати будь-які методи похідного класу і звертатися до його полів:

m.print;

При виконанні цього перетворення необхідно, щоб в змінній о знаходився саме об'єкт класу MyClass або будь-якого похідного від нього класу. В протилежному випадку відбудеться помилка при виконанні програми.  

Операції is і as

Операція is призначена для перевірки того, чи має класова змінна вказаний динамический тип. Операція as дозволяє безпечно перетворити змінну одного класового типу до іншого класового типу (у відмінність від явного приведения классового типа).

Якщо a1 - змінна класового типу, а B - тип класу, то вираз a1 is B повертає True якщо змінна a1 має динамічний тип, співпадаючий з B або є одним з його нащадків, і False в протилежному випадку. Наприклад:

type
  A=class
  end;
  B=class(A)
  end;
var a1: A;
...
a1:=B.Create;
writeln(a1 is B); // True

 Якщо a1 - змінна класового типу, а B - тип класу, то вираз a1 as B повертає об'єкт класу B, a1 має динамічний тип B або похідний від нього і nil в протилежному випадку. Наприклад:

var b1: B;
...
b1:=a1 as B;

Фактично останній рядок робить те ж, що і наступний фрагмент коду:

if a1 is B then
  b1:=B(a1)
else b1:=nil;

  Віртуальні методи і поліморфізм

Хай перевизначений в підкласі метод базового класу має той же список формальних параметрів (а для функцій - і тип значення, що повертається). Наприклад:

type
  Base=class
    procedure Print;
    begin
      writeln('Base');
    end;
  end;
  Derived=class(Base)
    procedure Print;
    begin
      writeln('Derived');
    end;
  end;

 Розглянемо різні способи виклику методу Print:

var
  b,b1: Base;
  d: Student;
  ...
  b:=Base.Create;
  d:=Derived.Create;
  b1:=d;
  b.Print; // викликається Base.Print
  d.Print; // викликається Derived.Print
  b1.Print;

 Яка версія методу Print викликається в останньому випадку - класу Base або класу Derived? В об'єктно-орієнтованих мовах програмування можливі дві ситуації. Якщо рішення про те, який метод викликати, ухвалюється на етапі компіляції на підставі типу, заявленого при описі b1, то викликається метод Base.Print (говорять також, що має місце раннє скріплення імені методу з його тілом). Якщо ж рішення про те, який метод викликати, ухвалюється на етапі виконання програми залежно від реального типу об'єкту, на який посилається змінна b1, то викликається метод Derived.Print (говорять також, що має місце пізнє скріплення). Методи, для яких реалізується пізнє скріплення, називаються віртуальними, а здатність об'єкту викликати через змінну базового класу метод похідного класу на підставі інформації під час виконання програми називається поліморфізмом.

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

Наприклад:

type
  Shape=class
    procedure Draw; begin end;
  end;
  Point=class
    procedure Draw; begin ... end;
  end;
  Rectangle=class
    procedure Draw; begin ... end;
  end;
  Circle=class
    procedure Draw; begin ... end;
  end;
var a: array[1..4] of Shape;
...
  a[1]:=Point.Create;
  a[2]:=Rectangle.Create;
  a[3]:=Point.Create;
  a[4]:=Circle.Create;
  for i:=1 to 4 do
    a[i].Draw;

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

Увага! Якщо перевизначається private-метод, то ланцюжок віртуальності ламається, тобто метод розглядається як перший з цим ім'ям в новому ланцюжку віртуальності.

 

 

Модулі

 

Модулі призначені для розбиття тексту програми на декілька файлів. В модулях описуються змінні, константи, типи, класи, процедури і функції. Для того, щоб ці об'єкти можна було використовувати в зухвалому модулі (якою може бути і основна програма), слід вказати ім'я файлу модуля (без розширення .pas) в розділі uses зухвалого модуля. Файл модуля повинен знаходитися або в тому ж каталозі, що і основна програма, або в підкаталозі Units системного каталога програми Pascal.

Модуль є файлом з наступною структурою:

unit ім'я модуля;

Interface

[Usese]розділ підключення модулів
розділ глобальних описів змінних,розділ заголовків процедур і функцій

Implementation

[Uses]розділ підключення модулів
розділ локальних описів змінних,розділ реалізації процедур і функцій

begin

розділ ініціалізації
розділ фіналізації

end.

Перший рядок обов'язковий і називається заголовком модуля.

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

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

Розділ ініціалізації складається із службового слова initialization, після якого слідують оператори, що розділяються символом "крапка з комою". Оператори з розділу ініціалізації модуля виконуються до початку основної програми.

Розділ фіналізації складається із службового слова finalization, після якого слідують оператори, що розділяються символом "крапка з комою". Оператори з розділу фіналізації модуля виконуються після закінчення основної програми.

Розділ фіналізації може бути відсутній, або обидва розділи ініціалізації і фіналізації можуть бути відсутній. Розділ ініціалізації може також починатися із службового слова begin, в цьому випадку розділ финализации відсутній.

Наприклад:

unit Lib;
uses GraphABC;
const Dim=5;
var Colors: array [1..Dim] of integer;
function RandomColor: integer;
begin
  Result:=RGB(Random(255),Random(255),Random(255));
end;
procedure FillByRandomColor;
var i: integer;
begin
  for i:=1 to Dim do
    Colors[i]:=RandomColor;
end;
initialization
  FillByRandomColor;
end.

 

   Повернутись в головне меню