Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Інформатика програма 9 класу.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
529.92 Кб
Скачать

§ 8. Підпрограми

        Підпрограми призначені для реалізації алгоритмів опрацювання окремих частин деякої складної задачі. Вони дають змогу реалі­зовувати концепцію структурного програму­вання, суть якого поля­гає в розкладанні складної задачі на послідовність простих підзадач і в складан­ні для алгоритмів розв’язування кожної підзадачі від­повідних підпрограм. Розріз­няють два види під­про­грам — під­про­грами-процедури та підпро­грами-функ­ції. Під­програми поді­ля­ються на стандартні та підпрограми користу­вача. Стандартні підпрограми створювати не потрібно — вони містяться у стандартних модулях System, Crt, Dos, Graph тощо. Під­програма користувача — це по­йме­нована група команд, яку створюють і опису­ють в основній програмі в розділах procedure або function і до якої звертаються з будь-якого місця програми потрібну кількість разів.         1. Процедури (procedure). Загальний опис процедури:

procedure <назва> (<список формальних параметрів>); <розділи описів і оголошень процедури>; begin    <розділ команд процедури> end;

        У списку формальних параметрів перераховують змінні разом із зазначенням їхніх типів. Розрізняють параметри-аргументи (ін­ший термін: параметри-значення) — вхідні дані для процедури, і параметри-результати (інший термін: параметри-змінні), через які можна по­вер­тати результати роботи процедури в основну про­граму. Перед списками параметрів-результатів кожного типу за­пи­сують слово var. Зауважимо, що масиви фіксованих розмірів у списках формальних параметрів не можна описувати за до­помогою слова array (див. зразки програм).         Розділи описів і оголошень у підпрограмах мають таку саму структуру як і в основній програмі.         Приклад. Розглянемо процедуру з назвою Cina, яка визначає с —вартість k хвилин телефон­ної розмови з похвилинною оплатою 0.6 грн. + 20% ПДВ.

procedure Cina(k:integer; var c:real); begin    c:=k*0.6; c:=c+0.2*c; end;

        У наведеному прикладі k є формальним параметром-аргументом, с — формальним параметром-результатом.         До процедури звертаються з розділу команд основної програми або іншої підпрограми. Процедуру викликають за допомогою ко­манди виклику

            <назва процедури> (<список фактичних параметрів>);

        Параметри, які записують у команді виклику процедури, нази­ва­ються фактичними. Фактичними параметрами-аргументами мо­жуть бути сталі, змінні, вирази, а параметрами-результатами — лише змін­ні. Типи даних тут не зазначають.         Між фактичними і формальними параметрами має бути відповід­ність за кількістю й типами. Зверніть увагу, відповідні фак­тичні та формаль­ні параметри можуть мати різні імена.         Команда виклику функціонує так: значення фактичних пара­метрів присвоюються відповідним формальним параметрам процеду­ри, виконується процедура, визначаються параметри-результати, зна­­чення яких надаються (повертаються) відповідним фактич­ним па­ра­метрам у команді виклику.         Змінні, описані в розділі описів основної програми, називаються глобальними. Вони діють у всіх підпрограмах, з яких складається про­грама. Змінні, описані в розділі описів конкретної процедури, називаються локальними. Вони діють тільки в межах даної про­це­дури.         Процедури можуть отримувати і повертати значення не тільки через параметри-результати, але й через глобальні змінні. Тому списків параметрів у процедурі може і не бути.         Задача 1. Розв’язати задачу про кількість викликів на АТС з по­пе­ред­нього параграфа, використовуючи три процедури: 1) для ви­зна­чення кількості викликів за кожну секунду (надамо їй назву Kilvykl); 2) для об­числення суми викликів за перші 10 секунд (Sumavykl); 3) для ви­зна­чення найбільшої кількості викликів за деяку секунду (Maxkilvykl). Використати функцію random.

program ATS1; uses Crt; type vyklyk= array[1..10] of integer; var y:vyklyk; max, s:integer; procedure Kilvykl(var y:vyklyk); var i:integer; begin    for i:=1 to 10 do       begin       y[i]:=random(i);       writeln('y(' , i , ')=' , y[i]:5);       end; end; procedure Sumavykl(y:vyklyk; var s:integer); var i:integer; begin    s:=0; for i:=1 to 10 do s:=s+y[i];    writeln('Сума викликів S=', s:3); end; procedure Maxkilvykl(y:vyklyk; var max:integer); var i:integer; begin    max:=y[1];    for i:=2 to 10 do       if max<y[i] then max:=y[i];    write('Максимальна кількість викликів за одну ');    writeln('секунду дорівнює ', max:3) end; begin    clrscr;    randomize;    Kilvykl(y);    Sumavykl(y, s);    Maxkilvykl(y, max);    readln end.

