Смекни!
smekni.com

Синтаксис описания и вызова процедуры (стр. 2 из 3)

Поясним изложенное.

.....

var

a, b: integer;

......

procedure squar(a: integer; var b: integer);

begin

a:=sqr(a);

b:=sqr(b);

writeln(‘в квадрате они выглядят так: ’,a,’, ’,b);

end;

........

begin

a:=4; b:=6;

writeln(‘внимательно посмотрите на эти числа: ’, a,’, ’, b);

squar(a,b);

writeln(‘а так а не в квадрате: ’,a, ’, ’,b);

end.

Результаты выглядят так: внимательно посмотрите на эти числа: 4, 6

в квадрате они выглядят так: 16, 36

а так а не в квадрате: 4, 36

Этот пример может служить еще и иллюстрацией механизма «закрывания» глобальной переменной а одноименной локальной: хотя переменная объявлена как глобальная (она описана в вызывающей программе перед описанием процедуры), в теле процедуры ее «закрыла» локальная переменная а, объявленная как параметр-значение.

Итак, параметры-переменные используются как средство связи алгоритма, реализованного в подпрограмме, с «внешним миром»: с помощью этих параметров подпрограмма может передавать результаты своей работы вызывающей программе. Разумеется, в распоряжении программиста всегда есть и другой способ передачи результатов - через глобальные переменные. Однако злоупотребление глобальными связями делает программу , как правило, запутанной, трудной в понимании и сложной в отладке. В соответствии с требованиями хорошего стиля программирования рекомендуется там, где это возможно, использовать передачу результатов через фактические параметры-переменные.

С другой стороны, описание всех формальных параметров как параметров-переменных нежелательно по двум причинам. Во-первых, это исключает возможность вызова подпрограммы с фактическими параметрами в виде выражений, что делает программу менее компактной. Во-вторых, и главных, в подпрограмме возможно случайное использование формального параметра, например, для временного хранения промежуточного результата, т.е. всегда существует опасность непреднамеренно «испортить» фактическую переменную. Вот почему параметры-переменные следует объявлять только те, через которые подпрограмма в действительности передает результаты вызывающей программе. Чем меньше параметров объявлено параметрами-переменными и чем меньше в подпрограмме используется глобальных переменных, тем меньше опасность получения непредусмотренных программистом побочных эффектов, связанных с вызовом подпрограммы, тем проще программа в понимании и отладке.

Существует одно обстоятельство, которое следует учитывать при выборе вида формальных параметров. Как уже говорилось, при объявлении параметра-значения осуществляется копирование фактического параметра во временную память. Если этим параметром будет массив большой размерности, то существенные затраты времени и памяти на копирование при многократных обращениях к подпрограмме могут стать peшающим доводом в пользу объявления такого параметра параметром-переменной или передачи его в качестве глобальной переменной.

Параметры массивы и параметры строки

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

Procedure S (а : array (1..10] of real);

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

Если мы хотим передать какой-то элемент массива, то проблем, как правило, не возникает, но если в подпрограмму передается весь массив, то следует первоначально описать его тип. Например:

…...

type

mas = array [1..10] of real;

.......

PROCEDURE S (a : mas);

…...

Поскольку строка является фактически своеобразным массивом, ее передача в

подпрограмму осуществляется аналогичным образом:

.......

type

intype =string[15];

outype = string[30];

FUNCTION St (i : intype) : outype:

Требование описать любой тип-массив или тип-строку перед объявлением подпрограммы на первый взгляд кажется несущественным. Действительно, в рамках простейших вычислительных задач обычно заранее известна структура всех используемых в программе данных, поэтому статическое описание массивов не вызывает проблем. Однако разработка программных средств универсального назначения связана со значительными трудностями. По существу, речь идет о том, что в Турбо Паскале невозможно использовать в подпрограммах массивы с «плавающими» границами изменения индексов. Например, если разработана программа, обрабатывающая матрицу из 10 х 10 элементов, то для обработки матрицы из 9 х 11 элементов необходимо переопределить тип, т.е. перекомпилировать всю программу. Этот недостаток, как и отсутствие в языке средств обработки исключительных ситуаций (прерываний), унаследован из стандартного Паскаля и представляет собой объект постоянной и вполне заслуженной его критики. Разработчики Турбо Паскаля не рискнули кардинально изменить свойства базового языка, но, тем не менее, включили в него некоторые средства, позволяющие в известной степени смягчить отмеченные недостатки.

Прежде всего, в среде Турбо Паскаля можно установить режим компиляции, при котором отключается контроль над совпадением длины фактического и формального параметра-строки. Это позволяет легко решить вопрос о передаче подпрограмме строки произвольной длины. При передаче строки меньшего размера формальный параметр будет иметь ту же длину, что и параметр обращения; передача строки большего размера приведет к ее усечению до максимального размера формального параметра. Следует сказать, что контроль включается только при передаче строки, объявленной как формальный параметр-переменная. Если соответствующий параметр объявлен параметром-значением, эта опция игнорируется и длина не контролируется.

Значительно сложнее обстоит дело с передачей массивов произвольной длины. Решить эту проблему при помощи не типизированных параметров

Процедурные типы

Процедурные типы - это нововведение фирмы Borland (в стандартном Паскале таких типов нет). Основное назначение этих типов - дать программисту гибкие средства передачи функций и процедур в качестве фактических параметров обращения к другим процедурам и функциям.

Для объявления процедурного типа используется заголовок процедур, в котором опускается ее имя, например:

type

Proc = Procedure (a, b, с : real; Var d : real);

Proc2 = Procedure (var a, b);

РгосЗ = Procedure;

В программе могут быть объявлены переменные процедурных типов, например, так:

var

р1 : Proc;

ар : array [1..N] of Proc2;

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

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

Нетипизированные параметры-переменные

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

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

Параметры- сложные типы данных

Рассмотрены прежде категории параметров не исчерпывают всех вопросов передачи информации в Pascal-e. Использование в качестве параметров сложных типов данных имеет свои особенности.

Рассмотрим массивы и строки открытого типа. Открытый массив (строка) – массив (строка) без указания типа индекса (размера массива(строки)).

Пример:

Procedure getfive(var massiv: array of real);

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

Программа вычисления x=(m!+n!)/(m+n)!, где m, n целые (неотрицательные)

program factorial_(input,output); {название программы}

label 0; {описываем метку}

var

rez:real;

m,n:longint; {описали глобальные переменные, используемые в программе}

functionfact(z: longint): real; {заголовок функции с формальным параметром-значением, типом}

var

y: real; {описали локальную переменную}

begin

y:=1; {для получения результата необходимо присвоить у значение 1. также при помощи этого реализуется вычисление 0! и 1!}

whilez>1 do {запускаем цикл в обратную сторону, для упрощения опустим множитель 1}

begin

y:=y*z;

z:=z-1

end;

fact:=y{вычисляем факториал, присваиваем его значение функции}

end; {конец функции}

begin{начало тела программы}

writeln('введите неотрицательные числа'); {для удобства пользователя просим ввести числа}

0:readln(m,n); {в память вводятся числа}

if m or n <0 then begin

writeln(‘вы ошиблись, вводите неотрицательные числа’);