- •Основи програмування мовою Паскаль
- •Часть 1. Основы языка Паскаль 2
- •Часть 2. Элементы профессионального программирования на Паскалі 62
- •Частина 1. Основи мови Паскаль
- •1. Алгоритм і програма
- •1.1. Алгоритм
- •1.2. Властивості алгоритму
- •1.3. Форми запису алгоритму
- •1.4. Програма й програмне забезпечення
- •1.5. Етапи розробки програми
- •2. Дані в мові Паскаль
- •2.1 Константи
- •2.2 Змінні й типи змінних
- •3. Арифметичні вирази
- •4. Лінійний обчислювальний процес
- •4.1 Оператор присвоювання
- •4.2 Оператор уведення
- •4.3 Оператор виведення
- •4.4 Керування виводом даних
- •4.5 Вивід на друк
- •5. Структура простої програми на Паскалі
- •6. Компілятор і оболонка Turbo Pascal
- •7. Обчислювальний процес, що розгалужується, і умовний оператор
- •7.4. Короткий умовний оператор
- •If логічний_вираз then оператор1;
- •7.5. Повний умовний оператор
- •If логічний_вираз then оператор1
- •7.7. Вкладені умовні оператори
- •7.9. Приклади програм з умовним оператором
- •8. Директиви компілятора й обробка помилок уведення
- •9. Оператор циклу. Цикли із передумовою і після-умовою
- •10. Цикл із лічильником і дострокове завершення циклів
- •11. Типові алгоритми табулювання функцій, обчислення кількості, суми й добутку
- •11.1 Алгоритм табулювання
- •11.2 Алгоритм організації лічильника
- •11.3 Алгоритми нагромадження суми й добутку
- •12. Типові алгоритми пошуку максимуму й мінімуму
- •13. Розв'язок навчальних завдань на цикли
- •14. Одномірні масиви. Опис, уведення, вивід і обробка масивів на Паскалі
- •15. Розв'язок типових завдань на масиви
- •Частина 2. Елементи професійного програмування на Паскалі
- •16. Кратні цикли
- •16.1 Подвійний цикл і типові завдання на подвійний цикл
- •16.2 Оператор безумовного переходу
- •17. Матриці й типові алгоритми обробки матриць
- •18. Підпрограми
- •18.1 Процедури
- •18.2 Функції
- •18.3 Масиви як параметри підпрограми
- •18.4 Відкриті масиви
- •19. Безлічі й перечислимые типи
- •20. Обробка символьних і строкових даних
- •20.1. Робота із символами
- •20.2 Робота з рядками
- •21. Текстові файли
- •21.1 Загальні операції
- •21.2 Приклади роботи з файлами
- •21.3 Робота з параметрами командного рядка
- •22. Записи. Бінарні файли
- •23. Модулі. Створення модулів
- •23.1. Призначення й структура модулів
- •Implementation
- •23.2. Стандартні модулі Паскаля
- •24. Модуль crt і створення простих інтерфейсів
- •25. Модуль Graph і створення графіки на Паскалі
- •Додаток 1. Таблиці Ascii-Кодів символів для операційних систем dos і Windows
- •Додаток 2. Основні директиви компілятора Паскаля
- •Додаток 3. Основні повідомлення про помилки Паскаля
- •Додаток 4. Додаткові лістинги програм
- •Додаток 5. Розширені коди клавіатури
- •Ascii‑ коди
- •Розширені коди
- •Додаток 6. Правила гарного коду
- •Додаток 7. Рекомендована література
18.3 Масиви як параметри підпрограми
Найчастіше підпрограма-процедура або функція повинна обробити деякий масив даних. Однак структурний тип масиву не можна безпосередньо вказати в списку формальних параметрів. У цьому випадку тип масиву оголошується заздалегідь у розділі описів за допомогою підрозділу type:
Type Имятипа = Описаниемассива;
Тут ИмяТипа– найменування, що дається програмістом, нового типу даних,а Описаниемассива – відомий нам оператор опису вектора або матриці. Наприклад, якщо підпрограма повинна обробляти дійсні масиви, що не перевищують по розмірності десяти елементів, у розділі описів програми має сенс зробити наступне оголошення:
Type vector = array [1..10] of real;
Оскільки новий тип даних vectorпризначений для використання підпрограмами, зазначене вище оголошення розташовуєтьсядовсіх підпрограм.
Надалі тип даних vectorможна використовувати як у розділі опису змінних:
Var a,b:vector;
так і в списку формальних параметрів функції або процедури:
function work (a:vector):real;
Якщо за умовою завдання в підпрограмі потрібно при різних обігах обробляти масиви різної розмірності, то в розділі typeоголошується тип масиву знайбільшоїз размерностей, що зустрічаються в завданні. Це чревате тим, що при обробці масивів меншої розмірності частина пам'яті залишиться невикористаної. Крім того, при звертанні до підпрограми в цьому випадку доводиться окремим параметром передавати фактичну розмірність масиву.
Допустимо, за допомогою підпрограми потрібно знайти максимальні елементи матриць A3x4, B4x3, C4x5. З обліком максимальної з наявних размерностей, оголошуємо типу matrix у розділі описів:
Type matrix = array [1..4,1..5] of real;
Далі описуємо конкретні матриці як об'єкти нового типу даних matrix:
Var a,b,c:matrix;
У якості підпрограми пошуку значення максимального елемента матриці напишемо функцію Max1(функцію, а не процедуру, оскільки максимум – скалярне значення). У цю функцію нам доведеться передати 2 додаткових параметра-значення рядків, щовизначають кількість, nікількість стовпців m у конкретній матриці, переданої фактичним параметром:
Function Max1 (n,m:integer; var a:matrix):real;
Var max:real; i,j:integer;
Begin
Max:=a[1,1];
For i:=1 to n do
For j:=1 to m do
If a[i,j]>max then max:=a[i,j];
Max1:=max;
End;
Використання додаткової локальної змінної maxпов'язане з тими ж причинами, що в першому прикладі на функції. Зверніть увагу, що, хоча функціяMax1і не змінює елементи своїх матриць-параметрів, у списку її формальних параметрів матриця зазначена як параметр-змінна. Для матриць і векторів це рекомендується робитизавжди, оскільки при вказівці параметра-змінної в матрицю передається тількиадресатого місця пам'яті, де зберігаються її дані, а не копія всіх елементів. В остаточному підсумку, передача матриць і векторів формальним параметрам-змінним дозволяє зменшити розмір генерируемого машинного коду.
Викликати нашу функцію для матриць A,BіCми могли б так:
Var ma,mb,mc:real;
. . .
ma:=max1(3,4,a);
mb:=max1(4,3,b);
mc:=max1(4,5,c);
Більш зручну роботу з масивами-параметрами пропонує механізм відкритих масивів, розглянутий нижче. Однак його безпосередньо використовують лише для одномірних масивів.
Поки ж розглянемо приклади розв'язку типових завдань.
Пр.Задані вектора A і B, що містять по 5 елементів. Використовуючи підпрограму, знайти їхній скалярний добуток по формулі
Пошук скалярного добутку реалізуємо у вигляді підпрограми-функції scal.
type vector=array [1..5] of real;
function scal (n:integer; var a,b:vector):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+a[i]*b[i];
scal:=s;
end;
var i:integer;
a,b:vector;
s:real;
begin
writeln ('Вектор 1 з 5 елементів:');
for i:=1 to 5 do read (a[i]);
writeln ('Вектор 2 з 5 елементів:');
for i:=1 to 5 do read (b[i]);
s:=scal(5,a,b);
writeln ('S=',s:10:3);
end.
Пр.Сформувати по введеному із клавіатури векторіAрозмірностіnвекторRes, компонентами якого є відхилення елементівAвід їхнього арифметичного середнього (подібне завдання вже вирішувалося вище, розширимо її на випадок вектора).
Завдання припускає написання, щонайменше, двох підпрограм: функція Middleбуде обчислювати арифметичне середнє елементів вектора, а процедураOtkl– формувати по векторуAі раніше знайденому середньому midшуканий вектор відхиленьb. Компоненти вектораbпри цьому будуть обчислюватися по формуліОскільки про розмірність векторів у завданні нічого не сказане вкажемо в розділіtypeмаксимальну розмірність, рівну100елементам.
type vector= array [1..100] of real;
function Middle (n:integer; var a:vector):real;
var j:integer;
res:real;
begin
res:=0.0;
for j:=1 to n do res:=res+a[j];
Middle:=res/n;
end;
procedure Otkl (n:integer; mid:real; var a,b:vector);
var j:integer;
begin
for j:=1 to n do b[j]:=abs(a[j]-mid);
end;
var a,res: vector;
i,n:integer;
s:real;
begin
write ('Розмірність? ');
readln (n);
for i:=1 to n do begin
write ('A[',i,']=');
readln (a[i]);
end;
s:=Middle (n,a);
Otkl (n,s,a,res);
for i:=1 to n do writeln ('Res[',i,']=',res[i]:8:2);
end.
Пр.Використовуючи підпрограму, написати й перевірити програму перемножування двох матриць.
Як відомо, матриця Aрозмірністюn*mможе бути помножена на матрицюBрозмірністюm*pпо наступній формулі:де ci,j– елемент матриці, щовиходитьурезультаті перемножування, З розмірністю n*m. З формули видне, що для множення двох матриць нам знадобиться потрійний цикл: зовнішній цикл поiперебирає рядка матриціA, вкладений у нього цикл поjвибирає в матриціBчерговий стовпець, а самий внутрішній цикл поlмножить рядок матриціAна стовпець матриціB, одержуючи елемент ci,j. Напишемо відповідну процедуруmmulі тестову програму для неї:
type matrix=array[1..10,1..10] of real;
var a,b,c: matrix;
i,j,n,m,p: integer;
procedure mmul (n,m,k:integer; var a,b,c:matrix);
var i,j,l:integer;
s:real;
begin
for i:=1 to n do
for j:=1 to k do begin
s:=0;
for l:=1 to m do s:=s+a[i,l]*b[l,j];
c[i,j]:=s;
end;
end;
begin
repeat
writeln;
write ('Уведіть кількість рядків 1 матриці: ');
readln (n);
write ('Уведіть кількість стовпців 1 матриці: ');
readln (m);
write ('Уведіть кількість стовпців 2 матриці: ');
readln (p);
until (n>1) and (n<11) and (m>1) and (m<11) and (p>1) and (p<11);
for i:=1 to n do begin
writeln ('Уведіть рядок ',i,' матриці A з',m,'елементів:');
for j:=1 to m do read (a[i,j]);
end;
for i:=1 to m do begin
writeln ('Уведіть рядок ',i,' матриці B з',p,'елементів:');
for j:=1 to p do read (b[i,j]);
end;
mmul (n,m,p,a,b,c);
for i:=1 to n do begin
writeln;
for j:=1 to p do write (c[i,j]:10:3);
end;
end.
Процедурно орієнтовані програми для розповсюджених завдань розв'язку системи лінійних рівнянь методом Гаусса, сортування одномірного масиву, пошуку всіх мінорів другого порядку у квадратній матриці Ви можете знайти й самостійно розібрати в Додатку 4.
У якості ще одного розгорнутого прикладу на використання масивів у підпрограмах, розберемо наступне завдання:
Пр.Є N міст, між якими налагоджені пасажирські перевезення. Між якими містами самий активний пасажиропотік?
Кількість міст позначимо константою Cities. Після математичної формалізації завдання, неважко помітити, що перевезення з містаiу містоjможуть бути занесені в елемент матриціai,j, таким чином, потрібно визначити величинуmax(ai,j+aj,i), враховуючи перевезення "туди" і "назад". Для пошуку максимального пасажиропотоку досить подвійного циклу зі змінною границею по лічильникові вкладеного циклу. Як і в інших програмах, виділимо в окремі підпрограми також типові завдання введення й виведення матриці, а також уведення речовинного значення з контролем припустимих числових границь уведення.
const Cities=10;
type matrix=array [1..Cities,1..Cities] of integer;
function Max1 (n:integer; var a:matrix; var imax,jmax:integer):integer;
var i,j,m,p:integer;
begin
m:=a[1,2]; imax:=1; jmax:=2;
for i:=1 to n do
for j:=1 to n do
if (i<>j) then begin
p:=a[i,j]+a[j,i];
if p>m then begin
m:=p; imax:=i; jmax:=j;
end;
end;
Max1:=p;
end;
function Readnumber (s:string; min,max:integer):integer;
var a:integer;
begin
repeat
write (s);
{$I-}readln(a);{$I+}
if Ioresult<>0 then writeln ('Помилка, уведене не число!')
else if (a<min) or (a>max) then
writeln ('Помилка, уведене число не належить інтервалу [',min,',',max,']')
else break;
until false;
Readnumber:=a;
end;
procedure Readmatrix1 (var n:integer; var a:matrix);
var i,j:integer;
s,s1:string;
begin
n:=Readnumber ('Уведіть число рядків і стовпців матриці: ',2,Cities);
for i:=1 to n do
for j:=i+1 to n do begin
s:='A['; Str(i,s1); s:=s+s1+',';
Str(j,s1); s:=s+s1+']=';
a[i,j]:=Readnumber (s,0,Maxint);
end;
end;
procedure Writematrix1 (s:string; n:integer; var a:matrix);
var i,j:integer;
begin
writeln (s);
for i:=1 to n do begin
for j:=1 to n do write (a[i,j]:7);
writeln;
end;
end;
var a:matrix;
n,gorod1,gorod2:integer;
begin
Readmatrix1 (n,a);
Max1 (n,a,gorod1,gorod2);
Writematrix1 ('A=',n,a);
writeln (' Найбільший пасажиропотік між містами ',gorod1,' і ',gorod2);
readln;
end.