{Процедура Kilvykl визначає} {кількість викликів кожної секунди} {Процедура обчислює cуму викликів за перші 10 секунд} {Процедура Maxkilvykl визначає} {найбільшу кількість викликів} {за деяку секунду} {Виклик процедури Kilvykl} {Виклик процедури Sumavykl} {Виклик процедури Maxkilvykl}

        Завдання 1. Розв’яжіть задачу № 14 свого варіанта.         2. Функції (function). Функція, на відміну від процедури, може повертати в місце виклику лише один результат простого стандарт­ного типу.         Загальний опис функції:

function <назва>(<список формальних параметрів>) : <тип функції>; <розділи описів і оголошень функції>; begin    <розділ команд функції, де має бути така команда: назва:=вираз> end;

        У розділі команд функції має бути команда присвоєння значення деякого виразу назві функції. Результат функції поверта­ється в основну програму через її назву (як і випадку вико­ристан­ня станда­рт­них функцій, таких як sin, cos). Виклик функ­ції здійс­ню­ється лише з виразів

            <назва> (<список фактичних параметрів>).

        Приклад. Створимо функцію для обчислення tg(x) та обчислимо значення виразу tg(x)+ctg(x)+tg2(x).

program Myfunc; uses Crt; var x,y:real; function tg(x:real):real; begin    tg:=sin(x)/cos(x) end; begin clrscr;    writeln('Введіть х');    readln(x);    y:=tg(x)+1/tg(x)+sqr(tg(x));    writeln('y=', y:5:2); readln end.

Задача 2. Розв’язати задачу про виробництво цукерок на фабри­ці з попереднього параграфа, використовуючи функції і про­цедури користувача.

program Fabryka1; uses Crt; const n=5; type vytraty = array [1..n, 1..n] of real; var imin:integer; a:vytraty; function func(i,j:integer):real; begin    func:=2*abs(sin(i))+j; end; procedure Table(var a:vytraty); var i,j:integer; begin    writeln(' Вид сировини');    writeln(' 1 2 3 4 5');    for i:=1 to n do       begin       write(i, ' сорт');       for j:=1 to n do          begin          a[i,j]:=func(i,j);          write( a[i,j]:7:2);          end;       writeln       end; end; procedure MinSyrov(a:vytraty; var imin:integer); var i,j:integer; min:real; begin    imin:=1; min:=a[1,3];    for i:=2 to n do       if a[i,3]<min then          begin          min:=a[i,3]; imin:=i          end;    writeln('Найменше сировини третього виду ');    writeln('необхідно для цукерок ', imin, ' сорту') end; begin    clrscr;    Table(a);    MinSyrov(a, imin);    readln end.

{Утворимо таблицю затрат} {Використаємо створену функцію} {Роздрукуємо елементи і-го рядка} {Перейдемо на новий рядок} {Виклик процедури Table} {Виклик процедури MinSyrov}

        Завдання 2. Розв’язжіть задачу № 15 свого варіанта, викорис­товуючи функції та процедури.         3. Рекурсивні функції. Рекурсією називається алго­ритміч­на кон­ст­рукція, де підпрограма викликає сама себе. Рекурсія дає змо­гу записувати циклічний алгоритм, не використовуючи команду цик­­лу. Розглянемо спочатку поняття стеку.         Стек — це структура даних в оперативної пам’яті, де дані запа­м’я­товуються і зберігаються за принципом «перший при­йшов — останнім пішов». Ана­логом у військовій справі є ріжок для набоїв до автомата.         Приклад. Рекурсивна функція обчислення суми цілих чисел від a до b має вигляд

function Suma(a,b:integer):integer; begin    if a=b then Suma := a       else Suma := b + Suma(a, b–1) end;

{Це стоп-умова рекурсії} {Це неявний цикл}

        Обчислимо функцію Suma(3, 5). Формально можна записати Su­ma(3, 5) = 5 + Suma(3, 4) = 5 + 4 + Suma(3, 3) = 5 + 4 + 3. Систе­ма ви­конує такі обчислення за два етапи: 1) спочатку формує стек, куди заносить числа 5, 4, 3. На другому етапі числа додає у зворот­ній послідовності (оскільки вони надходять зі стеку): 3+4+5 = 12.         Задача 3. Скласти рекурсивну функцiю Factorial для обчис­лення факторіала числа n! = 1·2·3·...·n, (0! = 1, 1! = 1), яка грунтується на багато­разовому (рекурсивному) застосуваннi формули n! = n·(n – 1)!.

