Основи програмування мовою Паскаль

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Як працювати з книгою
Уважно прочитайте відповідний розділ теорії (одну главу), розберіть всі приклади, щоб вам все було зрозуміло, при цьому, якщо у вас є комп'ютер, наберіть програми і запустіть їх на виконання. Переконайтеся в правильності отриманих результатів. Для того щоб вивчити дію того чи іншого оператора в програмі або фрагмента програми, можна "видалити" фрагмент, уклавши його в комментарние дужки {фрагмент .... }. можна, навпаки, додати в програму оператори writeln, readln для того, щоб подивитися проміжні результати. Експериментуйте - це допоможе вам у засвоєнні матеріалу.
Якщо у вас немає комп'ютера, будьте самі "комп'ютером" і "виконуйте" оператори, записуючи на аркуші паперу результати. Це допоможе зрозуміти вам їх роботу.
Вивчивши матеріал, визначте свій варіант і напишіть відповідну програму, перевірте її на комп'ютері (або без нього). Оформіть звіт, здайте на перевірку викладачеві.
Якщо ви будете уважно розглянути тексти програм, потім, завчивши текст, спробуєте його написати по пам'яті, перевірити, виправити помилки, запустити на комп'ютері, отримати результати, то ви навчитеся програмувати!
Пам'ятаєте: "не боги горщики ліплять!"
Удачі вам!
                                                            Автор.

1. Попередні відомості

