Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Функции, возвращающие нецелые значенияСодержание книги
Поиск на нашем сайте
Еще об аргументах функций В главе 1 мы уже обсуждали тот факт, что аргументы фун-кций передаются по значению, т.е. вызванная функция получаетсвою временную копию каждого аргумента, а не его адрес. этоозначает, что вызванная функция не может воздействовать наисходный аргумент в вызывающей функции. Внутри функции каж-дый аргумент по существу является локальной переменной, ко-торая инициализируется тем значением, с которым к этой функ-ции обратились. Если в качестве аргумента функции выступает имя массива,то передается адрес начала этого массива; сами элементы некопируются. Функция может изменять элементы массива, исполь-зуя индексацию и адрес начала. Таким образом, массив переда-ется по ссылке. В главе 5 мы обсудим, как использование ука-зателей позволяет функциям воздействовать на отличные отмассивов переменные в вызывающих функциях. Между прочим, несуществует полностью удовлетворительногоспособа написания переносимой функции с переменным числомаргументов. Дело в том, что нет переносимого способа, с по-мощью которого вызванная функция могла бы определить, сколь-ко аргументов было фактически передано ей в данном обраще-нии. Таким образом, вы, например, не можете написать дейст-вительно переносимую функцию, которая будет вычислять макси-мум от произвольного числа аргументов, как делают встроенныефункции MAX в фортране и PL/1. Обычно со случаем переменного числа аргументов безопасноиметь дело, если вызванная функция не использует аргументов,которые ей на самом деле не были переданы, и если типы сог-ласуются. Самая распространенная в языке "C" функция с пере-менным числом - PRINTF. Она получает из первого аргументаинформацию, позволяющую определить количество остальных ар-гументов и их типы. Функция PRINTF работает совершенно неп-равильно, если вызывающая функция передает ей недостаточноеколичество аргументов, или если их типы не согласуются с ти-пами, указанными в первом аргументе. Эта функция не являетсяпереносимой и должна модифицироваться при использовании вразличных условиях. Если же типы аргументов известны, то конец списка аргу-ментов можно отметить, используя какое-то соглашение; напри-мер, считая, что некоторое специальное значение аргумента(часто нуль) является признаком конца аргументов.Внешние переменные Программа на языке "C" состоит из набора внешних объек-тов, которые являются либо переменными, либо функциями. Тер-мин "внешний" используется главным образом в противопостав-ление термину "внутренний", которым описываются аргументы иавтоматические переменные, определенные внурти функций.Внешние переменные определены вне какой-либо функции и, та-ким образом, потенциально доступны для многих функций. Самифункции всегда являются внешними, потому что правила языка"C" не разрешают определять одни функции внутри других. Поумолчанию внешние переменные являются также и "глобальными",так что все ссылки на такую переменную, использующие одно ито же имя (даже из функций, скомпилированных независимо),будут ссылками на одно и то же. В этом смысле внешние пере-менные аналогичны переменным COмMON в фортране и EXTERNAL вPL/1. Позднее мы покажем, как определить внешние переменныеи функции таким образом, чтобы они были доступны не глобаль-но, а только в пределах одного исходного файла. В силу своей глобальной доступности внешние переменныепредоставляют другую, отличную от аргументов и возвращаемыхзначений, возможность для обмена данными между функциями.Если имя внешней переменной каким-либо образом описано, толюбая функция имеет доступ к этой переменной, ссылаясь к нейпо этому имени. В случаях, когда связь между функциями осуществляется спомощью большого числа переменных, внешние переменные оказы-ваются более удобными и эффективными, чем использованиедлинных списков аргументов. Как, однако, отмечалось в главе1, это соображение следует использовать с определенной осто-рожностью, так как оно может плохо отразиться на структурепрограмм и приводить к программам с большим числом связей поданным между функциями. Вторая причина использования внешних переменных связанас инициализацией. В частности, внешние массивы могут бытьинициализированы а автоматические нет. Мы рассмотрим вопрособ инициализации в конце этой главы. Третья причина использования внешних переменных обуслов-лена их областью действия и временем существования. Автома-тические переменные являются внутренними по отношению к фун-кциям; они возникают при входе в функцию и исчезают при вы-ходе из нее. Внешние переменные, напротив, существуют посто-янно. Они не появляютя и не исчезают, так что могут сохра-нять свои значения в период от одного обращения к функции додругого. В силу этого, если две функции используют некоторыеобщие данные, причем ни одна из них не обращается к другой,то часто наиболее удобным оказывается хранить эти общие дан-ные в виде внешних переменных, а не передавать их в функциюи обратно с помощью аргументов. Давайте продолжим обсуждение этого вопроса на большомпримере. Задача будет состоять в написании другой программыдля калькулятора, лучшей,чем предыдущая. Здесь допускаютсяоперации +,-,*,/ и знак = (для выдачи ответа).вместо инфикс-ного представления калькулятор будет использовать обратнуюпольскую нотацию,поскольку ее несколько легче реализовать.вобратной польской нотации знак следует за операндами; инфик-сное выражение типа (1-2)*(4+5)= записывается в виде 12-45+*= круглые скобки при этом не нужны Реализация оказывается весьма простой.каждый операнд по-мещается в стек; когда поступает знак операции,нужное числооперандов (два для бинарных операций) вынимается,к ним при-меняется операция и результат направляется обратно встек.так в приведенном выше примере 1 и 2 помещаются в стеки затем заменяются их разностью, -1.после этого 4 и 5 вво-дятся в стек и затем заменяются своей суммой,9.далее числа-1 и 9 заменяются в стеке на их произведение,равное -9.опе-рация = печатает верхний элемент стека, не удаляя его (такчто промежуточные вычисления могут быть проверены). Сами операции помещения чисел в стек и их извлеченияочень просты,но, в связи с включением в настоящую программуобнаружения ошибок и восстановления,они оказываются доста-точно длинными. Поэтому лучше оформить их в виде отдельныхфункций,чем повторять соответствующий текст повсюду в прог-рамме. Кроме того, нужна отдельная функция для выборки изввода следующей операции или операнда. Таким образом, струк-тура программы имеет вид: WHILE(поступает операция или операнд, а не конец IF (число) поместить его в стек еLSE IF (операция) вынуть операнды из стека выполнить операцию поместить результат в стек ELSE ошибка Основной вопрос, который еще не был обсужден, заключает-ся в том,где поместить стек, т. Е. Какие процедуры смогутобращаться к нему непосредственно. Одна из таких возможнос-тей состоит в помещении стека в MAIN и передачи самого стекаи текущей позиции в стеке функциям, работающим со стеком. Нофункции MAIN нет необходимости иметь дело с переменными, уп-равляющими стеком; ей естественно рассуждать в терминах по-мещения чисел в стек и извлечения их оттуда. В силу этого мырешили сделать стек и связанную с ним информацию внешнимипеременными, доступными функциям PUSH (помещение в стек) иPOP (извлечение из стека), но не MAIN. Перевод этой схемы в программу достаточно прост. Ведущаяпрограмма является по существу большим переключателем по ти-пу операции или операнду; это, по-видимому, более характер-ное применеие переключателя, чем то, которое было продемонс-трировано в главе 3. #DEFINE MAXOP 20 /* MAX SIZE OF OPERAND, OPERАTOR * #DEFINE NUMBER '0' /* SIGNAL THAT NUMBER FOUND */ #DEFINE TOOBIG '9' /* SIGNAL THAT STRING IS TOO BIG * MAIN() /* REVERSE POLISH DESK CALCULATOR */ /(INT TUPE; CHAR S[MAXOP]; DOUBLE OP2,ATOF(),POP(),PUSH(); WHILE ((TUPE=GETOP(S,MAXOP))!=EOF); SWITCH(TUPE) /(CASE NUMBER: PUSH(ATOF(S)); BREAK; CASE '+': PUSH(POP()+POP()); BREAK; CASE '*': PUSH(POP()*POP()); BREAK; CASE '-': OP2=POP(); PUSH(POP()-OP2); BREAK; CASE '/': OP2=POP(); IF (OP2!= 0.0) PUSH(POP()/OP2); ELSE PRINTF("ZERO DIVISOR POPPED\N"); BREAK; CASE '=': PRINTF("\T%F\N",PUSH(POP())); BREAK; CASE 'C': CLEAR(); BREAK; CASE TOOBIG: PRINTF("%.20S... IS TOO LONG\N",S) BREAK; /) /) #DEFINE MAXVAL 100 /* MAXIMUM DEPTH OF VAL STACK */ INT SP = 0; /* STACK POINTER */ DOUBLE VAL[MAXVAL]; /*VALUE STACK */ DOUBLE PUSH(F) /* PUSH F ONTO VALUE STACK */ DOUBLE F; /(IF (SP < MAXVAL) RETURN(VAL[SP++] =F); ELSE /(PRINTF("ERROR: STACK FULL\N"); CLEAR(); RETURN(0); /) /) DOUBLE POP() /* POP TOP VALUE FROM STEACK */ /(IF (SP > 0) RETURN(VAL[--SP]); ELSE /(PRINTF("ERROR: STACK EMPTY\N"); CLEAR(); RETURN(0); /) /) CLEAR() /* CLEAR STACK */ /(SP=0; /) Команда C очищает стек с помощью функции CLEAR, котораятакже используется в случае ошибки функциями PUSH и POP. кфункции GETOP мы очень скоро вернемся. Как уже говорилось в главе 1, переменная является внеш-ней, если она определена вне тела какой бы то ни было функ-ции. Поэтому стек и указатель стека, которые должны исполь-зоваться функциями PUSH, POP и CLEAR, определены вне этихтрех функций. Но сама функция MAIN не ссылается ни к стеку,ни к указателю стека - их участие тщательно замаскировано. Всилу этого часть программы, соответствующая операции =, ис-пользует конструкцию PUSH(POP()); для того, чтобы проанализировать верхний элемент стека, неизменяя его. Отметим также, что так как операции + и * коммутативны,порядок, в котором объединяются извлеченные операнды, несу-щественен, но в случае операций - и / необходимо различатьлевый и правый операнды. Упражнение 4-3 --------------- Приведенная основная схема допускает непосредственноерасширение возможностей калькулятора. Включите операцию де-ления по модулю /%/ и унарный минус. Включите команду "сте-реть", которая удаляет верхний элемент стека. Введите коман-ды для работы с переменными. /Это просто, если имена пере-менных будут состоять из одной буквы из имеющихся двадцатишести букв/.
|
||||
|
Последнее изменение этой страницы: 2016-08-26; просмотров: 311; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.119 (0.013 с.) |