Формальный и фактический параметр
Функции и процедуры. Рекурсия
Теоретический материал (Паскаль)
Понятие подпрограммы. Процедуры и функции. Стандартные подпрограммы
Подпрограммы решают три важные задачи:
Очень важно понимать, что в подпрограмму может выделяться любой законченный фрагмент программы. В качестве ориентиров просмотрите следующие рекомендации:
Подпрограммы могут быть стандартными, т.е. определенными системой, и собственными, т.е. определенными программистом.
Из набора стандартных процедур и функций по обработке одного типа информации составляются модули. Каждый модуль имеет своё имя (мы уже хорошо знакомы с модулями Crt, Graph). Доступ к процедурам и функциям модуля осуществляется при подключении этого модуля (Uses Crt, Graph).
Задание. Вызовите помощь по функции Cos и рассмотрите предоставленную информацию.
Сначала идет краткое описание подпрограммы (в одну фразу). Далее под словом Declaration (Объявление) следует интерфейсная часть процедуры или функции, которая необходима для определения типов фактических параметров. Далее под словом Target приводятся платформы, на которых может использоваться подпрограмма: Windows, real (реальный режим DOS), protected (защищенный режим DOS). После слова Remarks следуют заметки, содержащие необходимые детали использования. В разделе See Also приведены имена подпрограмм, связанных с данной по смыслу или по совместному применению. Если перемещать курсор по этим именам (они выделяются подсветкой), то, выбрав одно из них (нажав клавишу ), можно получить справку по следующей подпрограмме. Каждая процедура и функция сопровождается примером применения, переключение к которому дает последняя строка справочной информации. Любой текст из Help может быть скопирован в редактируемый файл обычными приемами копирования через буфер. Копирование примеров или заголовков функций может значительно облегчить работу.
Существует другой способ получения сведений о процедурах и функциях. Для этого нужно использовать пункт меню Help/Reserved words (зарезервированные слова) или Help/Standard units (стандартные модули).
Задание. Рассмотрите список процедур и функций, выберите какие-либо из них и ознакомьтесь со справочной информацией.
В стандартных модулях содержится большое количество подпрограмм, но невозможно создать модуль, который бы содержал все нужные программисту подпрограммы. Поэтому большую роль играют собственные подпрограммы, которые создает программист для решения конкретной задачи.
Существует два способа объединения программ и подпрограмм пользователя:
Первый способ применяется тогда, когда программа в целом не очень большая, а ее подпрограммы, скорее всего, не будут использоваться в других программах.
Структура текста подпрограммы соответствует структуре текста основной программы за двумя исключениями:
Вызов подпрограммы происходит при каждом употреблении ее имени в основной (или вызывающей) программе. При вызове подпрограммы выполнение основной программы приостанавливается, и управление передается в подпрограмму, где выполняются команды, заданные в ней. Подпрограмма завершается, если выполнены все ее операторы до завершающего слова End или по специальной команде выхода из подпрограммы Exit. По окончании работы подпрограммы управление возвращается основной программе, а именно, первой команде, следующей за обращением к этой подпрограмме.
Например, вызов функции
вернет в основную программу значение наименьшего из двух чисел и это значение будет присвоено переменной M.
Все переменные, которые использует подпрограмма, могут быть либо глобальными, либо локальными.
Определение. Глобальными называются переменные, объявленные в основной программе и доступные как программе, так и всем ее подпрограммам.
Определение. Локальными называются переменные, объявленные внутри подпрограммы и доступные только ей самой.
Обмен информацией между основной программой и подпрограммой может осуществляться только с помощью глобальных переменных и с помощью параметров подпрограммы.
Подпрограмма может использовать любые глобальные переменные кроме тех, которые имеют те же имена, что и ее локальные переменные. Если в подпрограмме описана локальная переменная, имя которой совпадает с именем некоторой глобальной переменной, то данная глобальная переменная становится недоступной в этой подпрограмме, и при указании идентификатора переменной произойдет обращение к локальной переменой подпрограммы, а не одноименной глобальной переменной. Память для локальных (т.е. описанных в подпрограмме) переменных выделяется на время исполнения данной подпрограммы в специальной области, называемой стеком. При завершении работы подпрограммы память освобождается, поэтому все внутренние результаты работы подпрограммы не сохраняются от одного обращения к другому.
Если говорить о плюсах использования подпрограмм, то можно назвать следующие:
В языке Паскаль выделяют два вида подпрограмм: процедуры (Procedure) и функции (Function). Любая программа может содержать несколько процедур и функций. Структура любой подпрограммы аналогична структуре всей программы.
Подпрограмма должна быть описана до того, как будет использована в программе или другой подпрограмме.
Процедуры и функции объявляются в разделе описания вслед за разделом переменных.
Общая структура программы выглядит так:
Выполнение программы начинается с операторов основной программы. При необходимости вызывается подпрограмма, и начинают действовать её операторы. Затем управление возвращается в основную программу, которая и продолжает выполняться.
Подпрограмма вызывается по своему имени с указанием необходимых параметров.
На этом занятии рассмотрим примеры организации наиболее простого вызова подпрограмм.
Задание. Рассмотрите решение предложенных задач, наберите программы на компьютере, проверьте их работоспособность, внесите свои изменения и дополните своими комментариями.
Задача 1. Написать программу, состоящую из трех подпрограмм и основной программы. Подпрограммы должны организовывать ввод чисел, вычисление их суммы и вывод результата.
Задача 2. Найти среднее арифметическое двух чисел.
Подпрограммы
В практике программирования часто складываются ситуации, когда одну и ту же группу операторов, реализующих определённую цель, требуется повторить без изменений в нескольких местах программы. Для избавления от столь нерациональной траты времени была предложена концепция подпрограммы.
4.1 Общие сведения о подпрограммах. Локальные и глобальные переменные
Для правильного определения области действия идентификаторов (переменных) необходимо придерживаться следующих правил:
4.2 Формальные и фактические параметры. Передача параметров в подпрограмму
Обмен информацией между вызываемой и вызывающей функциями осуществляется с помощью механизма передачи параметров. Переменные, указанные в списке в заголовке функции, называются формальными параметрами, или просто параметрами подпрограммы. Все переменные из этого списка могут использоваться внутри подпрограммы. Список переменных в операторе вызова подпрограммы — это фактические параметры, или аргументы.
Механизм передачи параметров обеспечивает обмен данных между формальными и фактическими параметрами, что позволяет выполнять подпрограмму с различными данными. Между фактическими параметрами в операторе вызова и формальными параметрами в заголовке подпрограммы устанавливается взаимно однозначное соответствие. Количество, типы и порядок следования формальных и фактических параметров должны совпадать.
Формальные параметры процедуры можно разделить на два класса: параметры-значения и параметры-переменные.
При передаче данных через параметры-значения в подпрограмму передаются значения фактических параметров, и доступа к самим фактическим параметрам из подпрограммы нет. При передаче данных параметры-переменные заменяют 1 Реально в подпрограмму передаются адреса фактических параметров. формальные параметры, и, следовательно, в подпрограмме есть доступ к значениям фактических параметров. Любое изменение параметров-переменных в подпрограмме приводит к изменению соответствующих им формальных параметров. Следовательно, входные данные следует передавать через параметры-значения, для передачи изменяемых в результате работы подпрограммы данных следует использовать параметры-переменные.
От общетеоретических положений перейдём к практическому использованию подпрограмм при решении задач. Изучение подпрограмм начнем с процедур.
4.3 Процедуры
Описание процедуры имеет вид:
procedure name_1( r : real; i : integer; c : char );
Однотипные параметры могут быть перечислены через запятую:
procedure name_2( a, b : real; i, j, k : integer );
Список формальных параметров необязателен и может отсутствовать:
Если в заголовке процедуры будут применяться параметры-переменные, то перед ними необходимо указывать служебное слово var :
procedure name_4( x, y : real; var z : real );
Для обращения к процедуре необходимо использовать оператор вызова:
Фактические параметры в списке оператора вызова отделяются друг от друга запятой:
a : = 5. 3; k : = 2; s := ’ a ’;
Если в описании процедуры формальные параметры отсутствовали, то и при вызове их быть не должно:
Алгоритм решения этой задачи был подробно описан в задаче 3.3 (рис. 3.14). Однако там не была рассмотрена ситуация некорректного ввода значений коэффициентов. Например, если пользователь введёт 