Сенс програмування полягає в тому, що програміст повинен пояснити ЕОМ, які дії машина повинна виконати, щоб вирішити потрібну задачу. Це пояснення має бути сформульовано на доступному для ЕОМ мовою і містити вказівки, які величини будуть вихідними для вирішення завдання, які операції, і в якій послідовності необхідно виконати над вхідними величинами, щоб отримати результат і, нарешті, в якому вигляді видати результат. Алгоритм, записаний в термінах мови, зрозумілого ЕОМ, називається програмою.
Програма мовою Паскаль складається з "заголовка" і "тіла" програми, званим блоком. У "заголовку" програми дається ім'я і перераховуються її параметри (якщо це необхідно). Блок складається з шести розділів, причому будь-який з них, крім останнього, може бути порожнім (тобто не бути). У визначенні блоку розділи повинні слідувати в такому порядку: опис міток, визначення констант, визначення типів, опис змінних, опис процедур і функцій, оператори.
1.1. Алфавіт
Для написання програм на мові Паскаль можна застосовувати такі символи: букви латинського алфавіту abc d. .. z (Прописні), abc d. .. z (рядкові), знак підкреслення. Прописні і малі літери взаємозамінні (еквівалентні) і використовуються для більш рельєфного написання програм;
- Цифри 0 1 2 3 4 5 6 7 8 9;
- Спеціальні знаки: + - * / = <> []. , ():; ^ {} $ # @;
- Складові знаки: <=> = .. (* *) (..).
Використовуючи символи алфавіту, ми можемо записати алгоритм вирішення задачі на мові Паскаль. Слід зазначити, що крім наведених вище символів в програмі можна застосовувати і букви кирилиці, тобто російський алфавіт, проте в конструкціях мови ці букви не можуть бути використані, вони використовуються лише для написання текстових констант, що відповідають цім строкового типу, наприклад: 'табл. 1 '.
1.2. Рішення задач
У першому наближенні рішення задачі на ЕОМ зводиться: до введення деяких вихідних даних в пам'ять машини і обробці їх за заданим алгоритмом; отримання та видачі користувачеві результатів розв'язання задачі у вигляді чисел, текстів, графіків таблиць і т.п. Алгоритм є переліком тих дій, які повинна виконувати ЕОМ для отримання результату. Введення даних може здійснюватися з різних пристроїв: з клавіатури, каналу зв'язку, сканера (введення текстів і малюнків), маніпулятора типу "миша", "джойстик" і т.д.
Висновок здійснюється на пристрої відображення - екран монітора, друкувальний пристрій, Графобудівник і т.д.
Спочатку в ЕОМ вводиться програма, що містить описи вихідних даних, переліку операторів, які визначають порядок обробки цих даних та їх перетворення в результати (алгоритм).
Порядок вирішення завдань:
1. Осмислення природи завдання, визначення вхідних і вихідних даних, а також форми вихідних даних (чисел, текстів, малюнків, графіків, таблиць). Підбір або розробка математичних методів перетворення вихідних даних у вихідні результати.
2. Розробка алгоритму рішення задачі. Тут можливо опис алгоритму в будь-якій зручній формі: або у вигляді словесного опису з включенням формул, або у вигляді блок-схем, що особливо наочно і зручно. наприклад, блок-схема алгоритму, що досліджує квадратне рівняння ax 2 + bx + c = 0, показано на рис. 2.1.
3. Запис алгоритму за допомогою засобів алгоритмічної мови Паскаль (написання програми).
4. Введення програми в ЕОМ.
5. Компіляція програми, тобто переклад алгоритму з термінів мови Паскаль у внутрішній мову ЕОМ, оскільки алгоритмічних мов - безліч, а внутрішній мову ЕОМ - один.
6. виконання програми на ЕОМ: якщо вона написана без помилок, то на цьому етапі ЕОМ, зустрівши оператор введення вихідних даних, запросить конкретні вихідні дані для вирішення завдання, користувач введе ці дані, машина їх обробить і видасть результат.
Не завжди рішення виходить з першого разу. Програма може містити помилки (неправильна запис операторів - синтаксичні помилки, не той тип виділених комірок пам'яті, що дані, що вводяться, плутанина в алгоритмі; отримані дані не збігаються з результатами контрольного прорахунку і т.д.). У цьому випадку необхідний процес налагодження програм і пошук помилок. У Паскалі є потужний відладчик, і ЕОМ може значно допомогти користувачеві в пошуку помилок.

2. Найпростіші програми

2.1. Оператор присвоювання
Ідентифікатор: = вираз. Тут ідентифікатор - ім'я змінної, змінна зберігається в комірці пам'яті з іменем - ідентифікатор. тип елементу пам'яті визначений у розділі описів. Вираз може бути арифметичним, логічним або яким-небудь іншим, в якому вже відомі (визначені) всі вхідні в його склад ідентифікатори.
Зауваження 1. Тип значення виразу і тип ідентифікатора повинні збігатися, інакше error - помилка.

Введення вихідних чисел a, b, c
Обчислимо дискримінант
d = b 2 -4 ac
d ³ 0
?
Висновок результатів: а ¹ 0, d <0, рівняння квадратне і має два комплексні кореня, дійсна частина яких , Уявна: , Тобто

Кінець роботи
Рис. 2.1
так, а = 0
немає, а
не дорівнює 0
так, d ³ 0
немає
Висновок результатів: так як а = 0, рівняння виявляється лінійним і має один результат
а = 0
?
Висновок результатів: а ¹ 0, d ³ 0, рівняння квадратне і має два різних корені:




Зауваження 2. При наявності хоча б однієї помилки програма не виконується.
Приклад. Нехай є комірки пам'яті з іменами a, b, c; осередку такі, що в них можуть бути поміщені величини тільки цілого типу. досягається це описом: Var a, d, c: integer, де Var - початок розділу опису змінних, a, b, c - ідентифікатори. Integer означає цілий, тобто в розділі Var ідентифікатори (імена) змінних визначені як цілі.
Робота опису: зустрівши такий опис, ЕОМ видає три осередки пам'яті з іменами a, b, c, причому такі, щоб туди могли бути поміщені цілі числа. Запишемо оператор присвоювання:        
a: = c + b;
Робота оператора: машина повинна мати опис ідентифікаторів a, b, c.
крім того, як сказано вище, в правій частині оператора стоять величини, яким вже присвоєні початкові значення. У цьому випадку машина отримає з комірки з її вміст і з осередку b вміст, зробить операцію складання і значення результату занесе (присвоїть) у клітинку a.
2.2. коментарі
Введемо поняття коментаря. Коментар - це все, що укладена між дужками {}. Символи, укладені між цими дужками, не сприймаються машиною, але видаються користувачеві. Коментарі використовуються користувачем для пояснення алгоритму.
2.3. Програма
Напишемо програму обчислення a = c + b. Програма починається з заголовка Program - ім'я програми, потім йдуть розділи описів (до 5) і розділ операторів, який починається словом Begin і закінчується END. (End з точкою, точка - кінець програми). Кожен опис і оператор закінчуються символом ';'
Program Prim1; {заголовок програми}
Var a, b, c: integer; {розділ опису змінних, виділення}
{Елементів пам'яті для зберігання цілих величин}
BEGIN {початок розділу операторів}
c: = 547; b: = 42; {занесення в осередки c і b початкових значень}
a: = c + b; {обчислення значення і видача на}
writeln (a); {екран (write - писати) значення a}
END. {Кінець програми}.
Нагадуємо, що тексти, укладені в дужки {}, є коментарями, не є частиною програми і можуть бути опущені, таким чином, програма для ЕОМ має наступний вигляд:
        Program Prim1;
Var
a, b, c: integer;
BEGIN
c: = 547; b: = 42;
a: = c + b;
writeln (a);
          readln;
END.
Програма записується у вигляді рядків. Максимальна довжина рядка 255 символів, але не варто робити рядки довші рядки екрану - 80 символів, інакше рядки будуть "ховатися" за межами вікна екрану, хоча рядки і можна переглянути, пересуваючи "вікно" (рис. 2.2).



"Гарне" розташування рядків "Погане" розташування рядків
рис. 2.2
Кожен рядок можна починати не з першої позиції, щоб програма була більш читабельною.
2.4. Найпростіший введення-виведення
У програмі Prim1 ми ставили вихідні дані за допомогою оператора присвоєння, що не завжди зручно, якщо одну і ту ж програму потрібно прораховувати з різними вихідними даними. Для присвоєння початкових значень можна використовувати оператор readln (ідентифікатор, ідентифікатор ,..., ідентифікатор); наприклад, readln (c, b). зустрівши такий оператор, машина зупиниться і буде чекати, поки користувач не набере на клавіатурі значення с, натисне клавішу "пробіл", набере значення b і натисне клавішу ENTER (введення). значення величин c і b відобразяться на екрані і після натискання клавіші ENTER занесуть в осередки пам'яті машини з іменами с і b відповідно. тоді програма Prim1 прийме вигляд:
Program Prim1a;
Var a, b, c: integer;
BEGIN readln (c, b);
a: = c + b;
writeln (a);
readln;
END.
Зауваження 1. Нагадаємо, що машині байдуже, рядкові або прописні букви однакових слів end, end і end (але не для вас).
Зауваження 2. Зручно ставити Readln перед END, так як після виконання програми машина видає на екран вікно тексту програми, а результат "ховається" за цим вікном і, щоб його подивитися, необхідно прибрати вікно з програмою за допомогою натиснення клавіш. Якщо перед END є Readln, то програма не завершить роботу, поки ви не натиснете клавішу ENTER, тобто в даному випадку на екран буде виведено значення а. Ви подивіться результат і натиснете ENTER для входу в редактор мови Паскаль.
2.5. Арифметичні вирази
Арифметичне вираз будується з об'єктів: арифметичних (числових) констант; ідентифікаторів змінних, описаних як числові; функцій, які повертають в результаті їх обчислення; арифметичних значень цих об'єктів, з'єднаних між собою знаками арифметичних операцій і круглими дужками. У якості констант можуть застосовуватися арифметичні константи, задані в явному вигляді: 5; 5.35, -7.374 Е + 01 і т.п., а також імена констант, визначені в розділі const.
В якості змінних використовуються змінні, визначені в розділі Var як byte, integer, real, і їх різновиди, наприклад, longinteger, і т.д., якщо їм вже привласнені початкові значення.
В якості функцій можуть застосовуватися стандартні функції мови Паскаль, бібліотечні функції та функції, написані самим користувачем. Бібліотечні функції доступні після підключення модулів бібліотек. функції користувача повинні бути описані в розділі function.
Основні стандартні функції Паскаля:
Позначення: I - цілочисельний тип; B - байтовий тип; R - дійсний тип; IBR - цілочисельний, або байтовий, або речовий типи.
ABS (IBR) - визначення абсолютної величини аргументу типу i, b, r.
ARCTAN (IBR) - обчислення кута (в радіанах), тангенс якого дорівнює IBR.
Cos (IBR), Sin (IBR).
Exp (IBR) - обчислення значення e IBR.
Ln (IBR) - натуральний логарифм IBR.Sgr (IBR) - зведення в квадрат IBR.
Sgrt (IBR) - обчислення кореня квадратного з IBR.
Піднесення до степеня виконується за формулою ar = exp (r * ln (a)) для позитивних a або організується послідовне множення на а r раз.Для негативних а можливий тільки другий спосіб.
Арифметичні операції: +, -, * - помножити; / - розділити; mod - знаходження залишку від ділення: 11 mod 5, результат1; div - цілочисельний розподіл (дробова частина відкидається) 11 div 5, результат 2. Арифметичні "і" - аnd і "чи" - or виробляють поразрядное булеве множення або складання цілих значень операндів згідно з таблицями:
A аnd BA or B
0 аnd 0 = 0 0 or 0 = 0
1 аnd 0 = 0 1 or 0 = 1
0 аnd 1 = 0 0 or 1 = 1
1 аnd 1 = 1 січня or 1 = 1
Приклад: a: = 12; b: = 27.
У внутрішньому коді машини, в двійково-десяткового системі, цифри видаються в десятковій системі:
0000 = нуль
0001 = один
0010 = два
0011 = три
0100 = чотири
0101 = п'ять
0110 = шість
0111 = сім
1000 = вісім
1001 = дев'ять
Тоді 12 у десятковій системі еквівалентно 0001 0010 двійково-десяткового системи. нагадаємо, що в двійково-десяткового системі кожна десяткова цифра представлена ​​4-значним двійковим кодом цієї цифри. У цьому випадку 27 - 0010 0111.
А аnd B А or B
0001 0010 0001 0010
0010 0111 0010 0111
результат: 0000 0010 результат: 0011 0111
Результат перетворюється в десяткову форму 2 та 37 відповідно.
ХOR, виключає "або", виробляє операцію згідно з таблицею
A xor B
1 xor 1 = 0
1 xor 0 = 0
0 xor 1 = 1
0 xor 0 = 0
Результат перетворюється в десяткову форму.
Циклічний зсув: k shl N - зрушення числа до вліво на N позицій,
k shr N - зрушення числа до вправо на N позицій,
k і N - цілі.
Приклад: 2 shl 7 = 256

0000 0000 0000 0010
0000 0001 0000 0000
Створимо ту ж програму, що і Prim 47, тільки пооб'єктно, тоді процедуру Org запишемо в C: \ TURBO \ Org1.pas, процедуру Obr - в C: \ TURBO \ Orb1.pas, процедуру Rash - в C: \ TURBO \ Rash1 . pas, а викликає (основну програму - в C: \ TURBO \ Prim. 48, в якій передбачимо підключення об'єктів - процедур Org, Obr, Rash до основної програми через директиви компілятора $ i.
   procedure Org1;
begin
assign (bf, 'C: \ TURBO \ bibl.dos');
Rewrite (bf);
with rb do
while True do
begin    writeln ('ввести номер книги');
                   readln (nomer);
if nomer = 9999 then
begin close (bf); Exit;
               end;
writeln ('ввести ім'я автора');
readln (avtor);
writeln ('ввести назву книги');
readln (nazv);
writeln ('ввести назву індексу');
                   readln (index);
write (bf, rb);
end;
end;
procedure Obr1;
begin
Assign (bf, 'C: \ TURBO \ bibl.dos');
Reset (bf);
with rb do
while not eof (bf) do
Begin read (bf, rb);
writeln (nomer: 5, avtor: 16, Nazv: 10, index: 6);
end;
Close (bf);
writeln ('натисніть enter'); readln;
end;
procedure Rash1;
begin Assign (bf, 'C: \ TURBO \ bibl.dos');
Reset (bf);
Seek (bf, Filesize (bf));
with rb do
while True do
begin writeln ('введіть номер '); readln (nomer);
if nomer = 9999 then begin Close (bf); exit end;
writeln ('введіть ім'я автора '); readln (avtor);
             writeln ('введіть назву книги'); readln (nazv);
writeln ('введіть значення індексу'); readln (index);
             write (bf, rb);
        end; end;
Роботу побудуємо в режимі меню.
Program Prim48;
label M;
type books = record
nomer: integer;
avtor: string [16];
nazv: string [30];
index: integer; end;
Var bf: file of books;
rb: books; regim: byte;
{$ I C: \ TURBO \ Org1.pas}
{$ I C: \ TURBO \ Obr1.pas}
{$ I C: \ TURBO \ Rash1.pas}
   BEGIN
M: writeln ('введіть режим роботи');
writeln ('1 - створення, 2 - обробка ',
"3 - розширення, 4 - вихід ');
           readln (regim);
case regim of
1: Org1;
2: Obr1;
3: Rash1;
4: Exit; else writeln ('неправильно заданий режим '); end;
goto M;
    END.
Для забезпечення роботи з різними іменами файлів ім'я файлу спочатку запитується, а потім передається в процедури. Таким чином, ми можемо створювати кілька файлів, що містять дані про книги, їх обробляти, розширювати і т.п.
Program Prim49;
label M1, M2;
type books = record
nomer: integer;
avtor: string [16];
nazv: string [30];
index: integer; end;
Var bf: file of books;
rb: books; regim: byte; si: char; fl: string;
{$ I C: \ TURBO \ Org.pas}
{$ I C: \ TURBO \ Obr.pas}
{$ I C: \ TURBO \ Rash.pas}
   BEGIN
M1: writeln ('де буде зберігатися файл? Диск: \ каталог \ ім'я'),
readln (fl);
M2: writeln ('введіть режим роботи');
writeln ('1 - створення, 2 - обробка ',
"3 - розширення, 4 - вихід ');
              readln (regim);
case regim of
1: Org;
2: Obr;
3: Rash;
4: begin writeln ('будемо ще працювати з файлами? - "Y" ');
                writeln ('або кінець роботи - будь-яка клавіша');
                readln (si);
if (si = 'Y') or (si = 'y') then goto M1 else HALT; end;
          else begin writeln ('неправильно заданий режим');
                goto M2; end; end; goto M2;
END.
Procedure Org2;
begin
assign (bf, fl);
Rewrite (bf);
with rb do
while True do
begin    writeln ('введіть номер книги');
                   readln (nomer);
if nomer = 9999 then
begin close (bf); Exit end;
writeln ('введіть ім'я автора ');
readln (avtor);
                   writeln ('введіть назву книги');
readln (nazv);
writeln ('введіть значення індексу');
                   readln (index);
                   write (bf, rb);
end; end;
Procedure Obr2;
begin
Assign (bf, fl);
Reset (bf);
with rb do
while not Eof (bf) do
begin read (bf, rb);
writeln (nomer: 5, avtor: 16, Nazv: 10, index: 6);
end; Close (bf);
end;
Procedure Rash2;
begin assign (bf, fl);
Reset (bf);
Seek (bf, Filesize (bf));
with rb do
while True do
begin writeln ('введіть номер '); readln (nomer);
if nomer = 9999 then begin Close (bf); Exit end;
writeln ('введіть ім'я автора '); readln (avtor);
             writeln ('введіть назву книги'); readln (nazv);
writeln ('введіть значення індексу'); readln (index);
             write (bf, rb);
        end; end;
10.5. Файли довільного доступу
Файли довільного доступу використовуються при наявності залежності значення якого-небудь поля компоненти від її порядкового номера в файлі. Порядковий номер компоненти іноді називають ключем компоненти файлу.
Організувати файл довільного доступу можна двома способами:
1. Створити послідовний файл і звертатися до компонентів за порядковим номером, трактуючи послідовний файл як файл прямого доступу.
2. Створити файл фіктивних (з порожніми полями) компонент, потім завантажити його по ключу фактичними даними. цей спосіб - створення файлу з фіктивними компонентами - називається форматизації.
Приклад. Форматувати файл довільного доступу з 20 компонент c: \ turbo \ bibl.dos. Структура компонент така ж, як і в Prim 47-49. Оформимо алгоритм у вигляді процедури form, запишемо її в c: \ turbo \ form.pas.
Procedure form;
Begin w r iteln ('дайте ім'я форматізіруемому файлу');
readln (filname);
assign (booksfile, filname);
rewrite (booksfile);
with recbooks do
  Begin write l n ('на скільки записів форматувати файл? ');
readln (razmer);
for i: = l to razmer do
Begin nomer: = i; avtor: = ''; index: = 0; nazv: = '';
write (books file, recbooks)
end; end; writeln op матизація ', razmer,' запис виконана ');
close (booksflle); end;
Напишемо процедуру завантаження (procedure zagruz), яка буде заміняти поля фіктивних записів реальними значеннями, і запишемо її в c: \ turbo \ zagruz.pas;
procedure zagruz; Begin writeln ('дати ім'я завантажуваного по ключу файлу');
              readln (filname);
assign (booksfile, filname); reset (booksfile);
              writeln ('скільки записів будете вводити?'); readln (k);
              with recbooks do
Begin for i: = 1 to k do
Begin writeln ('введіть номер '); readln (nomer);
writeln ('введіть ім'я автора '); readln (avtor);
              writeln ('введіть назву книги'); readln (nazv);
              writeln ('введіть індекс '); readln (index);
seek (booksfile, nomer-1); {номери компонент починаються з 0}
              write (booksfile, recbooks); end; end;
close (booksfile); end;
Оформити процедуру прямого доступу по ключу до компонентів файлу і видачу їх на екран монітора, записати її в C: \ TURBO \ OBRAB.PAS;
Procedure Obrab;
Begin writeln ('дайте ім'я файлу '); readln (filname);
assign (booksfile, filname); reset (booksfile);
while true do
Begin writeln ('вкажіть ключ оброблюваної записи '); readln (k);
if k = 9999 then Begin close (booksfile); exit; end;
seek (booksfile, k-1);
with recbooks do Begin read (booksfile, recbooks);
writeln (nomer: 5, avtor: 16, nazv: 15, index: 4);
end; end; end;
Написати процедуру коригування файлу довільного доступу в якій будуть передбачені режими коригування:
1. Заміна всіх полів компоненти.
2. Розширення файлу в межах відформатованого простору.
все це робить процедура Коо r, записана в c: \ turbo \ koor.pas.
   Procedure Koor;
Var nevavtor: string [16]; nevnazv: string [30]; nevindex: integer;
Begin writeln ('дайте ім'я файлу '); readln (filname);
assign (booksfile, filname); reset (booksfile);
with recbooks do
Begin writeln ('скільки записів будете коригувати?'); Readln (k);
          for i: = 1 to k do
   Begin writeln ('дайте номер корректируемой записи '); readln (k1);
         nevavtor: = ''; nevnazv: = ''; nevindex: = 0;
writeln ('введіть ім'я автора '); readln (nevavtor);
         writeln ('введіть назву книги'); readln (nevnazv);
         writeln ('введіть індекс '); readln (nevindex);
avtor: = nevavtor; nazv: = nevnazv; index: = nevindex;
seek (booksfile, k1-1); write (booksfile, recbooks);
end; end; close (booksfile); end;
У програмі Prim 50, за допомогою меню розглядаються робота з файлами довільного доступу у всіх режимах; форматування файлу, його завантаження, обробка, коректування. Тут слід зауважити, що програма універсальна в тому сенсі, що може працювати з різними файлами.
              Program Prim50;
Type books = record
nomer: integer; avtor: string [16];
nazv: string [30]; index: integer; end;
Var booksfile: file of books;
recbooks: books; razmer, k, k1, i, reg: integer;
filname: string [12];
{$ Ic: \ turbo \ form.pas}
{$ Ic: \ turbo \ zagruz.pas}
{$ Ic: \ turbo \ obrab.pas}
{$ Ic: \ turbo \ koor.pas}
Begin while true do
Begin writeln ('вкажіть режим ');
writeln ('1: Форматизация ');
writeln ('2: завантаження по ключу ');
writeln ('3: обробка по ключу ');
writeln ('4: коректування ');
writeln ('5: вихід з програми ');
              readln (reg);
case reg of 1: form; 2: zagruz; 3: obrab; 4: koor; 5: halt;
end;
end;
  end.
10.6. Текстові файли
Компонентами текстових файлів є рядки. Довжина рядка - 0-255 символів. Кожен рядок завершується маркером рядки, а файл - маркером кінця файлу. Для опису файлових змінних текстового типу використовується зарезервоване слово text.
Var instrl, instr2: text;
dokulnent: text;
Для роботи з текстовими файлами використовуються згадані вище функції і процедури assign, rewrite, reset, close, read, readln, write, writeln, seekeof, проте є і специфічні функції і процедури:
Append (fv) - відкрити текстовий файл і встановити покажчик на маркер кінця файлу.
Eoln (fv) - повернути true, якщо покажчик файлу досяг маркера кінця рядка, в іншому випадку, повернути значення false.
Seekeoln (fv) - функція, аналогічна попередньої, але покажчик проходить всі прогалини і знаки табуляції. повертає true при досягненні маркера кінця рядка.
Seekeof (fv) - повертає true, якщо покажчик файлу знаходиться на маркері кінця файлу.
Організація текстового файлу здійснюється за схемою:
1) оголошується файлова змінна текстового типу;
2) присвоюється файлу ім'я (assign);
3) відкривається файл (rewrite);
4) готується рядок - компонента для запису у файл;
5) записується рядок - компонента у файл (writeln);
6) повторюються п. 4, 5 стільки разів, скільки потрібно;
7) закривається файл.
Доступ до компонентів текстового файлу:
1) присвоїти файлу ім'я (assign);
2) відкрити файл для читання (reset);
3) прочитати компоненту-рядок (readln);
4) опрацювати компоненту-рядок (наприклад вивести на екран);
5) повторити п. 3, 4 стільки разів, скільки потрібно.
6) закрити файл (close);
Розширення текстового файлу здійснюється шляхом додавання в кінець файлу компонент-рядків:
1) присвоїти ім'я файлу (assign);
2) встановити маркер на кінець файлу (append);
3) підготувати рядок для запису;
4) записати рядок (writeln);
5) повторити потрібну кількість разів п. 3, 4.
6) закрити файл (close).
Зауваження. При записі файлів прямого і послідовного доступу, створених користувачем, вміст компонент упаковується, і тому подивитися їх у vc або nc по f3 або f4 не можна, а текстовий файл не упаковується, і його можна переглянути.
procedure sozdt;
Begin writeln ('дайте ім'я створюваному текстового файлу');
           readln (filename);
assign (stro, filename); rewrite (stro);
while true do
Begin writeln ('напишіть вміст рядки ');
readln (s); if s = 'zzz' then {'zzz' - ознака закінчення введення}
Begin close (stro); exit; end;
writeln (stro, s); end; end;
procedure obrt;
Begin writeln ('дайте ім'я оброблюваного файлу ');
; Readln (filename);
assign (stro, filename); reset (stro);
repeat readln (stro, s); writeln (s);
until seekeof (stro); close (stro); exit; end;
procedure rasht;
Begin writeln ('вкажіть ім'я корректируемого файлу '); readln (filename);
assign (stro, filename); append (stro);
while true do
Begin writeln ('введіть рядок '); readln (s);
if s = 'zzz' then Begin close (stro); exit; end;
writeln (stro, s); end; end;
Program Prim51;
Type dlina = string [60];
Var stro: text; s: dlina; reg: char; filename: string [12];
{$ Ic: \ turbo \ sozdt.pas}
{$ Ic: \ turbo \ obrt.pas}
{$ Ic: \ turbo \ rasht.pas}
Begin while true do
     Begin writeln ('вкажіть режим ');
       writeln ('1: створення, 2: вивід на екран, 3: розширення, 4: вихід ');
       readln (reg);
case reg of '1 ': sozdt;
'2 ': Obrt;
'3 ': Rasht;
'4 ': Halt else writeln (' повторіть номер режиму ');
end; end; end.

11. Використання бібліотеки CRT

Розробники Турбо-Паскаля передбачили кілька підпрограм, істотно збільшують можливості текстового вводу-виводу. Ці підпрограми зосереджені в бібліотеці (модулі) CRT, що входить в комплект постачання Турбо-Паскаля. У модуль включені також процедури sound, no sound, del a y, що дозволяють програмувати звуковий генератор комп'ютера.
11.1. Програмування клавіатури
Додаткові можливості управління клавіатурою реалізуються двома функціями: keydivssed і ReadKey.
Функція keydivssed повертає значення типу boolean, вказує стан буфера клавіатури: false означає, що буфер порожній, а true - що в буфері є хоча б один символ, ще не прочитаний програмою.
У реалізується так званий асинхронний буферизованная введення з клавіатури. У міру натискання на клавіші відповідні коди поміщаються в особливий буфер, звідки вони можуть бути потім прочитані програмою. Стандартна довжина буфера розрахована на зберігання до 16 кодів символів. Якщо програма досить довго не звертається до клавіатури, а користувач натискає клавіші, буфер може виявитися переповненою. У цей момент лунає звуковий сигнал і "зайві" коди губляться. Читання з буфера забезпечується процедурами read / rеadln і функцією ReadKey. звернення до функції keydivssed не затримує виконання програми: функція негайно аналізує буфер і повертає те чи інше значення, не чекаючи натискання клавіші.
Функція ReadKey повертає значення типу char. При зверненні до цієї функції аналізується буфер клавіатури: якщо в ньому є хоча б один не прочитаний символ, код цього символу береться з буфера і повертається в якості значення функції, в іншому випадку функція буде очікувати натискання на будь-яку клавішу. Введення символу за допомогою цієї функції не супроводжується луна-повтором і вміст екрану не змінюється. Наприклад, у якійсь точці програми необхідно ігнорувати всі раніше натиснуті клавіші, коди яких ще не прочитаної з буфера, тобто необхідно очистити буфер. Цього можна досягти наступним способом:
Uses CRT;
Var
с; char;
Begin
while Keydivssed do
c: == ReadKey;
. . . . .
end.
При використанні процедури ReadKey слід врахувати, що в клавіатурний буфер поміщаються так звані розширені коди натиснутих клавіш. Якщо натискається будь-яка алфавітно-цифрова клавіша, розширений код збігається з ASCII-кодом відповідного символу. Наприклад, якщо натискається клавіша з латинською буквою «а» (у нижньому регістрі), функція ReadKey повертає значення chr (97), а якщо - «а» (у верхньому регістрі) - значення chr (65). При натисканні функціональних клавіш F1. .. F 10 (клавіш управління курсором), клавіш I ns, Home, Del, End, PgUp, PgDn в буфер поміщається багатобайтових послідовність: спочатку символ # 0, а потім розширений код клавіші. Таким чином, значення # 0, повертається функцією ReadKey, використовується виключно для того, щоб вказати програмі на генерацію розширеного коду. Отримавши це значення, програма повинна ще раз звернутися до функції, щоб прочитати розширений код клавіші.
Наступна проста програма дозволить визначити розширений код будь-якої клавіші. Для завершення роботи програми потрібно натиснути клавішу esc.
Uses CRT;
Var з: char;
Begin
repeat
c: = ReadKey;
if c <> # 0 then
writeln (ord (c))
else
writeln ("0", ord (ReadKey): 8)
  until c = # 27 {27 - розширений код клавіші esc}
end.
Якщо ви скористаєтеся цією програмою, то виявите, що натискання на деякі клавіші ігнорується функцією ReadKey. Це насамперед так звані зсувні клавіші - Shift, Ctrl, Alt. Зсувні клавіші в MS-DOS зазвичай використовуються для перемикання регістрів клавіатури і натискаються в поєднанні з іншими клавішами. Саме таким способом, наприклад, розрізняється введення прописних і малих літер. Крім того, функція ігнорує перемикаючі клавіші Caps Lock, N um Lock, Scroll Lock.
у таблиці наведені розширені коди клавіш, які повертаються функцією o rd (ReadKey).

Розширені коди клавіш
Таблиця
Код
Клавіша або комбінація клавіш
Код
Клавіша або комбінація клавіш
перший байт
другий байт
перший байт
другий байт
Алфавітно-цифрові клавіші
8
-
backspace (забій)
9
-
tab (табуляція)
13
-
enter
32
-
пробіл
33
-
!
34
-
«
35
-
#
36
-
$
37
-
%
38
-
&
39
-
"
40
-
(
41
-
)
42
-
*
43
-
+
44
-
,
45
-
-
46
-
.
47
-
/
48 ... 57
-
0 ... 9
58
-
:
59
-
;
60
-
<
61
-
=
52
-
>
63
-
?
64
-
@
65 ... 90
-
A. .. Z
91
-
[
92
-
/
93
-
]
94
-
^
95
-
_
96
-
"
97 ... 122
-
a. .. z
123
-
{
124
-
??
125
-
}
126
-
~
128 ... 159
-
A. .. Я
160 ... 175
-
а ... п
224 ... 239
-
р ... я
Клавіші та їх поєднання зі зсувними
0
3
Ctrl-2
0
15
Shift - Tab
0
16 ... 25
Alt-Q ... Alt-P (верхній ряд букв)
0
30 ... 38
Alt-A ... Alt-L (середній ряд літер)
0
44 ... 50
Alt-Z ... Alt-M (нижній ряд букв)
0
59 ... 68
72
F1 ... F10
курсор вгору
0
71
Home
0
75
курсор вліво
0
73
PgUp
0
79
End
0
77
курсор вправо
0
81
PgDn
0
80
курсор вниз
0
83
Del

закінчення таблиці

код
клавіша чи комбінація клавіш
код
клавіша чи комбінація клавіш
перший байт
другий байт
перший байт
другий байт
0
82
Ins
0
94 ... 103
Ctrl-F1 ... Ctrl-F10
0
84 ... 93
Shift-F1 ... Shift-F10
0
114
Ctrl-PrtScr
0
104 ... 113
Alt-F1 ... Alt-F10
0
116
Ctrl - курсор вправо
0
115
Ctrl - курсор вліво
0
118
Ctrl - PgDn
0
117
Ctrl - End
0
120 ... 131
alt-1 ... alt-= (верхній ряд клавіш)
0
119
Ctrl - Home
0
132
Ctrl - PgUp
11.2. Текстовий вивід на екран
Бібліотека Turbo Vision здатна задовольнити самим високим вимогам, і ми настійно рекомендуємо звертатися до неї при програмуванні складних текстових зображень (меню, вікон тощо). Тим не менш, цілком можливо, що деякі з читачів захочуть використовувати значно більш прості, але досить ефективні засоби модуля CRT, описані в цьому розділі.
Процедура TextMode використовується для завдання одного з можливих текстових режимів роботи адаптера монітора. Заголовок процедури:
Procedure TextMode (mode: word);
Тут mode - код текстового режиму. в якості значення цього виразу можуть використовуватися такі константи, визначені в модулі CRT:
const
bw40 = 0; {чорно-білий режим 40 * 25}
co40 = l; {кольоровий режим 40 * 25}
bw80 = 2, {чорно-білий режим 80 * 25}
co80 = 3; {кольоровий режим 80 * 25}
mono = 7; {використовується з mda}
Font8 * 8 = 256; {використовується для завантаження шрифту в режимі 80 * 43 або 80 * 50 з адаптерами EGA або VGA}
Код режиму, встановленого за допомогою виклику процедури TextMode, запам'ятовується в глобальній змінній LastMode модуля CRT і може використовуватися для відновлення початкового стану екрану.
наступна програма ілюструє використання цієї процедури в різних режимах. зауважимо, що при виклику TextMode скидаються всі раніше зроблені установки кольору і вікон, екран очищається і курсор переводиться в його лівий верхній кут.
user CRT;
procedure print (s: string), {вивести повідомлення s і чекати ініціативи користувача}
Begin
write l n (s), {вивести повідомлення}
write l n ('натиснути клавішу enter ...');
read l n {чекаємо натискання клавіші enter}
end; {print}
Var
lm: word, {початковий режим екрана}
Begin
lm: = LastMode; {запам'ятати початковий режим роботи дисплея}
TextMode 40);
print ('режим 40 * 25');
TextMode (co8o);
print ('режим 80 * 25');
TextMode (co40 + font8 * 8);
print ('режим co40 + font8 * 8');
TextMode (co 80 + font 8 * 8);
print ('режим co80 + font8 * 8'), {відновити вихідний режим роботи:}
TextMode (lm)
end.
Процедура TextColor визначає колір символів, що виводяться. заголовок процедури:
Procedure TextColor (color: byte);
Процедура TextBackGround визначає колір фону. заголовок процедури:
Procedure TextBackGround (color: byte);
Єдиним параметром звернення до цих процедур повинно бути вираз типу byte, що задає код потрібного кольору. Цей код зручно визначати за допомогою наступних мнемонічних констант, оголошених в модулі CRT:
const
black = 0; {чорний}
blue = l; {темно-синій}
green = 2; {темно-зелений}
суаn = 3; {бірюзовий}
red = 4; {червоний}
magenta = 8; {фіолетовий}
brown = 6; {коричневий}
lightgray = 7; {світло-сірий}
darkgray = 8; {темно-сірий}
    light blue = 9; {синій}
    lightgreen = 10; {світло-зелений}
lightcyan = 11; {світло-бірюзовий}
lightred = 12; {рожевий}
lightmagenta = 13; {малиновий}
yellow = 14; {жовтий}
white = 15; {білий}
blink = 128; {мерехтіння символу}
Наступна програма ілюструє колірні можливості Турбо-Паскаля.
uses CRT,
const
col: array [1 .. 15] of string [16] =
('Темно-синій', 'темно-зелений', 'бірюзовий', 'червоний', 'фіолетовий', 'коричневий', 'світло-сірий', 'темно-сірий', 'синій', 'зелений', ' світло-бірюзовий ',' рожевий ',' малиновий ',' жовтий ',' білий ');
Var
k: byte,
Begin
for k: = l to 15 do
Begin {виводимо 15 повідомлень різними кольорами}
textcolor (k),
writeln ("колір", k, "-", col [k])
end;
textcolor (white + blink); {білі миготливі символи}
writeln ("мерехтіння символів");
{Відновлюємо стандартний колір}
textcolor (lightgray),
writeln
end.
Зверніть увагу на останній оператор write ln. Якщо його прибрати, режим мерехтіння символів збережеться після завершення програми, незважаючи на те, що перед ним стоїть оператор
TextColor (lightgray);
Справа в тому, що всі колірні визначення попередньо заносяться в спеціальну змінну TextAttr модуля CRT і використовуються для налаштування адаптера тільки при зверненні до процедур write / writ eln.
Процедура ClrScr очищає екран або вікно (див. нижче процедуру window). після звернення до неї екран (вікно) заповнюється кольором фону і курсор встановлюється в його лівий верхній кут. наприклад:
uses CRT;
Var
з: char
Begin
textbackground (red);
clrscr; {заповнюємо екран червоним кольором}
writeln ("натисніть будь-яку клавішу ...");
з: = ReadKey, {чекаємо натискання будь-який клавіші}
textbackground (black);
clrscr {відновлюємо чорний фон екрана}
end.
Процедура Window визначає текстове вікно - область екрану, яка в подальшому буде розглядатися процедурами виведення, як весь екран. Відразу після виклику процедури курсор поміщається в лівий верхній кут вікна, а саме вікно очищається (заповнюється кольором фону). У міру виведення курсор, як зазвичай, зміщується вправо і при досягненні правої межі вікна переходить на новий рядок, а якщо він до цього моменту знаходився на останньому рядку, вміст вікна зрушується вгору на один рядок, тобто здійснюється «прокрутка» вікна. Заголовок процедури:
Procedure Window (xi, yi, х2, y 2: byte);
Тут x1 ... y2 - координати лівого верхнього (х1, y1) і правого нижнього (х2, y2) кутів вікна. Вони задаються в координатах екрану, причому лівий верхній кут екрана має координати (1,1), горизонтальна координата збільшується зліва направо, а вертикальна - зверху вниз.
У наступному прикладі ілюструється висновок досить довгого повідомлення у двох різних вікнах:
uses CRT;
Var
k: integer;
Begin {створити ліве вікно - жовті символи на синьому тлі:}
textbackground (blue);
window (5, 2, 35, 17);
textcolor (yellow);
for k: = i to 100 do
write ("натиснути клавішу enter ... ");
readln, {чекаємо натискання enter}
clrscr; {очищаємо вікно}
{Створити праве вікно - білі символи на червоному тлі:}
textbackground (red);
textcolor (white);
window (40, 2, 70, 17);
for k: = i to 100 do
write ("натиснути клавішу enter ... ");
      readln;
TextMode (Co8o) {скинути всі установки}
end.
Звернення до процедури Window ігнорується, якщо яка-небудь з координат виходить за межі екрану або якщо порушується одна з умов: Х2> Х1 або Y2> Y1. Кожне нове звернення до Window скасовує попередню ухвалу вікна. Межі поточного вікна запам'ятовуються в двох глобальних змінних модулях CRT: мінлива WindMin типу Word зберігає X1 і Y1 (Х1 - у молодшому байті), а змінна того ж типу WindMax - Х2 і Y2 (Х2 - у молодшому байті). При бажанні ви можете змінювати їх потрібним чином без звернення до Window. наприклад, замість оператора
Window (40, 2, 70,17);
можна було б використовувати два оператори:
WindMin: = 39 + (lshl 8); WindMax: = 69 + (16 shl 8);
(На відміну від звернення до Window, координати, що зберігаються в змінних WindMin і WindMax, відповідають початку відліку 0, 0).
Процедура GotoXY переводить курсор в потрібне місце екрану або поточного вікна. Заголовок процедури:
Procedure GotoXY (Х, Y: Byte);
Тут X, Y - нові координати курсору. Координати задаються щодо меж екрану (вікна), тобто оператор
GotoXY (1,1);
Оператор вказує, перевести курсор у лівий верхній кут екрану (або вікна, якщо до цього моменту на екрані визначено вікно). Звернення до процедури ігнорується, якщо нові координати виходять за межі екрану (вікна).
Функції WhereX і WhereY. За допомогою цих функцій типу Byte можна визначити поточні координати курсору: WhereX повертає його горизонтальну, а WhereY - вертикальну координати.
У наступній програмі в центрі екрану створюється вікно світло-бірюзового кольору, яке обводиться рамкою.
Program Prim52;
Uses CRT; {підключити бібліотеку (модуль) CRT}
Const {константи, що визначають графічні символи}
{Необхідні для креслення рамки вікна}
lu = # 218; {лівий верхній кут рамки}
ru = # 191; {правий верхній кут рамки}
ld = # 192; {лівий нижній кут рамки}
rd = # 217; {правий нижній кут рамки}
h = # 196; {горизонтальна риса}
v = # 179; {вертикальна риса}
{Координати вікна:}
x1 = 14; y1 = 5; {верхній лівий кут}
x2 = 66; y2 = 20; {нижній правий кут}
Var k: integer;
Begin ClrScr; {очістіт' екран}
textmode (co80); {сбросіт' всі установки}
textbackground (lightcyan); {фон вікна світло-бірюзовий}
textcolor (yellow); {колір текстів у вікні жовтий}
window (x1, y1, x2, y2); {открит' вікно з координатами}
ClrScr;
{Малюємо рамку навколо вікна}
Write (lu); {лівий верхній кут}
   for k: = x1 +1 to x2-1 do
      write (h); {верхню горизонтальну риску}
write (ru); {правий верхній кут}
for k: = y1 +1 to y2-1 do {малюємо вертикальні лінії}
{Посимвольний ліворуч і праворуч і через підрядник за рахунок циклу}
Begin GotoXY (1, k-y1 +1); {курсор на ліву кордон}
write (v); {вивести вертикальну риску}
GotoXY (x2-x1 +1, whereY); {курсор на праву межу}
write (v); {вивести вертикальну риску}
{Перейти на новий рядок, поки не скінчиться цикл}
end;
write (ld); {лівий нижній кут}
       Window (x1, y1, x2, y2 +1);
GotoXY (2, y2-y1 +1); {kypcop в нижній лівий кут +1}
{Нового вікна, без урахування рамки}
   for k: = x1 +1 to x2-1 do write (h); {нижню горизонтальну риску}
write (rd); {нижній правий кут}
TextBackground (LightCyan);
GotoXY (2,2); {курсор у лівий верхній кут}
{Нового вікна без урахування рамки}
readln;
end.
Три наступні процедури без параметрів можуть виявитися корисними при розробці текстових редакторів.
Процедура ClrEOL стирає частина рядка від поточного положення курсора до правої межі вікна (екрана). Положення курсору не змінюється.
Процедура DelLine знищує весь рядок з курсором в поточному вікні (або на екрані, якщо вікно не створено). При цьому всі рядки нижче видаляється (якщо вона є) зсуваються вгору на один рядок.
Процедура InsLine вставляє рядок: рядок з курсором і всі рядки нижче її зрушуються вниз на один рядок; рядок, що вийшла за нижню межу вікна (екрана), безповоротно втрачається; поточне положення курсору не змінюється.
Процедури LowVideo, No rm Video і HighVideo. За допомогою цих процедур без параметрів можна встановлювати відповідно знижену, нормальну і підвищену яскравості символів. Наприклад:
Uses CRT;
begin
LowVideo;
Writeln ('знижена яскравість';);
NormVideo;
Writeln ('нормальна яскравість');
HighVideo;
Writeln ('підвищена яскравість')
end.
На практиці немає різниці між зниженою і нормальною яскравістю зображення.
Процедура Assign CRT пов'язує текстову файлову змінну F з екраном за допомогою безпосереднього звернення до відеопам'яті (тобто до пам'яті, використовуваної адаптером для створення зображення на екрані). У результаті висновок у такий текстовий файл здійснюється значно швидше (у 3 ... 5 разів), ніж якщо б цей файл був пов'язаний з екраном стандартною процедурою Assign. Заголовок процедури: Procedure Assign CRT (F: Text);
У наступній програмі вимірюється швидкість виведення на екран за допомогою стандартної файлової процедури і безпосереднього звернення до відеопам'яті. Спочатку файлова змінна F зв'язується «повільної» процедурою Assign зі стандартним пристроєм CON (тобто з екраном) і підраховується кількість N циклів виведення деякого тексту за 5 * 55 = 275 мілісекунд системних годин. Потім файлова змінна зв'язується з екраном за допомогою процедури швидкого доступу Assign CRT і точно так само підраховується кількість N2 циклів виводу. У кінці програми лічильники NI і N2 виводяться на екран.
Показання системних годин зберігаються в оперативній пам'яті комп'ютера у вигляді чотирибайтових слова на адресу [$ 0040: $ 006С] і нарощуються на одиницю кожні 55 мілісекунд.
Uses CRT;
var
F: Text;
                   t: Longint; {початок відліку часу}
N1, N2: Word; {лічильник виведення}
const
                   txt = 'Text';
begin
{----- Стандартний вивід в файл ------}
                   Assign (F, "CON");
                   Rewrite (F);
N1: = 0; {готуємо лічильник виведення}
ClrScr; {очищаємо екран}
                   {Запам'ятовуємо початковий момент:}
                   t: = Meml [$ 0040: $ 006 C];
{Чекаємо початок нового 55-мілісекундного інтервалу, щоб виключити погрішність у визначенні часу:}
                   while Meml [$ 0040: $ 006C] = t do;
                   {Цикл виведення за 5 інтервалів}
                   while Meml [$ 0040: $ 006 C] <t +6 do
                             begin
inc (N1);
Write (F, txt)
end;
                   Close (F);
{Висновок за допомогою швидкої процедури прямого доступу до екрану}
                   AssignCRT (F);
Rewrite (F);
N2: = 0;
ClrScr;
t: = Meml [$ 0040: $ 006C];
while Meml [$ 0040: $ 006] = t do;
while Meml [$ 0040: $ 006] <t +6 do
begin
inc (N2);
Write (F, txt)
end;
Close (F);
{Друкуємо результат}
ClrScr;
Writeln (N1, N2: 10)
end.
Слід врахувати, що виведення на екран звичайним чином, без використання файлової змінної (наприклад, оператором Write (txt)), також здійснюється за допомогою безпосереднього доступу до відеопам'яті, тому цінність процедури AssignCRT вельми сумнівна. Прямий доступ до відеопам'яті регулюється глобальної логічної змінної DirectVideo модуля CRT: якщо ця змінна має значення True, доступ дозволений, якщо False - доступ до екрану здійснюється за допомогою відносно повільних засобів операційної системи MS-DOS. За замовчуванням мінлива DirectVideo має значення True.
11.3. Програмування звукового генератора
Звукові можливості пк засновані на одноканальному керованому звуковому генератор, що виробляє електромагнітні коливання звукової частоти. Коливання подаються на вбудований в пк динамік і змушують його звучати.
У модуль CRT включені три процедури, за допомогою яких ви зможете запрограмувати довільну послідовність звуків.
Процедура Sound змушує динамік звучати з потрібною частотою. заголовок процедури Procedure Sound (F: Word); тут F - вираз типу Word, що визначає частоту звуку в герцах. Після звернення до процедури включається динамік, і управління негайно повертається в основну програму, у той час як динамік буде звучати надалі до виклику процедури NoSound.
Процедура NoSound вимикає динамік. Якщо він до цього моменту не був включений, виклик процедури ігнорується.
Процедура Delay oбеспечівает затримку роботи програми на заданий інтервал часу. Заголовок процедури: Procedure Delay (T: Word);
Тут Т - вираз типу Word, що визначає інтервал часу (у мілісекундах), протягом якого затримується виконання наступного оператора програми.
Для генерації звукового сигналу зазвичай використовується виклик описаних процедур за схемою Sound-Delay-NoSound. наступна програма змусить пк відтворити просту музичну гаму. Використовуваний в ній масив F містить частоти всіх півтонів в першій октаві від «до» про «сі». При переході від однієї октави до сусідньої, частоти змінюються у два рази.
Uses CRT;
const
F: array [1 .. 12] of Real =
                             (130.8, 138.6, 146.8, 155.6, 164.8, 174.6, 185.0, 196.0, 207.7,
220.0, 233.1, 246.9); {масив частот 1-ї октави}
Temp = 100; {темп виконання}
var
k, n: integer;
begin
{Висхідна гамма}
                   for k: = 0 to 3 do
for n: = 1 to 12 do
Begin
Sound (Round (F [n] * (1 shl k)));
Delay (Temp);
NoSound
end;
{Спадна гамма}
for k: = 3 downto 0 do
for n: = 12 downto 1 do
begin
Sound (Round (F [n] * (1 shl k)));
Delay (Temp);
NoSound
end
end.
У наступній програмі перемножується матриця на вектор, основу якої складає раніше розглянуті Program Prim 29 i Prim 29а. Тут максимальні розміри матриці - 10 * 10 елементів типу byte. Введення інформації проводиться у вікні світло-бірюзового кольору, виведення результатів - у вікні малинового кольору, колір букв - жовтий.
Програма на початку роботи видає звуки частотою від 130 до 2130 Гц, потім при введенні величини a - частотою 2000 Гц, b - 1500 Гц тривалістю n = 100 мс. В кінці роботи програма видає звуки від 2130 до 130 Гц. Програма використовує підпрограму Wind, написану на основі Prim 52.
  Program Prim53; Uses CRT; var i, j, n, m, k, l: integer; a: array [1 .. 50,1 .. 70] of byte; b: array [1 .. 10] of byte;
c: array [1 .. 10] of longint;
cv: byte;
{$ I C: \ TURBO \ wind.pas}
BEGIN
Clrscr; {очистити екран}
cv: = 11; {колір 11, світло - бірюзовий}
  wind (1,1,50,7); {відкрити вікно, звернення до процедури}
Sound (330); {включити звук, частотою 330 гц} Delay (1000); {затримати на 1000 мілісекунд} NoSound; {вимкнути звук}
writeln ('ввести кількість рядків і стовпців');
GotoXY (2,3); l: = 4; {l встановлює курсор по y}
        readln (n, m);
for i: = 1 to n do
for j: = 1 to m do
begin GotoXY (2, l);
      writeln ('введіть a [', i ,',', j, '] елемент матриці а');
GotoXY (34, l); {перевести курсор в кінець тексту:}
{Ввести a [i, j] - елемент матриці '}
ClrEol; {видалити кінець рядка до кордону вікна}
readln (a [i, j]); {ввести чергове а в кінці тексту}
       end;
L: = L +1; {}
for j: = 1 to m do
begin GotoXY (2, l);
writeln (ввести b [', j,'] елемент вектора b ');
GotoXY (33, l);
ClrEol;
       readln (b [j]); end;
   cv: = 5; {фіолетовий колір для нового вікна}
   wind (20,2,80,18); GotoXY (2,2); l: = 3;
for i: = 1 to n do {початок перемноження матриці на вектори}
  begin c [i]: = 0;
for j: = 1 to m do
c [i]: = c [i] + a [i, j] * b [j]; end;
                           {Кінець перемноження матриці на вектор}
writeln ('роздруківка масиву а');
       for i: = 1 to n do
          begin GotoXY (2, l); l: = l +1; {почати нову рядок}
       for j: = 1 to m do
write (a [i, j]: 5); end;
     GotoXY (2, l); l: = l +1; writeln ('роздруківка масиву b');
     GotoXY (2, l);
for j: = 1 to m do
       write ('', b [j]); L: = L +1;
     GotoXY (2, L); L: = L +1; writeln ('результуючий масив з');
     GotoXY (2, L);
for i: = 1 to n do
write ('', c [i]);
     readln; END.

12. Графіка в Паскалі

12.1. Ініціалізація графічного режиму
Для виведення графічних зображень на екран турбо Паскаль надає користувачеві бібліотеку Graph. Загальний вигляд програми з використанням Graph має наступний вигляд:
Program ім'я;
Uses Graph;
var
grDriver, grMode, errCode: integer;
begin
grDriver: = Detec t; {визначення номера, встановленого в системі драйвера}
initGraph (grDriver, grMode ,''); {ініціалізація графічного режиму}
          if errCode = grOK then
begin {режим відкритий і можна працювати}
end else
begin {графічний режим не вдалося відкрити, проаналізуйте зміст змінної errCode}
end.
Зауваження. Дві лапки в init Graph правомочні тільки тоді, коли графічна програма знаходиться в тому ж каталозі, що і бібліотека Graph. В іншому випадку в лапках повинен стояти шлях - вказівка, де знаходиться бібліотека Graph.

12.2. Процедури та функції бібліотеки Graph
Функції GetMaxX і GetMaxY повертають значення типу Word, що містять максимальні координати, відповідно, X і Y відносно лівого верхнього кута в пікселях (точках).
Різні монітори мають різну роздільну здатність, наприклад: VGA - 640'480 точок, IBM 8514Hi - 1024'768 точок.
Функції GetX і GetY повертають поточні координати покажчика. Процедура SetViewPort (Х1, Y1, Х2, Y2, Clipon); встановлює прямокутне вікно на графічному екрані, X1, Y1 - координати лівого верхнього кута; Х2, Y2 - координати нижнього правого кута вікна.
Якщо вираз Clipon має значення true і елементи зображення не поміщаються у вікні, то вони відсікаються, якщо - false, то відсічення ігнорується.
Процедура MoveTo (Х, Y); встановлює нове поточне положення вказівника.
Процедура MoveRel (Ox, Dy); встановлює збільшення нових координат покажчика щодо старих.
Процедура ClearDevice, очищає графічний екран, покажчик встановлюється в лівий верхній кут, екран заповнюється кольором, заданим процедурою SetBkColor.
Процедура PutPixel (Х, Y, Color); виводить на екран точку Color кольору. Процедура LineTo (Х, Y); викреслює лінію від поточного положення покажчика до точки Х, Y.
Процедура SetLineStyle (Туре, Pattern, Thick);
Де Туре - тип лінії. Pattern - зразок лінії. Thick - товщина лінії.
Тип лінії:
0 - суцільна,
1 - точкова,
2 - штрихпунктирними,
3 -. . . . . . . .
4 - візерунок лінії визначає користувач параметром pattern.
Thick = l - товщина лінії в 1 піксель.
Thick = 2 - товщина лінії в 3 піксела.
Процедура Rectangle (Х1, Y1, Х2, Y2); викреслює прямокутник з використанням поточного кольору і поточного стилю ліній.
Процедура Draw P oly (N, Р); викреслює довільну ламану лінію. N - кількість точок зламу, включаючи крайні; Р - змінна типу PointType, яка в Graph має вигляд:
type
PointType = record
X, Y: Word
end;
При кресленні використовуються поточний колір і поточний стиль ліній. Процедура Circle (Х, Y, R); викреслює коло з центром X, Y і радіусом R.
Процедура Arc (Х, Y, Beg А, End А, R); викреслює дугу кола Beg А і End А, відповідно, початковий і кінцевий кути дуги.
Процедура Ellipse (Х, Y, Beg А, End А, RX, RY); викреслює дугу еліпса з центром X, Y; Beg А, End А - початковий і кінцевий кут, RX і RY - горизонтальний і вертикальний радіуси.
Процедура Bar (Х1, Y1, Х2, Y2); заповнює прямокутну область екрана зразком узору і поточним кольором, які встановлюються процедурою SetF il lStyle.
Процедура Ва r 3 D (Х1, Y1, Х2, Y2, Depth, Тор); викреслює тривимірне зображення паралелепіпеда і зафарбовує його передню грань. Depth - глибина третього виміру, Top = t rue - верхня межа вичерчується, false - ні.
Процедура FillPoly (n, Coords); обводить лінією і зафарбовує замкнутий багатокутник; n - кількість вершин, Coords - змінна типу Poin t Type, що містить координати вершин (див. DrawPoly).
Процедура F il lEllipse (Х, Y, Rx, Ry); обводить лінією і заповнює еліпс.
Процедура Sector (Х, Y, Beg А, End А, Rx, Ry); викреслює і заповнює елліпсний сектор.
Процедура PieSlice (Х, Y, Beg А, End А, R); викреслює і заповнює сектор кола.
Процедура SetColor (Color); встановлює поточний колір для виведених ліній і символів.
Процедура SetbkColor (Color); встановлює колір фону вікна.
Процедура SetF ill Style (Fill, Color); встановлює стиль Fill і колір заповнення Color.
Значення Fill:
0 - заповнення тлом (візерунок відсутній);
1 - суцільне заповнення;
2 - заповнення - - - - -;
3 - - «- ///////;
4 - - «- потовщеними ///////;
5 - - «- потовщеними \ \ \ \ \ \;
6 - - «- \ \ \ \ \ \;
7 - - «- + + + + + +;
8 - - «- ******;
9 - - «- прямокутної клітинкою;
10 - - «- рідкісними точками;
11 - - «- частими точками;
12 - - «- візерунок визначається користувачем.
Процедура FloodPill (Х, Y, Color); заповнює довільну замкнену лінію (точки з'єднання повинні збігатися, наприклад, кінці ліній не можуть перетинатися) поточним стилем і поточним кольором. X, Y - координати точки всередині фігури, Color - колір обмежень лінії. Якщо лінії розімкнуті чи перетинаються і кінці «стирчать», то колір «розіллється» по всьому вікна.
Функція ImageSize (X1, Y1, X2, Y2); повертає розмір пам'яті в байтах, необхідний для розміщення прямокутного фрагмента зображення (наприклад, вікна з малюнком).
Процедура GetImage (X1, Y1, X2, Y2, Buf); поміщає в пам'ять копію прямокутного фрагмента зображення. Buf - змінна або ділянки купи, куди буде поміщена копія відеопам'яті з фрагментом зображення. Розмір Buf повинен бути не менше значення, що повертається функцією ImageSize з тими ж координатами X1 ... Y2.
Процедура PutImage (X, Y, Buf, Mode); виводить в задане місце екрану копію фрагмента зображення, раніше поміщену в пам'ять процедурою GetImage.
X, Y - координати лівого кута того місця на екрані, куди буде скопійований фрагмент зображення. Buf - змінна, або ділянка купи, звідки береться фрагмент зображення. Mode - спосіб копіювання.
12.3. Приклади програм
Нижче наведено програми, що демонструють деякі можливості графіки в Паскалі.
Програма Prim 54 демонструє висновок різних простих об'єктів-кіл, дуг, еліпсів, прямокутників, паралелепіпедів.
       Program Prim54; Uses Graph; var grDriver, grMode, errCode, Radius, i, Width, y0, y1, y2, x1, x2: integer; Begin grDriver: = detect; {визначення номери драйвера}
InitGraph (grDriver, grMode ,'');
{Ініціалізація графічного режиму}
      errCode: = GraphResult;
if errCode = grOK then
  begin {графічний режим відкритий, можна працювати}
        for radius: = 1 to 5 do
begin {малюємо кола з радіусами 10,20 .. 50,
з центром x = 200, y = 70 точок растра}
           Circle (200,70, Radius * 10); readln; end;
{Cleardevice;} {якби цей оператор не був у
комментарних дужках, тобто не заблокований, то
зараз окружності були б стерті з екрана}
Ellipse (200,200,0,360,30,50); {малюємо дугу еліпса з центром 200,200, початковий кут = 0, кінцевий - 360 (замкнутий,
еліпс радіусами 30,50}
readln;
Ellipse (300,200,0,180,50,30); {полелліпса}
        readln;
       for Radius: = 1 to 5 do
    Arc (300,100,0,90, radius * 10); {дуги з центром 300,100, від
                          0 до 90 градусів, радіусами 10,20 .. 50}
readln;
Width: = 10;
Bar (30,20,50,100); {прямокутник з координатами 30,20 -
верхній лівий кут і 50,100 - нижній правий кут}
        for i: = 1 to 5 do
Bar (10 + i * Width, 300 + i * 10,20 + i * Width, 400);
     {П'ять прямокутників: перший 20,310.30,400,
другий 30,320,40,400 і т.д. }
readln;
Bar3D (210,300,250,360,10, TopOn); {паралелепіпед з кришкою}
        readln;
x1: = 410; y1: = 300; x2: = 450; y2: = 360;
Bar3D (x1, y1, x2, y2, 10, TopOff); {паралелепіпед без кришки}
        readln;
CloseGraph; {закрити Graph}
        end
else Halt (1); {режим Graph НЕ вдалося відкрити. }
     End.
Prim 55 малює в динаміці випадково розташовані кольорові лінії на екрані до тих пір, поки не буде натиснута клавіша Enter. Потім машина виводить останнім випадковим кольором головну діагональ вікна, після Enter - випадкові промені і після Enter - прямокутник.
     Program Prim55;
Uses CRT, Graph;
var GrDriver, grMode, errCode: integer;
begin grDriver: = Detect;
InitGraph (grDriver, grMode, '');
errCode: = GraphResult;
if errCode = grOK then
   begin Randomize; {запустити генератор випадкових чисел}
repeat {малюються кольорові лінії в квадраті 500 x 500,
поки не буде натиснута будь-яка клавіша, координати
ліній випадкові, кольору ліній випадкові}
      SetColor (Random (GetMaxColor) +1);
Line (Random (500), Random (500), Random (500), Random (500));
      Delay (1000); {кожна лінія малюється з затримкою}
      until KeyPressed;
Cleardevice;
      MoveTo (1,2); {перевести курсор}
      LineRel (500,500); {провести лінію з попередньої точки в 500,500
останнім кольором}
readln; readln;
repeat
LineTo (random (500), random (500)); {провести лінію у випадкову точку}
      Delay (6000);
until KeyPressed; readln;
ClearDevice;
Rectangle (29,29, GetMaxX-29, GetMaxY-29); {прямокутник}
readln;
CloseGraph; end
else Halt (1); end.
Prim56 малює еліпси і кола, зафарбовані червоним кольором.
Program Prim56;
Uses CRT, Graph;
Var grDriver, grMode, errCode: integer;
Begin grDriver: = Detect;
InitGraph (grDriver, grMode, '');
errCode: = Graphresult;
if errCode = grOK then
Begin SetBkColor (blue);
SetFillStyle (1,4);
FillEllipse (220,150,50,50);
FillEllipse (420,150,50,50);
FillEllipse (320,230,50,130);
FillEllipse (370,405,50,30);
FillEllipse (275,410,50,30);
readln; end
else Halt (1); end.
Prim56 малює мавпу з тазиком.
       Program Prim57;
Uses Graph;
Var i, grDriver, grMode, TrrCode, errCode: integer; x, y: word;
xm, ym, rc, xc, yc, x1, y1, x2, y2, r: word;
k: arccoordsType; kr: array [1 .. 20] of PointType;
Begin grDriver: = detect;
InitGraph (grDriver, grMode, '');
errCode: = GraphResult;
if errCode = grOK then
begin
x: = 150; y: = 150;
SetBkColor (white);
{Вуха}
y1: = y-30; x1: = x-30; x2: = x +40; r: = 15;
SetColor (lightred);
SetFillStyle (solidfill, brown);
pieslice (x1, y1, 0,360, r);
pieslice (x2, y1, 0,360, r);
r: = r-3;
SetFillStyle (solidfill, lightred);
     pieslice (x1, y1, 0,360, r);
pieslice (x2, y1, 0,360, r);
            {Голова}
r: = (x2-x1) div 2-3;
     x1: = x1 + r +2;
y1: = y1 +2;
xc: = x1;
     yc: = y1;
rc: = r;
setColor (brown);
SetFillStyle (solidfill, brown);
pieslice (x1, y1, 0,360, r);
{Майка}
setColor (brown);
SetFillStyle (solidfill, yellow);
y2: = y1 + r-3;
x1: = x1-r div 2 +2;
     ym: = y2;
line (x1-5, y2-5, x1-27, y2 +68);
x2: = x1 + r +16;
xm: = x2;
line (x2-15, y2-5, x2 +27, y2 +68);
line (x1-27, y2 +68, x2 +27, y2 +68);
putpixel (x2-22, y2 +25, blue);
floodfill (x2-22, y2 +25, brown);
{Пояс}
setcolor (green);
setfillstyle (solidfill, green);
bar (112,215,214,225);
{Штани}
setcolor (blue);
setfillstyle (solidfill, blue);
kr [1]. x: = 113; kr [1]. y: = 223;
kr [2]. x: = 113; kr [2]. y: = 270;
kr [3]. x: = 165; kr [3]. y: = 270;
kr [4]. x: = 170; kr [4]. y: = 260;
kr [5]. x: = 180; kr [5]. y: = 270;
kr [6]. x: = 225; kr [6]. y: = 270;
kr [7]. x: = 212; kr [7]. y: = 223;
kr [8]. x: = 113; kr [8]. y: = 223;
fillpoly (8, kr);
{Ліва нога}
setcolor (brown);
setfillstyle (solidfill, brown);
kr [1]. x: = 135; kr [1]. y: = 270;
kr [2]. x: = 145; kr [2]. y: = 320;
kr [3]. x: = 123; kr [3]. y: = 350;
kr [4]. x: = 145; kr [4]. y: = 358;
kr [5]. x: = 145; kr [5]. y: = 350;
kr [6]. x: = 162; kr [6]. y: = 320;
kr [7]. x: = 145; kr [7]. y: = 270;
kr [8]. x: = 135; kr [8]. y: = 270;
fillpoly (8, kr);
{Права нога}
kr [1]. x: = 195; kr [1]. y: = 270;
kr [2]. x: = 205; kr [2]. y: = 320;
kr [3]. x: = 183; kr [3]. y: = 350;
kr [4]. x: = 205; kr [4]. y: = 358;
kr [5]. x: = 205; kr [5]. y: = 350;
kr [6]. x: = 222; kr [6]. y: = 320;
kr [7]. x: = 205; kr [7]. y: = 270;
kr [8]. x: = 195; kr [8]. y: = 270;
fillpoly (8, kr);
{Черевики}
setfillstyle (solidfill, red);
pieslice (160,360,0,360,10);
pieslice (200,370,10,160,20);
pieslice (215,360,0,360,10);
pieslice (142,370,10,160,20);
setfillstyle (solidfill, white);
fillellipse (145,115,5,8);
fillellipse (163,115,5,8);
setfillstyle (solidfill, blue);
pieslice (147,115,0,360,3);
pieslice (165,115,0,360,3);
setcolor (yellow);
arc (154,160,30,145,30);
setcolor (red);
setfillstyle (solidfill, lightmagenta);
fillellipse (154,146,5,8);
{Метелик}
kr [1]. x: = 140; kr [1]. y: = 153;
kr [2]. x: = 135; kr [2]. y: = 163;
kr [3]. x: = 155; kr [3]. y: = 158;
kr [4]. x: = 175; kr [4]. y: = 163;
kr [5]. x: = 170; kr [5]. y: = 153;
kr [6]. x: = 155; kr [6]. y: = 158;
kr [7]. x: = 140; kr [7]. y: = 153;
fillpoly (7, kr);
{Тазик}
setfillstyle (solidfill, blue);
kr [1]. x: = 243; kr [1]. y: = 225;
kr [2]. x: = 255; kr [2]. y: = 280;
kr [3]. x: = 325; kr [3]. y: = 280;
kr [4]. x: = 335; kr [4]. y: = 225;
kr [5]. x: = 255; kr [5]. y: = 225;
fillpoly (5, kr);
sector (290,230,0,360,50,12);
setfillstyle (solidfill, lightcyan);
fillellipse (290,230,40,10);
{Руки}
setfillstyle (solidfill, brown);
kr [1]. x: = 184; kr [1]. y: = 164;
kr [2]. x: = 295; kr [2]. y: = 225;
kr [3]. x: = 300; kr [3]. y: = 215;
kr [4]. x: = 175; kr [4]. y: = 150;
kr [5]. x: = 180; kr [5]. y: = 160;
fillpoly (5, kr);
pieslice (295,224,0,170,12);
pieslice (265,244,0,360,10);
kr [1]. x: = 136; kr [1]. y: = 184;
kr [2]. x: = 265; kr [2]. y: = 255;
kr [3]. x: = 270; kr [3]. y: = 245;
kr [4]. x: = 135; kr [4]. y: = 170;
kr [5]. x: = 136; kr [5]. y: = 184;
fillpoly (5, kr);
end else halt (1);
readln; end.
      Prim58 демонструє можливості мультиплікації: за фонового малюнка - будинок, місяць, що висить "базовий" НЛО; кидається зі змінною швидкістю малий НЛО і видає звуки випадковими частотами.
          Program Prim58;
Uses CRT, Graph;
   Label loop;
Const r = 30; p = 600; pr = 1000; {константи, що визначають швидкість}
{Малювання і переміщення об'єктів}
   Var d, m, e, xm, ym, x, y, lx, ly, rx, ry, size, i, dx, dy,
       width, height, grDriver, grMode, errCode, a, b, c,
f, s, j: integer;
saucer: pointer;
Begin grDriver: = Detect;
InitGraph (grDriver, grMode ,'');
errCode: = GraphResult;
if errCode = grOK then
Begin x: = r * 3; y: = r * 2; xm: = GetMaxX div 2; ym: = GetMaxY div 2;
{Тарілка}
SetBkColor (blue);
SetFillStyle (solidfill, red);
         Ellipse (x, y, 0,360, r +40, r div 10);
Ellipse (x, y-4, 0,360, r-1, r);
Line (x +7, y-6, x +10, y-12);
Line (x-7, y-6, x-10, y-12);
Circle (x +10, y-12, 2);
Circle (x-10, y-12, 2);
Floodfill (x +1, y +4, White);
{Визначаємо габарити НЛО і поміщаємо дані про нього в купу}
         lx: = xr-1;
ly: = y-14;
rx: = x + r +1;
ry: = y + r div 6;
         Width: = rx-lx +1;
Height: = ry-ly +1;
Size: = Imagesize (lx-9, ly, rx +3, ry +10);
GetMem (Saucer, size);
GetiMage (lx-9, ly, rx +10, ry +3, saucer ^);
{Створюємо зоряне небо}
Rectangle (xm, ym, 3 * xm, 3 * ym);
SetViewPort (xm +1, ym +1,3 * xm-1, 3 * ym-1, Clipon);
xm: = 2 * xm;
ym: = 2 * ym;
for i: = 1 to 200 do
PutPixel (random (xm), random (ym), white);
{Будинок}
SetFillStyle (solidfill, DarkGray);
bar (320,240,640,480); Delay (p * 10); {будинок}
bar (370,220,600,240); Delay (p * 10); {горище}
Line (320,240,640,240); Delay (p * 10); {дах}
     Line (370,240,370,220); Delay (p * 10); {ліва стіна горища}
Line (600,220,600,240); Delay (p * 10); {права стіна горища}
     Line (370,220,600,220); Delay (p * 10); {дах горища}
Line (430,220,430,180); Delay (p * 10); {щогла антени}
Line (430,180,410,170); Delay (p * 10); {верхній вус антени}
Line (430,180,410,190); Delay (p * 10); {нижній вус антени}
Line (430,180,410,180); Delay (p * 10); {середній вус антени}
bar (0,460,640,480); Delay (p * 10); {земля}
Line (0,460,640,460); Delay (p * 10);
SetFillStyle (solidfill, Yellow);
b: = 270; {вікна}
for i: = 1 to 4 do
begin a: = 350; f: = b +20; c: = a +15; Delay (p * 5);
for j: = 1 to 8 do
begin
bar (a, b, c, f); Delay (p * 5);
SetColor (DarkGray);
Line (a, b +8, c, f-12); Delay (p * 5);
Line (a +5, b +8, a +5, b +20); Delay (p * 5);
a: = a +35; c: = c +35; end;
b: = b +50; end; Delay (p * 10);
Pieslice (500,80,300,100,20); {місяць}
SetColor (green); Delay (p * 10);
Line (150,460,150,400); Delay (p * 10); {дерево}
Circle (170,365,25); Delay (p * 10);
Circle (165,375,25); Delay (p * 10);
Circle (150,375,25); Delay (p * 10);
Circle (135,365,25); Delay (p * 10);
Circle (155,345,25); Delay (p * 10);
  {Задаємо початкове положення нло і напрямок руху}
         x: = xm div 2;
y: = ym div 2;
dx: = 100;
dy: = 100;
{Основний цикл}
        Repeat
PutImage (x, y, Saucer ^, XorPut);
Sound (Random (2 * 2000));
Delay (pr * 2); NoSound;
Putimage (x, y, Saucer ^, XorPut);
      {Отримуємо нові координати}
    loop: x: = x + dx;
         y: = y + dy;
if (x <0) or (x + width +1> xm) or (y <0) or (y + height +1> ym) then
    begin
{НЛО досяг межі екрану, міняємо напрямок його руху}
       x: = x-dx; y: = y-dy;
       dx: = GetMaxX div 10 - random (GetMaxX div 5);
dy: = GetMaxY div 30 - random (GetMaxY div 15);
goto loop;
end until KeyPressed;
if ReadKey = # 0 then x: = ord (ReadKey);
end else CloseGraph;
end.

Список використаної і рекомендованої літератури:
1. О.М. Воловачев, В.С. Крісевіч. Програмування на мові Паскаль для персональних ЕОМ ЄС. - Мінськ: "Вища школа", 1989.
2. В.Я. Сердюченко. Розробка алгоритмів та програмування мовою TURBO PASCAL. - Харків: "Паритет", 1995.
3. В.В. Фаронов. TURBO PASCAL 7.0 / Практика програмування / - "Нолидж", 1997.
4. В.В. Фаронов. TURBO PASCAL 7.0 / Початковий курс / - "Нолидж", 1997.

ЗМІСТ
TOC \ o "1-1" \ t "Заг1; 2; Заголовок1; 2" 1. Попередні відомості ................................................ ..... 4
1.1. Алфавіт ................................................. .................................................. 4
1.2. Рішення задач ................................................ ......................................... 4
2. Найпростіші програми ................................................ ............ 5
2.1. Оператор присвоювання ................................................ ......................... 5
2.2. коментарі ................................................. .......................................... 7
2.3. Програма ................................................. .............................................. 7
2.4. Найпростіший введення-виведення .............................................. .......................... 8
2.5. Арифметичні вирази ................................................ .................. 9
2.6. Описи змінних ................................................ ......................... 12
2.7. Розділ опису типів ............................................... ......................... 14
3. Розгалужуються програми ............................................. 16
3.1. Загальні положення ................................................ ................................. 16
3.2. Оператор goto, розділ опису міток ............................................ . 17
3.3. Оператор if ................................................ ............................................. 19
3.4. Оператор case (оператор вибору )............................................ ............ 25
4. Циклічні програми ................................................ ........ 27
4.1. Оператор for ................................................ .......................................... 27
4.2. Оператор repeat. Загальний вигляд ................................................ ................ 32
4.3. Оператор While ................................................ ..................................... 33
4.4. Вкладені цикли ................................................ ................................. 34
5. Введення - виведення ............................................... ....................................... 37
5.1. Загальні положення ................................................ ................................. 37
5. 2. Введення ................................................. .................................................. .... 38
5. 3. Висновок ................................................. .................................................. .. 39
5. 4. Деякі можливості введення-виведення ........................................... 39
6. Масиви ................................................. ............................................. 41
6. 1. Опис масивів ................................................ ............................ 41
7. Підпрограми ................................................. ............................... 49
7.1. Загальні положення ................................................ ................................. 49
7.2. Підпрограми-функції, визначені користувачем ................. 51
7.3. Підпрограми-процедури ............................................... .................... 54
7.4. Локальні і глобальні опису об'єктів .................................. 58
8. Строкові дані ................................................ ....................... 59
8.1. Загальні зауваження ................................................ .................................. 59
8.2. Строкові вираження ................................................ .......................... 60
8.3. Стандартні процедури та функції для обробки рядків ................ 61
8.3.1. Процедури обробки рядків ............................................... ............... 61
8.3.2. Функції рядків ............................................... .................. 62
9. Записи ................................................. .................................................. 63
9.1. Комплексні дані ................................................ ........................... 68
9.2. Запис з варіантами ............................................... ............................. 70
10. Файли ................................................. ................................................. 71
10.1. Загальні зауваження ................................................ ................................ 71
10.2. Стандартні процедури та функції для роботи з файлами .......... 72
10. 3. Стандартні файли ................................................ ........................... 73
10.4. Файли послідовного доступу, створені користувачем. 74
10.5. Файли довільного доступу ............................................... ......... 80
10.6. Текстові файли ................................................ ................................ 83
11. Використання бібліотеки CRT ....................................... 85
11.1. Програмування клавіатури ................................................ ....... 85
11.2. Текстовий вивід на екран .............................................. .................. 88
11.3. Програмування звукового генератора ...................................... 96
12. Графіка в Паскалі ............................................... ....................... 99
12.1. Ініціалізація графічного режиму ............................................ 99
12.2. Процедури та функції бібліотеки Graph ........................................ 99
12.3. Приклади програм ................................................ ............................ 102
СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ ............................................ 109
0 одиниць
0 двійок
0 четвірок
0 вісімок
0 шістнадцять
0 тридцять два
0 шістьдесят-чотири
0 сто двадцять вісім
1 двісті п'ятьдесят-шість
Пояснення: у будь-якій позиційній системі числення на першому місці справа в числі стоїть кількість підстав системи счісенія в ступені 0, на другому місці праворуч - кількість підстав в ступені 1, на третьому місці праворуч - кількість підстав в ступені 2 і т.д. так, для десяткової системи маємо:

3 2 4
кількість одиниць 100 * 4 = 4
кількість десятків 101 * 2 = 20
кількість сотень 102 * 3 = 300
складемо = 324
Для двійкової системи:
1 0 1 1 0 0 1
кількість одиниць 20 * 1 = 1
кількість двійок 21 * 0 = 0
кількість четвірок 22 * ​​0 = 0
кількість вісімок 23 * 1 = 8
кількість шестнадцаток 24 * 1 = 16
кількість тридцять другий 25 * 1 = 0
кількість шістьдесят четвірок 26 * 1 = 64
складемо = 89
тобто десяткове 89 має зображення 1011001 в двійковій системі.
Для правильного написання арифметичних виразів необхідно дотримуватися наступних правил:
1. Заборонено послідовне поява знаків двох операцій, тобто
A + - B - невірно, A + (-B) - вірно.
2. Порядок виконання операцій: /,, div, mod, and, or, shl, shr, -, +. Порядок може бути порушений круглими дужками, тому що частина виразу, укладена в круглі дужки, виконується в першу чергу.
3. Якщо операції мають однаковий пріоритет, то вони виконуються послідовно.
4. Унарний операція має найнижчий пріоритет, тому-A * b інтерпретується як - (A * b).
5. Не слід записувати вирази, які не мають арифметичного сенсу, наприклад, поділ на вираз, рівне 0.
6. Слід пам'ятати, що операції / і * мають однаковий пріоритет, наприклад, 18 / 2 * 3 = 27, а не 3. щоб було 3, необхідно записати 18 / (2 * 3).
2.6. Описи змінних.
Описи змінних залежать від типу даних, які будуть зберігатися в комірках пам'яті, названих іменами цих змінних.
Дані в Паскалі можуть бути наступних типів:
Дані
Скалярні Структуровані


масиви запису
Стандартні Певні
користувачем рядка файли


цілі логічні інтервальні безлічі
речові перераховуються покажчики
байтові символьні
Кожному типу даних можуть відповідати константи. Кількість елементів констант (цифр, букв) сильно залежить від конкретної конфігурації машини. Однак можна сказати, що для цілого типу числа максимальне значення 32767, для дійсних, як мінімум, - до 7 цифр мантиси, для строкових - 255 символів і т.д.
Константи байтового типу - цілі числа в діапазоні 0 - 255. Цілі константи - набір цифр, можливо, зі знаком ¢ + ¢ або ¢ - ¢. Речові константи можуть записуватися у двох формах - з фіксованою точкою: 57.34;
-256.758 І з плаваючою точкою: 5.734е +01 (еквівалент 57.34) і-2.56758е +02
(Еквівалент -256.758).
Логічних (булевих) констант всього дві: TRUE і FALSE. прийнято, що в машинному коді TRUE = 1, FALSE = 0. знакові константи представляють всі символи алфавіту плюс символи кирилиці, але не для того, щоб символ став константою, його необхідно взяти в апострофи: ¢ А ¢, ¢ 1 ¢, ¢ + ¢, ¢? ¢ і т.д. Константи можуть зберігатися в комірках пам'яті, визначених будь-якими іменами (ідентифікаторами).
Ідентифікатор - набір букв і цифр, перша з них - завжди буква, наприклад А, ALP1, B2, GAMMA. Ідентифікатори можуть бути довжиною до 255 символів, однак більшість компіляторів накладає обмеження, тобто довжина імені не повинна перевищувати восьми символів. Ідентифікатор у своєму складі може містити знак ¢ _ ¢ (підкресліть).
Змінні можуть бути описані в розділі опису змінних Var. розділів опису може бути до п'яти, краще їх розташовувати в наступному порядку: Label, Const, Type, Var, functuon і procedure.
Якщо дана буде змінюватися (за величиною) в процесі виконання програми, то ім'я цього даного описується в розділі Var з відповідним атрибутом:
Байтовий тип - byte;
Цілий тип - integer;
Речовий тип - real;
Булевський тип - boolean;
Символьний тип - char і т.д.
Приклад:
Var
kn: integer;
S, T, Z: char;
a, b, c: real;
L25, L3: boolean;
FAZA: byte;
У цьому випадку всі описані ідентифікатори можна застосовувати в програмі. Робота цього розділу буде полягати в тому, що машина виділить два відділення пам'яті з іменами k і n. У комірках можуть зберігатися тільки цілі числа: в комірках з іменами S, T, Z - по одному символу; в осередках a, b, c - тільки величини типу дійсних чисел; в L25 і L3-величини true і FALSE, а в осередку з ім'ям FAZA - лише числа від 0 до 255. Якщо спробувати, наприклад, у комірку S помістити не символ, а число, то це призведе до помилки, тобто правильно S: = ¢ A ¢; або S: = ¢ $ ¢; або S: = ¢ 1 ¢, а проте невірно S: = 1 (1 - число на відміну від ¢ 1 ¢ - символу). Якщо в процесі виконання програми дане не змінюється, то його можна описати в розділі "Опис констант":
Const
A = 36.74; B = true;
С = ¢ а ¢;
Тут теж виділяються комірки пам'яті з іменами А, В, С для зберігання заданих величин, які не підлягають зміні.
Припустимо опис констант-виразів:
C o nst
М = (32.5 + 0.64) / 3.14;
Крім того, машина "знає", чому дорівнюють константи е і π.
Приклад. Скласти програму для обчислення виразу
, Де величини R, а, S, L, K вводяться з клавіатури.
Нехай k, l - цілі числа, решта - речові.
Program Prim2,
Var k, L: integer;
Y, R, a, S: real; {тут для зберігання результату y теж}
{Потрібна осередок пам'яті}
Begin writeln ('введіть Це', {видача на екран тексту, зазначеного в}
'Ціле k, L, дійсні' {лапках, зверніть увагу на прави-}
'R, а, S'); {ло перенесення тексту в операторі writeln:}
{Якщо потрібно перенести текст, то ставиться} {закриває апостроф, потім кома,}
{Новий рядок знову починається з апострофа}
readln (k, L, R, a, S);
Y: = 1-l (l + sqr (r * a / k)) / (exp (2) / sqr (s) * sqr (l + r * a / l));
writeln (Y); readln;
END.
Те ж саме буде, якщо записати програму:
Program Prim2a;
Var k, L: integer, R, a, S: real;
Begin writeln ('введіть цілі k, L '); readln (k, L);
writeln ('введіть речові r, S, a '); readln (R, S, a);
writeln (ll / (l + sqr (r * a / k)) / (exp (2) / sqr (s) * sqr (l + r * a / l)),
readln; END.
Останній оператор writeln спочатку обчислить арифметичне вираження, а потім виведе на екран його значення у вигляді числа. Якщо ми хочемо, щоб результат був у вигляді 'результат Y = число', то необхідно останній writeln написати в наступному вигляді:
writeln ('результат Y =' ,1-l / (l + sqr (r * a / k)) / exp (2) / sqr (s) * sqr (l + r * a / l)); тоді машина спочатку виведе текст, взятий в апостроф, тобто "Результат Yi", а потім його значення.
2.7. Розділ опису типів
Крім перерахованих вище стандартних типів у Паскалі можуть бути застосовані типи, визначені користувачем, тобто перераховуються та інтервальні типи. Перераховуються типи задаються безпосереднім перерахуванням всіх значень, які може приймати змінна даного типу. Описати типи, визначені користувачем, можна в розділі Var або попередньо в розділі Туре, а потім - в Var. розглянемо обидва варіанти.
Нехай нам потрібна змінна з ім'ям season (сезон року). вона може приймати значення winter (зима), spring (весна), summer (літо), autumn (осінь), інші значення вона приймати не може. Тоді потрібно зробити наступний опис:
Var season: (winter, spring, summer, autumn).
Тут тип season заданий перерахуванням всіх констант, які можуть бути занесені в комірку пам'яті season. Спроба занести в клітинку season будь-яке інше значення призведе до помилки - "невідповідність типу".
Якщо змінних даного типу буде кілька, зручніше і наочніше спочатку визначити тип в розділі Туре (опис типу), а потім у розділі Var послатися на цей тип, і машина в Var виділить конкретні комірки пам'яті для зберігання даних певного типу.
Наприклад, необхідно визначити, що Gi, G2, G3, G4 будуть осередками пам'яті, в яких можуть зберігатися найменування газів З, О, N, F, а в осередках пам'яті Metall1, Metall2, Metall3 - найменування металів Fе, Со, Na, Cu , Zn, тоді можна застосувати опис:
VAR GI, G2, G3, G4: (CO, O, N, F);
Metall1, Metall2, Metall3: (Fe, Co, Na, Cu, Zn).
Можна використовувати і інше, більш наочний опис. спочатку визначити тип Gaz, Met, а потім на них посилатись:
Туре Gaz = (Co, О, N, F);
         Met = (F е, З, Na, Cu, Zn);
Var GI, G2, G3, G4: GAZ;
Metall 1, Metall 2, Metall 3, Met;
Особливо зручне застосування розділу Туре, якщо він знаходиться у зовнішньому блоці, а посилання на нього йдуть у внутрішніх блоках (див. розділ "Блоки"). Тоді значно економиться пам'ять, оскільки вона може бути практично однієї і тієї ж у різних блоках.
При описі змінних перечисляемого типу дані всередині дужок є константами, які може приймати описувана змінна. Над даними такого типу допустимо виконувати операції відносини і логічні операції (див. далі). Наприклад, для наведеного вище опису даного season буде істинним вислів: "winter <spring".
При роботі з даними перечисляемого типу можна застосовувати стандартні функції Succ, Рred, Ord.
Succ (аргумент) повертає значення, наступне за елементом, зазначеним як аргумент. Якщо наступного елемента немає (закінчилися), то це призводить до програмного переривання (помилку).
Рred (аргумент) повертає попереднє значення з переліку констант, з яких складається даний тип.
Ord (аргумент) повертає порядковий номер аргументу в списку констант, перерахованих в описі у вигляді цілого числа. Елементи пронумеровані в порядку 0,1,2 ,..., тобто перший елемент має номер 0.
Приклад:
Туре month = ('jan', 'fab', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'ocf', 'nov', 'dec ');
       Var a, b, c, d, c, mes: month; f, h, g: integer;
Begin mes: = jul;
a: = Pred (mes); {в a знаходиться 'jun'}
b: = Succ (mes); {в b знаходиться 'aug'}
з: = Pred (divd (mes)); {у с знаходиться 'm ау'}
d: = Succ (succ (mes)); {в d знаходиться 'sep'}
e: = Succ (divd (mes)); е знаходиться 'jul'}
f: = Ord (mes); {в f знаходиться 6}
h: = Ord (divd (mes)); {в h знаходиться 5}
g: = Ord (succ (mes)); {в g знаходиться 7}
END
Інтервальний тип задається діапазоном зміни констант усередині якого-небудь вже наявного перечисляемого або стандартного типу, крім речового (integer, byte, booban, char). Значення першої константи повинно бути менше значення другого константи діапазону.
Туре
Dni = 1 ... 31;
Litera = 'a',...,' z',
Var Rabdni, bolndni, vuhod: dni; {можуть приймати значення 1-31}
im, ident: litera; {можуть приймати значення 'A' - 'Z'}
Вихід за межі діапазону викликає програмне переривання.
Допускається завдання діапазону іменами констант:
Const min = 1; max = 31;
Туре Dni = min ... max;
Var rabdni, boldni, vuhoddni: dni;
Для інтервального типу також можливо застосовувати функції S uc c, P red, Ord.

3. Розгалужуються програми

3.1. Загальні положення
До цих пір ми розглядали лінійні програми, алгоритм яких можна було уявити у вигляді блок-схеми (рис. 3.1)
Оператор 1

Оператор 2

Оператор n
Рис. 3.1
Початок

Можливі випадки, коли програма галузиться в залежності від будь-якої умови (див. рис. 3.2). Галуження може бути двох напрямків: за принципом умова вірна - йти по одній гілці, умова помилкова - за іншою. У цьому випадку застосовується оператор if. можливо розгалуження відразу декількох напрямів: якщо k = l - йти по одній гілці, якщо k = 2 - за іншою, k = 3 - по третій і т.д. в цьому випадку зручніше застосовувати оператор Case.
оператор
if
оператор
case
1
2
3
n
...
Рис. 3.2



3.2. Оператор goto, розділ опису міток
Послідовне виконання операторів у програмі може бути порушено оператором переходу. Загальний вигляд оператора: goto мітка; де мітка - буква, або цифра, або набір букв і цифр, з яких перша - завжди буква, Наприклад, М1, LI, NK. Мітка, що стоїть після goto, вказує, куди треба піти. Досягається це тим, що якщо в програмі знаходиться оператор goto мітка; то в цій же програмі обов'язково є який-небудь оператор виду мітка: оператор; який вважається поміченим, і машина, зустрівши goto мітка, і не буде виконувати оператор, записаний після оператора goto мітка ; а перейде до виконання оператора мітка: оператор;
Ілюстрація:
а: = b + с;
з: = sgrt (a + exp (b));
goto M1;
z: = x + y;
writeln (z);
M 1: S: = P;
 

У випадку, якщо б не було оператора goto М1; всі оператори виконувалися б послідовно один за іншим. тут же після оператора з: =... варто goto М1; отже, машина не буде виконувати z :=... і writeln ..., а відразу після з: =... перейде до виконання оператора М: S: = Р;
Мітки, що застосовуються в програмі, повинні бути описані в розділі опису міток, який бажано ставити першим серед описів. Виглядає розділ так: Label М1, М2, L, NK; тобто після слова Label перераховуються через кому все мітки, які будуть застосовуватися в даному блоці (програмі). Закінчується опис символом ';'.
Приклад: скласти програму, яка обчислює значення функції cos х, де початкове х = 0, наступне х = 0.01 і т.д.
          Program Prim3; Label M; Var x: real; BEGIN x: = 0; M: writeln ('x =', x, 'cos x =', cos (x)); x: = x +0.01;
goto M; readln; END.
Програма буде працювати наступним чином: х присвоїти значення 0; writeln виведе на екран текст, який вказаний в перших лапках х =, далі витягне з осередку х значення і виведе його на екран, потім знову виведе текст cos х =, потім обчислить значення cos х і видасть його на екран, тобто машина виведе перший рядок у вигляді
x = 0.0000000000Е + 00 cos х = 9.9999999999Е - 01.
Після цього візьметься то x, яке було вилучено з комірки пам'яті х (колишнє значення х), тобто 0.0, до нього додається величина 0.01 і результат знову занесеться в комірку пам'яті х так, що в х буде 0.01, після цього оператор goto m; передасть управління оператору, позначеного міткою м, тобто оператору writeln, і машина видасть новий рядок:
x = 1.0000000000Е - 02 cos х = 9.9995000041Е - 01;
- Виконає оператор
х: = x + 0.01, отримає х = 0.02;
- Виведе рядок
x = 2.0000000000Е - 02 cos х = 9.9980000666Е - 01;
- Зробить х = 0.03 і т.д., до нескінченності, тому що в даному алгоритмі закінчення роботи не передбачено. Для завершення роботи слід застосувати оператор if.

3.3. Оператор if
Загальний вигляд: If булеве вираз then оператор else оператор;
Робота оператора: спочатку обчислюється булеве вираз, значення якого в кінцевому підсумку може бути тільки TRUE або FALSE. Якщо булеве вираз TRUE, то виконується оператор, наступний за словом then, а потім відбувається перехід до оператора, наступного за if. Якщо булеве вираз false, то виконується оператор, наступний за словом else, потім відбувається перехід до оператора, наступного за оператором if.
Зауваження: після оператора, наступного за then, перед else символ ';' не ставиться, тому що оператор if ще тут не закінчений, а ';' ставиться після закінчення оператора. Можливе застосування скороченого оператора if:
If булеве вираз then оператор;
Тут, якщо булеве вираз true, виконується оператор, наступний за словом then, і відбувається перехід до оператора, наступного за оператором if. Якщо булеве вираз false, то оператор if ігнорується (взагалі не виконується), а виконується оператор, наступний за if.
Переробимо "нескінченну" програму п. 3.2. в таку, яка зупиниться тоді, коли х стане рівним 0.1.
          Program Prim4; Label M; Var x: real;
BEGIN x: = 0;
M: writeln ('x =', x, 'cos x =', cos (x));
x: = x +0.01;
if x <= 0.1 then goto M; readln;
      END.
Програма видає результати обчислень cos (x) для х = 0.01, 0.02, 0.03 і т.д., до 0.01.
В останній програмі булеве вираження х <= 0.1. Які бувають Булевського вираження? Взагалі кажучи, булеве вираз після обчислення завжди істинно або хибно, тобто TRUE або FALSE. Дійсно, вираження х <= 0.1 може бути істинно, якщо х менше або дорівнює 0.1, і хибно - у протилежному випадку. Взагалі булеве вираз може будуватися з булевских констант TRUE і FALSE; змінних булевского типу (в яких можуть зберігатися TRUE або FALSE); звернень до функцій, які повертають TRUE або FALSE і відносин, з'єднаних між собою Булевського операціями і круглими дужками.
Тут слід розшифрувати, що таке ставлення і Булевського операції. Прикладом відношення може бути наведене вище х <= 0.01, тобто в загальному випадку відношення - це два арифметичних вирази, з'єднаних між собою операціями відносини. Операції відносини: = (дорівнює), <> (нерівно),> (більше),> = (більше або дорівнює), <(менше), <= (менше або дорівнює).
Приклад відносин: а + b <= sin (c)
exp (p)> (cos (i) - a) / sgr (b).
Як ми вже говорили, ці відносини можуть бути істинними чи хибними в залежності від конкретного значення величин, в них входять, на момент обчислення.
Логічні операції - це нам вже відомі. Нагадаємо, як вони працюють: or (або), and (і).
Є опис Var A, B: boobean;
Or - логічне додавання, читається як "або". Результат операцій - істина, якщо або А, або В - істина, і брехня, якщо А і B помилкові.
Наприклад: А В А ог У
true true true
true false true
false true true
false false false
Зауваження: дана операція аналогічна арифметичної OR, якщо TRUE замінити 1, а FALSE - 0.
Аnd - логічне множення, читається "і". Результат операції - істина тільки тоді, коли і А, і В - істина, в інших випадках результат - брехня.
А В A and B
true true true
true false false
false true false
false false false
Крім того, зручно застосовувати однокомпонентну операцію Not, яка вводиться таким чином: якщо А є TRUE, то Not А є FALSE і якщо А є FALSE, то Not А є TRUE.
За допомогою цих операцій можна побудувати умови будь-якої складності. Наприклад, нехай необхідно вирішити завдання:


Напишемо програму:
Program Prim5;
Var a, x: real;
BEGIN
writeln ('введіть а, х '); readln (a, x);
if (a> 0) and (x> 0) and (x <= 0.5) then
writeln ('z =', a * ​​sqr (x) / sin (x)) else
if (a> 0) and (x> = 0.5) and (x <3) then
writeln ('z =', exp (x)) else
if (a <= 0) or (x <= 0) then
writeln ('z =', sqrt (a) * sqrt (x) / sin (x)) else
writeln ('z = 0');
readln; END.
Зауваження: в останньому прикладі ми бачимо, що оператори if можуть бути вкладені одна в одну. Вкладати їх можна необмежену кількість разів, причому новий if може починатися як після слова then, так і після слова else.
Ще один приклад: нехай дана область (заштрихована на рис. 3.3). Ми вводимо з клавіатури координати точки. Машина повинна визначити, чи належить дана точка цієї галузі, чи ні.
Розіб'ємо область рис. 3.3 на кілька простих:
1. Внутрішня частина сектора, обмеженого негативною частиною осі OX, позитивної OY і колом з центром у початку координат і радіусом, рівним 2.
Х
4
2
3
1
Y
6
5
0
Рис. 3.3


2. Прямокутник, обмежений осями OX, OY і прямими x = 4, y = 2.
3. Прямокутник, обмежений осями OX, ОУ і прямими x =- 2, y =- 4.
4. Внутрішня частина сектора, обмеженого позитивної частиною осі OX, негативною OY і колом з центром у початку координат і радіусом, рівним 3.
5. Внутрішня частина квадрата, обмеженого прямими лініями x = 2, x = 3, y =- 3, y =- 4.
6. Область, що лежить всередині кола з центром x = 5, y =- 3 та
радіусом = 1,5.
Програма:
Program Prim6;
Label N, K, L;
Var x, y: real; f: char;
  BEGIN N: writeln ('введіть координати точки');
         readln (x); writeln ('x =', x);
readln (y); writeln ('y =', y);
if (x <= 0) and (y> = 0) and (sqr (x) + sqr (y) <= 4) {1 - я область}
or (x> = 0) and (x <4) and (y> = 0) and (y <= 2) {2 - я область}
or (x <= 0) and (x> =- 2) and (y <= 0) and (y> =- 4) {третій область}
or (x> = 0) and (y <= 0) and (sqr (x) + sqr (y) <= 9) {4 - я область}
or (x> = 2) and (x <= 3) and (y <=- 3) and (y> =- 4) {5 - я область}
      or (sqr (x-5) + sqr (y +3) <= 2.25) {6 - а область}
then writeln ('точка з координатами х =', x, 'y =', y, 'належить області')
else writeln ('точка з координатами х =', x, 'y =', y, 'не належить оласті);
L: writeln ('чи будемо ще вводити координати точки?, Y, N'); readln (f);
     if (f = 'Y') or (f = 'y') then goto N else
if (f = 'N') or (f = 'n') then goto K else
     writeln ('неправильно натиснули клавішу, спробуйте ще раз'); goto L;
     K: readln; End.
YYYY
Х
Рис. 3.4
0
полуплоскость
Зауваження: для того, щоб побудувати область, необхідний здоровий глузд та елементарні знання аналітичної геометрії. Так, х> = 0 визначає область (рис. 3.4)
x> = 0 and x <= 4 визначає смугу (рис. 3.5)

4

Y

Рис. 3.5
0
X


Згадавши, що рівняння кола з центром у початку координат x 2 + y 2 = r 2, маємо x 2 + y 2 £ 4 (рис. 3.6),
Х
0
2

Y

Рис. 3.6


x £ 0 є полуплоскость (рис. 3.7),
полуплоскость
Х

Y

Рис. 3.7
0


y ³ 0 визначає полуплоскость (рис. 3.8),
полуплоскость
Х

Y

Рис. 3.8
0


x £ 0 and y ³ 0 є квадрант (рис. 3.9)
квадрант
Х

Y

Рис. 3.9
0


і, нарешті,
x £ 0 and y ³ 0 and sqr (x) + sqr (y) £ 4 є сегмент (рис. 3.10)
сегмент
Х

Y

Рис. 3.10
2
0


3.4. Оператор case (оператор вибору)
Загальний вигляд:
Case вираз - селектор of
Список констант вибору 1: оператор 1;
Список констант вибору 2: оператор 2;
- - - - - - - - - - - - - - - - - - - - - - - - - -
Список констант вибору n оператор n;
else оператор end;
Тут вираз-селектор є вираз, який після виконання має будь-скалярний значення, крім речового (типи даних; розд. 2.6.), Тобто вираз-селектор може бути байтового, цілого, логічного, символьного, що перераховується та інтервального типів.
Список констант вибору складається з переліку констант, розділених комами, або з констант, заданих інтервалом, або з комбінацій переліку констант і інтервалів. Тип констант в списках Case повинен відповідати типу вираження селектор. Значення констант у списках не повинні повторюватися.
Робота оператора. спочатку обчислюється вираз-селектор, потім отримане значення порівнюється з константами вибору, і, якщо значення виразу-селектора збігається з будь-якою константою вибору, то виконується оператор, що стоїть після списку констант, в якому є константа, що збігається зі значенням вирази-селектора. якщо значення виразу-селектора не співпадає ні з однією з констант вибору, то виконується оператор, наступний за else. Else може в Case відсутніми, тоді в разі розбіжності констант оператор Case ігнорується.
Приклади:
1. Селектор цілого типу, список констант представлені переліком констант:



Program Prim7; Var i, z: integer; BEGIN writeln ('введіть ціле i '); readln (i);
Case i of
1,2,5: writeln ('i =', i, 'z =', i +10);
12,16: writeln ('i =', i, 'z =', i +100);
31,35,46: writeln ('i =', i, 'z =', i +1000);
else writeln ('неправильно задано i'); end;
            readln; END.
2. Селектор цілого типу - список констант представлений діапазоном.
вводиться ціле i, визначити, чи знаходиться воно в діапазоні 1-10 або 11-100, або 101-1000, або поза цих діапазонів.
Program Prim8; Var i: integer; BEGIN writeln ('введіть ціле i '); readln (i); Case i of
   1 .. 10: writeln ('число в діапазоні 1-10');
11 .. 100: writeln ('число в діапазоні 11-100');
101 .. 1000: writeln ('число в діапазоні 101-1000');
   else writeln ('число поза діапазону 1-1000 '); end;
readln; END.
3. Селектор цілого типу, список констант представлені переліком констант і діапазоном:

Program Prim9; Var i: integer; x, m, a, b, c, d: real; BEGIN writeln ('введіть значення i '); readln (i); writeln (' введіть значення x, m, a, b, c, d ');
readln (x, m, a, b, c, d);
Case i of
1,2,4,8,11 .. 20,24,28,30: writeln ('y =', (x +1) / (sqr (x) +2)-ln (m) +2 * a / b);
31,45 .. 55: writeln ('y =', (sqr (a) + m) / sqrt (b + m) -3 * a * b / c + d);
58,60,63 .. 76,78,93,100: writeln ('y =', sqr (x)-a * x + sqr (sin (a * x)-exp (x))
/ (1-ln (sqr (x)-exp (х / 2 ))));
else writeln ('неправильно задано i'); end;
            readln; END.
4. Селектор знакового типу:
            Program Prim10; Var name: char;
BEGIN writeln ('введіть шифр '); readln (name);
Case name of
'S', 's': writeln ('факультет літако-і вертольотобудування');
'D', 'd': writeln ('факультет авіадвігателестороенія');
'Y', 'y': writeln ('факультет систем управління ");
'L', 'l': writeln ('факультет літальних апаратів');
'R', 'r': writeln ('факультет радіотехнічний');
'M', 'm': writeln ('факультет інженерно - менеджерський'); 'Z', 'z': writeln ('факультет заочного навчання');
else writeln ('введений шифр не відповідає жодному',
'З факультетів ХАІ'); end; readln; END. 5. Селектор перечисляемого типу:
              Program Prim11; Var season: (winter, spring, summer, autumn); rez: integer; BEGIN season: = spring; Writeln ('результат ord (season) =', ord (season)); case season of winter: writeln ( 'winter');
spring: writeln ('spring');
summer: writeln ('summer');
autumn: writeln ('autumn');
end; readln;
END.

4. Циклічні програми

Найбільш часто в практиці програмування зустрічаються циклічні програми. У циклічних програмах будь-якої алгоритм повторюється багато разів, при цьому один з параметрів змінюється. Наприклад, описана в п. 3.3 програма Рrim 4 є класичним прикладом циклічного алгоритму. Операторів циклу в Паскалі три: for, repeat, while.
4.1. Оператор for
Оператор складається із заголовка, в якому визначається порядок зміни змінної параметра циклу і тіла циклу, що є багато разів повторюється алгоритмом. Загальний вигляд оператора:
for - параметр циклу: = початкове значення to, кінцеве значення do {заголовок}; оператор; {тіло циклу}. Цей оператор застосовується, якщо початкове значення <кінцевого значення;
for - параметр циклу: = початкове значення downto, кінцеве значення do; оператор; застосовується, якщо початкове значення> кінцевого значення.
Приклад: знайти суму квадратів цілих чисел від 8 до 1.24.
          Program Prim12; Var i, s: integer; BEGIN s: = 0; for i: = 8 to 124 do s: = s + sqr (i); writeln ('s =', s); readln;
                      END.
Робота програми. У розділі Var виділяється осередок пам'яті з ім'ям i і s для зберігання величин. Оскільки в S ми повинні накопичувати суму, то спочатку занесемо в S нуль. Потім заголовок циклу присвоює i = 8. далі виконується тіло циклу: витягується вміст комірки S (а там у нас 0) і до цього вмісту додається sgr (i), тобто i 2 = 8 2. Результат присвоюється осередку S, тобто в S тепер 8 2.
Перевіряється, чи не став параметр циклу більше кінцевого значення параметра 128. Це не відбулося, тому i присвоюється наступне значення рівне 9 і знову виконується тіло циклу, тобто S: = 2 серпня +9 2. Можна сказати так: S привласнити тому S, яке було раніше, + наступне i 2. Так як цикл ще не закінчився, то i стане рівним 10, а S привласнити тому S, яке було раніше, тобто 8 лютого +9 2, і до нього додасться ще поточне i 2, тобто 10 2. Цей процес повторюється до тих пір, поки параметр циклу не стане рівним 124. Тоді востаннє 124 2 додається до накопичуваної сумі.
Отже: виконання циклу значення i значення S
1 8 8 2
2 9 8 2 +9 2
3 10 8 2 +9 2 +10 2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116 117 8 2 +9 2 +10 2 + ... +123 2
117 124 8 2 +9 2 +10 2 + ... +123 2 +124 2
При i = 125 відбувається вихід з циклу і перехід до оператора writeln ('S =', S);
Ця, здавалося б, правильно написана програма дає результат S =- 12250. Як може вийти негативний результат при підсумовуванні квадратів - явно позитивних чисел? Такий результат ми отримуємо шляхом підсумовування та занесення результатів у клітинку S типу integer, а в integer можуть бути поміщені числа в діапазоні -32768 +32767, тому після переповнення комірки пам'яті в знаковий розряд переноситься 1, яка інтерпретується машиною як '-'. Щоб цього уникнути, можна описати S як longint. Тоді результат роботи програми буде правильний і дорівнює 643110.
          Program Prim 12 a; Var            i, s: longint;
   BEGIN s: = 0;
for i: = 8 to 124 do
s: = s + sqr (i);
writeln ('s =', s);
              readln; END.
Можна також описати S як real.           Program Prim12b; Var i: integer; s: real;
BEGIN s: = 0;
for i: = 8 to 124 do
s: = s + sqr (i);
writeln ('s =', s);
              readln;
END.
Результат роботи цієї програми буде дорівнює 6.4311000000E +05, що те ж саме, що і 643110, якщо вважати, що запис 6.4311000000E +05 рівносильна математичного запису 6,4311 * 10 +5.
Правила застосування оператора циклу for
1.Тело циклу - завжди один оператор. Якщо потрібно, щоб тіло циклу складалося з декількох операторів, то їх об'єднують в один за допомогою операторних дужок begin, end.
          for i: = l to n do
Begin S: = S + sin (x) / cos (x);
x = x +0.01;
writeln ('S =', S)
       end.
Оператори, взяті в операторні дужки begin, end, вважаються одним складеним оператором.
2. Початкове і кінцеве значення параметра циклу в загальному випадку є виразами. Тип цих висловів та тип параметра циклу повинні збігатися. Тут допускається застосування будь-яких типів, які впорядковані з яким-небудь фіксованим кроком, це може бути будь-який скалярний тип, крім матеріального, тобто байтовий, цілий, символьний, що перераховується, інтервальний, булевський. на практиці найчастіше застосовують цілочисельний тип.
3. У тілі циклу параметр циклу не повинен змінюватися.
4. Не можна за допомогою оператора переходу goto увійти в тіло циклу, минаючи заголовок.
5. Вийти з тіла циклу в програму можна за if .. goto, не чекаючи повного перебору параметрів циклу.
Приклад: написати програму, що виводить букви латинського алфавіту в один бік, з пропуском між ними.
Застосовуємо тут як параметр циклу символьну змінну, як початкове значення параметра - константу 'A', кінцевого - 'Z'.
          Program Prim13;
Var
i: char;
BEGIN
for i: = 'a' to 'z' do
write ('', i);
readln; END.
Приклад: обчислити значення визначеного інтеграла на ділянці a, b для функції cos х, тобто визначити площу, заштрихованную на рис. 4.1.

Х
b
а
Рис. 4.1
0
Y


Застосуємо метод трапецій, суть якого полягає в тому, що область ділиться на ряд трапецій, площі яких обчислюються і сумуються. Чим на більшу кількість трапецій ми розділимо область, тим точніше отримаємо результат (см.ріс.4.2).
Х
b
а
Рис. 4.2
0
Y


Program Prim14;
Var i, n: integer; a, b, x, h, s: real;
BEGIN writeln ('введіть к-сть точок розбиття n і величини а, b');
       readln (n, a, b);
h: = (ba) / n; s: = 0; x: = a;
for i: = 1 to n do
Begin s: = s + (abs (cos (x)) + abs (cos (x + h))) / 2 * h;
x: = x + h; end;
writeln ('s =', s);
                   readln; END.
Зауваження: при обчисленні S (так як функція перетинає вісь OX) частину площ може мати негативне значення, тому ми беремо abs (f (x)).
Ускладнити завдання: нехай потрібно знайти площу криволінійної трапеції (інтеграл), де функція від точки а до b sin (x), а після b до с cos (x).
         Program Prim15;
Var i, n: integer; a, b, c, x, h, s, fxdivd, fxposl: real;
BEGIN writeln ('введіть к-сть точок розбиття n і величини а, b, c');
       readln (n, a, b, c);
h: = (ca) / n; s: = 0; x: = a;
for i: = 1 to n do
   Begin
{Визначимося, по якій з функцій вважати боку трапецій}
   if (x> = a) and (x <= b) then fxdivd: = abs (sin (x)) else
fxdivd: = abs (cos (x));
if (x + h> = a) and (x + h <= b) then fxposl: = abs (sin (x + h)) else
fxposl: = abs (cos (x + h));
s: = s + (fxdivd + fxposl) / 2 * h;
x: = x + h; end;
writeln ('s =', s);
                   readln; END.
В останніх двох програмах ми замінюємо площа криволінійної трапеції (інтеграл) сумою трапецій. При цьому нам невідомо, яку помилку ми допустимо; знаємо, що чим більше точок розбиття, тим точніше буде результат. Поставимо задачу: абсолютно точно знати, що ми порахуємо інтеграл з точністю не менше заданої, наприклад, що різниця між площею криволінійної трапеції та сумою прямокутних трапецій буде не більше Е = 0.01. Для цього нам потрібно порахувати результат для кількості точок, наприклад 10, потім - 100. Порівняти величини площ, і, якщо їх різниця буде менше Е, то можна з упевненістю сказати, що площа для розбиття на 100 інтервалів буде знайдена з точністю не менше Є. Якщо різниця між розрахунками на 10 і 100 інтервалів більше Е, то слід розбити область інтегрування на 1000 інтервалів і порівняти суму для 100 інтервалів з сумою для 1000 інтервалів, і якщо їх різниця буде менше Е, то за результат прийняти площа, порахованих для 1000 розбиттів і т.д. рано чи пізно ми отримаємо позитивний результат. Порівняння сум площ трапецій будемо робити за допомогою оператора if.
Нехай функція буде cos (x). Напишемо програму:
Program Prim16;
Label NAH, KON;
Var i, n: integer; a, b, x, h, sdivd, spos, e: real;
BEGIN writeln ('введіть точність е і межі a, b');
       readln (e, a, b); sdivd: = 9.9e +10; h: = 0; n: = 10;
NAH: spos: = 0; h: = (ba) / n; x: = a;
for i: = 1 to n do
Begin spos: = spos + (abs (cos (x)) + abs (cos (x + h))) / 2 * h;
x: = x + h; end;
if abs (spos-sdivd) <= e then Begin
writeln ('s =', spos, 'n =', n); goto KON; end
else sdivd: = spos; n: = n * 10; x: = a; goto nah;
KON: readln; END.
Робота програми: for i: = i to n do, в перший раз оператор
Sp про s: = spos + (abs (cos (x)) + abs (cos (x + h))) / 2 * h
вважатиме значення інтеграла на 10 точок розбиття. Потім if порівняє отримане значення spos з 9.9Е +10. Звичайно, різниця між цими величинами не буде менше е, тоді ми забудемо число 9.9Е +10, так як привласнимо sdivd: = spоs, щоб при наступному виконанні if порівнювати попереднє і наступне значення інтеграла. Після цього збільшимо кількість точок розбиття n: = n * 10 і повернемося на початок обчислення sp o s, тобто інтеграла для 100 інтервалів goto nach. Після нового обчислення sp o s порівняємо 100 інтервалів для 10 інтервалів sdivd. Якщо різниця між ними не менше Е, то забудемо значення s для 10 інтервалів і занесемо в sdivd значення для 100 інтервалів. Потім обчислимо значення інтеграла для розбиття 1000 і результат занесемо в spos, порівняємо sdivd і spos і т.д.
4.2. Оператор repeat. Загальний вигляд
На відміну від for, оператор repeat (а також while) застосовують тоді, коли невідомо точно, скільки разів буде виконуватися тіло циклу. Загальний вигляд оператора
repeat
оператор;
оператор;
- - - - - - - -
оператор until булеве вираз;
Робота оператора. Спочатку виконуються оператори, складові тіло циклу, потім виконується булеве вираз, і якщо воно помилкове, знову виконується тіло циклу. Вихід з циклу відбувається, коли булеве вираз стане істинним.
Явного перебору параметрів у repeat не передбачено, тому зміна параметрів здійснюється в тілі циклу. Тут же ми повинні подбати, щоб рано чи пізно булеве вираз став істиною.
Зауваження: 1.Тело оператора repeat виконується щонайменше один раз. Оператор repeat ще називають циклом з послеусловіем.
2. Перед until ';' не ставиться.
Приклад: знайти суму парних чисел в інтервалі від 0 до 100.
         Program Prim17;
Var i, s: integer;
BEGIN i: = 0; s: = 0;
repeat
i: = i +2; s: = s + i
until i> 100;
writeln ('s =', s);
        readln; END.
Приклад: знайти струм в ланцюзі змінного струму в залежності від частоти струму. Відомо, що при послідовному з'єднанні активної, ємнісний та індукційної навантажень сила струму може бути обчислена за формулою

Нехай U = 220, R = 100, L = 0.57, С = 3.2 * 10 -3, F початкове = 10; F будемо міняти з кроком 0.5. Друкувати всі результати. Результати, коли i> 3, нас не цікавлять.
         Program Prim 18;
    Var i, r, f, l, c, u: real;
  BEGIN writeln ('введіть значення url c');
          readln (u, r, l, c);
f: = 50;
repeat i: = u / sqrt (sqr (r) + sqr (2 * pi * f * l-1 / (2 * pi * f * c)));
f: = f-1;
writeln ('f =', f, 'i =', i)
until i> 3;
readln; END.
4.3. Оператор While
Оператор While циклу з передумовою.
While - булеве вираз; do - тіло циклу.
Робота оператора. Спочатку обчислюється булеве вираз, і якщо воно істинне, то виконується тіло циклу; якщо воно помилкове, то відбувається вихід з циклу.
Тіло циклу - один оператор, як правило, складовою. Ми повинні подбати про те, щоб булеве вираження в тілі циклу на якомусь етапі стало хибним, інакше цикл ніколи не закінчиться. Цикл можна зробити умисне нескінченним, написавши: while true do оператор;
Ми будемо застосовувати цю конфігурацію при написанні програм обробки файлів.
Приклад: знайти суму парних чисел в інтервалі від 0 до 100.
         Program Prim19;
Var i, s: integer;
BEGIN i: = 0; s: = 0;
while i <100 do
Begin i: = i +2; s: = s + i; end;
writeln ('s =', s);
readln; END.
Приклад: у колі змінного струму знайти струм в залежності від його частоти.

Program Prim20;
Var i, r, f, l, c, u: real;
  BEGIN writeln ('введіть значення u, r, l, c');
          readln (u, r, l, c);
f: = 50;
while i <3 do
Begin i: = u / sqrt (sqr (r) + sqr (2 * pi * f * l-1 / (2 * pi * f * c)));
f: = f-1;
writeln ('f =', f, 'i =', i); end;
writeln ('i> 3, i =', i);
                     readln; END.
4.4. Вкладені цикли
Оскільки тіло будь-якого циклу складається з операторів або складеного оператора, то ніщо не перешкодить у тілі циклу розташовувати інші оператори циклу. Розглянемо роботу програми:
Program Prim21;
Var
i, j: integer;
BEGIN
for i: = 1 to 5 do
Begin writeln;
for j: = 20 to 23 do
write ('i =', i, 'j =', j);
end;
readln; END.
Для циклу for i: = 1 to 5 do тілом циклу є
begin for j: = 20 to 23 do
write ('i =', i, ', j =', j);
  writeln;
end;
Назвемо цей цикл зовнішнім. Крім того, є внутрішній цикл
for j: = 20 to 23 do з тілом write ('i =', i, j = ', j);
Робота програми. Спочатку машина зустрічає зовнішній цикл і починає його виконувати: присвоює i = l, потім переходить до його тіла, а тут зустрічає внутрішній цикл і привласнює j значення 20, після чого виконує тіло внутрішнього циклу, тобто виводить на екран i = l, j = 20. Так як внутрішній цикл ще не закінчена, то машина продовжує його виконувати, тобто присвоює j значення 21 і додає до вже виведеної рядку i = l, j = 21.
Зауважимо, що оператор write відрізняється від оператора writeln тим, що він не починає виведення з нового рядка, а продовжує писати в тому ж рядку, тобто після другого виконання внутрішнього циклу на екрані з'явиться
i = 1, j = 20 i = 1, j = 21.
Машина продовжить виконання внутрішнього циклу, і, коли він закінчиться (виконається для j = 20.21.22.23), на екрані буде рядок
i = 1 j = 20 i = lj = 21 i = 1 j = 22 i = 1 j = 23.
Внутрішній цикл закінчиться, проте тіло зовнішнього циклу ще не закінчилося, тому виконується оператор writeln, який переводить курсор на новий рядок. Після цього тіло зовнішнього циклу закінчиться, але сам цикл відпрацював тільки для i = 1. Тому зовнішній цикл продовжить роботу, присвоївши i: = 2 і знову почавши виконання свого тіла. Зустрівши внутрішній цикл j: = 1, на екран з нового рядка виведеться: i = 2, j = 20, потім j: = 2 і до цієї рядку додасться i = 2, j = 21 і т.д., поки не закінчиться внутрішній цикл.
Таким чином, зовнішній цикл, змінюючи i від 1 до 5, змусить кожного разу виконуватися повністю внутрішній цикл, і в результаті роботи програми на екрані з'явиться:
i = l, j = 20 i = 1, j = 21 i = 1, j = 22 i = 1, j = 23
i = 2, j = 20 i = 2, j = 21 i = 2, j = 22 i = 2, j = 23
i = 3, j = 20 i = 3, j = 21 i = 3, j = 22 i = 3, j = 23
i = 4, j = 20 i = 4, j = 21 i = 4, j = 22 i = 4, j = 23
i = 5, j = 20 i = 5, j = 21 i = 5, j = 22 i = 5, j = 23
Вкладати цикли один в одного можна будь-яку кількість разів, необхідно лише пам'ятати, що кількість виконань самого внутрішнього тіла циклу при цьому буде рости в геометричній прогресії. Так, наприклад,
for i: = l to 100 do
for j: = l to 100 do
for k: = l to 100 do
writeln (i, j, k);
дає стовпчик цифр:
111
112
113
114
- - - - -
121
122
123
124
- - - - -
211
212
213
- - - - -
100100100,
що становить 1000000 рядків.
Приклад: знайти rez = f (х 1) + f (х 2) + .. . + F (x 6),
де
f (x) вважати з точністю не менше e = 0.01;
х 1 = 0.1, потім x n = x nl +0.2, поки х не стане рівним 1.1.
Нам потрібно обчислити rez. Оскільки це буде сума, то спочатку покладемо rez = 0, потім обчислимо f (х 1) з потрібною точністю і додамо до rez, і т.д., тобто:
Rez: = 0; x: = 0.l;
for i: = l to 6 do
Begin Rez: = Rez + f (x);
x: = x +0.2;
end;
Тепер у дану програму потрібно "вставити" обчислені f (x) з необхідною точністю. Для цього знайдемо суму, що становить f (x) для n елементів, потім - для n + l елемента, порівняємо їх по модулю і, коли різниця між ними буде менше Е, суму для n + l елемента низки приймемо за більш точну і додамо до Rez. При обчисленні f (x) кількість членів ряду, які нам доведеться підсумувати, не відомі, тому доведеться застосовувати цикл типу repeat або while. Крім того, в елементи ряду входить 2n! Факторіал підраховується за схемою 1! = 1, 21 = 1 * 2; ж! = 1 * 2 * 3 і т.д., тобто наприклад, 8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8. Далі, при підрахунку наступного значення ряду, можна величину 2n! знайти за схемою: fak: = fak * (nl) * n. Ряд у нас знакозмінний, тобто змінюється '+', '-' перед кожним членом ряду. Міняємо знак за допомогою схеми znak: = znak * (-1). Якщо вихідний знак = + l, то в комірці znak буде зберігатися то + l, то -1.
З урахуванням сказаного вище f (x) з потрібною точністю обчислюється:
fxdivd: = 0; fxpos: = l, n: = 2; znak: = 1; fak: = 1;
while Abs (fxpos - fxdivd)> = 0.01 do
Begin fxdivd: = fxpos: znak: = znak * (-1); fak: = fak * (nl) * n;
fxpos: = fxpos + znak * exp (n * in (x)) / fak;
n: = n +2;
     end;
Поєднавши обидва фрагмента програми і забезпечивши їх описами, отримаємо готову програму:
        Program Prim22;
Var n, fak, i, znak: longint;
rez, x, fxdivd, fxpos: real;
BEGIN rez: = 0; x: = 0.1; writeln;
for i: = 1 to 6 do
Begin fxdivd: = 0; fxpos: = 1; n: = 2; znak: = 1; fak: = 1;
while abs (fxpos-fxdivd)> = 0.001 do
Begin znak: = znak * (-1); fak: = fak * (n-1) * n;
fxdivd: = fxpos;
fxpos: = fxpos + znak * exp (n * ln (x)) / fak; n: = n +2;
end; writeln ('x =', x * 180/pi, '(ја ¤) cos (x) =', fxpos);
x: = x +0.2; rez: = rez + fxpos; end;
writeln ('rez =', rez);
readln; END.

5. Введення - висновок

5.1. Загальні положення
Введення-виведення виконується за допомогою операторів read, readln - читати і write, writeln - писати. Читати і писати визначається по відношенню до оперативної пам'яті (ОП). Так, read, readln - читати, тобто вводити із зовнішнього пристрою (файлу) і заносити дані в ОП, write, writeln - писати, тобто виводити дані з ОП на зовнішній файл (пристрій). Файл складається з компонент, структура яких визначається при його створенні.
Зовнішніми пристроями (файлами) можуть бути: екран монітора, клавіатура, пам'ять на гнучких дисках, пам'ять на жорсткому або лазерному дисках, лінії зв'язку і т.п. У операторах вводу-виводу вказується ім'я файлу, з яким буде здійснюватися введення-виведення, цей файл вважається логічним. Крім того, є поняття фізичного файлу. Фізичний файл - це пристрій, Наприклад, гнучкий магнітний диск, жорсткий диск і т. д. Логічний файл має ім'я, яке можна вказувати в операторах вводу-виводу.
5. 2. Введення
Введення проводиться за допомогою операторів read або readln.
Формат операторів: read (FV, х 1, х 2, ..., х n);
або readln (FV, х 1, х 2, ..., х n);
де FV - ім'я файлу, з якого зчитується інформація, а х 1, х 2 і т.д. - Комірки пам'яті, в які заноситься інформація, прочитується з файлу. Якщо FV відсутній, то читання проводиться з клавіатури. Файл представляє собою як би стрічку з компонентами (рис 5.1):
1 комп.
2 комп.
3 комп.
n комп.
- - - - - - - - - - - - - - - - -
Рис. 5.1


Компонента може бути даними будь-якого типу (див. с.9). Оператор readln починає зчитування з початку нової компоненти, а read може починати не з початку. Якщо колишнє читання закінчилося всередині компоненти, то наступний read буде читати з того місця, на якому закінчився попереднє читання (рис. 5.2).
1-е дане
2-е дане
Третій дане
3,2
8,6
3,2
7,01
8,3
0,61
1-а компонента
2-я компонента
Рис. 5.2
1-е дане
2-е дане
Третій дане


У даному випадку файл організований на будь-якому носії (наприклад на диску) і складається з компонент, в кожній знаходиться по три даних. Якщо для читання з файлів застосувати оператори read (a, b); read (c, d); то в пам'яті буде а = 3.2, b = 8.6, c = 0.2, d = 7.01; якщо - оператори readln (a, b) ; readln (c, d), то в пам'яті а = 3.2, b = 8.6, c = 7.01, d = 8.3.
Зауваження. При читанні даних з клавіатури необхідно завжди використовувати оператори readln 1, х 2, ..., х n); (без вказівки імені файлу).
5. 3. Висновок
Висновок проводиться за допомогою операторів write або writeln.
Формат операторів: write (FV, x1, x2, ..., xn);
    writeln (FV, x1, x2, ..., xn);
Робота оператора: у файл з ім'ям FV виводиться інформація з комірок оперативної пам'яті x1, x2, ..., xn. Якщо FV відсутня, висновок виробляється на екран монітора. При цьому оператор write починає виведення в те місце компоненти файлу, де був закінчений колишній висновок, а оператор writeln почне виведення з початку нової компоненти. Проілюструємо роботу цих операторів на прикладі виведення даних на екран монітора.
Є фрагмент програми (нагадаємо, що текст у дужках {} є коментарем і машиною не сприймається);
  Var a, b, c, d: integer;
Begin a: = 25; b: = 38; c: = 126; d: = 256;
writeln (a, b, c, d); {результат 2538126256}
writeln (a, b); writeln (c, d); {результат 2538}
{126256}
   writeln ('a =', a, 'b =', b); {результат a = 25 b = 38}
  {Символи в апострофа виводяться як рядкова константа}
  write (a, b, c, d); {результат 2538126256}
write (a, b); write (c, d); {результат 2538126256}
write ('a =', a, 'b =', b);
  write ('c =', c, 'd =', d); {результат a = 25 b = 38 c = 126 d = 256}
5. 4. Деякі можливості введення-виведення
Оператор Readln; (без дужок, імені файлу та списку елементів пам'яті) викличе зупинку машини. Продовження виконання програми відбудеться після натискання кнопки Enter. Це дуже зручно при перегляді будь-яких проміжних результатів, наприклад:
writeln ('a =', a); Readln;
Машина виведе а =. . . і зупиниться, після натискання кнопки Enter виконання програми продовжиться.
Оператор writeln; викличе перехід до нової компоненті, у разі виведення на екран - до нового рядка екрану. Розглянемо фрагмент програми:
  Var i, k; integer;
Begin i: = 126; k: = 1997;
writeln ('i =', i, 'k =', k); {результат i = 126 k = 1997}
   writeln (i: 3, k: 6); {результат 126 тисяча дев'ятсот дев'яносто сім}
{Числа, зазначені після: визначають поле виводу, при виведенні}
{Дане "притискається" у полі до правого краю 1997}
writeln (i: 7, k: 8); {результат .... 126 .... 1997}
Приклад:
Program Prim23; Var r, pl: real; BEGIN writeln ('введіть радіус кулі'); readln (r); pl: = 4 * pi * sqr (r); writeln ('____________________________________________________'); writeln ('! Площа кулі рад.r = ', r: 14,' = ', pl: 14 ,'!'); writeln ('____________________________________________________');
readln; END.
У результаті на екран виведеться інформація:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
! площа кулі радіусом R = ХХХХХХХХХХХХХХ = ххххххххххххххх!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Тут ХХХХХХХХХХХХХ - зображення чисел.
За допомогою такого прийому будуються різні таблиці.
При виведенні величини Real в операторах write і writeln відводиться поле шириною 18 символів для виведення даних з "плаваючою точкою" в наступному форматі .. х.ххххххххххЕ * хх; тут х - цифри, * - знак, який може бути "+" чи ' - ','. ' - Десяткова крапка, що відокремлює цілу частину від дробової. Перед цілою частиною, у разі негативного даного, може стояти знак мінус.
Таким чином:
в пам'яті машини вид оператора результат
R = 715.432 writeln (R); 7.1543200000E +02
R =-1.919e +01 writeln (R);-1.9190000000E +01
R = -567.986 writeln (R);-5.6798600000E +02
Нагадуємо: Е +02 означає 10 2, а 7.1543200000Е +02 рівносильно математичного запису 7.15432 * 10 2.
Ширину поля висновку можна вказувати для даних будь-якого типу, наприклад:
в пам'яті машини вид оператора результат
R = 511.04 writeln (R: 22); ...... 5.1104000000E +02
ch = 'x' writeln (ch: 3); .. x
ch = '!' writeln (ch: 2, ch: 4, ch: 3); .!...!..!
strin = 'Day N' writeln (strin: 8); ... Dau.N
S = 'RDD' writeln (S: 5, S: 5); .. RDD .. RDD
Для даних типу Real можна ще вказувати крім ширини поля також кількість цифр після десяткової точки.
Висновок даних з "фіксованою точкою".
в пам'яті машини вид оператора результат
R = 511.04 writeln (R: 8: 4); 511.0400
R = -46.78 writeln (R: 7: 2); .- 46.78
R = -46.78 writeln (R: 9: 4); .- 46.7800
R = -46.78 writeln (R: 12: 3); .....- 46.780
Program Prim24;
Var r1, r2: real;
BEGIN r1: =- 46.78; r2: =- 46.78;
writeln ('r1 =', r1: 12:3, 'r2 =', r2: 9:4);
writeln ('_______________________________');
readln; END.

6. Масиви

6. 1. Опис масивів
У мові Паскаль можна обробляти не тільки окремі змінні, але і їх сукупності. Однією з таких сукупностей (структурованих) даних є масив. Масив - це впорядкована сукупність даних, що складаються з фіксованої кількості елементів одного і того ж типу. Тип елементів, з яких складається масив, може бути як скалярним, так і структурованим. Цей тип називається базовим, їм може бути цілий, байтовий, логічний, символьний, що перераховується, інтервальний, речовий, множинний типи і т. д.
Масиви можуть бути одномірні:
вектор a 1, a 2, a 3, a 4, a 5, ... a n, тобто лінійка величин - - - - - - - - - - - -
двовимірні масиви являють собою матриці:
a 11 a 12. . . a 1n, тобто матрицю величин або прямокутник величин
a 21 a 22. . . a 2n ---- ---- ----
- - - - - - - - - - ---- ---- ----
a m1 a m2. . . a mn ---- ---- ----
Тривимірний масив - тривимірна матриця або паралелепіпед величин, що складається з набору двовимірних матриць (рис.6.1).
Рис. 6.1


Лінійка тривимірних масивів складає чотиривимірний масив, матриця тривимірних масивів (паралелепіпедів величин) - пятімерний масив і т. д. Кількість розмірностей не обмежена, однак слід пам'ятати про те, що кількість елементів у масиві зростає в геометричній прогресії від кількості розмірності.
Опис масивів може бути, як і інших величин, пряме або через опис типів Тype.
Пряме опис Var - ідентифікатор, ідентифікатор, ..., ідентифікатор:
array - [кордону індексу, межі індексу, ..., межі індексу] of - базовий тип.
Опис через TYPE:
TYPE - ім'я типу = array [кордону індексу, межі індексу,. . ., Межі індексу] of базовий тип;
Var - ідентифікатор, ідентифікатор,. . . , Ідентифікатор: ім'я типу;
Приклад: описати двовимірні масиви з кількістю елементів 4 рядки по 5 елементів у кожному рядку (5 шпальт),
базовий тип real, масивів три: а, b, c.
Пряме опис:
Var a, b, c: array [1. . . 4, 1. . . 5] of real;
через TYPE:
TYPE mas = array [1. . . 4, 1. . . 5] of real;
Var a, b, c: mas;
Для вказівки меж масиву можна застосовувати попередньо описані константи:
Const a1 = 4; a2 = 6;
Var mas y1: array [1. . . a1, 1. . . a2] of integer;
Доступ до елементів масиву здійснюється через змінні з індексами. Індекси повинні не виходити за межі кордонів в описах масиву.
Наприклад, описана ma: array [1. . . 12] of integer; виділено 12 комірок пам'яті для зберігання цілих даних типу integer з іменами
ma [1], ma [2], ma [3], і т. д. , Ma [12].
Приклад:
TYPE klass = (K1, K2, K3, K4);
znak = array [1. . . 255] of char;
Var m1: znak; {описаний масив з ім'ям M1 типу znak для зберігання даних}
{Типу char в кількості 255 шт. M1 [1], M1 [2], ... , M1 [255]}
M2: array [1 ... 60] of integer {пряме опис, описаний масив з ім'ям}
{M2 для зберігання цілих величин. всього}
{Осередків 60.M2 [1], ... , M2 [60]}
M3: array [1 ... 8] of klass; {описаний масив М3, виділено 8 осередків пам'яті М3 [1], ... , M3 [8],}
{В кожній з яких можуть зберігатися тільки величини з}
{Klass, тобто туди можуть бути занесені тільки K1, K2, K3, K4}
Приклад:
           Program Prim25;
Var i: integer; s: real;
a: array [1 .. 10] of real;
BEGIN
for i: = 1 to 10 do
      Begin writeln ('введіть значення величини a [', i ,']');
  readln (a [i]); end; {введення елементів масиву}
s: = 0;
for i: = 1 to 10 do
s: = s + a [i]; {знаходження суми елементів а [i]}
    writeln ('s =', s); readln;
                                END.
Тут ми проілюстрували роботу з одномірним масивом. Звичайно, дану програму легше представити в наступному вигляді:
          Program Prim25a;
Var i: integer; s, a: real;
BEGIN
s: = 0;
for i: = 1 to 10 do
      begin writeln ('введіть значення величини a [', i ,']');
readln (a); {введення по одному а (без масиву)}
{Імітація введення елементів масиву}
      s: = s + a;
    writeln ('s =', s); end;
      readln; END.
Ніяких масивів тут не застосовувати. На прикладі prim25 ми чітко простежимо два моменти: занесення даних у масив (перший цикл) і обробка даних у масиві (другий цикл).
Приклад: дана квадратна матриця. Вивести на екран елементи її головної діагоналі (елементи головної діагоналі перекреслені)
a 11 a 12 a 13 a 14
a 21 a 22 a 23 a 24
a 31 a 32 a 33 a 34
a 41 a 42 a 43 a 44
Якщо прийняти, що індекс рядків i, а стовпців j, то на головній діагоналі лежать елементи, у яких i = j.
           Program Prim26;
Var i, j, k: integer;
a: array [1 .. 4,1 .. 4] of integer;
b: array [1 .. 4] of integer;
BEGIN
for i: = 1 to 4 do
for j: = 1 to 4 do
Begin writeln ('введіть a [', i ,',', j ,']');
readln (a [i, j])     end; {введення елементів масиву а закінчений}
k: = 1; {встановлюємо індекс для занесення b [1]}
     for i: = 1 to 4 do
for j: = 1 to 4 do
if i = j then Begin b [k]: = a [i, j]; k: = k +1; end;
{Відшукуємо і заносимо в b [1] a [1,1]}
{Міняємо k і заносимо в b [2] a [2,2] і т.д.}
writeln ('на головній діагоналі лежать злементи:');
    writeln ('a [1,1] =', b [1], 'a [2,2] =', b [2], 'a [3,3] =', b [3], 'a [ 4,4] = ', b [4]);
      readln;
END.
У цій програмі машина запросить введення 16 елементів матриці А, знайде елементи головної діагоналі, занесе їх в масив B і надрукує результат у наступному вигляді:
на головній діагоналі лежать елементи:
A [1,1] = число A [2,2] = число A [3,3] = число A [4,4] = число
                       Program Prim26a; Var i, j, k: integer; a: array [1 .. 4,1 .. 4] of integer; b: array [1 .. 4] of integer; BEGIN for i: = 1 to 4 do
for j: = 1 to 4 do
Begin writeln ('ввести a [', i ,',', j, ']');
      readln (a [i, j]); end; {ввести масив а}
{Вивести елементи масиву а}
     for i: = 1 to 4 do Begin writeln; {перевести курсор на нову рядок}
for j: = 1 to 4 do
     write (a [i, j], ''); {вивести елементи в один рядок}
  end;
k: = 1;
for i: = 1 to 4 do
for j: = 1 to 4 do
if i = j then Begin b [k]: = a [i, j]; k: = k +1; end;
                             {Відшукуємо і заносимо в b [1] a [1,1]}
{Міняємо k і заносимо в b [2] a [2,2] і т.д.}
writeln ('на головній діагоналі лежать елементи:');
    writeln ('a [1,1] =', b [1], 'a [2,2] =', b [2], 'a [3,3] =', b [3], 'a [ 4,4] = ', b [4]);
      readln;
END.
Ця програма відрізняється від попередньої тим, що вона спочатку вводить масив А, потім його роздруковує у вигляді
a 11 a 12 a 13 a 14
a 21 a 22 a 23 a 24
a 31 a 32 a 33 a 34
a 41 a 42 a 43 a 44
а після виводить результати в тому ж вигляді, що й програма Prim26, тобто
           Program Prim26b;
Var i, j, k, n: integer;
a: array [1 .. 40,1 .. 40] of integer;
b: array [1 .. 40] of integer;
  BEGIN writeln ('введіть розмірність масиву');
          readln (n);
for i: = 1 to n do
for j: = 1 to n do
Begin writeln ('введіть a [', i ,',', j ,']');
readln (a [i, j]); end;
                             {Вивести елементи масиву а}
     for i: = 1 to n do
Begin writeln; {перевести курсор на новий рядок}
        for j: = 1 to n do
     write (a [i, j], ''); {вивести елементи в одну рядок}
  end;
k: = 1;
for i: = 1 to n do
for j: = 1 to n do
if i = j then Begin b [k]: = a [i, j]; k: = k +1; end;
                             {Відшукуємо і заносимо в b [1] a [1,1]}
{Міняємо k і заносимо в b [2] a [2,2] і т.д.}
writeln ('на головній діагоналі лежать елементи:');
    for k: = 1 to n do
write ('a [', k ,',', k ,']=', b [k]);
      readln;
END.
Ця програма працює так само, як і попередня, але з масивами і зі змінними вимірами.
Величина вхідного масиву може бути до 40 рядків і 40 стовпців. Щоб це забезпечити, в розділі Var описуємо масив a: array [1 .. 40,1 .. 40] of integer; а потім в програмі вводимо за запитом n, яке буде визначати, з матрицею якої величини ми будемо працювати конкретно (n повинно бути в діапазоні 1-40). Далі всі цикли програми працюють від 1 до n, тобто машина вирішить завдання для масиву введеної розмірності n.
           Program Prim27;
Var i, j, k, n: integer;
a: array [1 .. 40,1 .. 40] of integer;
b: array [1 .. 40] of integer;
BEGIN writeln ('ввести n'); readln (n);
for i: = 1 to n do
for j: = 1 to n do
Begin writeln ('ввести a [', i ,',', j ,']');
readln (a [i, j]); end;
                             {Вивести елементи масиву а}
     for i: = 1 to n do
Begin writeln; {перевести курсор на новий рядок}
        for j: = 1 to n do
     write (a [i, j], ''); {вивести елементи в одну рядок}
  end;
k: = 1;
for i: = 1 to n do
for j: = 1 to n do
if i + j-1 = n then Begin b [k]: = a [i, j]; k: = k +1; end;
{Відшукуємо і заносимо в b [1] a [1,1]}
{Міняємо k і заносимо в b [2] a [2,2] і т.д.}
writeln;
writeln ('на додатковому діагоналі лежать елементи:');
    for k: = 1 to n do
write (b [k], '');
      readln;
END.
Програма Prim 27 працює аналогічно програмі Prim 26b, проте виводить елементи, що лежать на додатковому діагоналі.
        Program Prim28;
Var i, j, min, m, n, k: integer;
a: array [1 .. 20,1 .. 10] of integer;
b: array [1 .. 10] of integer;
BEGIN writeln ('ввести m, n'); readln (m, n);
     for i: = 1 to m do {m - кількість рядків}
for j: = 1 to n do {n - кількість стовпців}
Begin writeln ('ввести a [', i, ',', j ,']');
readln (a [i, j]); end;
                             {Вивести елементи масиву а}
     for i: = 1 to m do
  Begin writeln;
for j: = 1 to n do
write (a [i, j], ''); end;
  min: = 32767; {максимальне integer, щоб у подальшому порівнювати}
{І заносити до min всі елементи a [i, j], які менше min}
     for i: = 1 to m do
for j: = 1 to n do
if a [i, j] <min then Begin min: = a [i, j]; k: = i; end;
  writeln ('рядок, що містить найменший елемент');
    for j: = 1 to n do
write ('a [', k ,',', j ,']=', a [k, j]);
      readln; END.
Програма Prim 28 знаходить в масиві рядок розміром до 20х10, містить найменший елемент.
  Program Prim29;
Var i, j: integer; a: array [1 .. 5, 1 .. 7] of integer;
b: array [1 .. 7] of integer;
c: array [1 .. 5] of integer;
BEGIN for i: = 1 to 5 do
for j: = 1 to 7 do
begin writeln ('введіть a [', i ,',', j, '] елемент матриці а ');
readln (a [i, j]); end;
for j: = 1 to 7 do
begin writeln ('введіть b [', j, '] елемент вектора b ');
            readln (b [j]); end;
for i: = 1 to 5 do {початок перемноження матриці на вектор}
  begin c [i]: = 0;
for j: = 1 to 7 do
c [i]: = c [i] + a [i, j] * b [j]; end;
{Кінець перемноження матриці на вектор}
     writeln ('роздруківка масиву а ');
       for i: = 1 to 5 do
          begin writeln; {почати новий рядок}
       for j: = 1 to 7 do
write ('', a [i, j]); end; writeln;
       writeln ('роздруківка масиву b ');
          for j: = 1 to 7 do
write ('', b [j]); writeln;
     writeln ('результуючий масив з ');
          for i: = 1 to 5 do
write ('', c [i]);
             readln; END.
Програма вводить матрицю А розміром 5х7 і вектор розміром 7 елементів, потім їх перемножує за правилом Сi = Сi + a [i, j] * b [j] і виводить п'ять елементів масиву С.
Зауважимо, що для обчислення кожного з необхідно кожен елемент рядка масиву a помножити на відповідний по індексу елемент масиву b, а потім всі ці твори скласти. таким чином, кількість елементів масиву з дорівнюватиме кількості рядків матриці a (і, відповідно, кількості елементів масиву b).
  Program Prim29a;
Var i, j, n, m: integer; a: array [1 .. 50,1 .. 70] of integer;
b: array [1 .. 70] of integer;
c: array [1 .. 50] of integer;
   BEGIN writeln ('ввести кількість рядків і стовпців');
          readln (n, m);
for i: = 1 to n do
for j: = 1 to m do
begin writeln ('ввести a [', i ,',', j, '] елемент матриці а ');
readln (a [i, j]); end;
for j: = 1 to m do
begin writeln ('ввести b [', j, '] елемент вектора b ');
            readln (b [j]); end;
for i: = 1 to n do {початок перемноження матриці на вектор}
  begin c [i]: = 0;
for j: = 1 to m do
c [i]: = c [i] + a [i, j] * b [j]; end;
                           {Кінець перемноження матриці на вектор}
     writeln ('роздруківка масиву а ');
       for i: = 1 to n do
          Begin writeln; {почати новий рядок}
       for j: = 1 to m do
write ('', a [i, j]); end; writeln;
     writeln ('роздруківка масиву b ');
          for j: = 1 to m do
write ('', b [j]); writeln;
     writeln ('результуючий масив з ');
          for i: = 1 to n do
write ('', c [i]);
             readln; END.
Програма Prim 29a теж перемножує матрицю на вектор. Тут матриця може мати розміри до 50х70, відповідно вектор B може мати розмір до 70, а вектор С - розмір до 50 елементів.

7. Підпрограми

7.1. Загальні положення
1-а група операторів
Знаходження коренів ах 2 + bx + c = 0
2-я група операторів
Знаходження коренів sz 2 + tz + p = 0
3-тя група операторів
Знаходження коренів sz 2 + tz + p = 0
Рис. 7.1.
У практиці програмування часто зустрічаються ситуації, коли одну й ту ж групу операторів необхідно виконати в різних місцях програми, неважливо, що при цьому по-різному будуть називатися вихідні дані та результати роботи цих операторів. Важливо, що ці групи операторів виконують одну й ту ж роботу. Наприклад, у різних місцях програми необхідно обчислити корені квадратного рівняння, причому в одному місці це буде рівняння ax2 + bx + c = 0, в іншому - sz2 + tz + p = 0, у третьому - ky2 + ly + n = 0 і т . д. У цьому випадку алгоритм обчислення коренів рівняння в програмі можна писати один раз у вигляді підпрограми, а використовувати його багато разів. Блок-схема такої програми без застосування підпрограми зображена на рис. 7.1.
1-а група операторів
2-я група операторів
3-тя група операторів
Знаходження коренів квадратного рівняння ax 2 + bx + c = 0
Рис. 7.2
a, b, c
s, t, p
k, l, n
x 1, x 2
z 1, z 2
y 1, y 2
Блок-схема алгоритму з використанням підпрограми зображена на рис. 7.2.
Підпрограмою називається має ім'я логічно закінчена група операторів (можливо зі своїми описами), до якої на ім'я можна звернутися для виконання необмежену кількість разів з різних місць основної програми, можливо, з різним, але фіксованим набором вхідних величин і результатів. Підпрограми можуть бути оформлені у вигляді функцій і процедур.
Функції застосовують тоді, коли результат роботи підпрограми один. Звернення до функції може записуватися у виразах, наприклад: (а + b) / cos (x). Тут cos (x) є звернення до підпрограми типу "функція", правда, стандартної, а не написаної користувачем. Зустрівши ім'я cos, машина з вхідною величиною x звертається до підпрограми, обчислює за допомогою ряду функцію cos (x) (див. програму в підрозділ. 4.4.), І результат цієї роботи у вигляді значення функції повертається в арифметичне вираз. Функція може мати декілька вхідних параметрів, але завжди один результат. Процедура також може мати декілька вхідних параметрів, але кілька результатів. Кілька - це 0, або 1, або 2, або 3 і т.д. результатів. Звернення до процедури складається з окремого оператора. Наприклад, звернення до процедури, що обчислює коріння квадратного рівняння, може мати вигляд: root (a, b, c, x 1, x 2);
Підпрограми, як функції, так і процедури можуть бути стандартними, наприклад sin (x), cos (x), sqrt (x), succ (y), ord (y) і т.п.; бібліотечними, які стають доступними при підключенні модулів і бібліотек (див. далі), а також визначені користувачем, тобто написані програмістом для вирішення свого завдання.
7.2. Підпрограми-функції, визначені користувачем
Функції користувача описуються в розділі опису функцій і процедур основної програми. Опис функції будується як закінчена програма, тобто може складатися із заголовка і шести розділів: опису, міток, констант, типів, змінних, функцій і процедур та розділу операторів. Закінчується опис функції символом крапка з комою.
Написати програму, яка обчислює за допомогою підпрограми-функції, вираз:
f1 (x) = x +256.4; f2 (y) = y +256.4; f3 (z) = z +256.4;
Program Prim30;
Var
x, y, z, f1, f2, f3: real;
function f (x: real): real; {заголовок функції;}
                                  {F - ім'я функції, це ж і ім'я}
{Результату, х - формальний параметр}
Begin f: = (x +256.4); end; {тіло функції}
BEGIN {початок основної програми}
writeln ('ввести x, y, z'); readln (x, y, z);
f1: = f (x); {звернення до підпрограми f з фактичним параметром x}
f2: = f (y); {звернення до підпрограми f з фактичним параметром y}
f3: = f (z); {звернення до підпрограми f з фактичним параметром z}
          writeln (f1: 20, f2: 20, f3: 20); readln; END.
Написати програму, яка обчислює G:

Оформимо обчислення у вигляді підпрограми-функції:
      Program Prim31;
Var h, x, y, z, g: real;
  function f (a, b: real): real; {вхідні формальні параметри a, b}
Begin
f: = sqr (ln (a) + sin (b)) / (cos (a) * exp (b));
                              end;
BEGIN writeln ('введіть позитивні h, x, y, z');
        readln (h, x, y, z);
if (x> = 1) and (x <3) then writeln ('g =', h + f (x, y)) else;
if (x> = 3) and (x <5) then writeln ('g =', sqrt (h) + f (z, x)) else;
if (x> = 5) and (x <= 9) then writeln ('g =', sqr (h) + f (y, z)) else;
writeln ('g = 0');
             readln; END.
У цій програмі опис формули починається словом function, ім'я функції f, результат обчислення функції типу real. Тіло функції укладено в операторні дужки begin, end; a, b називаються формальними параметрами. У даній функції нам не знадобилися розділи описів.
При виконанні основної програми, яка починається begin, зустрічається вираз f (x, y). Зустрівши такий вираз, машина на ім'я f визначає, що це звернення до функції. потім машина перевіряє збіг кількості і типу фактичних параметрів (x, y) з формальними (a, b). При їх збігу в тіло функції замість формальних параметрів підставляються фактичні і тіло виконується, отриманий результат використовується при обчисленні виразу, що стоїть в операторі writeln.
Скласти програму обчислення за умови, що а <b:

Якщо a і b не вкладаються в задані межі, потрібно повідомити про це користувачеві і запитати, чи будуть інші діапазони - відповідь: "Y, N". Якщо задано не ті літери (y, n), повторити питання.
Перш ніж писати програму, визначимося з функціями:
оформимо у вигляді функції f1;
- У вигляді f2;
sin (x) + f1 - у вигляді f3;
cos (x) + f1 - у вигляді f4;
cos (x)-f2 - у вигляді f5;
обчислення за методом трапецій з точністю 0.1 oформім у вигляді підпрограми-функції f6.
    Program Prim32; label NAH, P;
Var b, a, z: real;
lit: char;
function f1 (x: real): real;
Begin f1: = exp (x/10) + sqrt (x / (x +3)); end;
function f2 (x: real): real;
Begin f2: = sqrt (sqr (x) / (3 * x +10)); end;
function f3 (x: real): real;
Begin f3: = sin (x) + f1 (x); end;
function f4 (x: real): real;
Begin f4: = cos (x) + f1 (x); end;
function f5 (x: real): real;
Begin f5: = cos (x)-f2 (x); end;
function f6 (a, b: real): real;
label K, N1, K1, KC, T;
Var h, s1, s, x: real; i, n: integer;
Begin
s1: = 9.999e +10; n: = 10;
N1: h: = (ba) / n; s: = 0; x: = a;
for i: = 1 to n do
Begin if a> b then goto t else
if (0 <= a) and (b <5) then Begin s: = s + (f3 (x) + f3 (x + h)) / 2 * h;
goto kc; end else
if (5 <= a) and (b <10) then Begin s: = s + (f4 (x) + f4 (x + h)) / 2 * h;
goto kc; end else
if (10 <= a) and (b <= 16) then Begin s: = s + (f5 (x) + f5 (x + h)) / 2 * h;
goto kc; end else goto t;
KC: x: = x + h; end;
if abs (s-s1) <0.1 then goto k
else Begin s1: = s; n: = n * 10; goto n1; end;
K: f 6: = s; goto k 1;
T: writeln ('межі інтегрування не відповідають умові');
      f6: =- 9999999999.;
K1: end;
BEGIN
NAH: writeln ('введіть значення a, b ');
readln (a, b); z: = f6 (a, b);
if z =- 9999999999. then goto p;
writeln ('z =', z);
P: readln;
       writeln ('будемо ще обчислювати z?, якщо "так"',
'То натисніть клавішу "y", якщо ні, то будь-яку клавішу');
       readln (lit);
if (lit = 'Y') or (lit = 'y') then goto NAH;
                              END.
7.3. Підпрограми-процедури
Опис процедури:
Procedure ім'я (вхідні формальні параметри: тип;
Var вихідні формальні параметри: тип);
опису (якщо вони є)
begin оператори
end;
Нехай необхідно знайти коріння квадратних рівнянь
ax2 + bx + c = 0,
ky2 + my + d = 0,
sz2 + tz + p = 0,
де коефіцієнти a, b, c вводяться за запитом. кількість рівнянь не обмежена. результати обчислень виводити на екран (в основну програму не повертати), див. рис. 2.1.
  Program Prim33;
label K, NAH;
Var let: char; a, b, c: real;
  procedure root (a, b, c: real); {процедура не має вихідних параметрів}
            label K;
Var d, x1d, x1m, x2d, x2m: real;
Begin        if a = 0 then Begin
writeln ('рівняння першого ступеня, корінь один');
              x1d: =- c / b; writeln ('x =', x1d); goto K; end
else d: = b * b-4 * a * c;
if d> = 0 then Begin
        writeln ('рівняння другого ступеня, коріння дійсні');
             x1d: = (-b-sqrt (d)) / (2 * a);
x2d: = (-b + sqrt (d)) / (2 * a);
writeln ('x1d =', x1d, 'x2d =', x2d); goto K; end
          else writeln ('рівняння другого ступеня, коріння комплексні');
               x1d: =- b / (2 * a); x2d: = x1d;
x1m: =- sqrt (-d) / (2 * a); x2m: =- x1m;
writeln ('z1 =', x1d, '', x1m, 'i;');
writeln ('z2 =', x2d, '', x2m, 'i;');
K: end;
BEGIN NAH: writeln ('введіть a, b, c'); readln (a, b, c); root (a, b, c);
        writeln ('буде ще рівняння? якщо "так", натисніть клавішу "Y"',
'Якщо "ні", натисніть будь-яку клавішу');
        read (let);
if (let = 'Y') or (let = 'y') then goto nah else goto K;
  K: END.
Знайти x, y, z - коріння системи рівнянь:

Як відомо з лінійної алгебри,
де
Розкриття визначника
+
-
проводиться за схемою: тобто
у процедурі a, b, c, d - вхідні дані, x, y, z - результати.
    Program Prim34;
label N, K;
Type w = array [1 .. 3] of integer;
Var a, b, c, d: w; x, y, z: real; let: char;
function det (a: w; b: w; c: w): real;
Begin det: = a [1] * b [2] * c [3] + b [1] * c [2] * a [3] + c [1] * a [2] * b [3]
-C [1] * b [2] * a [3]-a [1] * c [2] * b [3]-b [1] * a [2] * c [3]; end;
procedure ur (a, b, c, d: w; Var x, y, z: real);
Var d0: real;
Begin d0: = det (a, b, c);
if d0 = 0 then Begin writeln ('det = 0 рішення немає ');
                       let: = '0 '; Exit; end else {EXIT - вихід з процедури}
x: = det (d, b, c) / d0;
               y: = det (a, d, c) / d0;
z: = det (a, b, d) / d0; let: = '1 '; end;
BEGIN N: writeln ('введіть a1, b1, c1, d1'); readln (a [1], b [1], c [1], d [1]);
writeln ('введіть a2, b2, c2, d2'); readln (a [2], b [2], c [2], d [2]);
writeln ('введіть a3, b3, c3, d3'); readln (a [3], b [3], c [3], d [3]);
ur (a, b, c, d, x, y, z);
if let = 0 "then goto K else
         writeln ('/', a [1], 'x +', b [1], 'y +', c [1], 'z =', d [1]);
writeln ('система i', a [2], 'x +', b [2], 'y +', c [2], 'z =', d [2]);
writeln ('\', a [3], 'x +', b [3], 'y +', c [3], 'z =', d [3]);
         writeln ('має рішення: x =', x, 'y =', y, 'z =', z);
K: writeln ('Буде ще ур-ті? Так - "Y", ні - будь-яка клавіша');
     read (let);
if (let = 'Y') or (let = 'y') then goto N;
   END.
Є одновимірний масив. Необхідно визначити суму позитивних елементів, номер останнього негативного елемента, кількість негативних елементів масиву.
Завдання 1. Масив один і складається з 7 елементів.
Завдання 2. Масивів два, розмірність першого - 7 елементів, другого - 5.
Завдання 3. Кількість масивів не обмежена, кількість елементів у масивах довільне, але не більше 70.
  Program Prim35; {масив 1 і складається з 7 елементів} label j; Type mas = array [1 .. 7] of real; Var n, k, i, no: integer;
a: mas;
s: real; ch: char;
procedure prmas (a: mas; n: integer; Var s: real; Var k, no: integer);
Var i: integer;
Begin s: = 0; k: = 0; no: = 0;
for i: = 1 to n do Begin
if a [i]> = 0 then s: = s + a [i] else Begin k: = i; no: = no +1;
end; end; end;
BEGIN
for i: = 1 to 7 do Begin
          writeln ('ввести значення a [', i ,']');
        readln (a [i]); end;
prmas (a, 7, s, k, no);
  j: writeln ('сума позитивних елементів =', s);
writeln ('останній негативний елемент має N =' no);
writeln ('кількість негативних елементів =', k);
          readln;
END.
Program Prim36; {масиву 2, розмірність перший масиву 7, другий - 5} label j; Type mas = array [1 .. 7] of real; Var k, no, y: integer; s: real; ch: char; procedure prmas (n: integer; var s: real; var k, no: integer);
Var i: integer; a: mas;
Begin for i: = 1 to n do Begin
            writeln ('введіть', i, 'значення елемента масиву');
            readln (a [i]); end;
s: = 0; k: = 0; no: = 0;
for i: = 1 to n do begin
if a [i]> = 0 then s: = s + a [i] else begin k: = i; no: = no +1;
end; end; end;
BEGIN prmas (7, s, k, no); y: = 0;
  j: writeln ('сума позитивних елементів =', s);
writeln ('останній негативний елемент має N =', no);
writeln ('кількість негативних елементів =', k); y: = y +1;
          if y = 1 then Begin prmas (5, s, k, no); goto j; end
else readln;
END.
Program Prim37; {масиви з змінними вимірами, кількість     масивів НЕ обмежено} Type mas = array [1 .. 70] of real; Var n, k, i, no, kol, r, j: integer; a, b: mas; s: real; ch: char; procedure prmas (n : integer; var s: real; var k, no: integer); var i: integer; a: mas;
begin for i: = 1 to n do begin
               writeln ('введіть', i, 'значення елемента масиву', j);
                readln (a [i]); end;
s: = 0; k: = 0; no: = 0;
for i: = 1 to n do Begin
if a [i]> = 0 then s: = s + a [i] else Begin k: = i; no: = no +1;
end; end; end;
  BEGIN
writeln ('задайте кількість масивів '); readln (kol);
       for j: = 1 to kol do Begin
         writeln ('задайте розмірність масиву', j); readln (r);
         prmas (r, s, k, no);
         writeln ('сума позитивних елементів =', s);
writeln ('останній негативний елемент має N =', no);
writeln ('кількість негативних елементів =', k); end;
readln;
END.
7.4. Локальні і глобальні опису об'єктів
Ми вже знаємо, що програма - блок, тобто розділ операторів, забезпечений описами і має заголовок. Вид блоку-програми:
Program ім'я програми (можливі опції); {опції не обов'язкові}
Label ...; {розділ опису міток}
Co n st ...; {розділ опису констант}
Туре ...; {розділ визначення типів}
Var ...; {розділ опису змінних}
Function ...; Procedure ...; {розділ опису функцій і процедур}
BEGIN ... END. {Розділ операторів}.
Функції та процедури, у свою чергу, також є блоками:
Procedure ім'я (список вхідних формальних параметрів);
Var (список вихідних формальних параметрів);
Label ...;
Const ...;
Туре ...;
Var ...;
function ...;
procedure ...;
розділи описів
begin ... end; {тіло процедури}
Таким чином, програма - завжди блок, в який можуть бути вкладені інші блоки.
Як один з варіантів, можлива наступна структура програми:
          Program Prim38; {початок блоку 1} label N, M; Const k = 5.6; Type d = array [1 .. 10] of integer; Var b, c: real; i, j: integer; z, y: d;
function f (f, b, c: real): real; {початок блоку 2}
begin f: = 1; end; {кінець блоку 2}
procedure proc (f, b, c: real; Var x, y, z: real); {початок блоку 3}
label K, L;
var d, w, s: real;
function fp (a, b: real): real; {початок блоку 4}
begin fp: = 1; end; {тіло fp, кінець блоку 4}
begin x: = 1; y: = 1; z: = 1; end; {тіло proc, кінець блоку 3}
BEGIN b: = 1; END. {Тіло основної програми, кінець блоку 1}
Таким чином, програма складається з чотирьох блоків. Всі імена міток, констант, типів, змінних, функції f і Р r ос відомі в блоці 1, оскільки вони дані в його описі. Вважається, що вони описані тут локально.
У блоці 2 - function - описів немає, тому своїх власних об'єктів цей блок не має. Формальні параметри не в рахунок, оскільки вони служать тільки для опису алгоритму обчислення результату з ім'ям f у функції f, а осередки пам'яті для b, с, f тут не виділяються. Проте в цьому блоці можна використовувати всі об'єкти, які описані в блоці 1, так як блок 2 є складовою частиною блоку 1. Іноді кажуть, що імена об'єктів блоку 1 описані глобально для блоку 2.
Аналогічна ситуація і з блоком 3 - Procedure Р r ос. Для неї всі об'єкти блоку 1 є глобальними, тобто доступні. Крім того, в блоці 3 є свої описані тут об'єкти - мітки K, L, змінні d, W, 8, функція fp, які можуть бути використані тільки в блоці 3 і не відомі в блоках 1 і 2.
Як наслідок можливе застосування однакових імен в різних блоках (див. ім'я d). У блоці 1 d - масив. У блоці 3 (в Р r ос) є своє d, яке є власним у блоці 3, є не масив, а елемент пам'яті типу real.

8. Строкові дані

8.1. Загальні зауваження
Рядок - це послідовність символів довжиною 0-255. Для опису даних строкового типу використовується слово string, за яким можуть слідувати у квадратних дужках цифри, що визначають кількість символів в рядку. Якщо цифри у квадратних дужках і самі дужки відсутні, то для даної комірки пам'яті буде виділятися максимально можлива довжина: 256 байт для зберігання 265 символів. Символьні константи (які можуть зберігатися) мають вигляд сукупності символів, укладених в апострофи.
Приклад: 'a, b, с - символи'.
Приклади описів:
Var а, b, с: string [70];
Виділяються осередку з іменами а, b, с, в кожну з яких може бути занесена сукупність символів у кількості до 70.
Наприклад, можливі оператори:
а: = 'вулиця Садова';
b: = вулиця Чкалова, 17, хаї ';
з: = м. Харків - велике місто ';
можливо попередній опис типу:
Туре a = string [70];
Var b, с: а;
8.2. Строкові вираження
Вирази, в яких операндами служать рядки, є строковими виразами. Результат - рядок. Опишемо операції, які можна застосовувати при написанні строкових виразів:
Операція зчеплення, знак операції '+'.
'Дім' + 'номер' + '43 'дає результуючу рядок' Будинок номер 43 '.
Операції відносини: =, <>,>, <,> =, <=.
Операції відносини виконуються раніше операції зчеплення, тобто мають більш високий пріоритет.
Порівняння між рядками виробляються посимвольний, зліва направо, до першого неспівпадаючого символу. Той рядок вважається більше, в якій перший неспівпадаючий символ має більший код за таблицею кодів. Результати порівняння - True або False.
Якщо рядки мають різну довжину і коротша збігається з початком більш довгою, то остання вважається більшою.
При використанні оператора присвоювання, якщо значення результату обчислення строкового вираження має велику довжину, ніж комірка пам'яті, в яку записується результат, то зайві праві символи відкидаються. Якщо значення результату обчислення строкового типу коротше, ніж комірка пам'яті, відведена для його зберігання, то результат записується в комірку пам'яті «притиснутим» вправо, а зайві ліві розряди заповнюються пробілами.
Допускається при записі виразів строкового типу застосовувати дані, описані з атрибутом char. У такому разі ці дані інтерпретуються як string [1]. До окремих символів даного строкового типу можна звернутися за номером цього символу в рядку (аналогічно індексу в масивах). У нульовому байті зберігається довжина рядка.
        Program Prim 39; var st 1, st 2: string [30]; BEGIN st 1: = 'відділ № 256'; writeln (st 1); {на екрані "відділ № 256"} st 2: = st 1 [10]; writeln (st 2); {на екрані "5"} writeln ( ord (st 1 [0])); {на екрані "11"}
readln; END.
Якщо б у var було зазначено string [10], то writeln (st1), вивів би результат "відділ № 25"
8.3. Стандартні процедури та функції для обробки рядків
8.3.1. Процедури обробки рядків
Delete (st, Poz, N) - видалення N символів з ​​рядка з ім'ям st, починаючи з позиції Poz.
st: = 'река_Волга'; Delete (st, 1, 5);
Результат 'Волга'.
insert (stl, st2, poz); - вставка рядка stl в рядок st2, починаючи з позиції Poz.
st1: = 'Дом_25_'
st2: = 'На_уліце_жівет_петух_';
insert (stl, st2, 10);
Результат: "На_уліце_дом 25_жівет_петух";
st r (IBR, st); перетворює число IBR (типу integer, byte або Real) і поміщає результат в рядок st. Можливо після IBR вказати ширину поля. Якщо ширини поля не вистачає, воно автоматично розширюється до потрібної величини.
str (1500:6, stl); дасть результат '_1500';
str (4.8е +03:10, stl); - результат '_ 4.800E +03';
str (-46854:3, stl); - результат '-46854'.
Val (st, IBR, Cod); процедура перетворює значення st у величину цілочисельного або дійсного типу і поміщає результат в IBR. Значення st повинно містити символьне зображення числа і не містити символів, не властивих зображенню чисел (наприклад, пробілів перед цифрами), букв і т.п. Cod - цілочисельна мінлива індукують помилку. Якщо Cod = 0, перетворення вироблено без помилки, якщо Cod = 5, то помилка при перетворенні - 5 символів.
Програма Program Prim 40; ілюструє роботу вищеописаних процедур:
        Program Prim40; var st1, st2: string [30];
BEGIN st1: = 'річка Волга';
delete (st1, 1,5); writeln (st1);
         st1: = 'будинок 25'; st2: = 'на вулиці живе півень ';
        insert (st1, st2, 10); writeln (st2);
str (1500:6, st1); writeln (st1);
str (4.8e +03:10, st1); writeln (st1);
str (-46854:3, st1); writeln (st1);
             readln; END.
8.3.2. Функції рядків
Сміттю (st, Poz, N) виділяє з st підрядок довжиною N символів, починаючи з позиції Poz.
stl: = 'absdefg'; writeln (Сміттю (stl, 2, 3));
результат bсd
Co n st (stl, st2 ,..., stn) виконує зчеплення рядків stl ... stn. Довжина сумарною рядка не повинна перевищувати 255 символів.
Length (st) визначає довжину рядка, результат - integer.
Pos (stl, st2) виявляє перша поява рядка stl в рядку st2. Результат - ціле число, що визначає номер позиції, в якій знаходиться перший символ підрядка st1. Якщо st1 не міститься в рядку st2, то результат дорівнює 0.
UpCase (ch) перетворить рядкову букву на велику.
Параметр і результат мають літерний тип.
ch: = a '; UpCase (ch) має результат' A '.
Program Prim 41, Prim 42, Prim 43 ілюструють роботу вищеописаних функцій.
        Program Prim41; var st1, st2: string [30]; s: char; BEGIN st1: = 'відділ № 256'; writeln (copy (st1, 7,5)); st2: = 'знаходиться в НДІ 5 ';
writeln (concat (st1, st2));
writeln (length (st2));
st2: = 'n 256';
writeln (pos (st2, st1));
s: = 'a';
writeln (upcase (s));
             readln; END.
Program Prim42; {програма видаляє всі прогалини в рядку, що стоять в рядку зліва, якщо вони є}
         Var str: string [255]; {Var str: string; буде працювати так ж} function del (stroka: string): string;
Var dlina: byte;
Begin dlina: = Ord (stroka [0]);
while ((dlina> 0) and (copy (stroka, 1,1) = '')) do
delete (stroka, 1,1);
del: = stroka;
end;
BEGIN writeln ('введіть рядок ');
readln (str);
writeln (del (str)); readln;
      END.
             Program Prim43; {Дани три вихідні рядки A, B, C. У рядку А визначити першу бук} {ву; Потім замінити першу букву рядка А з малої на заголовну;} {об'єднати в один рядок A, B, C; Визначити довжини рядків A, B, C} {і в результуючій рядку вставити '- 'між складовими її} {рядками. У результуючої рядку знайти номер позиції, в якій} {буква "а" зустрічається вперше; визначити довжину результуючої} {рядка. Після кожної дії друкувати результати. } Var A, B, C: string [14]; str: string [50]; ch: string [1]; d 1, d 2, d 3: integer;
   Begin   A: = 'електронна'; B: = 'обчислювальна'; C: = 'машина'; ch: = copy (A, 1,1); writeln (ch);
          delete (A, 1,1); writeln (A);
writeln (upcase (ch [1]));
insert (upcase (ch [1]), A, 1); writeln (A);
str: = concat (A, B, C); writeln (str);
d1: = length (A); d2: = length (B); d3: = length (C);
writeln ('довжини рядків ', d1: 6, d2: 6, d3: 6); insert ('-', str, d1 +1); insert ('-', str, d1 + d2 +2);
                                writeln (str);
writeln ('перший раз буква "а" стоїть у результуючої стрічці', 'у позиції', pos ('а', str)); writeln ('загальна довжина рядка =', length (str));
readln; END.

9. Записи

Раніше ми розглядали структуровані дані, що складаються з компонентів одного типу (масиви). Однак на практиці часто необхідно мати під одним ім'ям сукупність даних різного типу. Наприклад, інформація про студента може складатися з даних: прізвище, ім'я, по батькові (тип string), домашня адреса (тип string), стать (тип char), номер групи (тип integer), номер кімнати проживання в гуртожитку (тип integer), досліджувані предмети (тип, масив рядків) і т.д.
Для об'єднання різнотипних даних під одним ім'ям і можливості подальшої їх обробки в мові Pascal передбачений тип даних запис.
Запис - пойменований структурований тип даних, що складається з фіксованої кількості різних компонент. Визначення (опис) даного типу "запис" починається атрибутом record і закінчується end.
Між record і end полягає список компонент запису, званих полями, із зазначенням їхніх імен і типу кожного поля. Туре ім'я типу = record ідентифікатор поля: тип компоненти; ідентифікатор поля: тип компоненти;
end;
Var ідентифікатор: ім'я типу; Можливо і «прямий» опис запису, без попереднього опису типу. Приклад опису запису за допомогою попереднього завдання типу: Туре Car = record Nomer: integer; {номер} Marka: string [20]; {марка автомобіля} F I O: string [40], {п.і.б. власника} adres: string [60]; {адресу власника} end; Var M, V: Car; Або «пряме» опис: Var М, V: Record Nomer: integer; Marka: string [20];
F I O: string [40]; adres: string [60]; end; Ідентифікатор поля повинен бути унікальний тільки в межах записи, однак, щоб уникнути помилок краще його робити унікальним в межах програми.
Обсяг пам'яті, що виділяється в розділі Var, для зберігання запису складається з обсягів пам'яті - суми довжин полів. Значення полів запису можуть використовуватися у висловлюваннях, при цьому в них повинні вказуватися складові (уточнені) імена, тому що імена полів у різних записах можуть збігатися. Наприклад, щоб отримати доступ до полів запису Са r, необхідно користуватися іменами М. FIO, М. NOMER для запису М, а для запису V - іменами V. F IO, V. NOMER. Ці імена можна використовувати скрізь, де застосовуються звичайні імена, наприклад, в операторах присвоювання:
М. Nomer: = 1678;
V. Nomer: = 3789;
М. Marka: 'газ -24';
V. Marka: = 'Таврія';
У операторах вводу-виводу:
writeln (м. marka);
Допускається застосування операторів присвоювання до записів у цілому, якщо вони мають однакові структури. Так, для наведеного вище опису записів М і V допустимо M: = V;
Після виконання цього оператора значення полів запису V стануть рівними значенням полів запису М.
У ряді завдань зручно користуватися такими масивами записів:
Туре Person = record
FIO: string [30];
Prof: string [30); end;
Var List: array [1 .. 50] of Person;
Тут масив List буде складатися з 50 записів типу Person.
Сама запис може мати поля будь-якого відомого нам типу, в тому числі і масивного. Допускається, щоб поле запису саме було записом. Звернення до полів запису за допомогою складових імен має кілька громіздкий вигляд, що особливо незручно при використанні мнемонічних ідентифікаторів довжиною більше 5 символів. Для полегшення цієї ситуації в мові Pascal є оператор with, який має наступний формат:
with ім'я змінної типу запис do
begin ···················· end.
Один раз вказавши в операторі with змінну типу запис, потім - в межах begin ... end, що стоять після with, можна працювати з іменами полів цього запису як із звичайними змінними, тобто без вказівки перед ім'ям поля імені запису. Наприклад:
без застосування оператора with:
М. NOM: = 5543;
M. MARKA: = 'м a 3-24';
М. FIO: = 'Петров П. П.';
М. Adres: = 'вул. Чкалова, 7, кв.32 ';
end;
Скласти програму обліку успішності студентів курсу, що складається з шести груп до 30 студентів в кожній групі. Кожен студент здавав екзамени з п'яти дисциплін: вища математика, основи інформатики, філософія, історія України, архітектура ЕОМ. По кожному предмету можна одержати оцінки 2, 3, 4, 5. Кожен іспит можна здавати до трьох разів. Зробити аналіз: якщо у студента є три двійки по одному предмету або три непересданние двійки з трьох предметів, то він повинен бути відрахований; якщо студент все двійки перездав, то його потрібно посварити.
              Program Prim44;
label u, w;
type mo = array [1 .. 5,1 .. 3] of 0 .. 5;
st = record
namb: integer;
fio: string [20];
o: mo; end;
var
gr: array [1 .. 6,1 .. 30] of st;
i, j, k, l, kol_dvoek, v, kgr, n: integer;
md: mo; ch: char;
divdmet: string; kst: array [1 .. 6] of byte;
procedure rea_ocenki (fio: string; Var oc: mo);

Label M1, M2, M3, M4;

Var i: integer;
begin
for i: = 1 to 5 do
Begin
case i of
            1: divdmet: = 'основи інформатики ';
2: divdmet: = 'вищої математики ';
3: divdmet: = 'філософії';
4: divdmet: = 'архітектурі ЕОМ ';
5: divdmet: = 'історії Україна '; end;
              writeln ('введіть оцінку студента ', fio,' no ', divdmet);
M1: readln (oc [i, 1]);
if (oc [i, 1] <2) or (oc [i, 1]> 5) then
        Begin writeln ('введіть правильно оцінку'); goto M1; end;
         if oc [i, 1]> 2 then Begin oc [i, 2]: = 0; oc [i, 3]: = 0; goto M4; end else
   M2: writeln ('введіть другу оцінку студента', fio, 'за', divdmet);
       readln (oc [i, 2]);
if (oc [i, 2] <2) or (oc [i, 2]> 5) then
        Begin writeln ('введіть правильно оцінку'); goto M2; end;
         if oc [i, 2]> 2 then begin oc [i, 3]: = 0; goto M4; end else
   M3: Writeln ('введіть третій оцінку студента', fio, 'за', divdmet);
       readln (oc [i, 3]);
if (oc [i, 3] <2) or (oc [i, 3]> 5) then
        begin writeln ('введіть правильно оцінку'); goto M3; end;
           M 4: end; end;
BEGIN {початок блоку введення оцінок студентів}
writeln ('при введенні оцінки набираються: 5, якщо іспит');
writeln ('зданий на 5 і, якщо були перездачі, то 2,2,3');
   z: writeln ('до першої позитивної оцінки');
writeln ('задайте кількість груп, не більше 6');
readln (kgr);
for i: = 1 to kgr do {установка індексу групи}
begin case i of {визначаємо групу з i}
1: n: = 610;
2: n: = 611;
3: n: = 612;
4: n: = 613;
5: n: = 614;
6: n: = 615;
else writeln ('неправильно задано кількість груп'); goto 2; end; end;
writeln ('задайте кількість студентів у групі', n);
        readln (kst [i]);
for j: = 1 to kst [i] do {установка номера студента i в групі}
begin with gr [i, j] do {працювати без складових імен}
   begin namb: = n; writeln ('введіть прізвище ', J,' студента гр. ', Namb);
readln (fio);
for k: = 1 to 5 do {Обнуляємо масив оцінок}
for l: = 1 to 3 do
o [k, l]: = 0;
            writeln ('введіть оцінки студентів', fio);
            rea_ocenki (fio, o); end; end; end;
                                {Кінець введення оцінок студентів}
{Відображення на екрані введення оцінок}
       for i: = 1 to kgr do
for j: = 1 to kst [i] do
Begin with gr [i, j] do
Begin for k: = 1 to 5 do
write (o [k, 1], o [k, 2], o [k, 3], ''); writeln; end; end;
{Кінець виводу на екран оцінок}
{Початок блоку аналізу успішності студентів}
            for i: = 1 to kgr do {індекс групи}
for j: = 1 to kst [i] do {номер студента}
Begin    kol _ dvoek: = 0; v: = 0; {працювати без складових імен}
            with gr [i, j] do
Begin
for k: = 1 to 5 do {номер предмета}
    Begin
   {А тепер, аналізуємо стан успішності студента, інформація}
{Про який зберігається в записі gr [i, j]; так як ми працюємо під уп-}
{Равленіе оператора with gr [i, j], то можна користуватися не}
{Складовими іменами полів}
case k of {визначити назву предмета j}
1: divdmet: = 'основи інформатики';
2: divdmet: = 'вища математика';
3: divdmet: = 'філософія';
4: divdmet: = 'архітектура ЕОМ';
          5: divdmet: = 'історія Україна '; end;
    if o [k, 1] = 2 then if o [k, 2] = 2 then if o [k, 3] = 2 then begin
  writeln ('студент', fio, 'групи', namb, 'підлягає відрахуванню так як');
writeln ('має три двійки по предмету', divdmet);
v: = 1; readln; goto w; end {на новий предмет}
    else Begin kol_dvoek: = kol_dvoek +2; goto w; end
    else Begin kol_dvoek: = kol_dvoek +1; goto w; end;
w: end;
if v = 1 then goto u {до новому студенту}
else if kol_dvoek = 0 then goto u
    else Begin
writeln ('студент', fio, 'групи', namb, 'є розгільдяєм так як');
writeln ('має в зимову сесію', kol_dvoek, 'двійок і є');
writeln ('кандидатом на відрахування у весняному семестрі');
      readln; end; end;
u: end; END.
Програма забезпечена коментарями, тому при уважному розгляді читається легко. Труднощі можуть виникнути при розборі блоку аналізу результатів, тому ми наведемо блок-схему логічної частини цього блоку (рис. 9.1).
9.1. Комплексні дані
При роботі з комплексними даними зручно користуватися записами з двома полями, перше містить інформацію про дійсної частини даного, а друга - про уявної частини даного.   
   Program Prim45;
Type complex = record
deistv: real; mnim: real;
end;
Var a, b, c: complex;
BEGIN
a.deistv: = 6.3;
a.mnim: = 1.9; END.

та
та
та
V = 0
1-а оцін-ка = 2?
Вивести на екран: "Студент ... повинен бути відрахований, так як має три двійки по предмету ...."
V: = 1
Ознака того, що не потрібно виводити на екран текст про те, що студент може бути відрахований, так як він вже відрахований
W: розглянути оцінки наступного предмета
V: = 1?
Кількість двійок = 0?
2-я оціню-ка = 2?
Третій оціню-ка = 2?
Вивести на екран: "Студент має ... двійок і є кандидатом на відрахування"
V: розглянути оцінки наступного студента
ні так
та
ні так
Предмети всі
та
ні так
ні так
ні так
Кількість двійок збільшити на 2
Кількість двійок збільшити на 1
Рис. 9.1
 


9.2. Запис з варіантами
Записи, описані вище, мають строго певну структуру. проте є можливість створювати записи, що мають кілька варіантів одного і того ж поля. Варіантні поля записуються після опису безваріантність полів за допомогою оператора Case.
ТУРІ
zap = record
опис безваріантність полів;
Case ім'я поля: тип імені поля of
список констант вибору: (поле, ... тип); ...
список констант вибору: (поле, ... тип);
end;
Приклад:
Туре zap = record
Nomer: byte; {фіксовані поля}
Articul: integer;
Case Flag: boolean of {варіантні поля}
TRUE: (cena l: integer);
FALSE: (cena 2; real);
end;
Var P, Si Zap;
полі Cena l є тільки тоді, коли Flag = TRUE
полі Cena 2 доступно тільки тоді, коли Flag = FALSE
При використанні записів з варіантами необхідно дотримуватися наступних правил:
- Всі імена полів повинні відрізнятися один від одного, навіть якщо вони зустрічаються в різних варіантах;
- Запис може мати тільки одну варіантну частину, причому варіантна частина повинна розміщуватися в кінці її;
Якщо поле, відповідне будь-якої мітці, є порожнім, то воно записується таким чином:
список констант вибору: ();
         Program Prim 46;
    Type zap = record
nomer: byte;
artikul: integer;
case flag: boolean of
true: (cena1: integer);
false: (cena2: real); end;
Var h, s: zap;
BEGIN with h do
Begin nomer: = 1; artikul: = 2345; flag: = true; cena1: = 25;
writeln ('nomer =', nomer, 'artikul =', artikul, 'cena1 =', cena1);
flag: = false; cena2: = 3.2;
writeln ('cena2', cena2);
end; readln; END.

10. Файли

10.1. Загальні зауваження
У практиці програмування часто зустрічаються завдання, які вирішуються із застосуванням малоізменяемих у часі даних. До них відносяться, наприклад, завдання бухгалтерського обліку оптимального планування і т.п. Введення даних з клавіатури при кожному рахунку завдання дуже трудомісткий, а іноді просто неможливий через часових обмежень. Для вирішення цієї проблеми в мовах програмування реалізована концепція файлів, що дозволяє після разового набору інформації запам'ятати її на зовнішніх носіях і звертатися до неї безпосередньо з обробних програм при кожному рахунку завдання.
Файл - пойменована область пам'яті, як правило, на зовнішніх носіях, призначена для зберігання інформації. файл можна також вважати структурованим типом даних, що складається з послідовності компонентів одного і того ж типу і однакової довжини та структури. найчастіше компонентами файлу є записи.
Файл може бути пов'язаний із зовнішнім носієм інформації, тобто розташовуватися на магнітному або СД диску, магнітній стрічці, клавіатурі при введенні інформації або на екрані, принтері і при виведенні її і т.д.
Файли бувають стандартними, тобто певними розробниками або адміністраторами операційної системи або обчислювального середовища, а також користувачем, тобто людиною, що становлять програми в якій-небудь алгоритмічній мові (наприклад в Pascal), або за допомогою інших програмних продуктів (баз даних, редакторів і т.д.).
Кожен файл має своє ім'я, яке зареєстровано у відповідній директорії (змісті).
Визначення файлового типу будується за такою схемою:
Туре ім'я типу = file of тип компонентів;
Var ідентифікатор, .., ідентифікатор: ім'я типу;
Наприклад:
Туре zap = record
Nom: integer;
FIO: string [20];
oklad: real; end;
Ft = file of zap;
Var a, b, с: Ft;
Описано три файли з іменами а, b, з типу Ft. Компонентами файлів служать записи типу zap. Іншими словами, файл схематично можна представити у вигляді «стрічки» компонент, кожна з яких є записом типу zap. Доступ до компонентів файлу може бути послідовним і прямим. Послідовний доступ - це коли для звернення до n-ї компоненті необхідно «подивитися» n-1 компонент; прямий доступ - звернення до компоненті йде прямо по «ключу» (номером компоненти), без «перегляду» попередніх компонент.
При роботі з файлом «увага» машини зосереджено на компоненті, визначеної покажчиком файлу (цією компонентою буде працювати машина при наступному зверненні до файлу).
Назва файлу повинна бути унікальним і що складається з власного імені і необов'язкового розширення - типу файлу, який містить три символи та відокремленого від основного імені крапкою. Розширення, як правило, вказує в мнемонічною формі на вміст файлу: pas, ехе, txt і т.д. У деяких випадках тип файлу присвоюється автоматично операційною системою або використовуваних пакетом.
Кожен диск, що містить файли, має зміст, в яке можна відслідковувати його імені, розширенні, час і дату його створення, про місцезнаходження на фізичному носії (наприклад, на диску С або D).
Для пошуку файлу необхідно вказати диск, каталог, підкаталог, ім'я файлу, його розширення.
Наприклад: C: \ TURBO \ Prim \ Prim46.pas.
Тут файл Prim 46.pas знаходиться в підкаталозі Prim каталогу TURBO диска С.
10.2. Стандартні процедури та функції для роботи з файлами
Далі приймемо позначення: FV - ім'я файлової змінної або просто ім'я файлу, str - рядковий вираз, Р - ім'я структурної компоненти файлу, n - ціле вираз.
Assig і (FV, str); - процедура присвоєння імені файлу.
Ім'я файлу, яке є значенням str, присвоюється змінної файлового типу FV. Далі всі дії над цієї змінної будуть еквівалентні діям над файлом, певним ім'ям str. Наприклад: Assign (books, 'c: \ bibl.dos'); дозволяє працювати не з ім'ям 'c: \ bibl.dos', яке може бути досить довгим (якщо є каталоги і підкаталоги), а з ім'ям books.
Rewrite (FV); - процедура створення нового файлу з ім'ям FV на диску. Назва файлу повинна бути попередньо визначено процедурою Assign. Якщо на диску вже був файл із таким ім'ям, то він знищується. Покажчик файлу встановлюється в першу позицію з номером 0. Файл ще не містить жодної компоненти, а тільки підготовлений до завантаження.
Reset (FV); - процедура відкриття (дозвіл працювати з файлом ім'ям FV) вже наявного файлу. Покажчик встановлюється на початок файлу, в позицію з номером 0.
Read (FV, Р); - процедура читання компоненти файлу, на яку встановлено вказівник, її вміст поміщено в область пам'яті з ім'ям Р.
Write (FV, Р); - процедура запису інформації з області пам'яті Р в файл FV і компоненту, на яку встановлено вказівник.
Seek (FV, n); - процедура встановлення покажчиків на компонент з номером n.
Fl ush (FV); - очищення буфера сектора. Виконання процедури призводить до виштовхування вмісту внутрішнього буфера (області пам'яті) у файл.
Close (FV); - процедура закриття файлу, при цьому записується маркер кінця файлу. Після роботи з файлом його необхідно обов'язково закрити.
Erase (FV); - процедура знищення файлу. Якщо робиться знищення відкритого файлу, його необхідно попередньо закрити.
Rename (FV, str); - процедура перейменування файлу. Файлу FV присвоюється ім'я str.
Truncate (FV); - процедура знищення всіх компонент файлу, починаючи з місця поточного положення покажчика та підготовки файлу до запису.
Eof (FV) - функція перевірки маркера кінця файлу. Значення функції одно True, якщо вказівник файлу знаходиться за останньою компонентою, і False - інакше.
Filepos (FV) - функція визначення положення покажчика.
Filesize (FV) - функція визначення довжини файлу. Функція повертає цілочисельне значення, яке дорівнює кількості компонент файлу: якщо File Size (FV) = 0, то файл порожній.
Loresult (FV) - функція перевірки результату останньої операції введення-виведення на наявність помилок. Якщо помилку виявлено, повертається код помилки, якщо немає, то код = 0.
10. 3. Стандартні файли
Con: - консоль (клавіатура або екран дисплея). Турбо-Паскаль встановлює відмінності між цими пристроями у напрямку передачі даних: читання даних можливо тільки з клавіатури, а запис - тільки на екран. Введення з клавіатури буферизується: символи у міру натиснення клавіш поміщаються в буфер, вміст якого передається в ЕОМ тільки після натискання клавіші ENTER, оскільки запроваджуються та буферізірованний символи відображаються на екрані. Con застосовується «за умовчанням» для введення за допомогою операторів READ і Readln і для виведення на екран - операторів write і writeln, якщо не вказано ім'я файлу FV.
Всі зовнішні пристрої ЕОМ трактуються в Pascal як логічні пристрої, що мають імена файлового типу і яким повинні відповідати заздалегідь визначені (стандартні) файли. Ідентифікацію (ототожнення) пристрою і стандартного файлу здійснюють спеціальні програми (драйвери), які забезпечують виконання операцій введення-виведення між процесором і конкретним фізичним пристроєм. Нижче вказані імена файлів і відповідні їм пристрою так, як вони визначені розробниками системи.
Trm: - термінал, призначений для введення з клавіатури і виведення на екран без редагування.
Kbd: - клавіатура, використовувана лише для введення з клавіатури, при введенні інформація не відображається на екран.
P R N: - порядково друкуючий пристрій (принтер), що використовується тільки для виводу.
Aux: - допоміжний пристрій, що підключається через порт.
Usr: - пристрої користувача, що застосовується при написанні власних драйверів для організації нестандартного введення-виведення.
10.4. Файли послідовного доступу, створені користувачем
Робота з файлом послідовного доступу передбачає його створення, обробку та коригування. Для створення файлу послідовного доступу необхідно:
- Оголосити файлову змінну;
- «Прив'язати» файл до фізичного носія інформації (надати файлу ім'я). (Assign);
- Відкрити новий файл (Rewrite);
- Підготувати інформацію для введення в компоненту файлу, тобто сформувати запис для введення в файл як компоненти;
- Записати в файл компоненту (Write);
- Повторити п. 4, 5 необхідну кількість разів;
- Закрити створений файл (Close).
Для доступу до компонентів послідовного файлу (наприклад, для перегляду вмісту файлу на екрані або для обробки компонент з метою включення їх в якості фрагментів в програму обробки яких-небудь даних і т.п.) слід:
- Привласнити файлу ім'я (Assign);
- Відкрити вже існуючий файл (Reset);
- Вважати поточну компоненту з файлу в робочу область пам'яті (як правило, типу запис зі структурою компоненти), (Read);
- Виконати обробку інформації (наприклад, вивести на екран поля запису);
- Закрити файл (Close).
Можливі три типи коригування файлу як прямого, так і послідовного доступу:
1. Розширення файлу за рахунок внесення нових компонент.
2. Повна заміна вмісту компоненти.
3. Заміна будь-яких полів окремих компонент.
Заміна вмісту компонент окремих записів або заміна полів окремих записів буде розглянута в наступному підрозділі при вивченні коригування компонент файлів прямого доступу.
Додавання нових записів у файл послідовного доступу виконується шляхом запису компонент у кінці файлу. Маркер кінця файлу при цьому переноситься. Природно, на фізичному носії при цьому має бути вільний простір.
Для запису нових компонент в кінці наявного файлу необхідно:
- Привласнити файлу ім'я (Assign);
- Відкрити вже існуючий файл (Reset);
- Встановити покажчик файлу за останньою компонентою (Seek (FV, File sise (FV)):
- Створити в спеціально виділеної області пам'яті (як правило запису) нову компоненту;
- Записати нову компоненту в файл (write);
- Закрити файл (Close).
Приклад. Організувати послідовний файл з ім'ям PRIM bibl.dos в підкаталозі Prim каталогу TURBO на диску С, тобто C: \ TURBO \ bibl.dos. Компонента повинна мати структуру: індекс книги, порядковий номер примірника, прізвище, ініціали перших трьох авторів (якщо їх декілька), назву книги. Блок створення файлу оформити у вигляді процедури з ім'ям org. Блок доступу до компонентів файлу оформити у вигляді процедури з ім'ям obr., А блок коректування - у вигляді процедури з ім'ям Rash.
             Program Prim47;
type books = record {базова запис}
nomer: integer;
avtor: string [16];
nazv: string [30];
index: integer; end;
      var bf: file of books; {описати файлову змінну}
           rb: books; {ділянку пам'яті зі структурою}
                                   {Компоненти файлу}
procedure org;
begin assign (bf, 'C: \ TURBO \ PRIM \ bibl.dos');
               Rewrite (bf);
with rb do {працювати із записом rb без уточнених імен}
          while True do
begin writeln ('ввести номер книги ');
readln (nomer);
               if nomer = 9999 then {9999 - ознака закінчення введення даних}
               Begin close (bf); Exit end;
writeln ('ввести ім'я автора ');
readln (avtor);
                   writeln ('ввести назву книги');
readln (nazv);
writeln ('ввести значення індексу');
readln (index);
write (bf, rb); {записати компоненту з rb в файл}
        end; end;
procedure Obr;
Begin Assign (bf, 'C: \ TURBO \ PRIM \ bibl.dos');
Reset (bf);
with rb do
while not Eof (bf) do {вийти з циклу, коли закінчиться файл}
begin read (bf, rb);
writeln (nomer: 5, avtor: 16, Nazv: 10, index: 6); {висновок на екран}
end; Close (bf); end;
procedure Rash;
begin Assign (bf, 'C: \ TURBO \ PRIM \ bibl.dos');
             Reset (bf);
Seek (bf, Filesize (bf)); {встановити покажчик на кінець файлу}
             with rb do
while True do
begin writeln ('ввести номер '); readln (nomer);
if nomer = 9999 then begin Close (bf); Exit end;
writeln ('ввести ім'я автора '); readln (avtor);
             writeln ('ввести назву книги'); readln (nazv);
writeln ('ввести значення індексу'); readln (index);
             write (bf, rb); end; end;
BEGIN {основна програма}
Org; Obr; Rash; Obr; readln;
    END.
При створенні великих програм їх частини зручно створювати у вигляді окремих файлів (об'єктів), які потім за допомогою директиви компілятора {$ i. ..} можна об'єднати в одну програму. Це зручно ще й тим, що кілька програмістів можуть створювати різні програми, що в декілька разів може прискорити процес їх створення.
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Книга
687.6кб. | скачати


Схожі роботи:
Вступ у програмування мовою Паскаль
Програмування мовою С з використанням об єктно орієнтованого програмування
Програмування мовою С з використанням обєктно-орієнтованого програмування
Основні поняття мови програмування Турбо Паскаль
Програми технології мови програмування Паскаль у прикладній механіці
Розвязання інженерних задач мовою програмування VBA
Засоби мови програмування Паскаль для розв`язування математичних задач
Розв язання інженерних задач мовою програмування VBA
Основи програмування в C
© Усі права захищені
написати до нас