birmaga.ru
добавить свой файл

1
Лабораторная работа № 9


ПОДПРОГРАММЫ
Если в программе в нескольких местах встречаются одни и те же действия, то их можно выделить в один блок, называемый подпрограммой. В этом случае программа может называться главной или вызывающей. В языке Delphi предусмотрены два вида подпрограмм: функции и процедуры. Функция позволяет вычислить значение только одной переменной, а процедура может выполнять комплекс действий (например, решение уравнений, сортировку, поиск, вычисление значений нескольких переменных и т.п.). Программа может содержать несколько подпрограмм. Каждая подпрограмма в свою очередь может содержать несколько функций и процедур.

Текст подпрограммы состоит из заголовка, раздела описаний и раздела операторов. Заканчивается текст словом end и точкой с запятой. Текст подпрограммы записывается между описательной и операторной частями программы. Разделы описаний и операторов подпрограммы составляются по общим правилам языка Delphi.
9.1. Функции

Заголовок записывается в следующей форме:

function <имя функции>(<список формальных параметров >:<тип параметров>;<список формальных параметров>:<тип параметров>):<тип возвращаемого значения функции>; <список директив>;

Формальными параметрами на стадии описания функции называются аргументы функции. Формальные параметры могут и отсутствовать.

Примеры: function p: real;

function tor(x,y:integer): char;

function kod(x,y:real; k,m:integer; t:mat):boolean;

В функции p формальные параметры отсутствуют. В функции tor два формальных параметра одного типа. В функции kod формальный параметр t нестандартного типа. Этот тип обязательно должен быть описан в описательной части вызывающей программы. Формальные параметры не описываются ни в тексте подпрограммы, ни в тексте программы. Каждая функция имеет внутреннюю переменную result, совпадающую по типу с типом возвращаемого функцией значения. В операторной части функции хотя бы один раз имя переменно result или имя функции должно быть записано в левой части оператора присваивания.


Обращение к функции (вызов) производится по ее имени подобно обращению к стандартной функции. Вместо формальных параметров подставляются фактические параметры. Фактическими параметрами могут быть значения, имена или выражения, по которым они вычисляются. Типы и порядок следования фактических параметров должны совпадать с типами и порядком следования формальных параметров. Разделяются все фактические параметры запятой, а типы не указываются. При вызове имя функции записывается только в правой части оператора присваивания или в списке оператора вывода.
Пример 1. Рассчитать

при x = 6, y = -8, z = 5.
function qvad( s:real): real;

begin result:=(2*s+3)*s+4

end;

procedure TForm1.Button1Click(Sender:TObject);

var w, x, y, z:real;

begin x:=6: y:=-8; z:=5;

w:=qvad(x)*qvad(y)/qvad(z);

Label1.Caption:=FloatToStr(w)

end;
Процедура TForm1.Button1Click(Sender:TObject) может быть записана с вызовом функции в списке вывода:

procedure TForm1.Button1Click(Sender:TObject);

var x, y, z:real;

begin

x:=6: y:=-8; z:=5;

Label1.Caption:=FloatToStr(qvad(x)*qvad(y)/qvad(z))

end;
Пример 2. Даны три целочисленных вектора длиной n = 5.

a = 1, 3, 5, 7, 9.

b = 2, 4, 6, 8, 10.

c = 6, 5, 4, 3, 2.

Рассчитать суммы элементов массивов.

implementation
{$R *.dfm}
const n=5;

type vec=array[1..n] of integer;
function ss(d: vec): integer;

var i, s:integer;

begin

s:=0;

for i:=1 to n do s:=s+d[i];

ss:=s

end;
procedure TForm1.Button1Click(Sender: TObject);
const a:vec=(1, 3, 5, 7, 9);

b:vec=(2, 4, 6, 8, 10);

c:vec=(6, 5, 4, 3, 2);

var sa, sb, sc: integer;

begin

sa:=ss(a);

sb:=ss(b);

sc:=ss(c);

Memo1.Lines.Add('sa='+IntToStr(sa)+' sb='+IntToStr(sb)+

' sc='+IntToStr(sc))
end;

end.
Пример 3. Рассчитать длины всех трёх биссектрис треугольника. Длина биссектрисы угла А может быть вычислена по формуле:



где a, b, c - длины сторон, p=(a+b+c)/2 - полупериметр треугольника. Перед вычислением биссектрис проверить, существует ли треугольник.
implementation
{$R *.dfm}

//функция вычисления биссектрис

function lbs(x, y, z: real): real;

var p: real;

begin

p:=(x+y+z)/2; //вычисление полупериметра

result:=2*sqrt(p*(p-x)*y*z)/(y+z)//вычисление биссектрисы

end;
procedure TForm1.Button1Click(Sender: TObject);

var la, lb, lc :real; a,b,c:real;

d:boolean;

begin

Memo1.Clear; //очистка поля Memo1

a:=StrToFloat(Edit1.Text); //ввод стороны a

b:=StrToFloat(Edit2.Text); //ввод стороны b

c:=StrToFloat(Edit3.Text); //ввод стороны c
//проверка существования треугольника

d:=(a+b>c)and(a+c>b)and(b+c>a);

if not d then

begin

ShowMessage(Треугольник не сущестовует');

exit

end;
//вычисление биссектрис с помощью функции lbs

la:=lbs(a, b, c);

lb:=lbs(b, c, a);

lc:=lbs(c, a, b);
//вывод результата

Memo1.Lines.Add('Биссектрисы:');

Memo1.Lines.Add('la='+FormatFloat('0.0000',la));

Memo1.Lines.Add('lb='+FormatFloat('0.0000',lb));

Memo1.Lines.Add('lc='+FormatFloat('0.0000',lc));

end;

end.
9.2. Процедуры

Заголовок процедуры записывается в форме:

procedure <имя процедуры>(<список формальных параметров>: <тип параметров>; <список формальных параметров>:<тип параметров>);<список директив>;


В процедурах как ввод так и вывод данных выполняются с помощью параметров. Поэтому параметры делятся на две группы: параметры значения и параметры-переменные. В заголовке процедуры перед списком параметров-переменных ставится слово var, а перед списком параметров значений не ставится ничего. Параметры значения используются для ввода данных, а параметры переменные для вывода.

Примеры записи заголовков:

procedure ss;

procedure gj( n:integer; a:matr; var x:vec);

Здесь процедура ss без параметров, а в процедуре gj результат записывается в параметре-переменной x, а для ввода используются параметры значения n и a.

Вызов процедуры производится по ее имени с подстановкой фактических параметров вместо формальных параметров. Имя процедуры с фактическими параметрами образует самостоятельный оператор, после которого ставится точка с запятой. Вместо каждого формального параметра записывается фактический параметр того же типа. Имена типов и слово var не указываются. Фактические параметры разделяются запятыми.

В качестве фактических параметров-значений могут быть константы, имена переменных, имена массивов и выражения. Параметры переменные могут использоваться для ввода данных, но их основная задача сохранение результатов. При выполнении процедуры эти параметры изменяются. В качестве фактических параметров-переменных могут быть только имена переменных и имена массивов.

Параметрами-переменными следует объявлять только те, через которые подпрограмма в действительности передаёт результаты вызывающей программе. Не рекомендуется использовать параметры-переменные в заголовке функции.
Пример 4. Даны три одномерных массива длиной n=5. Составить процедуру упорядочения этих векторов по возрастанию. При передаче в подпрограмму всего массива следует первоначально описать его тип.

В приведённой ниже программе объявлена константа n для хранения размерности массива и пользовательский тип vec=array[1..n] of real.


Для упорядочения векторов по возрастанию создана процедура procedure sort(var x:vec) с формальным параметром-переменной var x:vec. Через параметр-переменную результат (упорядоченный массив) будет передаваться в вызывающую программу.
implementation
{$R *.dfm}
const n=5;

type vec=array[1..n] of real;
procedure sort(var x:vec );

var i,j:integer; u:real;

begin for i:=1 to n-1 do

for j:=1 to n-i do

if x[j]>x[j+1] then

begin

u:=x[j];

x[j]:=x[j+1];

x[j+1]:=u

end

end;
procedure TForm1.Button1Click(Sender: TObject);

var a,b,c:vec; i:byte;

begin

Randomize;

for i:=1 to n do

begin

a[i]:=Random(100);

b[i]:=-20+Random(41);

c[i]:=-20+Random(45)

end;

sort(a);

sort(b);

sort(c);

Memo1.Lines.Add(' a b c');

for i:=1 to n do

Memo1.Lines.Add(FormatFloat('0.0',a[i])+' '+

FormatFloat('0.0',b[i])+' '+

FormatFloat('0.0',c[i]))

end;

end.
При передаче подпрограмме одномерных массивов переменной длины часто используют открытые массивы. Открытый массив представляет собой формальный параметр подпрограммы, описывающий базовый тип элементов массива, но не определяющий его размерности и границы. Внутри подпрограммы такой параметр трактуется как одномерный массив с нулевой нижней границей. Верхняя граница открытого массива возвращается стандартной функцией High.
Пример 5. Дан упорядоченный по возрастанию одномерный символьный массив. Составить процедуру поиска символа, вводимого с клавиатуры.

implementation
{$R *.dfm}

const m=10;

type vec=array[1..m] of char;

const a:vec='abcdefghij';

var p:boolean; s:char; nom:integer;

procedure bin(b:vec; t:char; var r:boolean; var z:integer);


var n,k:integer; label met;

begin n:=1; k:=m;

repeat z:=(n+k) div 2;

if b[z]=t then

begin r:=true; goto met

end;

if b[z]>t then k:=z-1 else n:=z+1

until k
r:=false;

met:end;
procedure TForm1.Button2Click(Sender: TObject);

begin

s:=Edit1.Text[1]; //запись вводимого символа

bin(a, s, p, nom);

if p then Label1.Caption:=' символ есть, номер='+IntToStr(nom)

else Label1.Caption:=' символа нет '

end;
end.
Пример 6. Использование открытого массива. Три одномерных массива произвольной длины формируются с помощью датчика случайных чисел. Найти максимальный элемент в каждом массиве и максимальный элемент из найденных максимумов. При решении задачи были разработаны подпрограммы: функция function Max_Elem(d:array of integer): integer; для поиска максимального элемента с открытым массивом в качестве формального параметра; процедура procedure vvod(var z:array of integer;var st:string); для формирования исходных массивов. В заголовке процедуры указаны два формальных параметра-переменных – открытый массив z и строка st, в которую будут записываться элементы массивов. Параметры-переменные возвращают в вызывающую программу массив и строку, которая затем выводится в поле Memo1.
implementation
{$R *.dfm}
function Max_Elem(d:array of integer): integer;

var i, max:integer;

begin

max:=d[0];

for i:=1 to High(d) do

if d[i]>max then max:=d[i];

result:=max

end;
procedure vvod(var z:array of integer;var st:string);

var i:byte;

begin

st:='';

for i:=Low(z) to High(z) do

begin

z[i]:=random(50);

st:=st+IntToStr(z[i])+' '

end;

end;
procedure TForm1.Button1Click(Sender: TObject);

var a,b,c:array of integer;s:string;


ma, mb, mc,n,y:integer;
begin

Randomize;

n:=StrToInt(Edit1.Text);

SetLength(a,n); SetLength(b,n+1); SetLength(c,n-1);

vvod(a,s);Memo1.Lines.Add(s);

vvod(b,s);Memo1.Lines.Add(s);

vvod(c,s);Memo1.Lines.Add(s);

ma:= Max_Elem(a);

mb:= Max_Elem(b);

mc:= Max_Elem(c);

Memo1.Lines.Add('ma='+IntToStr(ma)+' mb='+IntToStr(mb)+

' mc='+IntToStr(mc));

y:=Max_Elem([ma,mb,mc]); //использование конструктора массива

Memo1.Lines.Add(IntToStr(y));

a:=nil; b:=nil; c:=nil

end;
//обработка ошибок ввода в Edit1

procedure TForm1.Edit1Exit(Sender: TObject);

begin

if (Length(Edit1.Text)=0) or (StrToInt(Edit1.Text)<1) then

begin

ShowMessage ('В поле должно быть число >1');

Edit1.SetFocus;

end;

end;
end.


9.3. Область действия имен

Переменные и метки, описанные в вызывающей программе, действуют в разделах операторов вызывающей программы и в подпрограммах. Они называются глобальными. Переменные, описанные в подпрограмме, действуют только в этой подпрограмме и называются локальными. После выполнения подпрограммы значение локальной переменной становится недоступным для операторов вызывающей программы. Аналогично в подпрограмме могут описываться и использоваться локальные метки.

Подпрограмме доступны только те объекты верхнего уровня, которые определены до описания данной подпрограммы. Эти объекты являются глобальными по отношению к подпрограмме.

Если переменная описана и в вызывающей программе и в подпрограмме (глобальная и локальная переменная имеют одинаковое имя), то после вызова подпрограммы глобальная переменная как бы забывается, а локальная вычисляется независимо от глобальной переменной. После выполнения подпрограммы глобальная переменная принимает то значение, которое было у нее перед вызовом подпрограммы.


Две простейшие программы иллюстрируют различия работы с глобальными и локальными переменными.


var i:integer; var i:integer;

procedure loc; procedure loc;

var i:integer;

begin i:=0; begin i:=0;

i:=i+2; i:=i+2;

Form1.Label1.Caption:= Form1.Label1.Caption:=

‘iloc=‘+IntToStr(i) ‘iloc=‘+IntToStr(i)

end; end;

//вызывающая программа //вызывающая программа
begin i:=10; begin i:=10;

loc; loc;

i:=i+4; i:=i+4;

Form1.Label2.Caption:= Form1.Label2.Caption:=

‘iglob =‘+IntToStr(i) ‘iglob =‘+IntToStr(i)

end; end;
Ответ iloc=2 iloc=2

iglob=6 iglob=14
Рабочее задание


  1. Составить вызывающую программу и подпрограмму согласно варианту задания.

  2. Составить программу расчета функции из лабораторной работы №1 с помощью подпрограммы - функции.

Написать отчет, содержащий

- задание,

- принятые обозначения,

- блок-схему

- программу,

- результаты.
Варианты заданий к лабораторной работе № 9

  1. Заданы три вектора длиной n каждый. Составить функцию вычисляющую количество нулевых элементов в каждом векторе. Вывести на экран массив с наибольшим количеством нулевых элементов.

  2. Заданы три вектора одинаковой длины. Составить процедуру поиска минимального элемента. Вывести на экран наименьший из трех найденных элементов.

  3. Даны два одномерных массива произвольной длины. Вычислить для каждого массива среднее арифметическое. Из элементов исходных массивов сформировать новый массив и рассчитать среднее арифметическое. Для расчета средних арифметических составить подпрограмму.
  4. 4. Вычислить и вывести таблицу значений С= для n=28 и k=1  (n-1). Для расчета факториала применить подпрограмму.


  5. Задана целочисленная матрица размером n*n. Переставить столбцы в порядке убывания максимальных элементов столбцов. Поиск максимальных элементов оформить в виде подпрограммы.

  6. Задана квадратная матрица. Переставить элементы каждой строки по возрастанию. Для упорядочения элементов строки составить процедуру.

  7. Задана матрица n*m. Переставить элементы столбцов в порядке убывания. Для упорядочения элементов столбца составить процедуру.

  8. В памяти ЭВМ хранится список фамилий абонентов в алфавитном порядке и номера их телефонов. Составить подпрограмму, обеспечивающую быстрый поиск номера телефона по фамилии абонента.

  9. В памяти ЭВМ хранится список фамилий абонентов в алфавитном порядке и номера их телефонов. Составить подпрограмму, обеспечивающую быстрый поиск фамилии абонента по номеру телефона.

  10. Дана матрица n*m. Элементы нечетных столбцов матрицы расставить в порядке возрастания. Для упорядочения элементов столбца составить процедуру.

  11. В кассе имеются купюры (монеты) достоинством 500, 100, 50, 10, 5, 2 и 1 рубль. Составить процедуру подбора любой суммы в пределах 1000 рублей для оплаты или сдачи имеющимися купюрами.

  12. Даны длины трех сторон треугольника. Составить функцию для расчета длины медианы и вычислить длины всех медиан.

  13. Даны длины трех сторон треугольника. Составить функцию для расчета высоты треугольника и вычислить все три высоты.

  14. Даны порядковые номера, фамилии спортсменов - лыжников и показанное время. Составить процедуру , определяющую место ( индекс) каждого лыжника.

  15. Координаты вершин треугольника записаны в виде двух векторов из трех элементов каждый - x1, x2, x3 и y1, y2, y3 . Составить функцию для расчета площади треугольника.
  16. Даны массивы координат x, y, z и масс m системы из n материальных точек. Составить функцию для определения координат центра тяжести системы.

  17. Плоская система из n сил задана массивами координат x и y точек приложения сил и массивами проекций сил px и py на координатные оси. Составить процедуру для расчета главного вектора и главного момента.

  18. Даны две матрицы: А размером n*m и В размером m*k. Составить процедуру расчета элементов матрицы С - произведения матриц А и В.