Формальные и фактические параметры
Рассмотрим более подробно вопросы взаимодействия формальных и фактических параметров.
Определения формальных и фактических параметров являются исключительно важными для понимания механизма их взаимодействия в подпрограммах. Поэтому на этом вопросе следует остановиться подробнее.
Формальные параметры подпрограммы указывают, с какими параметрами следует обращаться к этой подпрограмме (количество параметров, их последовательность, типы). Они задаются в заголовке подпрограммы в виде списка формальных параметров, разбитого на группы, разделенные точками с запятыми. В группу формальных параметров включаются однотипные параметры одной категории.
Все формальные параметры можно разбить на четыре категории:
— параметры-значения (эти параметры подпрограмма может изменить в основной подпрограмме);
— параметры-переменные (эти параметры подпрограмма может изменить в основной программе);
— параметры-константы (только в версии 7.0);
— параметры-процедуры и параметры-функции (т.е. процедурного типа).
Для каждого формального параметра следует указать имя и, как правило, тип, а в случае параметра-переменной или параметра-константы — категорию. Имена параметров могут быть любыми, в том числе и совпадать с именами объектов программы. Необходимо лишь помнить, что в этом случае параметр основной программы с таким именем становится недоступным для непосредственного использования подпрограммой. Тип формального параметра может быть практически любым, однако в заголовке подпрограммы нельзя вводить новый тип.
Например, нельзя писать
Function SUMM (A: array[1..100] of Real): Real;
Чтобы правильно записать этот заголовок, следует в основной программе ввести тип-массив, а затем использовать его в заголовке:
Type aArr = array[1..100] of real;
Function SUMM (A: aArr): Real;
При обращении к подпрограмме формальные параметры заменяются на соответствующие фактическиевызывающей программы или подпрограммы.
Параметры-значения передаются основной программой в подпрограмму через стек (специальный канал передачи данных) в виде их копий и, следовательно, собственный параметр программы подпрограммой измениться не может.
Параметр-значение указывается в заголовке подпрограммы своим именем и через двоеточие — типом. Тип параметра-значения может быть любым, за исключением файлового.
Если параметров-значений одного типа несколько, их можно объединить в одну группу, перечислив их имена через запятую, а затем уже указать общий тип. Как было отмечено выше, отдельные группы параметров отделяются друг от друга точкой с запятой.
Procedure MIN_MAX(Max,Min: Real; n: Word);
Function Tabulir(X,Y: Integer): Real;
В качестве фактического параметра на месте параметра-значения при вызове подпрограммы может выступать любое выражение совместимого для присваивания типа, не содержащее файловую компоненту, например:
Пример 2.6.Использовать функцию для вычисления максимального элемента в массиве.
Определим в основной программе тип-массив.
aArr = Array[1..] of Integer;
Var Massiv: aArr; Maxim: Integer;
Функция в этом случае может иметь следующий вид.
Function Max(Mas: aArr; N: Byte): Integer;
Var Ma : Integer; i : Byte;
If MaMas[i] then Ma := Mas[i];
Пусть надо определить максимальное число из первых 35 чисел массива. Это можно сделать с помощью оператора, использующего обращение к функции: Maxim := Max(Massiv,35);
Примечание. Данная программа может работать только с массивами типа аАrr. Для массивов другого типа надо создавать другую аналогичную подпрограмму. Данная программа создает в стеке копию исходного массива, поэтому она работает медленно.
Параметр-переменная указывается в заголовке подпрограммы аналогично параметру-значению, но только перед именем параметра записывается зарезервированное слово VAR. Действие слова VAR распространяется до ближайшей точки с запятой, т.е. в пределах одной группы.
Пример 2.8. Procedure MaxMin(A: аАrr; Var Max, Min: Real; N: Word);
Здесь Max, Min- параметры-переменные, а переменные А и N — параметры-значения.
Тип параметров-переменных может быть любым, включая и файловый. При вызове подпрограммы на месте параметра-переменной в качестве фактического параметра должна использоваться переменная идентичного типа. Так, если формальный параметр имеет тип, определенный следующим образом:
Type аАrr = array [1.. 100] of Integer;
то и фактический параметр должен быть переменной или типизированной константой типа аАrr.
Использовать функцию для вычисления максимального элемента в массиве.
В основной программе определяется тип-массив.
Type аАrr = Array [1.. 50] of Integer;
Var Massiv: аАrr; Maxim: Integer;
Функция в этом случае может иметь вид:
Function Max(Var Mas: аАгг; N: Byte): Integer;
Var Ma : Integer; i : Byte;
If MaMas[i] then Ma := Mas[i];
Пусть надо определить максимальное число из первых 35 чисел массива Это можно сделать с помощью оператора:
Примечание. Эта программа лучше предыдущей тем, что в данном случае в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память. Однако при такой передаче параметра возможно его нежелательное изменение (этот вариант передачи параметра допустим только в таких небольших подпрограммах, как в данном случае, когда программист может проконтролировать несанкционированное изменение параметра). Недостатком этой программы, как и ранее описанной, является то, что она может работать только с одним типом массива.
Часто в качестве параметра в подпрограмму следует передать ту или иную переменную, но изменять ее подпрограмма не должна. В этом случае нежелательно передавать этот параметр как параметр-переменную. Можно его передать как параметр-значение, однако если эта переменная имеет больший размер (массив, запись и т.д.), то копия этого параметра займет большую часть стека и даже может его переполнить. Это приводит также к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметр-константу. Такой параметр, если он структурированного типа, передается своим адресом, но предусматривается защита от его изменения. Использовать параметр-константу можно только в версии Турбо Паскаля 7.0.
Параметр-константа указывается в заголовке подпрограммы аналогично параметру-значению, но перед именем параметра записывается зарезервированное слово Const. Действие слова Const распространяется до ближайшей точки с запятой, т.е. в пределах одной группы.
Пример 2.10.Function NewString(Const S: String): String;
Тип параметра-значения может быть любым, за исключением файлового. При вызове подпрограммы на месте параметра-переменной в качестве фактического параметра можно использовать любое выражение совместимого для присваивания типа, не содержащего файловую компоненту.
Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра.
Функция вычисления максимального элемента в массиве, и в качестве первого параметра – параметр-константа.
Function Max(Const Mas: аАrr; N: Byte): Integer;
Var Ma : Integer; i : Byte;
If MaMas[i] then Ma := Mas[i];
Параметры без типа
В Турбо Паскале можно использовать параметры-переменные и параметры-константы без указания типа. В этом случае фактический параметр может быть переменной любого типа,а ответственность за правильное использование того или иного параметра возлагается на программиста.
Пример 2.12.Function Tqual(Var Param1, Param2; Len: Word):Boolean;
Здесь Param1, Param2 — параметры-переменные без типа (вместо них можно использовать, например, любые переменные простого типа, типа-массив, типа-запись и т.д.); Len — параметр-значение.
Следует иметь в виду, что параметр “без типа” внутри подпрограммы типа не имеет и его перед использованием следует преобразовать к конкретному типу, применяя идентификатор соответствующего типа так, как ранее указывалось, при этом полученный результат может быть любого размера.
Пример 2.13.Функция вычисления максимального элемента в массиве. При этом в качестве первого параметра используется параметр-переменная без типа:
Function Max(Var Masr; N: Byte): Integer;
Type aArray = array[Maxint] of Integer;
Var Ма : Integer; i : Byte;
Begin Ма := aArray(Mas)[1];
If МаaArray(Mas)[i] then Ма := aArray(Mas)[i];
В этом случае в качестве первого передаваемого параметра можно использовать любой массив (и не только массив), так что подпрограмма становится более универсальной. Тем не менее здесь необходимо передавать в качестве второго параметра фактический размер информации, что не очень удобно.
Статьи к прочтению:
Ээ в этом случае наши полномочия все окончены
Похожие статьи:
Лабораторная работа №3 Использование подпрограмм в системе MATLAB Цель работы: Знакомство с организацией функций в MATLAB, особенностями их работы….
Существует несколько способов передачи параметров в подпрограмму. § Передача параметров по значению. Формальному параметру присваивается значение…
Формальный и фактический параметр
Синтаксис определения и вызова функции
Синтаксис функций (определения и вызова) включает в себя до десятка терминов и определений, поэтому придется сначала договориться о терминологии, не вникая в суть, а затем обсуждать механизмы ее работы.
Как любая другая переменная, результат функции относится к определенному типу данных, который указан в заголовке функции ( 6). Это делается тем же способом, что и для обычных переменных. Используется тот же самый синтаксис, в котором имя функции выступает в роли переменной-результата. Тип результата может быть любым, за исключением функции или массива.
return (nn+1) ; // FF = (double)(nn + 1)
Nothing(); // Просто вызов без использования результата
Определение функции представляет собой всего лишь статическую «заготовку» программы. Выполнение ее происходит тогда, когда в процессе вычисления выражения встречается вызов функции. Синтаксически вызовом функции называется упоминание имени этой функции в выражений ( 10), причем после имени функции в скобках следует список фактических параметров (12).
Фактические параметры – переменные, константы и выражения, которые ставятся в соответствие формальным параметрам при текущем вызове функции. По поводу них можно сказать следующее :
· между формальными и фактическими параметрами устанавливается «один-один» соответствие, которое действует только в течение текущего вызова функции (динамически);
· существуют различные способы установления соответствия, на настоящий момент реально распространенными в языках программирования являются способы передачи параметров по ссылке и по значению;
Способы соответствия формальных и фактических параметров
В настоящее время в большинстве языков программирования используются два способа передачи параметров: по ссылке и по значению. Особенностью Си является то, что он имеет возможность использовать ссылки не только неявно, но и с использованием такого архитектурно-ориентированного средства как указатель Кроме того, указатель и ссылка могут быть не только формальным параметром, но и результатом функции ( 5.2). Пока же мы ограничимся общепринятыми для всех языков программирования рамками.
· формальные параметры являются собственными переменными функции, аналогом локальных переменных;
· при вызове функции происходит присваивание формальным параметрам значений фактических (копирование вторых в первые);
· при изменении формальных параметров значения соответствующих им фактических параметров не меняются;
· передача параметров по значению используется для задании функции входных данных.
· формальные параметры существуют как синонимы фактических, в этом смысле они не являются «настоящими» переменными, под которые отводится память, а реализуется как элемент отображения;
· при изменении значений формальных параметров эти изменения проецируются на соответствующие им фактические;
· передача параметров по ссылке может использоваться для данных, которые являются либо чисто выходными (неявный результат функции), либо представляют собой внешние для функции данные, которые она должна изменить.

