В.Г. Абрамов, Н.П. Трифонов, Г.Н. Трифонова - Введение в язык Паскаль (1107618), страница 40
Текст из файла (страница 40)
Посколькув процедуре Р формальные параметры х, у есть параметры-значения, топри активации процедуры будут порождены промежуточные переменныевещественного типа х и у, которым при входе в процедуру будут присвоены значения фактических параметров (х = 1, у = 0.8). Эти переменныесуществуют только на время выполнения тела процедуры, а после выходаиз процедуры они прекращают свое существование.2. Глобальные идентификаторы. Этоидентификаторы, которыенеявляются формальными параметрами и которые не описаны в теле процедуры (чтобы такие индентификаторы имели определенный смысл, онидолжны быть стандартными идентификаторами или должны быть описанывне тела процедуры).
Глобальные идентификаторы в теле процедурыимеют тот же самый смысл, который они имели к моменту входа в процедуру.В нашей процедуре Р глобальными являются идентификаторы t и writeln.Идентификатор t является именем той же самой вещественной переменной t, которая была описана в основной программе, и эта переменная привходе в процедуру имеет то же самое значение, которое она имела приобращении к процедуре (t = 0.5). Идентификатор writeln является именемстандартной процедуры вывода.В блоке, являющемся телом процедуры, глобальные идентификаторыимеют тот же самый смысл, что и в блоке, в который входит данная процедура — в данном случае таким блоком является тело основной программы.Таким образом, с помощью глобальных идентификаторов осуществляетсяпостоянная и непосредственная связь процедуры с объемлющим ее блоком,минуя связь через фактические параметры.3.
Локальные идентификаторы. Это идентификаторы, которые не являются формальными параметрами, но которые описаны в теле процедуры.В процедуре Р таким локальным идентификатором является п. Обратимвнимание на то, что идентификатор п был описан и в основной программе.Принцип локализации и заключается в том, что если какой-либо идентификатор описан в теле процедуры, то внутри процедуры такой идентификатор приобретает смысл в соответствии с этим описанием. Если же этотидентификатор был описан вне тела процедуры (в объемлющем ее блоке),то действие предыдущего описания временно (до выхода из процедуры)приостанавливается.
В частности, если в соответствии с этим предыдущимописанием идентификатор являлся именем некоторого программногообъекта, то этот объект становится недоступным из тела процедуры. Привыходе из процедуры утрачивает свою силу описание, содержащееся в телепроцедуры, и этот идентификатор вновь приобретает тот же смысл, который он имел до входа в процедуру (если этот идентификатор был описанвне процедуры). Если идентификатор, локализованный в теле процедуры,является именем программного объекта, то при выходе из процедурыэтот программный объект прекращает свое существование, а при каждомочередном вхождении в процедуру указанный объект порождается заново.В нашем примере идентификатор п описан в основной программе к а кимя константы. Это описание сохраняет свою силу до входа в процедурупо оператору Р(п, 0.8), так что к этому моменту будет получено значениеt = п/2 = 0.5 и значение первого фактического параметра в указанномоператоре процедуры есть n = 1.
Поскольку в теле процедуры также содержится описание идентификатора п, то предыдущее описание этого идентификатора к а к имени константы временно теряет свою силу. Внутри процедуры этот идентификатор п приобретает новый смысл: в соответствиис описанием var n: real он становится именем вещественной переменной.До входа в процедуру такая переменная вообще не существовала, так чток началу выполнения раздела операторов тела процедуры значение этойпеременной неопределено. В результате выполнения оператора n: = х + tпеременной п будет присвоено значение п = 1.5 (значение первого фактического параметра, равное единице, плюс значение глобальной переменной t, равное 0.5).
Далее по оператору t : = у глобальной переменной tприсваивается новое значение, равное значению второго фактическогопараметра оператора процедуры (равное 0.8), так что по операторуwriteln(n, t, х) будут отпечатаны значения 1.5, 0.8 и 1. На этом выполнениепроцедуры (а тем самым и выполнение оператора процедуры) заканчивается и происходит переход к выполнению следующего по порядку оператора основной программы writeln(n, t, х). При выходе из процедуры утрачивает свою силу описание идентификатора п, содержащееся в процедуре,и идентификатор п приобретает свой прежний смысл, который он имелдо входа в процедуру, т.е. имя константы. Смысл идентификатора t в процедуре не менялся, но поскольку этот идентификатор для процедуры былглобальным, то в результате выполнения процедуры исходное значениеt = 0.5 было заменено на значение 0.8.
Идентификатор х, который в процедуре являлся формальным параметром-значением, теперь снова является именем литерной переменной х, которой до обращения к процедуребыло присвоено значение ' + ' — это значение в процессе выполнения процедуры не изменялось. Таким образом, по оператору writeln(n, t, х) в основной программе будут отпечатаны числовые значения 1, 0.8 и литерноезначение '+' (без апострофов).Естественно, при вызове фактических параметров по имени можетпроизойти коллизия между ними и идентификаторами, локализованнымив теле процедуры.
Такая коллизия, если она возникает, автоматическиустраняется за счет, систематического изменения идентификаторов, локализованных в теле процедуры, что обеспечивается транслятором.165Таким образом, в качестве идентификаторов, локализованных в процедуре, можно брать любые идентификаторы, не используемые в качествеформальных параметров данной процедуры и не совпадающие с глобальными идентификаторами - независимо от того, использовались или нет этиидентификаторы вне данной процедуры.Чтобы не допустить ошибок в этом отношении, полезно придерживатьсяследующих правил при составлении описаний процедур:а) выписать все те идентификаторы, по которым осуществляется непосредственная связь процедуры с основной программой - эти идентификаторы должны быть глобальными для процедуры, т.е.
не должны использоваться в качестве формальных параметров и не должны описываться в процедуре;б) выбрать и зафиксировать идентификаторы, которые будут использоваться в качестве формальных параметров — это могут быть любые идентификаторы, не совпадающие с глобальными идентификаторами;в) для внутренних целей процедуры могут использоваться любые другие идентификаторы, однако все они должны быть соответствующим образом определены (описаны) в теле процедуры.Как видно, принцип локализации действительно предоставляет достаточно большую свободу в выборе обозначений при изготовлении описанийпроцедур и тем самым параллельную и независимую работу различныхисполнителей.Следует подчеркнуть, что принцип локализации относится ко всемописаниям, содержащимся в теле процедуры, в том числе и к описаниямпроцедур.
Дело в том, что при описании какой-либо процедуры Р, приводим о м в теле основной программы, может возникнуть необходимость (илицелесообразность) использования других процедур. Если эти другие процедуры носят локальный характер, т.е. они будут использоваться тольков процедуре Р, то было бы нецелесообразно давать их описание в основнойпрограмме наряду с процедурой Р - такие процедуры удобнее ввестив употребление (описать) внутри процедуры Р.Пусть, например, в какой-либо программе оказалось целесчобразнымввести в употребление процедуру нахождения наибольшего из шести вещественных значений с запоминанием результата в качестве значения некоторой переменной.
Решение этой частной задачи удобно свести к решению еще более простых задач - нахождению наибольшего из трех и из двухвещественных значений, а алгоритмы решения этих последних задач можнооформить в виде процедур. Если эти частные задачи нигде больше решатьне приходится, то описания соответствующих им процедур целесообразнодать в той процедуре, в которой они только и будут использоваться. Такчто процедуру нахождения наибольшего из шести значений можно описать, например, следующим образом:p r o c e d u r e МАХ6(Ы,Ь2,ЬЗ,Ь4,Ь5,Ь£: r e a l ; var y tvar c , d :real;p r o c e d u r e MAX2(rl,r2s r e a l ; var us r e a l ) ;b e g i n i f r l > r 2 t h e n u s » r l e l s e u : - r 2 end;procedure MAX3(si,s2,s3:166r e a l ; var v : r e a l ) ;real);var ys real;begin if sl>s2 then y:=sl else yi=s2;if s3>y then ys=s3; v:=yend;begin МАХЗ(Ы,Ь2,ЬЗ,с);МАХЗ(Ь4,Ь5,Ь6,d);МАХ2(с,d,у)endЗдесь процедуры МАХЗ и МАХ2 локализованы в процедуре МАХ6,так что к этим процедурам можно обращаться только в процедуре МАХ6 —вне тела этой процедуры они недоступны.
Заметим, что формальные параметры внешней процедуры (МАХ6) могут использоваться в качестве фактических параметров при обращениях к локализованным в ней процедурам (МАХ2 и МАХЗ).8.5. Примеры использования процедурПриведем дополнительные примеры паскаль-программ с использованиемпроцедур.П р и м е р 8.1.
Задаются три последовательности целых чисел, каждаяиз которых состоит из 20 элементов. В последовательности, содержащейнаибольшее количество отрицательных чисел, каждое отрицательное число заменить на единицу ( если указанная последовательность определяетсянеоднозначно, то преобразовать любую из них).При формулировании алгоритма решения поставленной задачи числуэлементов (20) в каждой последовательности удобно дать имя, например N(с помощью описания константы), чтобы программу можно было легкомодифицировать для работы с последовательностями другой длины. Самипоследовательности целых чисел естественно отобразить на целочисленныемассивы, введя в употребление соответствующий тип значений с именем,например, массив.Как мы знаем, в паскале нет стандартной процедуры ввода и выводамассивов.
А поскольку в нашей программе придется вводить и выводитьмассивы, то введем в употребление соответствующие процедуры на базестандартных процедур ввода и вывода. Введем также в употребление процедуру подсчета количества отрицательных компонент массива и процедуру нужного нам преобразования массива.{Пример 8.1. Матвеева Т.К.ф-т ВМиК МГУ В.3.87г.Задаются три последовательности целых чисел,N элементов.состоящие изВ последовательности, содержащей наибольшееколичество отрицательных элементов,каждое отрицательноечисло заменить на единицу}{Использование процедур}program ПРЕОБРВЕКТ<input,output);const N=20;167type инд-l..N;массив=аггау Синд] o-f integer;var a,b,c: массив; k,l,m: инд;Сjprocedure ВВОДМАС(var х:массив);var i: инд;begin -for i: = l to N do read<xCi]) end;{}procedure ВЫВМАС<var x:массив);var i: инд;begin -for i:=l to N do wr i te (x С i ] ) ; wr i tel n end;{}procedure ОТРКОМП(var x:массив;var к:инд);var i: инд;begin k:=0;for i: = l to N do i-f xCi]<0 then k:=k+l end;{>procedure npBEKT<var x:массив);var i: инд;begin for i:=l to N do if xCi]<0 then xCi]:="l end;{>begin ВВОДМАС < a > ^ writeln<'МАССИВ_а_ '); ВЫВМАС(а);ВВОДМАС(b); writeln("MACCHB_h:_'); ВЫВМАС <b);ВВОДМАС(с);writeln<'МАССИВ_с:_');0ТРК0МП(а,k); ОТРКОМП(b,1);ВЫВМАС(с);ОТРКОМП(с,т);wr i te ( ' ПР'ЕОБРАЗОВАННЫЙ МАССИВ _ ' ) ;if <k>l) and (k>m) thenbegin writeln< 'a:_ ' ); ПРВЕКТ(а); ВЫВМАС(a) endel 5eifthenbegin writeln<'b:_'); ПРВЕКТ(Ь); ВЫВМАС(Ь) endel sebegin wr i tel n < ' с : _ ' > ; ПРВЕКТ-(с); ВЫВМАС (с) endend.Здесь в каждой процедуре введена в употребление локальная переменная i.