Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по информатике все.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
986.62 Кб
Скачать

Пример 27

Исходные данные:

A, B, C

Результат:

максимальное число Max

program Maximum; {вычисление максимального из трех чисел} var

A, B, C: real;

function Max(X,Y:real):real; {задан тип возвращаемого результата} {функция возвращает значение Max X, Y - формальные параметры} begin

if X > Y then Max := X else Max := Y;

end; {конец функции} begin    {основная программа}

write('Введите A, B, C:'); read(A, B, C); writeln('Максимальное число'); writeln( Max(Max(A, B), C) );

end.

Как видно из примера, вызов функции осуществляется указанием имени функции в выражении.

Обмен данными

Существует два способа обмена данными между программой и подпрограммой:

- использование глобальных переменных; - использование механизма формальных и фактических параметров. Первый способ является очевидным, ведь глобальные переменные являются доступными для всех подпрограмм, расположенных в тексте программы ниже объявления глобальных переменных. Такие подпрограммы могут использовать глобальные переменные как исходные данные, а после соответствующей их модификации передавать через них в программу результаты своих вычислений.

При использовании глобальных переменных для обмена данными между программой и подпрограммой необходимо следить за непредусмотренными изменениями значений глобальных переменных в подпрограммах. Ошибки такого рода часто встречаются у начинающих программистов и довольно трудно обнаруживаются. По этой причине переменная цикла всегда должна быть локальной. Обсудим механизм формальных и фактических параметров. В предыдущем разделе была описана процедура DrLine, которая печатает W символов '_'. Эту процедуру изменим таким образом, чтобы можно было при вызове указывать печатаемый символ и число символов в строке. Для этого добавим в заголовок формальные параметры W: integer и C: char. Заметим, что в этом случае не нужно вводить значение переменной W в программе. Тогда текст процедуры примера 26 будет выглядеть следующим образом:

procedure DrLine(W: integer; C: char); {печать линии из символов C длиной W} var

J: integer;

begin

for J := 1 to W do

write(C);

writeln;

end;

Теперь вызов этой процедуры может выглядеть следующим образом:

DrLine(64, '*');

Здесь 64 и '*' являются фактическими параметрами. В результате вызова процедуры DrLine формальному параметру W будет поставлено в соответствие значение фактического параметра 64, а формальному параметру C - '*' и напечатается строка из 64 символов '*'. Такой способ передачи данных в подпрограмму обеспечивает более гибкое ее использование. Таким образом, заголовки процедур и функций могут содержать список формальных параметров, в котором перечисляются имена формальных параметров и их типы, например:

procedure ABC(X: real; Y, Z: integer); function F1(A, B: real): real;

Формальные параметры в списке разделяются точкой с запятой, причем однотипные параметры перечисляются через запятую. Формальные параметры являются локальными и расширяют секцию описаний соответствующего блока. В вызове процедур и функций указываются фактические параметры. По существу идентификаторы формальных параметров являются условными обозначениями в подпрограмме тех фактических параметров, которые передаются при ее вызове из программы. Механизм использования параметров позволяет передавать данные из подпрограммы обратно в вызывающую программу. Тогда перед списком таких параметров указывается ключевое слово Var, например:

procedure S(A, B: real; var X: real); {суммирование двух переменных} begin

X := A + B; end;

Вызов: S(2, 3, Z); позволяет получить в программе значение Z равное 5, вычисленное в процедуре как формальный параметр X, который является параметром-переменной, в то время, как A и B - параметры-значения. При использовании параметров для передачи данных необходимо выполнять следующие правила:

- количество и типы фактических параметров должны строго соответствовать количеству и типам формальных параметров; - порядок следования формальных параметров в заголовке подпрограммы и фактических параметров в ее вызове должен совпадать. Заметим, что имена соответствующих формальных и фактических параметров могут различаться или совпадать.

Итак, любой из формальных параметров является либо параметром-значением, либо параметром-переменной. При вызове подпрограммы формальному параметру-переменной должен соответствовать фактический параметр в виде переменной нужного типа. Формальному параметру-значению при вызове может соответствовать выражение. Если параметр определен как параметр-значение, то перед вызовом подпрограммы это значение вычисляется, результат копируется во временную память и передается подпрограмме. В случае параметра-переменной при вызове подпрограммы осуществляется передача по ссылке, т.е. в подпрограмму передается адрес переменной, соответствующий фактическому параметру-переменной. Все операции в подпрограмме осуществляются с фактической переменной. Поэтому после выхода из подпрограммы эта фактическая переменная может поменять свое значение в результате выполнения в подпрограмме, например, операции присваивания. Любые изменения параметров-значений в подпрограмме не оказывают никакого влияния на вызывающую программу. Для того, чтобы изменение значения формального параметра приводило к аналогичному изменению соответствующего фактического параметра, необходимо использовать передачу параметров по ссылке, используя ключевое слово Var в списке формальных параметров. Таким образом, передачу результатов работы подпрограммы в вызывающую программу можно осуществить двумя способами:

- по ссылке с помощью параметров-переменных; - через глобальные переменные.

В соответствии с требованиями хорошего стиля программирования рекомендуется осуществлять передачу результатов через параметры-переменные, т.к. использование большого количества глобальных переменных делает программу трудно читаемой и сложной в отладке. Для передачи массива, строки в подпрограмму или в вызывающую программу, целесообразно использовать формальные параметры-переменные, т.к. в этом случае не происходит копирования памяти при многократном обращении к блоку. Следует иметь в виду, что типом любого параметра в списке формальных параметров может быть только стандартный или ранее объявленный тип, поэтому тип массива следует предварительно определить, например:

type

Mas = array [1..50] of integer;

