laba5
.pdfНАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ УКРАИНЫ «КИЕВСКИЙ ПОЛИТЕХНИЧЕСКИЙ ИНСТИТУТ»
___________________________________________________
Факультет биомедицинской инженерии Кафедра биомедицинской кибернетики
МЕТОДИЧЕСКИЕ УКАЗАНИЯ К ВЫПОЛНЕНИЮ ЛАБОРАТОРНОЙ РАБОТЫ № 5
ПО ДИСЦИПЛИНЕ «ТЕОРИЯ АЛГОРИТМОВ»
Преподаватель ас. Яковенко А.В.
Киев 2013
Тема: «Процедуры и функции»
5.1 Общие сведения
В языке Turbo Pascal, как и во всех других современных языках программирования, имеется возможность разбиения программы на относительно независимые части, называемые подпрограммами. Разбивают программы на подпрограммы для того, чтобы:
1. Облегчить создание и отладку программы (маленькие независимые куски программы легче создавать и отлаживать, чем одну большую программу).
2. Сократить размер исходного текста и кода программы (в программе часто имеются повторяющиеся части, и если их вынести в подпрограммы, то размер исходного текста программы уменьшится).
В разных языках программирования существуют разные правила работы с подпрограммами. В языке Turbo Pascal существует два вида подпрограмм. Первый - это процедуры, второй - функции. Процедура -это подпрограмма, в которой выполняются определенные действия. Функция - это подпрограмма, в которой также выполняются определенные действия, но, в отличие от процедуры, в функции вычисляется и возвращается значение функции. Определения процедур и функций в Turbo Pascal очень похожи. Определение функций немного сложнее, чем определение процедур. Мы начнем изучать работу с подпрограммами именно с процедур.
Процедура — это независимая поименованная часть программы, которую можно вызвать по имени для выполнения какой-то законченной последовательности действий.
Структура процедуры на языке Turbo Pascal имеет следующий вид:
procedure <имя процедуры>(<описание формальных параметров>); <директивы>; {блок описания локальных меток, констант, типов, переменных, процедур и функций низшего уровня}
begin
{тело процедуры}
end;
<имя процедуры> — идентификатор языка Turbo Pascal. При вызове процедуры формальные параметры заменяется фактическими параметрами. Формальные параметры резервируют место для фактических параметров. Через эти параметры происходит обмен данными процедуры с основной программой. Имена формальных параметров выбираются произвольно. При обращении к процедуре из основной программы количество и порядок следования фактических параметров должен в точности соответствовать количеству и порядку следования формальных параметров в заголовке процедуры. В противном ату чае обращение к процедуре может привести к ошибке. В частности, ошибка может возникнуть из-за несовпадения типов формального и фактического параметра.
Функция отличается от процедуры тем, что результатом ее работы является единственное значение, поэтому обращение к функции можно использовать в выражениях наряду с переменными и константами.
Структура функции на языке Turbo Pascal имеет следующий вид:
function <имя функции>(<описание формальных параметров>); <тип результата>; <директивы>; {блок описания локальных меток, констант, типов, переменных, процедур и функций низшего уровня}
begin
{раздел операторов} <имя функции> := <результат>
end;
Обратите внимание — в разделе операторов функции должен находиться но крайней мере один оператор, который присваивает ее имени значение, возвращаемое как результат работы функции. Если таких присваиваний несколько, то результатом выполнения функции будет значение последнего оператора присваивания. Если же такой оператор отсутствует или не был выполнен, то значение, возвращаемое функцией, останется определенным.
Функция, также как и процедура вызывается по ее имени: <имя функции>(<фактические параметры>)
Пусть имеется функция вычисления тангенса угла α:
function Tangent(alpha:real):real; begin
Tangent:=sin(alpha)/cos(alpha) {alpha - значение угла в радианах!!!
1 рад. = 180°/π ≈ 57°}
end;
Вызвать функцию можно следующим образом:
Tangent(Pi);
y := Tangent(Pi);
Здесь Pi — это фактический параметр функции, который в свою очередь является стандартной функцией языка Turbo Pascal возвращающей число π. Таким образом, в функции будем иметь следующее значение:
alpha = 3.1415926535897932385
В отличие от процедуры, вызов функции не оформляется в виде отдельного оператора (хотя это и не запрещено). Обращение к функции осуществляется путем использования указателя функции в качестве операнда в некотором выражении.
Указатель функции представляет собой имя функции со списком аргументов - фактических параметров, если таковые предусмотрены в описании функции. Как для функции, так и для процедуры список формальных параметров, следующий за ее именем, является необязательным.
Формальные и фактические параметры
Формальные параметры подпрограммы указывают, с какими параметрами следует обращаться к этой подпрограмме (количество параметров, их последовательность, типы). Как уже было показано выше, формальные параметры задаются в заголовке подпрограммы в виде списка параметров, разбитого на группы, разделенные точками с занятыми. В группу формальных параметров включаются однотипные параметры одной категории.
Все формальные параметры можно разбить на четыре категории:
■параметры-значения (эти параметры в основной программе подпрограммой не меняются);
■параметры-переменные (эти параметры подпрограмма может изменить в основной программе);
■параметры-константы;
■параметры-процедуры и параметры-функции (т.е. параметры процедурного
типа).
Для каждого формального параметра следует указать имя и, как правило, тип, а в ату чае параметра-переменной или параметра-константы -его категорию.
При обращении к подпрограмме формальные параметры заменяются на соответствующие фактические вызывающей программы или подпрограммы.
Параметры-значения
Описание:
var <имя параметра> : <тип параметра>
Процедуре передается копия фактического параметра, и в ходе выполнения процедуры изменяется только эта копия. Ее изменение никак не влияет на значение фактического параметра. Это называется передачей параметра по значению. Параметру-значению при вызове процедуры должен соответствовать фактический параметр - выражение указанного типа. Тип параметра-значения может быть любым за исключением файлового.
Если параметров значений одного типа несколько, их можно объединить в одну группу, перечислив их имена через занятую, а затем уже указать общий тип.
Отдельные функции параметров отделяют друг от друга точкой с занятой, например:
procedure Inp(max, min: real; n: word); function Mult(x, y: integer): real;
В качестве фактического параметра на месте параметра-значения при вызове подпрограммы может выступать любое выражение совместимого для присваивания типа, не содержащее файловую компоненту, например:
Inp(abs(z), -abs(t), 2*k);
M := Mult(x+y, x-y);
M := Mult(7, a div 3);
Параметры-переменные
Для того, чтобы значение фактического параметра могло изменяться в ходе выполнения процедуры, его описанию должно предшествовать служебное слово var, действие которого распространяется до ближайшей точки с занятой, т.е. в пределах одной группы. Такой параметр рассматривается как параметр-переменная.
Описание:
var <имя параметра> : <тип параметра>
Процедуре передается адрес фактического параметра, поэтому изменение соответствующего формального параметра внутри процедуры изменяют и фактический параметр. Это называется передачей параметра по ссылке (имеется в виду ссылка на адрес фактического параметра). Параметру-переменной при вызове процедуры должен соответствовать фактический параметр - неременная указанного типа. Тип параметров-переменных может быть любым, включая и файловый.
Параметры-константы
Описание:
const <имя параметра> : <тип параметра>
Процедуре передается адрес фактического параметра, однако такому параметру невозможно присвоить новое значение в ходе выполнения процедуры
(это блокируется компилятором). Параметру-константе при вызове процедуры должен соответствовать фактический параметр — выражение указанного типа.
Все выходные параметры процедуры, через которые основной нро-1рамме передаются результаты работы процедуры, должны быть описаны как параметрыпеременные. С другой стороны, использование параметров-значений или констант позволяет работать с фактическими параметрами - выражениями, а также гарантирует невозможность случайно изменить значение фактического параметра при работе процедуры, что повышает надежность программы. Необходимо также учитывать, что использование параметров-значений требует дополнительных затрат памяти (так как для копии каждого параметра-значения отводится дополнительное место в памяти).
Параметры одного типа и назначения можно перечислить через запятую. Описание параметров разных типов и разного назначения отделяются точкой с запятой, например:
procedure elephant(const cl23: integer; i, j: integer;
a, b, c: real; var f1: real);
Здесь с123 — параметр-константа, i и j — параметры-значения целого типа, а, b и с - параметры-значения вещественного типа, f1 - параметр-переменная вещественного типа.
Параметры без типа
В Turbo Pascal можно использовать параметры-переменные и параметрыконстанты без указания типа. В этом случае фактический параметр может быть переменной любого типа, а ответственность за правильность использования того или иного параметра возлагается на программиста, например:
procedure Shark(var par1, par2; len: word): real;
Здесь par1, par2 — параметры-переменные без типа (вместо них можно использовать, например, любые переменные простого типа, типа-массив, типазапись и т.д.); len - параметр-значение.
Следует иметь в виду, что параметр без типа внутри программы типа не имеют и его перед использованием следует преобразовать к конкретному типу, применяя идентификатор соответствующего типа, при этом полученный результат может быть любого размера.
Массивы и строки открытого типа
В Turbo Pascal версии 7.0 можно в качестве параметров-переменных использовать одномерные массивы и строки открытого типа, у которых не задаются размеры. В качестве фактического параметра в этом случае можно использовать массив или строку любого размера, однако массив должен состоять из тех же компонент, что и компонент открытого массива. Такие параметры выделены для того, чтобы подпрограмма могла обрабатывать массив или строку любого размера. Фактический размер массива в этом случае может быть определен с помощью функции High.
Рассмотрим функцию вычисления максимального элемента в массиве. Используем в качестве передаваемого параметра массив открытого типа:
function Max(var Mas: array of integer):integer; var N: integer;
i: byte;
begin
N := Mas[0] ;
{цикл до наибольшего индекса} for i:=l to High(Mas) do
if N < Mas[i] then N := Mas[i]
Max := N
end;
В этом примере в подпрограмму передается только один параметр, и она может работать с любым одномерным массивом целых чисел. Однако следует иметь в виду, что при работе подпрограммы для открытого массива в стеке создается его копия, что может привести к переполнению стека.
Function High(Х: <тип>): Word;
Возвращает максимальное значение величины.
X - параметр или идентификатор порядкового типа, типа-массива, типа-строки или открытый массив. Результат функции для величины порядкового типа - максимальное значение этой величины, типа-массива - максимальное значение индекса, типа-строки — объявленный размер строки, открытого массива — количество компонент массива минус 1 (максимальный индекс, при начале нумерации с нуля).
Function Low(X:<тип>): Word;
Возвращает минимальное значение величины.
X - параметр или идентификатор порядкового типа, типа-массива, типа-строки или открытый массив. Результат функции для величины порядкового типа - минимальное значение этой величины, типа-массива - минимальное значение индекса, типа-строки или открытого массива — 0.
Пример 1. Проиллюстрируем использование процедур и функций в программе вычисляющей значения функции Sin(x) с заданной точностью с помощью суммирования степенного ряда.
Требуется написать программу расчета суммы членов степенного ряда
,
представляющего собой разложение тригонометрической функции Sin(x). Вычисление необходимо организовать в виде отдельной процедуры и функции. Результаты следует сравнить со значением, полученным с помощью стандартной функции Sin(x) языка Turbo Pascal.
Входные данные: Два вещественных числа epsilon (точность вычисления) и х (значение аргумента).
Выходные данные: Суммы членов степенного ряда полученные с помощью процедуры и функции, написанные пользователем, и стандартной функции Sin(.v)
языка Turbo Pascal.
Примеры входных и выходных данных:
Входные данные |
Выходные данные |
|
|
|
|
ерзі1оп=0.0\х=0 |
0.00000000 - результат работы процедуры |
|
|
0.00000000 |
- результат работы функции |
|
0.00000000 |
- результат работы стандартной функции |
|
|
|
ерзі1оп=0.0\ х=2 |
0.90934744 - результат работы процедуры |
|
|
0.90934744 |
- результат работы функции |
|
0.90929742 |
- результат работы стандартной функции |
|
|
|
В нашем примере достаточно описать в основной программе переменные: epsilon - заданная точность вычисления; х - аргумент функции; sinus - результат вычисления функции с помощью ряда. Эти переменные будут глобальными но отношению к процедуре вычисления функции sinus. Вспомогательные переменные будут локальными (локализованными внутри процедуры). В процедуре суммирования ряда sinl используются следующие формальные параметры: el - заданная точность вычисления; xl — аргумент функции. Эти параметры не изменяются при выполнении процедуры и поэтому передаются но значению (как параметры-значения), sin — результат вычисления; он должен быть передан в основную программу и поэтому описывается как параметр-переменная. В принципе, можно было использовать для формальных параметров имена epsilon, х, sinus, поскольку в данном случае это не должно привести к недоразумению. Результатом работы процедуры является единственное значение si. Поэтому в данном случае можно было использовать функцию. Такая функция описана далее в программе под именем sin2. Используются формальные параметры: е2 - заданная точность вычисления; х2 — аргумент функции. Значение функции имеет тип extended.
{$N+} program P1; uses Crt;
{Описание глобальных переменных} var epsilon, x, sinus: extended;
procedure sinl(el,xl:extended; var si:extended);
{Описание локальных переменных} var s, sqrx: extended;
n: byte;
begin
{Раздел операторов процедуры sinl} s := x1; {перзый член ряда}
n := 1; {степень члена ряда} s1 := 0; {сумма ряда}
sqrx := sqr(x1); while abs(s) > e1 do
begin
s1 := si + s; n : = n + 2;
s := -s * sqrx / ((n-1) * n);
end
end;
Function sin2(e2,x2:extended): extended;
{Описание локальных переменных} var s, sqrx, s2: extended;
n: byte;
begin
{Раздел операторов функции sin2} s := x2; {перзый член ряда}
n := 1; {степень члена ряда} s2 := 0; {сумма ряда}
sqrx := sqr(x2); while abs(s) > е2 do begin
s2 := s2 + s; n := n + 2;
s := -s * sqrx / ((n-1) * n)
end;
{Присваивание вычисленного значения s2 функции sin2} sin2 := s2
end; begin
clrscr; {очистка экрана} writeln('Вычисление функции SIN(X):');
write('Введите заданную точность: epsilon='); readln(epsilon);
write('Введите аргумент функции: х='); readln(х);
{Вызов процедуры sinl} sinl(epsilon, х, sinus);
{При обращении к процедуре sinl формальные параметры el, xl, si заменяются фактическими epsilon, х, sinus}
write(sinus:20:18, ' - '); writeln('результат работы процедуры'); write(sin2(epsilon, х):20:18, ' - ');
{Здесь обращение к функции происходит внутри оператора writeln, что допустимо, поскольку аргументом этого оператора является выражение} writeln(' результат работы функции'); write(sin(х):20 :18, ' - ') ;
writeln('результат работы стандартной функции'); readkey; {считывание кода нажатой клавиши} {readkey: char - стандартная функция языка
Turbo Pascal описанная в модуле CRT}
end.
Пример 2. Необходимо ввести массив целых чисел, заменить минимальный элемент, вывести получившийся массив. Данная задача имеет следующий общий алгоритм решения: -
1.Ввести массив.
2.Найти индекс минимального элемента.
3.Замена элемента с найденным индексом.
4.Вывести массив.
Program SimpleProcedureExample; Const {Определение констант}
maxN = 20; {Максимально возможное количество элементов в массиве} Туре {Определение типов}
IndexEl = 1..maxN; {Индексы массива лежат в интервале от 1 до maxN}
arrInt = array[IndexEl] of integer; {Массив целых чисел, содержащий до maxN элементов}
Var {Объявление переменных}
А: arrlnt; |
{Массив} |
N: integer; |
{Количество элементов в массиве} |
I: IndexEl; |
{Переменная для сканирования массива} |
IndMin: IndexEl; {Номер минимального элемента массива} {Определение процедур}
{ReadArray - процедура ввода массива с клавиатуры} procedure ReadArray;
begin
{1 - ввод количества элементов} repeat
write('Введите n:'); readln(n);
until (n >= 1) and (n <= maxN);
{2 - ввод элементов массива поодиночке} for і := 1 to n do
begin
write('a[',i,']='); readln(a[i]);
end;
end; {Конец процедуры ReadArray}
{FindlndMin - процедура поиска индекса минимального элемента} procedure FindlndMin;
begin
{Ищем индекс min элемента} indMin := 1;
for і := 2 to n do
if A[i] < A[indMin] then IndMin := i; end; {Конец процедуры FindlndMin}
{DeleteMin - процедура удаления минимального элемента} procedure DeleteMin:
begin
{Удаляем элемент массива с индексом indMin} for і := indMin to n-1 do
A[i] := A[i+1]; dec(n);
end; {Конец процедуры DeleteMin}
{PrintArray - процедура вывода массива на экран} procedure PrintArray;
begin
{Выводим массив} writeln;
for i := 1 to n do