Матросов А.В. Maple 6. Решение задач высшей математики и механики (1185909), страница 56
Текст из файла (страница 56)
Если какой-нибудь параметр не будет соответствовать заданному типу, то отобразится сообщение о несоответствии параметра объявленному типу, которое более информативно, нежели сообщение о невозможности выполнить некоторую операцию: > по(уг(З, 'у',з1( ЕГГОГ, Зикуг ЕХрЕСГЗ гсв 2ПС( аГООЗЕЕПГ, у, ГО ЬЕ ОГ ГурЕ ПзЗПЗЕГХС, Ьпс хесе>кое<( у Замечание Прп проверке типа передаваемого в процедуру параметра можно использовать все основные типы мвр(е, структурные типы и типы, созданные пользователем. При обьявлении процедуры не обязательно задавать имена формальных параметров. Язык Мар1е предоставляет специальное имя егоз, с помощью ко- Глава 5.
Основы программирования в Чар/в торого можно получить доступ к любому переданному в процедуру фактическому параметру. Значением переменной агдя является последователыюсть всех фактических параметров, а получить значение 1-го параметра можно, воспользовавшись индексной записью агдя [1). Обшее количество переданных при вызове процедуры фактических параметров хранится в специальной переменной пагчя. Это позволяет легко писать процедуры с произвольным количеством фактических параметров (пример 5.10). > МАХ: =ргос ( ) 15 пагдя40 ГПеп — гпбгп1гу е111 пагдя=1 Гьеп агчя(1!; е1яе т."=агчя (1); бог 1 Ггсга 2 Го пагчя бо 11 агдя(1-1)<агчя(1) гьеп агчя( ) е1яе агдя(1-1) епо 11; епб с)о; еи1 11; епб ргос: иагп1пч, 'т 1я мпр11сгг1у бес1агеб 1оса1 го ргосес(пге 'млх' жагп1пч, '1' гя мар11с1г1у бес1агег) 1оса1 го ргосебсге 'мАх' > МАХ(45/4б,5б/57,97/99); 56 57 Процедура примера 5.!0 вычисляет максимальное значение числовой последовательности любой длины.
Однако при использовании подобной техники в теле процедуры следует обязательно проверять полученные параметры на соответствие допустимым типам процедуры. Понятно, что в нашем случае ВСЕ фаКтИЧЕСКИЕ ПараМЕтрЫ дОЛжНЫ бЫтЬ ЧИСЛОВЫМИ ( п аеггс), ПОЭтОМу следующий оператор, поставленный самым первым оператором в теле процедуры, исправит это упущение: бог 1 гп агдя бо 11 пес Гуре(1,пожег1с) Гпеп еггог "Параметр " )( 1 )( " должен быть пьгаег1с" епб 1г епб бо; В этом операторе цикла для завершения процедуры использован оператор еггог, который генерирует исключительное состояние ошибки, печатает сообшение, переданное ему в качестве параметра, и останавливает выполнение процедуры.
Теперь исправленный вариант нашей процедуры при обра- Часть!. Основы Мвр)е щении к ней с нечисловыми фактическими параметрами будет печатать со- общение о несоответствии параметра числовому типу: > ИАХ(8/9, 58/57, х, 97/99) ) Еггог, (ьп ИАХ) Параметр х должен быть псжег1с В примере 5.!О после объявления процедуры илх() система Мар!е вывела два сообщения, информирующие пользователя о том, что переменные т и ', которые используются при реализации алгоритма процедуры, неявным образом определены как ее локальные переменные.
Это сообщение появилось из-за того, что мы явно не объявили эти переменные как локальные опера- тОрОМ )оса1. ЧтО таКОЕ ЛОКаЛЬНЫЕ И ГЛОбаЛЬНЫЕ ПЕРЕМЕННЫЕ И КаК ОНИ ИС- пользу)отея при программировании в Мар(е, разъясняется в следующем разделе. 5.2.3. Локальные и глобальные переменные Переменные, используемые в процедуре, могут быть либо локальными для нее, либо глобальными. Все переменные, определенные вне процедуры, являются для нее глобальными. Процедура может использовать и менять их значения, причем измененные значения будут, естественно, доступны и вне тела процедуры. Создаваемые локальные переменные доступны только в теле той процедуры, где они созданы, и их имена не конфликтуют с аналогичными именами локальных переменных других процедур и глобальными именами.
Это означает, что на рабочем листе, например, могут быть определены глобальная переменная с именем таг и много локальных переменных с аналогичным именем, но в объявлениях разных процедур. Хотя в Мар!е и существует алгоритм автоматического определения, какая переменная в процедуре является глобальной, а какая локальной, рекомендуется, однако, всегда явно объявлять глобальные и локальные переменные в заголовке процедуры с помощью операторов: 1оса1 Щ, Ь2, ..., Ым 91опа1 С1, аз, ..., Сп) Явно объявлять используемые переменные стоит хотя бы из-за того, чтобы не получать предупреждающих сообщений, как в примере 5. )О.
Измененный текст процедуры этого примера с учетом проверки типа фактических параметров окончательно выглядит так: > ИАХ:=ргос() 1оса1 1, т Гог 1 Ьп агча бо 1Г пос Гуре(1,пспег1с) гпеп еггог "Параметр " )) 1 (( " должен быть псжег1с" епб 1г епб бо; Глава Б. Основы программирования в Мар!е 1Г сегда=О Снео -1етгогеу е11Г еагде=1 елее агде!1)) е1ее т:=егда)1); Гег 1 агом 2 ео сегда г)о ) В агдз !1-1)сегда )1) с)1ео агдз[1] е1зе агде )1-1) еео 11; еес) Оо) еое 1Г; еес) ргос: Если в процедуре нет никаких объявлений локальных или )лобальных переменных, то Мар!е пользуется следующими правилами для определения, что переменная является локальной: гз она появляется в левой части оператора присваивания; Г! она появляется в качестве переменной цикла оператора г = или как ин- дЕКСНаЯ ПЕРЕМЕННаЯ В КОМаНДаХ еед) ), ес)с)! ) ИЛИ те)) ). Если ни одно из приведенных правил нельзя применить к переменной в теле процедуры, то она считается глобальной.
Локальные переменные также отличаются от глобальных по алгоритму их вычисления. Напомним, что для глобальных переменных используется правило полного вычисления !си, гл. 2), т. е. если в выражении, которое изначально было присвоено переменной, входила неизвестная величина и впоследствии ей было присвоено какое-либо значение, то это значение подставляется в первоначальное выражение для исходной переменной. Значение, которое было присвоено этой неизвестной величине, само может содержать неизвестные величины, которым позднее также были присвоены некоторые значения. Подобная процедура выполняется и для них и повторяется до тех пор, пока не дойдет до неизвестных величин, которым не присваивалось никакого значения, или до числовых объектов Мар!е.
Каждая такая подстановка считается одним уровнем вычисления. Локальнь)е переменные в процедурах не вычисляются в соответствии с правилом полного вычисления. Для них Мар1е применяет правило вычисления точно на один уровень, т. е. если в ее определении была использована неизвестная переменная, которой впоследствии присвоили некоторое значение, то при вычислении локальной переменной этот факт не принимается во внимание. В примере 5.11 демонстрируются алгоритмы Мар!е вычисления глобальных и локальных переменных.
е Л~йй!~~ЙЙРй'-::1 > оь|=рхос() 1оса1 1,х,у; д1оьа1 ду Часть 1. Основы Мар1в д:=х"2! ):=х"2! х с=у 2; у:=б; ргтпп 19);рггпс 11); епп ргос! 6А Г рГОЕ() !ОЕО! Л Г у В!ОЬО! Гн д .= Г>2; 1.= Г2: Х .== у 2; у .= б: рПП1(В); рПП1( !) ЕОО рГОЕ > сш); 1296 х > я;г; 1296 1 В примере 5.11 определена процедура сь1), в которой глобальной д и локальной 2 переменным первоначально присваиваются выражения, содержащие неизвестную величину х. Далее переменной х присваивается выражение, содержащее неизвестную величину у, которой чуть позже присваивается числовое значение. Завершается процедура печатью значений глобальной и локальной переменных. Вызов этой процедуры показывает, что глобальная переменная вычислена полностью (ее значение равно числу 1296), тогда как локальная переменная только до первого уровня (ее значение равно х2). Вычисление значений глобальных переменных с именами 9 и ! вне тела процедуры полностью соответствует правилам использования переменных в Мар!е: переменная ч действительно имеет значение, которое она получила во время выполнения процедуры сь11, а переменная ц никоим образом не связанная с локальной переменной с таким же именем в процедуре сь,;, не имеет никакого значения, и поэтому вычисляется равной своему имени.
Почему в теле процедуры переменные вычисляются на глубину только одного уровня, а не полностью, как в случае глобальных переменных". Это связано с проблемой эффективности выполнения процедуры, которая обычно реализует алгоритм, используя последовательное присваивание значений переменных, и практически не обращается к технике "обратного" присваивания (сначала определить переменную через неизвестную величину, которой позже присвоить некоторое значение), часто используемой при интерактивной работе. Однако если все-таки при реализации алгоритма без нее трудно обойтись, то для полного вычисления локальной переменной следует ИСПОЛЬЗОВатЬ КОМаНду о 21).
ПрОцЕдура Гпщсос1) ПрИМЕра 5.12, В КОтсрОй локальная переменная вычисляется на полную глубину вложенности командой о от 1х), возвращает значение о, тогда как процедура гпттьост1), возвращаемым значением которой является вычисленное на глубину одного уровНя ВЛОжЕННОСтИ ЗНаЧЕНИЕ ЛОКаЛЬНОй ПЕрЕМЕННОй х, ВЫЧИСЛяЕтСя раВНОй у2. Глава о Основы программирования в )нар(в > Гп111осг ргос() 1оса1 х,у; х:=у 2; у:=2> еча1(х) > епо ргос: > Гп11ъос()! 4 > Гп11ъоо1:=ргос() 1оса1 х,у) х:=у"2; у."=2; х; епс( ргос: > Гп111оо1() ) У В Мар(е У Ке! 5 была введена возможность объявления и использования локальных процедур, т.