В Си приняты следующие правила передачи, которые определяются синтаксическим видом формальных параметров в заголовке функции:
· по умолчанию (т.е. при отсутствии явных символов обозначения) все параметры, кроме массивов, передаются по значению, т.е. копируются ;
· массивы передаются исключительно по ссылке, т.е. отображаются;
· для явного указания способа передачи параметра по ссылке служит символ « &», который записывается перед именем формального параметра.
Механизм вызова функции
Механизм вызова функции является динамическим, т.е. действия, связанные с его реализацией, осуществляются при выполнении программы. Именно поэтому текст программы и его «развертка» во времени представляют для функции «две большие разницы». Это касается двух вещей :
· последовательность выполняемых действий (поток управления) при вызовах функций:
· соответствие между формальными и фактическими параметрами.
Именно поэтому мы и рассмотрим процесс вызова вышеприведенной функции в «исторической перспективе»:
1. результатом трансляции функции является программный код, размещенный в сегменте команд;
3. выполняется программный код вызывающей функции, пока в ней не встретится выражение, содержащий вызов функции;
4. в соответствии со списком фактических параметров устанавливается соответствие между элементами контекста вызывающей функции и формальными параметрами;
7. сохраняется точка возврата в вызывающую функцию, после чего происходит переход к началу блока программного кода функции sum ;
8. выполняется программный код функции sum ;
9. в контексте вызываемой функции используются локальные переменные и формальные параметры, в соответствии со способами передачи параметров массив A отображается на исходный массив B в контексте main ;
12. продолжается выполнение программного кода вызывающей функции.
Области действия функций. Определения и объявления
До сих пор мы ничего не говорили ни о взаимном расположении в программе определения функции и ее вызова, ни о соответствии формальных и фактических параметров, ни о контроле такого соответствия. Конечно, нельзя считать, что транслятор «знает» о всех функциях, когда либо написанных, либо находящихся в библиотеках, текстовых файлах и т.д.. Каждая программа должна сама сообщать транслятору необходимую информацию о функциях, которые она собирается вызывать. Перечислим, какую именно:
· список формальных параметров (переменные и типы).
При ее наличии транслятор может корректно сформировать вызов функции, даже если текст ее (определение) отсутствует в программе. Вся перечисленная информация о функции находится в ее заголовке. Таким образом, достаточно этот заголовок привести отдельно, и проблема корректного вызова решается. Такой заголовок называется объявлением или в рассматриваемом нами варианте синтаксиса прототипом функции
// определенной далее по тексту
extern int printf(char *. ); // Объявление библиотечной функции
// с переменным числом параметров
extern int other(void); // Объявление функции без
// параметров из другого
void main() // файла программы
int sum(int s[], int n) <. >// Определение ранее объявленной функции
Из примера видно, что объявление функции практически дублирует заголовок, отличаясь в некоторых деталях:
· объявление заканчивается символом «;» ;
· если функция находится вне текущего файла, то объявление предваряется служебным словом extern;
· имена переменных в списке формальных параметров объявления могут отсутствовать;
· если функция не имеет формальных параметров, то в объявлении присутствует формальный параметр типа void.
Имея предварительно определенную функцию или ее объявление, транслятор в состоянии проверить соответствие формальных и фактических параметров как по их количеству, так и по типам. При этом транслятор может выполнить неявные преобразования типов фактических параметров к типам формальных, если это потребуется:
extern double sin(double);
y = sin(x); //——Неявное преобразование (double)x
Глобальные переменные. Инициализация
Программа в целом представляет собой набор вызывающих друг друга функций с обязательной функцией main, имеющих собственные наборы локальных переменных.