function Factorial(n : integer) : integer; begin if n = 0 then Factorial := 1       {Це стоп-умова} else Factorial := n * Factorial(n–1) end;

        Обчислимо 4!: Factorial(4) = 4 · Factorial(3) = 4 · 3 · Factorial(2) = 4 · 3 · 2 · Factorial(1) = 4 · 3 · 2 · 1 · Factorial(0) = 4 · 3 · 2 · 1 · 1. У стек будуть занесені числа 4, 3, 2, 1, 1. Результат утвориться так: 1 · 1 · 2 · 3 · 4 = 24.         Зауваження. Застосовуючи рекурсію, потрібно правильно скла­да­ти стоп-умови, які забезпечують закінчення циклічних обчислень.         Завдання 3. Скласти програму розв’язування задачі 6, викори­стовуючи рекурсивні функції.         4. Відкриті масиви. У списках формальних параметрів підпрог­рами можна описувати так звані відкриті масиви (масиви зазда­легідь невідомого розміру) так

            <назва масиву> : array of <назва базового типу>;

        У підпрограмі мінімальне значення індекса такого масиву є 0, а номер останнього елемента дає стандартна функція high(<назва масиву>). Нумерація елементів такого формального масиву у підпрог­рамі починається з нуля. Відкритий масив використовують для почер­гового опрацювання у процедурі масивів різних розмірів.         Задача 4. Використовуючи підпрограми, утворити масив y, еле­мен­ти якого задані фор­му­лою уm= fy(m)=10cos(m)+2, , та масив g з елементами gn=fg(n)=n2/2, . Об­числити в цих масивах суми еле­мен­тів більших, ніж 2. Вивести на екран резуль­тати обчислень.

program MyProcedure; {$F+} uses Crt; type myfunc=function(n:integer):real; var y:array [1..7] of real; g:array [1..9] of real; function fy(m:integer):real; begin    y:=10*cos(m)+2 end; function fg(n:integer):real; begin    g:=n*n/2 end; procedure Utvoryty(f:myfunc; var z: array of real); var i:integer; begin    for i:=0 to high(z) do       begin       z[i]:=f(i+1); write(z[i]:5:2);       end;    writeln end; function suma(z: array of real):real; var i:integer; s: real; begin    s:=0;    for i:=0 to high(z) do       if z[i]>2 then s:=s+z[i];    suma:=s end; begin    clrscr;    Utvoryty(fy, y);    Utvoryty(fg, g);    write('Сума потрібних елементів y – ');    writeln('S=', suma(y):6:2);    write('Сума потрібних елементів g – ');    writeln('S=', suma(g):6:2);    readln end.

        Зауваження. Зверніть увагу на утворення та застосування нового типу – типу функції: type myfunc=function(n:integer):real. До цього типу віднесено конкретні функції fy(x) та fg(x). Завдяки типу myfunc можна за допомогою однієї процедури утворю­ва­ти різні масиви. У зв'язку з цим використано директиву {$F+}, яка під­тримує необхідну модель (far-модель) виклику функцій.         Завдання 4. Розв’яжіть задачу № 16 свого варіанта.         5. Стандартні модулі. Підпрограми, які мають універсальне при­зна­­чення та можуть згодитись багатьом користувачам, варто об’єд­нувати у бібліотеки та модулі.         Модуль — незалежна програмна одиниця. Він містить описи констант, ти­пів даних, змінних та підпрограм. Розрізняють стандартні модулі та мо­дулі, створені користувачем.         Є такі стандартні модулі:

Crt — для роботи з екраном і клавіатурою; System — містить найчастіше вживані процедури та функ­ції; String — містить функції для роботи з рядковими змінними; Printer — для роботи з пристроєм друкування; Graph — містить процедури та функції для графічних побудов; Overlay — модуль засобів для роботи з великими програ­мами; Dos, Windows — дають змогу виконувати команди опера­ційної системи під час виконання паскаль-прог­рам чи отримувати певні дані від операційної системи; Graph3, Turbo3 — забезпечують сумісність з попередніми вер­сіями ТР тощо

        Під’єднання модулів у конкретній програмі здійснюють за до­по­могою коман

            uses <список назв модулів>;

        Процедури і функції модуля System можна застосовувати за замовчу­ванням. Саме з цього модуля компілятор бере процедури read, readln, write, writeln, стандартні функції sin, cos тощо.         Розглянемо по чотири корисні процедури з модулів System та Crt:

exit — для виходу з поточної підпрограми або при­пи­нен­ня роботи основної програми; halt — для зупинки виконання програми і передачі керу­ван­ня в операційну систему; break — для примусового виходу з циклів for, while, repeat; continue — для переходу до виконання наступної ітерації в циклах for, while, repeat; delay(n) — для затримки виконання наступної команди на заданий (n) користувачем час (у мікросекундах); clrscr — для очищення екрану перед виконанням про­грами; textcolor(колір) — задання кольору (числом від 0 до 15) текста; textbackground(колір) — для задання кольору тла (фону).

        З-поміж функцій модуля Crt часто застосовують символьну фун­кцію readkey, яка отримує значення натиснутого користувачем символу на основній символьно-цифровій частині клавіатури, а також логічну функцію keypressed, яка набуде значення true, якщо користувач натисне на будь-яку клавішу на основній клавіатурі.         У модулі Dos є процедури і функції для роботи з файловою сис­темою в режимі виконання паскаль-програми. Про­цедура         exec('<повна назва exe-файлу>', '<параметри програми>' або '') служить для запуску на виконання exe-файлу іншої програми з середини програми користувача (на початку програми користувача слід зазначити директиву {$M $2000,0,1000}, див. довідники). Корисними є також дві процедури, які дають змогу хронометрувати час вико­нання програми користувача чи її фрагментів і опрацьо­вувати дати:         GetTime(Hour, Minute, Second, SotiSec) — надає зазначеним у спи­с­ку змінним числові значення поточного часу (год, хв, сек, соті сек);         GetDate(Year, Month, Day, Number) — надає змінним зі списку типу word значення поточної дати(рік, місяць, день, день тижня).         Завдання 5. Розгляньте завдання № 3 з § 5 про обчислення зна­ко­змінної суми трьо­ма способами з точністю e=0,00001 (§ 5, п.2, задача-зразок № 4, власна задача-завдання № 7 з розділу "Задачі"). Зро­біть exe-файли для відповідних трьох програм. Складіть програму, яка буде складатися з директиви {$M...}, команди uses Crt, Dos; трьох команд типу exec('suma1.exe', ''); декількох команд get­time(...), розташованих так, щоб хронометрувати час виконання процесором кожної з під’єднаних програм. Визначіть час у мікро­се­кундах, затрачений процесором для розв’язування задачі кожним способом. Який спосіб найефективніший за часом обчислень? 6. Модулі користувача (unit). Свій модуль користувач будує за певними правилами. Струк­тура модуля така:

unit <назва>; interface <розділ описів> implementation <тексти підпрограм користувача> begin <блок ініціалізації> end.

{інтерфейсна частина} {реалізаційна частина}

        Назву модулю дає користувач. Вона має бути унікальною. У роз­ділі описів оголошують інші потрібні модулі, описують типи, сталі та заголовки підпрограм, доступні у даному модулі.         У реалізаційній частині наводять тексти підпрограм за порядком згадування їхніх заголовків у описах. Списки параметрів можна не писати, оскільки вони наведені в описах заголовків. Інтерфейс і реалізаційна частина можуть бути порожніми. Таку можливість використовують, коли необхідно описати, наприклад, спільні для багатьох програм сталі, змінні, типи даних.         У блоці ініціалізації у разі потреби задають початкові дані, від­кривають файли, чистять екран тощо. Цей блок виконується першим, тобто перед командами основного блоку головної програ­ми, до якої приєднаний даний модуль. Якщо стартовий блок не потрібний, то службове слово begin опускають.         Модулі використовуються, зокрема, у візуальному програмуванні (див. розділ 3).         Приклад. Створимо модуль для обчислення значень функцій tg(x), xy . Під час звертання до нього очистимо екран.

unit Mymodul; interface uses Crt; function tg(x:real):real; function step(x,y:real):real; implementation function tg(x:real):real; begin    tg:=sin(x)/cos(x) end; function step(x,y:real):real; begin    step:=exp(y*ln(x)) end; begin clrscr end.

        Щоб оформити підпрограму як модуль в меню середовища Турбо Паскаль в пункті Compile/Destination встановлюємо значення Disk і транслюємо її (Ctrl+F9). На диску отримаємо файл з тим же іме­нем, але з розширенням tpu. Модуль створено.         Приклад. Обчислимо tg(x) і 1.35, використовуючи модуль Mymodul.

program UseModul; uses Mymodul; var x,y,a,b,c:real; begin    a:=1.3; b:=5;    writeln('Введіть x:');    readln(x);    y:=tg(x);    writeln('tg(', x:5:2,')=', y:6:2);    c:=step(a, b);    writeln('1.3^5=', c:5:2);    readln end.

        Окремі модулі користувач може об’єднати в особисту бібліотеку (на­приклад Mybibl.tpl) за допомогою програми TpuMover, вико­навши в середовищі MS-DOS команду             tpumover <повний шлях до файлу>\Mybibl.tpl /+ Mymodul         Зауваження. Файл Mybibl.tpl необхідно розташувати в каталозі, де немає файла з системною бібліотекою turbo.tpl.         Завдання 6. Розв’яжіть задачу № 17 свого варіанта.