procedure Sum(N: integer; var A: Mas; var Summa: integer);

Может сложиться впечатление, что передача формальных параметров через Var (т.е. по ссылке) является универсальным средством обмена данными. Однако этот способ исключает передачу фактических параметров при вызове подпрограмм в виде выражений. Кроме того, как и в случае с глобальными переменными, повышается вероятность случайного изменения значения фактической переменной. Обычно, глобальные переменные используются для обмена данными между программой и подпрограммой в тех случаях, когда оформление части алгоритма в виде отдельного блока продиктовано прежде всего удобством отладки программы, повышением ее читабельности. Если некоторая подпрограмма вызывается в программе несколько раз с различными исходными данными, то, очевидно, в этом случае лучше применять механизм формальных и фактических параметров. Работа подпрограммы завершается после выполнения последнего оператора ее тела. Турбо-Паскаль предоставляет программисту дополнительное средство прерывания подпрограммы в произвольной точке с помощью процедуры Exit без параметров. Эта процедура осуществляет немедленный выход из подпрограммы и передачу управления в точку вызова. В основной программе вызов процедуры Exit приводит к останову программы. Использование процедуры Exit продемонстрировано в примере 56 главы 4.

Модули

Одним из слабых мест механизма подпрограмм в стандартном Паскале является их встроенность в тело программы и невозможность по этой причине раздельной компиляции и отладки. В известной мере этот недостаток устраняется дополнительными возможностями в Турбо-Паскале по заданию подпрограммы через внешнее описание External, когда подпрограмма разработана вне среды Турбо-Паскаль на другом языке (обычно, на языке ассемблера) и ее необходимо подключить к программе на Паскале. Новые возможности по раздельной разработке больших программ и развитию принципов структурного программирования открылись с введением в язык Турбо-Паскаль понятия модуля. Модуль представляет собой совокупность различных компонентов раздела описаний (констант, типов, переменных, подпрограмм), предназначенную для использования другими модулями и программами. Сам по себе модуль не является выполняемой программой. Однако, он хранится и компилируется отдельно. Модуль имеет свой заголовок и два основных раздела: интерфейс и реализация (исполняемая часть). Кроме того, модуль может содержать раздел инициализации, предназначенный для установки начальных значений переменных модуля перед его использованием, который не является обязательным. Общая структура модуля может быть представлена следующим образом:

unit < имя модуля > interface    {интерфейс} < описание видимых объектов > implementation    {реализация} < описание скрытых объектов > [ begin < операторы инициализации объектов модуля > ] end.

Имя модуля должно совпадать с именем файла, в котором запоминается исходный текст модуля. В качестве простейшего примера приведем текст модуля описания типов данных, используемых в программах:

unit Typedat; interface    {описание глобальных типов} type

MasI = array [1..100] of integer; MasR = array [1..100] of real; MatrI = array [1..10, 1..10] of integer; MatrR = array [1..10, 1..10] of real; DayNom = 1..31; YearNom = 1900..2000;

implementation end.

В этом случае часть реализации отсутствует. В модуле могут использоваться процедуры и функции, причем в интерфейсной части модуля указываются только заголовки процедур и функций со списками формальных параметров, видимые для других программ, а их полное описание (заголовок и тело) будет содержаться в исполняемом разделе. Последовательность описаний подпрограмм в разделе Implementation должна быть такой же, как при их объявлении в разделе Interface. Кроме того, в разделе реализации можно описывать локальные для данного модуля подпрограммы. В качестве типового примера рассмотрим модуль, вычисляющий сумму, разность и произведение двух вещественных числе, например:

unit Arifm; {модуль запоминается в файле с именем Arifm.pas} interface procedure Summa (A, B: real; var Z: real); procedure Rasnost(A, B: real; var Z: real); procedure Proizv (A, B: real; var Z: real); implementation procedure Summa(A, B: real; var Z: real); begin

Z := A + B; writeln('Сумма = ', Z);

end; procedure Rasnost(A, B: real; var Z: real); begin

Z := A - B; writeln('Разность =', Z);

end; procedure Proizv(A, B: real; var Z: real); begin

Z := A * B; writeln('Произведение = ', Z);

end; end.

В данном модуле раздел инициализации отсутствует. Каким же образом можно использовать модули? Прежде всего отметим, что модуль компилируется точно так же, как и подпрограммы. Поскольку модуль не является выполняемой программой, то в результате его компиляции образуется файл с расширением .tpu. Имя файла совпадает с именем модуля. Определения, присутствующие в модуле, могут быть использованы либо в основной программе, либо в другом модуле. Для этого предназначено специальное предложение:

Uses < список используемых модулей >;

В программе это предложение располагается сразу после заголовка программы, а в модуле следует за ключевым словом Interface. В Турбо-Паскале имеется восемь стандартных модулей, в которых содержатся все системные процедуры и функции. Этими модулями являются:

- SYSTEM - содержит все процедуры и функции стандартного Паскаля, а также дополнительные подпрограммы общего назначения; модуль SYSTEM подключается к любой программе на Турбо-Паскале.

Все остальные модули становятся доступными после указания соответствующих имен в предложении Uses;

- DOS - содержит средства доступа к операционной системеMS DOS; - CRT - обеспечивает все возможности доступа к экрану дисплея в текстовом режиме; кроме того, включены средства чтения информации с клавиатуры и управления звуком; - PRINTER - упрощает вывод текстов на матричный принтер через переменную Lst, связанную с логическим устройством Prn; - OVERLAY - строит оверлейные программы, обеспечивая эффективную организацию больших программ с перекрытиями; - GRAPH - управляет графическим режимом работы дисплея; - TURBO3, GRAPH3 - обеспечивают совместимость системы Турбо-Паскаль с версией 3.0.