В.Г. Абрамов, Н.П. Трифонов, Г.Н. Трифонова - Введение в язык Паскаль (1107618), страница 39
Текст из файла (страница 39)
При этом допускаетсяк а к полная, так и частичная переменная, например переменная' с индексами. Следует, однако, иметь в виду, что если такая частичная переменнаяимеет переменный индекс, например х [i], то значение индекса вычисляется и фиксируется при входе в процедуру. Например, при наличии в программе описанийvar n,k: integer; В: array CI.. 203 o-f integer;procedure P(var x,y:integer);допустимы обращения к процедуре Р вида Р(п, к) и Р(п. В [ к ] ) . Во втором из этих случаев частичная переменная В [к] имеет тот же тип integer,что и формальный параметр у, однако в момент обращения к процедуре160фиксируется текущее значение к, и если в этот момент было к = 3, то везде в теле процедуры формальный параметр у будет заменен на В [ 3 ] .
Следующие же обращения к процедуре Р будут недопустимы: Р(п, 5) (в качестве второго фактического параметра задано число, а не переменная),Р(В, к) (переменная В, заданная в качестве первого фактического параметра, является переменной не типа integer, а типа массива). Обратимвнимание на то, что фактическим параметром-переменной не может бытькомпонента (переменная с индексами) упакованного массива.Если же формальный параметр является параметром-значением, то в качестве соответствующего ему фактического параметра можно задаватьлюбое выражение соответствующего типа, в частности, константу или переменную, которые являются частным случаем выражения.
При этомформальному параметру типа real может соответствовать и выражениетипа integer, а формальному параметру простого типа — выражение ограниченного типа, построенного на базе этого простого типа.Например, при наличии в программе описанийv a r m: i n t e g e r ; k: 1 . . 9 ; x , y s r e a l ;p r o c e d u r e Q<a: i n t e g e r ; b : r e a l ; v a r c i r e a l ) ;допустимы следующие обращения к процедуре Q:Q(k,х/5,у)иQ(25,2*m,x),но недопустимы обращения Q(3.141, х/5, у) (задан фактический параметртипа real для формального параметра типа integer) и Q(k, х/5, 0.5) (дляпараметра-переменной в качестве фактического параметра задано число).Вопрос о том, как используются параметры-значения и параметрыпеременные, был уже рассмотрен ранее.У читателя может возникнуть вопрос - почему в случае параметровпеременных требуется точное совпадение типов формального и фактического параметров, а в случае параметров-значений допускаются определенные отклонения от этого требования?Дело в том, что в случае параметра-значения фактический параметриспользуется вполне определенным образом: значение этого фактическогопараметра при входе в процедуру присваивается внутренней для процедурыпеременной, которая ставится в соответствие формальному параметру,и нигде дальше значение фактического параметра уже не используется.Л в таком случае, как мы знаем, упомянутые выше отклонения типовв паскале разрешены.
Если же речь идет о параметре-переменной, то переменная, являющаяся фактическим параметром, в модифицированномтеле процедуры может фигурировать как в правой,, так и в левой частяхоператоров присваивания. В таких случаях может возникнуть проблемапреобразования вещественного значения в целое, а паскаль требует явногоуказания правил такого преобразования.
По этой причине для параметровпеременных и требуется точное совпадение типов формального и фактического параметров.11. В.Г. Абрамов1618.4. Принцип локализацииЕстественно, что наибольшие трудности в программировании возникаютпри разработке и изготовлении больших и сложных программ, которыеочень часто представляют собой целые комплексы ряда взаимодействующих друг с другом программ.С основным практическим методом борьбы со сложностью решаемыхзадач, а значит и соответствующих им программ, мы уже познакомились —это выделение из исходной задачи некоторых достаточно самостоятельныхподзадач, каждая из которых, естественно, более проста по сравнениюс исходной задачей.
Если какая-либо из выделенных подзадач все еще оказывается слишком сложной, то с ней поступают так же, как и с исходнойзадачей. Этот процесс продолжается до тех пор, пока сложность каждойиз выделенных подзадач не окажется приемлемой. Именно в этом и состоитсуть метода пошаговой детализации (нисходящего проектирования) программы.В практической работе всегда очень остро стоит вопрос о сроках изготовления нужных программ. Если учесть, что трудоемкость изготовлениямногих реальных программ составляет десятки человеко-лет, то очевидно,что изготовить подобного рода программу силами одного человека в приемлемые сроки практически невозможно (а срок в 5—8 лет обычно таковым уже не является). Существенно сократить срок изготовления программы обычно удается лишь за счет привлечения к этой работе не одного,а целого коллектива программистов, которые могли бы над данной программой работать параллельно.
Метод пошаговой детализации и аппаратпроцедур как раз и дают потенциальные возможности для такой параллельной работы. Действительно, когда из основной задачи выделена та или инаяподзадача, то разработку частичного алгоритма, предназначенного для решения этой подзадачи, можно поручить другому исполнителю (в качествекоторого может выступать как отдельное лицо, так и группа лиц). Приэтом разработанный частичный алгоритм может быть представлен в видедостаточно автономной части общей программы, а именно — в виде описания процедуры, которое затем достаточно вставить в раздел процедури функций паскаль-программы.Ясно, однако, что параллельная работа ряда исполнителей над однойи той же программой (точнее, над разными частями одной и той же программы) может быть достаточно эффективной лишь в том случае, еслиотдельные исполнители будут иметь возможность работать независимодруг от друга.
Реализация же этой возможности вызывает определенныетрудности.Действительно, в задании на изготовление какой-либо процедуры естественно зафиксировать лишь ее назначение и связи с основной программойпо входным и выходным данным, но не алгоритм, представляемый этойпроцедурой, ибо этот алгоритм еще подлежит разработке и рещэиис этоговопроса должно быть передано на усмотрение соответствующего исполнителя. Однако в процессе выбора и записи этого алгоритма обычно возникает необходимость ввести в употребление некоторые дополнительныетипы значений и (или) программные объекты, например вспомогательныепеременные для представления промежуточных результатов.162Конечно, все необходимые для процедуры программные объекты и типызначений можно было бы вводить в употребление (описывать) в основнойпрограмме.
Однако необходимость заботиться о потребностях каждойиз используемых процедур ложилась бы весьма тяжким бременем на основную программу, и к тому же многие из изменений, вносимых в отдельные процедуры, приводили бы к необходимости вносить соответствующиеизменения и в основную программу. В итоге параллелизма и независимостипри составлении различных частей программы не удалось бы достигнуть.Для устранения подобного рода трудностей паскаль разрешает любойпроцедуре вводить в употребление для своих внутренних потребностейлюбые допустимые в языке типы значений и программные объекты.
В связи с этим вспомним, что тело процедуры синтаксически определяется точнотак же, как и тело паскаль-программы, так что тело процедуры — нарядус разделом операторов — может содержать и любые разделы описаний.Однако здесь уместно вспомнить одно из основных требований я з ы к ао том, что один и тот же идентификатор в данной программе не должениспользоваться для различных целей. С одной стороны, это требованиедостаточно естественно, так как в противном случае может возникнутьнеоднозначность понимания и интерпретации программы.
С другой стороны, абсолютное выполнение этого требования привело бы к значительнымтрудностям при параллельной работе исполнителей, поскольку при выбореимен для вводимых в употребление в процедуре новых типов и программных объектов пришлось бы очень внимательно следить за тем, не использовались ли эти имена в других процедурах и в основной программе. Ясно,что в этом случае параллелизма и независимости в работе отдельных исполнителей практически не получилось бы. Кроме того, это привело бы к необходимости использования не очень удобных и наглядных имен.Эти трудности в паскале устраняются благодаря блочной структурепрограммы и принципу локализации, суть которого состоит в том, чтоимена, вводимые в употребление в какой-либо процедуре, имеют силутолько в пределах данной процедуры (ниже это положение будет уточнено) .
Проиллюстрируем этот принцип на примере следующей паскальпрограммы:program LOC(output);const n=l;v a r t: real; x: char;p r o c e d u r e P(x,y:real);v a r n: real;b e g i n nr«х+t;t:«у;writeln(n,t,x) end;begin t : = n / 2 ; x : « ' + ' ;P (n, 0.8 >;writeln(n,t,x)end.Сейчас нам будет удобно все описания трактовать как описания идентификаторов, поскольку каждое описание конкретизирует смысл идентификаторов, вводимых в употребление с его помощью.
Можно, например,считать, что описаниеv a r х,ys11*real163говорит о том, что идентификаторы х и у будут использоваться в качествеимен переменных типа real.Как видно, в блоке основной программы описаны четыре идентификатора (не считая имени самой программы). В соответствии с этими описаниями п есть имя целочисленной константы, t — имя вещественной переменной, х — имя литерной переменной и Р — имя процедуры. Эти описаниясохраняют свою силу во всем теле основной программы, за исключением,может быть, описаний процедур и функций.
Таким образом, к моментувыполнения оператора процедуры Р (п, 0.8) вещественная переменная tполучит значение 0.5, а литерная переменная х — литерное значение ' + '.По оператору процедуры Р(п, 0.8) производится обращение к процедуре Р. Описание процедуры в общем случае может содержать следующие тривида идентификаторов (все они присутствуют в приведенном выше описании процедуры Р).1. Формальные параметры. О выборе формальных параметров и их использовании при обращении к процедуре мы уже говорили.