Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основи програмування Паскаль.docx
Скачиваний:
51
Добавлен:
12.05.2015
Размер:
511.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.