ЛАБОРАТОРНАЯ РАБОТА №3
Разработка процедур и функций
Цель и задача работы: изучить работу с подпрограммами-процедурами и подпрограммами-функциями.
Процедуры и функции
Процедуры и функции представляют собой важный инструмент Турбо Паскаля, позволяющий писать хорошо структурированные программы. В структурированных программах легко прослеживается основной алгоритм, их нетрудно понять любому читателю, они проще в отладке и менее чувствительны к ошибкам программирования.
Процедуры и функции представляют собой во многом самостоятельные фрагменты программы (подпрограммы), связанные с основной программой лишь с помощью нескольких параметров.
Самостоятельность подпрограмм позволяет локализовать в них все детали программной реализации того или иного алгоритмического действия, поэтому изменение этих деталей, например, в процессе отладки обычно не приводит к изменениям основной программы.
Процедурой в Турбо Паскале называется особым образом оформленный фрагмент программы, имеющий собственное имя. Упоминание этого имени в тексте программы приводит к активизации процедуры и называется её вызовом. Сразу после активизации процедуры начинают выполняться входящие в неё операторы, после выполнения последнего из них управление возвращается обратно в основную программу и выполняются операторы, стоящие непосредственно за оператором вызова процедуры (рис. 1).
Рис. 1. Взаимодействие вызывающей программы и процедуры
Функция отличается от процедуры тем, что результат её работы возвращается в виде значения этой функции, поэтому вызов функции может использоваться наряду с другими операндами в выражениях.
Примеры стандартных процедур: READ, READLN, WRITE, WRITELN.
Примеры стандартных функций: SIN, COS, ORD.
Нестандартные процедуры и функции необходимо описать, чтобы компилятор мог установить связь между оператором вызова и теми действиями, которые предусмотрены в подпрограмме.
Локализация имен
При описании подпрограммы указывается её заголовок и тело. Тело подпрограммы, подобно программе, состоит из раздела описаний и раздела исполняемых операторов. В разделе описаний подпрограммы могут встретиться описания подпрограмм низшего уровня, т.е. вложенных подпрограмм (рис. 2).
Подпрограмма любого уровня может иметь множество имен констант, переменных, типов и вложенных в неё подпрограмм низшего уровня. Все имена, описанные внутри подпрограммы, локализуются в ней, т.е. они как бы «невидимы» снаружи подпрограммы.
Например, из программы (рис. 2) можно обратиться к подпрограммам А и В, но нельзя вызвать ни одну из вложенных в них процедур. Сказанное относится не только к именам подпрограммам, но и вообще к любым именам, объявленным в них – типам, константам, переменным и меткам. Все имена в пределах подпрограммы, в которой они объявлены, должны быть уникальными и не могут совпадать с именем самой подпрограммы.
Рис. 2. Пример структуры программы
При входе в подпрограмму низшего уровня становятся доступными не только объявленные в ней имена, но и сохраняется доступ ко всем именам верхнего уровня.
Образно говоря, любая подпрограмма как бы окружена полупрозрачными стенками: снаружи подпрограммы мы не видим её внутренности, но, попав в подпрограмму, можем наблюдать всё, что делается снаружи. Так, например, из подпрограммы А21 мы можем вызвать подпрограмму В, использовать имена, объявленные в основной программе, подпрограммах А и А2, и даже обратиться к ним. Любая подпрограмма может, наконец, вызвать саму себя – такой способ вызова называется рекурсией.
Подпрограмме доступны только те объекты верхнего уровня, которые описаны до описания данной подпрограммы. Эти объекты называются глобальными по отношению к подпрограмме.
Поэтому из подпрограммы В можно вызвать подпрограмму А, но из подпрограммы А вызвать В невозможно (рис. 2) (это правило можно обойти используя механизм опережающего описания).
Имена, локализованные в подпрограмме, могут совпадать с ранее объявленными глобальными именами. В этом случае считается, что локальное имя «закрывает» глобальное и делает его недоступным. Одноименные глобальные и локальные переменные – это разные переменные.
Описание подпрограммы
Заголовок процедуры имеет вид:
PROCEDURE <имя> [(<сп. ф. п.>)];
заголовок функции:
FUNCTION <имя> [(<сп. ф. п.>)]: <тип>;
Здесь <имя> – имя подпрограммы;
<сп. ф. п.> – список формальных параметров;
<тип> – тип возвращаемого функцией результата.
Список формальных параметров необязателен и может отсутствовать (на что указывают квадратные скобки). Если же он есть, то в нем должны быть перечислены имена формальных параметров и их тип, например:
procedure SB (a: real; b: integer; c: char);
Несколько следующих подряд однотипных параметров можно объединять в подсписки, например, вместо
function F (a: real; b: real): real;
можно написать проще:
function F (a, b: real): real;
Операторы тела подпрограммы рассматривают список формальных параметров как своеобразное расширение раздела описаний: все переменные из этого списка могут использоваться в любых выражениях внутри подпрограммы.
Пример. Возведение числа в степень. ()
var
x,y: real;
function power(a, b: real): real;
begin
if a>0 then power:= exp(b*ln(a))
else power:= 0;
end; {function power}
begin
repeat
readln(x,y);
writeln(power(x,y));
until false;
end.
Для вызова функции power мы просто указали её в качестве параметра при обращении к встроенной процедуре writeln. Параметры x и y в момент обращения к функции – это фактические параметры. Их значения присваиваются формальным параметрам a и b в заголовке функции, а затем производится выполнение операторов функции. Полученный результат присваивается идентификатору функции – именно он и будет возвращен как значение функции при выходе из неё.
Турбо Паскаль следит за тем, чтобы количество и тип формальных параметров строго соответствовали количеству и типам фактических параметров в момент обращения к подпрограмме. Смысл используемых фактических параметров зависит от того, в каком порядке они перечислены при вызове подпрограммы. В последнем примере первый по порядку фактический параметр будет возводиться в степень.
Любой из формальных параметров подпрограммы может быть либо параметром-значением, либо параметром-переменной. В предыдущем примере параметры a и b определены как параметры-значения. Чтобы определить параметры как параметры-переменные, перед ними необходимо поставить зарезервированное слово var, например
function power(var a: real, b: real): real;
Если параметр определён как параметр-значение, то перед вызовом подпрограммы это значение вычисляется, полученный результат копируется во временную память и передается подпрограмме. Если же параметр определён как параметр-переменная, то при вызове передается сама переменная, а не её копия. Любые возможные изменения параметра-значения никак не воспринимаются вызывающей программой, так как в этом случае изменяется копия фактического параметра, в то время как изменение параметра-переменной приводит к изменению самого фактического параметра в вызывающей программе.
При вызове подпрограммы, в качестве параметра-переменной должна указываться переменная соответствующего типа, в качестве параметра-значения может быть указано любое выражение соответствующего типа.
power(x, 3*sin(x)); или power(x, 3.17);
Пример.
var
a, b: integer;
procedure inc2(var c: integer; b: integer);
begin
c:= c + c; b:= b+b;
writeln(‘удвоенные:’, c:5, b:5);
end;
begin
a:= 5; b:= 7;
writeln(‘исходные:’, a:5, b:5);
inc2(a,b);
writeln(‘результат: ’, a:5, b:5);
end.
Результат выполнения программы:
исходные: 5 7
удвоенные: 10 14
результат: 10 7
Параметры-переменные используются как средство связи алгоритма, реализованного в подпрограмме, с «внешним миром»: с помощью этих параметров подпрограмма может передавать результаты своей работы вызывающей программе. Передача результатов может быть также осуществлена через глобальные переменные, однако злоупотребление глобальными связями делает программу, как правило, запутанной, трудной в понимании и сложной в отладке.
Использование параметров-переменных в функциях не приветствуется: если результатом работы функции не может быть единственное значение, то логичнее использовать процедуру.
Но! Если подпрограмма используется для обработки массива большой размерности, то при передаче такого массива как параметра-значения возникают существенные затраты времени и памяти на копирование значений массива во временную память. Эти затраты могут стать решающим доводом в пользу объявления такого параметра параметром-переменной или передачи его в качестве глобальной переменной.
Задания для самостоятельной работы
Разработать программу на Турбо Паскале, которая обеспечивает решение поставленной задачи в соответствии с предложенным вариантом. Первая цифра - номер задания, вторая - номер варианта.
Задачи
1. Разработать функцию, реализующую расчёт значения заданной функции. В качестве параметра должно передаваться значение x. Разработать программу, осуществляющую вызов функции.
1.1.
1.2.
1.3.
1.4.
1.5.
1.6.
1.7.
1.8.
1.9.
1.10.
1.11.
1.12.
2. Разработать функцию, осуществляющую расчёт i -го элемента заданной рекуррентной зависимости. В качестве параметра в функцию передаётся номер элемента (i >0).
2.1. ai = 2 × ai– 2 + ai– 1, i = 1, 2, 3, …; a 1=1, a 2=1.
2.2. ai = (ai– 2 + ai– 1) / 3, i = 1, 2, 3, …; a 1=1, a 2=1.
2.3. ai = ai– 2 / 5 + ai– 1, i = 1, 2, 3, …; a 1=1, a 2=1.
2.4. ai = (ai– 2 + ai– 1) × 2, i = 1, 2, 3, …; a 1=1, a 2=1.
2.5. ai = ai– 2 / 7 – ai– 1, i = 1, 2, 3, …; a 1=56, a 2=1.
2.6. ai = (ai– 2 – ai– 1) × 2, i = 1, 2, 3, …; a 1=3, a 2=1.
2.7. ai = (ai– 2 – ai– 1) / 2, i = 1, 2, 3, …; a 1=5, a 2=1.
2.8. ai = 3 × ai– 2 – 2 × ai– 1, i = 1, 2, 3, …; a 1=2, a 2=1.
2.9. ai = (2 × ai– 2 + ai– 1) / 3, i = 1, 2, 3, …; a 1=2, a 2=1.
2.10. ai = ai– 2 / 4 + 2× ai– 1, i = 1, 2, 3, …; a 1=16, a 2=1.
2.11. ai = ai–1 – 1 + 4× ai– 1, i = 1, 2, 3, …; a 1=3, a 2=5.
2.12. ai = -ai– 2 /2 + ai– 1, i = 1, 2, 3, …; a 1=2, a 2=4.
3. Используя функцию, разработанную в п.2, разработать программу расчета суммы и произведения n первых элементов последовательности.
4. Разработать процедуру, выводящую на экран заданное количество заданных символов (в качестве параметров передаётся количество символов и сам символ (тип char)). Разработать программу, реализующую вывод на экран следующей последовательности символов в заданном формате, используя разработанную процедуру и оператор цикла.
4.1. | 4.2. | ||
4.3. | 4.4. | ||
4.5. | 4.6. | ||
4.7. | 4.8. | ||
4.9. | 4.10. | ||
4.11. | 4.12. |