S: String;. {Читаем строку из edinput и выделяем из нее два вещественных числа, разделенных хотя бы одним пробелом.} S := edinput.Text;
X, Y: Real; begin {Читаем строку из edinput и выделяем из нее два вещественных числа, разделенных хотя бы одним пробелом.} S:= edinput.Text; if (S = '') or (pos(' ',S) = 0) then Exit; // Лет текста или в нем нет // пробела - прекращаем дальнейшую работу try // Выделяем первое число: X:= StrToFloat(copy(S, I, pos(' ', S) - 1)); // Если успешно, удаляем символы до пробела // и выделяем второе число: Delete (S, 1, pos (' ', S)); Y:= StrToFloat(Trim(S)); Except Exit; // Завершаем работу при ошибке преобразования end; mmOutput.Lines.Add(FloatToStr(Power(X, Y))); mmOutput.Lines.Add(FloatToStr(Power(X, -Y))); end; Для вызова функции Power мы просто указали ее в качестве параметра при обращении к стандартной функции преобразования вещественного числа в строку FloatToStr. Параметры х и y в момент обращения к функции power - это фактические параметры. Они подставляются вместо формальных параметров а и в в заголовке функции, и затем над ними осуществляются нужные действия. Полученный результат присваивается специальной переменной с именем Re-suit, которая в теле любой функции интерпретируется как то значение, которое вернет функция после окончания своей работы. В программе функция power вызывается дважды - сначала с параметрами х и y, а затем х и -y, поэтому будут получены два разных результата. Механизм замены формальных параметров на фактические позволяет нужным образом настроить алгоритм, реализованный в подпрограмме. Object Pascal следит за тем, чтобы количество и типы формальных параметров строго соответствовали количеству и типам фактических параметров в момент обращения к подпрограмме. Смысл используемых фактических параметров зависит от того, в каком порядке они перечислены при вызове подпрограммы. В нашем примере первый по порядку фактический параметр будет возводиться в степень, задаваемую вторым параметром, а не наоборот. Программист должен сам следить за правильным порядком перечисления фактических параметров при обращении к подпрограмме. Любой из формальных параметров подпрограммы может быть либо параметром-значением, либо параметром-переменной, либо, наконец, параметром-константой. В предыдущем примере параметры а и в определены как параметры-значения. Если параметры определяются как параметры-переменные, перед ними необходимо ставить зарезервированное слово var, а если это параметры-константы - слово const, например: Procedure MyProcedure(var A: Real; В: Real; const C: String); Здесь а - параметр-переменная, в - параметр-значение, а с - параметр-константа. Определение формального параметра тем или иным способом существенно в основном только для вызывающей программы: если формальный параметр объявлен как параметр-переменная, то при вызове подпрограммы ему должен соответствовать фактический параметр в виде переменной нужного типа; если формальный параметр объявлен как параметр-значение или параметр-константа, то при вызове ему может соответствовать произвольное выражение. Контроль за неукоснительным соблюдением этого правила осуществляется компилятором Object Pascal. Если бы для предыдущего примера был использован такой заголовок функции: Function Power (A: Real; var В: Real): Real; то при втором обращении к функции компилятор указал бы на несоответствие типа фактических и формальных параметров (параметр обращения -Y есть выражение, в то время как соответствующий ему формальный параметр B описан как параметр-переменная). Для того чтобы понять, в каких случаях использовать тот или иной тип параметров, рассмотрим, как осуществляется замена формальных параметров на фактические в момент обращения к подпрограмме. Если параметр определен как параметр-значение, то перед вызовом подпрограммы это значение вычисляется, полученный результат копируется во временную память (стек) и передается подпрограмме. Важно учесть, что даже если в качестве фактического параметра указано простейшее выражение в виде переменной или константы, все равно подпрограмме будет передана лишь копия переменной (константы). Любые возможные изменения в подпрограмме параметра-значения никак не воспринимаются вызывающей программой, так как в этом случае изменяется копия фактического параметра. Если параметр определен как параметр-переменная, то при вызове подпрограммы передается сама переменная, а не ее копия (фактически в этом случае подпрограмме передается адрес переменной). Изменение параметра-переменной приводит к изменению фактического параметра в вызывающей программе. В случае параметра-константы в подпрограмму также передается адрес области памяти, в которой располагается переменная или вычисленное значение. Однако компилятор блокирует любые присваивания параметру-константе нового значения в теле подпрограммы. Итак, параметры-переменные используются как средство связи алгоритма, реализованного в подпрограмме, с внешним миром: с помощью этих параметров подпрограмма может передавать результаты своей работы вызывающей программе. Разумеется, в распоряжении программиста всегда есть и другой способ передачи результатов - через глобальные переменные. Однако злоупотребление глобальными связями делает программу, как правило, запутанной, трудной в понимании и сложной в отладке. В соответствии с требованиями хорошего стиля программирования рекомендуется там, где это возможно, использовать передачу результатов через фактические параметры-переменные. С другой стороны, описание всех формальных параметров как параметров-переменных нежелательно по двум причинам. Во-первых, это исключает возможность вызова подпрограммы с фактическими параметрами в виде выражений, что делает программу менее компактной. Во-вторых, и главных, в подпрограмме возможно случайное использование формального параметра, например, для временного хранения промежуточного результата, т. е. всегда существует опасность непреднамеренно испортить фактическую переменную. Вот почему параметрами-переменными следует объявлять только те, через которые подпрограмма в действительности передает результаты вызывающей программе. Чем меньше параметров объявлено параметрами-переменными и чем меньше в подпрограмме используется глобальных переменных, тем меньше опасность получения не предусмотренных программистом побочных эффектов, связанных с вызовом подпрограммы, тем проще программа в понимании и отладке. По той же причине не рекомендуется использовать параметры-переменные в заголовке функции: если результатом работы функции не может быть единственное значение, то логичнее использовать процедуру или нужным образом декомпозировать алгоритм на несколько подпрограмм. - Существует еще одно обстоятельство, которое следует учитывать при выборе вида формальных параметров. Как уже говорилось, при объявлении параметра-значения осуществляется копирование фактического параметра во временную память. Если этим параметром будет массив большой размерности, то существенные затраты времени и памяти на копирование при многократных обращениях к подпрограмме можно минимизировать, объявив этот параметр параметром-константой. Параметр-константа не копируется во временную область памяти, что сокращает затраты времени на вызов подпрограммы, однако любые его изменения в теле подпрограммы невозможны - за этим строго следит компилятор. Еще одно свойство Object Pascal - возможность использования нетипизированных параметров. Параметр считается нетипизированным, если тип формального параметра-переменной в заголовке подпрограммы не указан, при этом соответствующий ему фактический параметр может быть переменной любого типа. Заметим, что нетипизированными могут быть только параметры-переменные: Procedure MyProc(var aParametr); Нетипизированные параметры обычно используются в случае, когда тип данных несущественен. Такие ситуации чаще всего возникают при разного рода копированиях одной области памяти в другую, например, С помощью процедур BlockRead, BlockWrite, Move-Memory И Т. П. 8.2.3. Умалчиваемые параметры В Delphi 4, 5 и 6 можно использовать так называемые умалчиваемые параметры, т. е. параметры, которые могут опускаться при обращении к подпрограмме. Умалчиваемые параметры замыкают список формальных параметров и имеют вид <имя>:<тип> = <значение> Например, Procedure P(a: array of Integer; S: String = ''); В этом случае два следующих обращения идентичны: Р([1,2,3], ' '); Р([1,2,3]); Если в подпрограмме используются два и более умалчиваемых параметра, то в случае переопределения одного из них при обращении к подпрограмме следует указывать все параметры вплоть до последнего переопределяемого (т. е. нельзя заменять непереопределяемые умалчиваемые параметры запятыми). Например: Procedure P(a: array of Integer; S: String = ''; В: Integer = 0); Допустимые обращения: Р([1,2,3]); Р([1,2,3], 'Строка'); Р(1,2,3],",1)
|