Главная Случайная страница


Полезное:

Как сделать разговор полезным и приятным Как сделать объемную звезду своими руками Как сделать то, что делать не хочется? Как сделать погремушку Как сделать так чтобы женщины сами знакомились с вами Как сделать идею коммерческой Как сделать хорошую растяжку ног? Как сделать наш разум здоровым? Как сделать, чтобы люди обманывали меньше Вопрос 4. Как сделать так, чтобы вас уважали и ценили? Как сделать лучше себе и другим людям Как сделать свидание интересным?


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Внешние переменные





 

Программа на языке "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());

 

 

для того, чтобы проанализировать верхний элемент стека, не

изменяя его.

Отметим также, что так как операции + и * коммутативны,

порядок, в котором объединяются извлеченные операнды, несу-

щественен, но в случае операций - и / необходимо различать

левый и правый операнды.

 

 







Date: 2015-09-17; view: 525; Нарушение авторских прав



mydocx.ru - 2015-2024 year. (0.014 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию