Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pascal Themes 5-10

.pdf
Скачиваний:
29
Добавлен:
15.04.2015
Размер:
452.27 Кб
Скачать

41

NB Если в теле цикла используются процедуры, изменяющие длину строки (Delete или Insert), то организация такого цикла оператором

for i:=1 to Length(s) do

недопустима, поскольку значение функции Length(s) в этом операторе вычисляется только один раз перед входом в цикл. Для реализации таких циклов следует использовать операторы while или repeat.

Контрольные вопросы

1.Что такое строковая константа, чем ограничивается ее длина?

2.Какие способы представления символов в программе вы знаете?

3.Каким образом представляются в программе отображаемые символы?

4.Какой способ можно использовать для представления всех символов таблицы ASCII?

5.Каким образом представляются в программе управляющие символы?

6.Как включаются в строку символы, представляемые с помощью префиксов # и ^? Как поместить в строку символ «апостроф»?

7.Что такое строка типа string? Что такое объявленный (максимальный) размер строки и ее текущий размер, как они задаются?

8.Какому массиву эквивалентна строка из n символов?

9.Для чего предназначен нулевой байт строки, и каким образом с ним можно работать?

10.Каким образом можно получить значение длины строки?

11.Каковы правила присваивания строковой переменной значения

спомощью оператора присваивания?

12.Каким образом выполняется ввод строк?

13.Как выполняется вывод строки при заданном формате вывода?

14.Как вывести строку в поле заданной ширины с выравниванием по левой границе поля?

15.Какие операции применимы для строк?

16.Каким образом выполняется сравнение строк?

17.Каким образом можно вставить подстроку в строку или удалить ее из строки?

18.Какие процедуры используются для преобразования числа в строку и наоборот?

19.Каким образом можно объединить несколько строк?

42

Тема 8. ЗАПИСИ

1. Описание записи

Запись – это структура данных, элементы которой могут иметь различные типы и называются полями. Синтаксическая форма описания записи имеет вид:

record {зарезервированное слово }

f1: t1; f2: t2;

fk: tk; end;

где f1, f2, fk – имена полей записи; t1, t2, tk – типы соответствующих полей. За словом record перечисляются все поля записи с указанием через двоеточие их типов, описания полей отделяются друг от друга точкой с запятой, количество полей записи может быть любым. Описание записи завершается зарезервированным словом end. Если несколько полей записи имеют один и тот же тип, то их имена можно перечислить через запятую и затем указать этот общий тип.

На типы полей записи ограничения не накладываются, поэтому поля сами могут быть записями, т.е. в записи допустимо существование внутренних записей (см. пример выполнения задания к лабораторной работе).

Приведенное описание можно использовать в разделе type программы для определения типов записей, в разделе var для определения конкретных переменных-записей, в разделе const для определения типизированных констант.

NB

Описания полей в записи имеют ту же самую структуру, что и описания переменных в разделе var программы.

Пример. Описания типов записей.

type

 

 

TComplex = record

{тип комплексного числа

}

Re: Real;

 

 

Im: Real;

 

 

end;

 

 

TDate = record

{тип даты

}

Year: Integer;

 

 

Month: 1..12;

 

 

Day: 1..31;

 

 

end;

 

 

43

TPerson = record

{тип сведений о сотруднике

}

Name: string[20];

Sex: (Male, Female); {используется перечисляемый тип } Age: Word;

Married: Boolean; end;

Альтернативное описание типа TComplex имеет вид:

type

TComplex = record

Re, Im: Real; end;

2.Типизированные константы- и переменные-записи

При задании значения типизированной константе ее поля записы-

ваются в круглых скобках через точку с запятой, значение каждого поля указывается через двоеточие за его именем.

Например, для определенных выше типов можно задать следующие типизированные константы:

const

Birthday: TDate = (Year: 1971; Month: 12; Day: 9);

Person: TPerson = (Name: 'Иванов'; Sex: Male; Age: 40; Married: True);

Переменные-записи описываются обычным образом, например:

var

X, Y, Z: TComplex; Date: TDate;

Тип записи можно указывать и непосредственно при определении переменных или типизированных констант. Например, во фрагменте:

var

X, Y, Z: record

Re, Im: Real; end;

описаны те же комплексные переменные, что и в предыдущем примере.

3.Оператор присваивания для записей

Записи совместимы по присваиванию, т.е. одной записи можно

присвоить значение другой записи оператором присваивания, если эти записи имеют идентичные типы – они описаны одним идентификатором типа или в одном списке. Записи X, Y, Z предыдущих примеров совместимы по присваиванию, т.е. допустимы следующие операторы:

X := Y; X := Z; Y := X; Y := Z; Z := X; Z := Y;

Действие оператора присваивания очевидно: значения полей правой записи присваиваются одноимённым полям левой записи.

4.Доступ к полям записи

Синтаксическая форма обращения к элементу записи имеет вид:

v.f

где v – имя записи; f – имя поля записи, к которому осуществляется доступ. Например:

Person.Age, X.Re, Date.Day.

44

Пример. Использование полей записей.

X.Re:= 1.5;

X.Im:=1.7;

Y.Re:=–X.Re;

Y.Im:= –X.Im;

Person.Married := False;

Указанный способ доступа к элементам записи называется досту-

пом по составному имени. Возможен альтернативный доступ по про-

стым именам полей. Он реализуется с помощью оператора присоединения with.

5.Оператор with

Для того чтобы не записывать каждый раз имя записи при обраще-

нии к её полям, можно использовать оператор над записями with. Его синтаксическая форма имеет вид:

with l do s

где l – список имён записей; s – оператор (может быть и составным). Внутри оператора s для обращения к полям записей, имена которых

упомянуты в списке l, достаточно указывать только имена этих полей. Например, фрагмент:

with X, Person do begin

Re := 1.5;

Im := 1.7;

Y.Re := –Re;

Y.Im : –Im;

Married := False; end;

эквивалентен фрагменту из предыдущего примера.

Для упрощения доступа к элементам внутренних записей внутри оператора with можно размещать другие операторы with.

6.Представление записи в памяти ЭВМ

Впамяти ЭВМ поля записи располагаются последовательно друг за другом, занимая участки памяти, размеры которых определяются типами полей.

7.Использование текстового файла: ввод и вывод записей

Ввод записи из тестового файла – это процесс присваивания полям

записи значений констант, размещаемых в файле. Ввод записей осуществляется поэлементно. При этом поля записи размещаются в списке ввода точно также как простые переменные и элементы массива. Идентификация полей осуществляется, как описано ранее: либо используются составные имена (см. п. 4), либо обращение к процедурам Read и Readln помещается в оператор with (см. п. 5).

Вывод записей в текстовый файл – это размещение значений полей записи в виде констант в этом файле. Поля записи размещаются в списке вывода процедур Write и Writeln точно также как простые переменные и элементы массива. Используются либо составные имена, либо простые имена полей в операторе with.

45

8.Моделирование базы данных типизированным файлом записей

Реляционная база данных представляет собой файл, содержащий

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

Для создания «базы данных» в программе на языке Паскаль необходимо создать файл записей надлежащего типа (с требуемым составом и типом полей). Данные для помещения в базу могут вводиться с клавиатуры, но гораздо удобнее извлекать их из текстового файла – это упрощает процесс коррекции исходных данных при повторных просчётах программы. Данные из базы и результаты их обработки можно выводить на экран дисплея, но лучше помещать их в текстовый файл – это упрощает процесс интерпретации результатов после завершения работы программы.

Для перемещения по базе данных используется процедура позиционирования Seek. Напомним, что применение процедур Read и Write к текущему элементу типизированного файла приводит к автоматическому перемещению указателя текущей позиции файла на следующий элемент, поэтому если требуется изменить только что прочитанную запись, то надо вернуться к ней с помощью процедуры Seek.

9.Поиск в базе данных

Поиск в базе данных необходимых записей осуществляется по сле-

дующей схеме. Исходными данными для поиска являются некоторые требования к значениям одного или нескольких полей. Результатом поиска являются все записи, удовлетворяющие предъявленным требованиям. Информация для обработки и/или для формирования отчёта может извлекаться из всех или части полей найденных записей. Например, в базе данных о сотрудниках некоторого учреждения можно отыскивать сведения (имена, оклады, семейное положение и т.д.) о сотрудниках заданного года рождения. Можно подсчитывать средний возраст работающих женщин, средний оклад сотрудников конкретного отдела и т.д.

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

46

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

Контрольные вопросы

1.Что такое запись? Каков синтаксис объявления записи?

2.Для чего именуются поля записи, какие типы они могут иметь?

3.Опишите тип записи для указания текущей даты (день, месяц,

год).

4.Опишите тип записи для указания имени и дня рождения челове-

ка.

5.В каком случае записи можно присвоить значение другой записи?

6.Как осуществляется доступ к элементам записи?

7.Для чего используется оператор присоединения, каков его синтаксис?

8.Какие записи имеют идентичный тип?

9.Как записи представляются в памяти ЭВМ

10.Какова особенность записи с вариантами?

11.Как вводятся из текстового файла переменные типа запись?

12.Как описать структуру, используемую для создания базы дан-

ных?

13.Как выбрать нужную запись из файла записей?

Тема 9. ПРОЦЕДУРЫ И ФУНКЦИИ

1. Общие сведения

Подпрограмма – это именованная часть программы, которая вызывается, получает параметры, выполняет определённые действия и возвращает управление в точку вызова.

Вызов подпрограммы (или обращение к подпрограмме, или активизация подпрограммы) – это скачок по программному коду: если в тексте программы встречается обращение к подпрограмме, то выполнение текущей программы приостанавливается, осуществляется переход на код подпрограммы, выполняются её операторы, а затем осуществляется возврат в текущую программу в точку вызова.

NB

Параметры подпрограммы – это величины, имеющие смысл входных и выходных данных, т.е. это исходные данные, получае-

47

мые подпрограммой, и результаты вычислений, возвращаемые в вызвавшую программу.

Подпрограммы описываются в разделе описаний. Подпрограмма, используемая другой подпрограммой, должна описываться ранее (до того, как она будет использована в другой подпрограмме).

2. Структура подпрограммы

Структура любой подпрограммы аналогична структуре программы. Она имеет: 1) заголовок; 2) блок, состоящий из раздела описаний (с подразделами label, const, type, var, описания подпрограмм) и раздела операторов; 3) финальное слово «end». Обратим внимание на тот факт, что внутри подпрограммы могут размещаться другие подпрограммы. Уровень вложения синтаксически не ограничен. Таким образом, можно говорить о вложенных и охватывающих (объемлющих) подпрограммах.

Заголовок подпрограммы отличается от заголовка главной программы тем, что в нём: 1) используется иное зарезервированное слово (procedure или function вместо program); 2) размещается список формальных параметров; 3) в заголовке function дополнительно указывается тип возвращаемого значения. Переместите взгляд на 4 абзаца вверх и прочитайте ёще раз о том, какой смысл имеют параметры подпрограммы. Параметры, указываемые в заголовке для подпрограммы, называются формальными потому, что они представляют собой не реальные величины, а некоторые образы величин, используемые для того, чтобы описать действия, выполняемые над исходными данными, и месторасположение результатов вычислений.

Блок подпрограммы структурно ничем не отличается от блока главной программы. Раздел операторов реализует некоторый алгоритм обработки информации, т.е. осуществляет отображение исходных данных в искомые результаты. Исходные данные и результаты вычислений подпрограммы размещаются в списке её формальных параметров, поэтому подпрограмме не требуется вводить данные и выводить результаты. Вместе с тем, подпрограммы часто используются для обработки файлов и вывода информации на экран или в файл.

За финальным словом «end» подпрограммы размещается точка с запятой, а не точка.

3.Область действия и затенение имён в подпрограммах

Подпрограмма – это программный блок, имеющий собственную

область видимости (действия) идентификаторов. В подпрограмме действуют, т.е. могут использоваться: 1) все имена, объявленные в программе до описания данной подпрограммы; 2) имена, объявленные в

48

самой подпрограмме, включая формальные параметры.

Имена, объявленные в подпрограмме, называются локальными, а объявленные в программе и объемлющих подпрограммах – глобальными.

NB Локальные идентификаторы перекрывают (затеняют) глобальные. Одноимённые глобальные и локальные элементы программы могут иметь разный смысл. Например, подпрограмма может иметь локальную переменную X, имя которой совпадает с глобальным именем X метки, или константы, или типа, или подпрограммы. При этом в подпрограмме будет действовать только имя локальной переменной X. Глобальное же имя хотя и затеняется, но не закрывается вовсе: к нему можно обращаться по составному имени: progName.X

где progName – имя программы; X – затенённое глобальное имя.

4.Виды подпрограмм в Паскале

Вязыке Паскаль имеются две разновидности подпрограмм – процедуры и функции. Формально любой алгоритм может быть оформлен и в виде процедуры, и в виде функции. Синтаксическое различие между этих видами подпрограмм состоит только в следующем: 1) имя функции является носителем одного из результатов работы подпрограммы (в процедуре все результаты размещаются в списке формальных параметров); этот результат может иметь любой скалярный тип или тип string, или тип Pointer; 2) вызов процедуры осуществляется отдельным оператором (вспомните вызов процедуры ввода Read), а обращение к функции – путем размещения её имени со списком фактических параметров в выражении.

Гораздо более существенным является стилистическое различие между функциями и процедурами. Нормой структурного проектирования программы является следующее:

NB

алгоритм должен оформляться в виде функции, если он имеет единственный и при том скалярный (или полускалярный string или Pointer) результат, в противном случае, – если алгоритм имеет несколько результатов или один, но структурированный (например, массив), либо вовсе не имеет никаких результатов – он должен оформляться в виде процедуры.

Стилистической нормой является требование: описание подпрограммы должно включать в себя спецификацию подпрограммы в виде комментария, содержащего: назначение подпрограммы, описание

49

формальных параметров и значения функции (если подпрограмма – функция), требования, накладываемые на входные параметры: диапазон изменения, допустимые значения.

Синтаксические формы заголовков процедур и функций соответственно имеют вид:

procedure <имя процедуры> (<список формальных параметров>);

function <имя функции> (<список формальных параметров>): <тип значения>;

где <тип значения> – тип результата вычислений, возвращаемого функцией.

5.Формальные параметры

Формальные параметры подпрограммы указывают, с какими вели-

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

N

Формальные параметры синтаксически – это идентификаторы.

 

Описание группы однотипных формальных параметров в списке имеет вид:

p x1, x2, …,xk: t

где p – префикс, определяющий вид параметров; x1, x2, …,xk – имена формальных параметров; t – идентификатор типа формальных параметров группы. Отдельные группы описаний отделяются друг от друга точкой с запятой.

Префикс p может представлять собой: 1) зарезервированное слово const; 2) зарезервированное слово var; 3) ничего, т.е. может отсутствовать вовсе. В соответствии с эти префиксом различают: 1) параметрыконстанты; 2) параметры-переменные; 3) параметры-значения.

NB

Тип формального параметра может быть любым,

 

но со следующим ограничением: файловый тип может иметь только параметр-переменная. Тип формального параметра может не указываться вовсе (в этом случае в подпрограмме к формальному параметру применяется операция приведения типа).

В заголовках подпрограмм можно использовать только идентификаторы типов, развёрнутые описания структурированных типов не допустимы. Например, нельзя писать

function Max(A: array[1..100] of Real): Real;

Чтобы правильно записать этот заголовок, следует в основной программе определить тип массива, а затем использовать его в заголовке:

type TArr = array[1..100] of Real; function Max(A: TArr): Real;

50

6. Замена формальных параметров фактическими

NB

Во время обращения к подпрограмме происходит замена формальных параметров фактическими параметрами – величинами, определёнными в вызывающей программе.

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

Фактические параметры должны соответствовать формальным параметрам по количеству, порядку следования и по типу!

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

7.Пример описания и использования процедуры

Подпрограмма-процедура предназначена для выполнения закон-

ченной последовательности действий, приводящей к получению нескольких результатов или одного, но структурированного, либо вовсе не формирующей никаких результатов. Любая процедура начинается с заголовка. В отличие от основной программы заголовок в процедуре обязателен.

Пример. Процедура ввода N целых чисел. Пусть в основной программе определен тип

type

TArr = array[1..100] of Integer;

Процедура может иметь вид:

procedure Inplnt(var Mas:TАrr;N:Integer); {ввод N целых значений в массив Mas} var

i: Integer; {локальная переменная – переменная цикла } begin

WriteLn('Введите ', N, ' целых чисел'); for i := 1 to N do Read(Mas[i])

end;

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

InpInt(Matrix, k);

означает вызов процедуры InpInt для ввода k целых чисел в массив Matrix. Очевидно, что в этом случае параметр k должен иметь целый тип, а Matrix – должен быть массивом типа TArr.

51

8.Пример описания и использования функции

Подпрограмма-функция предназначена для вычисления какого-

либо скалярного или полускалярного (типа string или Pointer) значения. В отличие от процедуры, в заголовке функции указывается тип возвращаемого значения. В разделе операторов функции хотя бы раз имени функции должно быть присвоено значение.

Пример. Функция вычисления факториала числа N.

function Factorial(N: Byte): Longint; var

Fact: Longint; {вспомогательная переменная для вычисления факториала } i: Byte;

begin

Fact := 1; {0! = 1!= 1 по определению.} for i := 2 to N do Fact := Fact * i; Factorial := Fact;

end;

Имя функции нельзя использовать как простую переменную. В частности, если имя функции внутри ее описания используется не в левой части оператора присваивания, то это означает, что функция вызывает себя рекурсивно. Поэтому в примеры для вычисления значения факториала используется вспомогательная локальная переменная Fact, значение которой затем присваивается имени функции Factorial.

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

Part:=Sqr(x)/Factorial(k);

Вэтом операторе: Sqr(x) – вызов стандартной функции возведения

вквадрат с фактическим параметром x; Faсtorial(k) – вызов функции, вычисляющей факториал с фактическим параметром k.

9.Способы передачи параметров в подпрограммы

При обращении к подпрограмме формальные параметры заменяют-

ся соответствующими фактическими параметрами – величинами вызывающей программы или другой подпрограммы, т.е. происходит передача фактических параметров в подпрограмму. В Турбо Паскале используются три способа передачи параметров: 1) по значению; 2) по адресу; 3) по адресу с синтаксической защитой от изменения (только в Турбо Паскале версии 7.0)

Предварительно заметим, что внутренние величины подпрограммы, в том числе и формальные параметры, постоянно в памяти ЭВМ не хранятся. Место под них отводится в специальном сегменте программы, называемом стеком, только при вызовах подпрограммы, и

52

только на время выполнения её операторов. После возврата в точку вызова стек очищается, и на месте внутренних величин отработавшей подпрограммы можно размещать величины другой.

При передаче по значению происходит следующее: значения фактических параметров копируются на стек – в участки, выделенные под формальные параметры. Именно с этими копиями и манипулирует подпрограмма, возможно изменяя их. Однако изменение копий не приводит к изменению фактических параметров, размещённых по иным адресам.

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

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

А теперь запоминаем:

NB

Параметры-значения передаются в подпрограмму по значе-

 

нию, параметры-переменные – по адресу, параметры-константы по адресу с синтаксической защитой от изменения.

Параметры-значения следует использовать для представления скалярных исходных данных, параметры-константы – для представления структурированных исходных данных, параметрыпеременные – для представления результатов вычислений.

10.Параметры-значения

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

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

Если параметров одного типа несколько, их можно объединить в одну группу, перечислив их имена через запятую, а затем уже указать

53

общий тип. Отдельные группы параметров отделяются друг от друга точкой с запятой:

procedure Inp(Max, Min: Real; N: Word); function Mult(X, Y: Integer): Real;

В качестве фактического параметра на месте параметра-значения при вызове подпрограммы может выступать любое выражение совместимого для присваивания типа, не содержащее файловую компоненту, например:

Inp(Abs(Z), –Abs(T), 2*K); M:=Mult(X+Y, X–Y); MA:=Max(B, 5);

Пример. Функция вычисления максимального элемента в массиве. Пусть в основной программе определен тип-массив, массив этого

типа и переменная целого типа

type

TArr = array[1..100] of Integer; var

Massiv: TArr; Maxim: Integer;

Функция в этом, случае может иметь вид:

function Max(Mas: TArr; N: Byte): Integer; var

Ma: Integer; i: Byte;

begin

Ma := Mas[1];

for i := 2 to N do if Ma < Mas[ i ] then Ma := Mas[ i ] ; Max := Ma

end;

Теперь, например, для определения максимального числа из первых пяти чисел массива Massiv и записи его в переменную Maxim можно записать оператор:

Maxim := Max(Massiv,5);

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

11.Параметры-переменные

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

54

var . Действие слова var распространяется до ближайшей точки с запятой, т. е. в пределах одной группы. Например:

procedure MaxMin(A: TArr; var Max, Min: Real; N: Word);

Здесь Max, Min – параметры-переменные, А и N – параметры значения. Тип параметров-переменных может быть любым, включая и фай-

ловый.

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

type

TArr = array[1..100] of Integer;

то и фактический параметр должен быть переменной или типизированной константой типа TArr.

Пример. Функция вычисления максимального элемента в массиве. Модифицируем подпрограмму примера п. 4, используя в качестве

первого параметра параметр-переменную:

function Max(var Mas: TArr; N: Byte): Integer; var

Ma: Integer; i: Byte;

begin

Ma := Mas[ 1 ];

for i := 2 to N do if Ma < Mas[ i ] then Ma := Mas[ i ]; Max := Ma

end;

Этот вариант лучше предыдущего тем, что в данном случае в стеке не создается копия исходного массива, что улучшает быстродействие и экономит память. Однако при такой передаче параметра возможно его нежелательное изменение (такой вариант передачи параметра допустим только в таких небольших подпрограммах, как в данном примере, когда программист может проконтролировать отсутствие несанкционированного изменения параметра).

12.Параметры-константы

Часто в качестве параметра в подпрограмму следует передать ту или иную переменную, но изменять ее подпрограмма не должна. В этом случае нежелательно передавать этот параметр как параметрпеременную. Можно его передать как параметр-значение, однако, если эта переменная имеет большой размер (массив, запись и т. д.), то копия такого параметра займет большую часть стека и даже может его переполнить. Это же приводит и к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметрконстанту. Такой параметр, если он структурированного типа, передается своим адресом, но предусматривается защита от его изменения.

55

Перед именем параметра-константы записывается зарезервированное слово const. Действие слова const распространяется до ближайшей точки с запятой, т. е. в пределах одной группы.

Пример.

function NewString(const S: string): string;

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

Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра на место формального параметрапеременной.

Пример. Функция вычисления максимального элемента в массиве. В примере п. 4 используем в качестве первого параметра пара-

метр-константу:

function Max(const Mas: TArr; N: Byte): Integer; var Ma: Integer;

i: Byte; begin

Ma := Mas[ i ];

for i := 2 to N do if Ma < Mas[ i ] then Ma := Mas[ i ]; Max := Ma

end;

Пример. Функция, возвращающая строку пробелов заданной длины.

function Blanks(Len: Byte): string;

}

{ Len – заданная длина формируемой строки пробелов

var

{вспомогательная строка пробелов

}

Bl: string;

i: Byte;

{переменная цикла

}

begin

{ создаем пустую строку

}

Bl := '';

for i := 1 to Len do Bl := Bl + ' '; { Len раз сцепляем строку с пробелом

}

Blanks:=Bl;

{ возвращаем строку пробелов

}

end; { function Blanks }

 

 

Все сказанное выше можно объединить в следующую таблицу:

Формальный

Внешний

Способ

Фактический

Использование

параметр

признак

передачи

параметр

 

Параметр-

 

по

выражение совместимо-

представление ска-

значение

 

значению

го для присваивания

лярных исходных

 

 

 

типа, не содержащее

данных

 

 

 

файловую компоненту

 

Параметр-

var

по адресу

переменная

представление ре-

переменная

 

 

идентичного типа.

зультатов вычислений

Параметр-

const

по адресу

выражение совместимо-

представление струк-

константа

 

с защитой

го для присваивания

турированных исход-

 

 

от измене-

типа, не содержащее

ных данных

 

 

ния

файловую компоненту

 

56

13.Процедуры HALT и EXIT

Процедура Halt прекращает выполнение программы и осуществляет выход в операционную систему. Если программы запускалась из среды Турбо Паскаль, то выполнение процедуры Halt осуществит возврат в среду Турбо Паскаль.

Для досрочного выхода из подпрограммы используется процедура Exit. Ее вызов означает немедленный выход из подпрограммы и возврат в вызывающую программу. В основной программе Exit действует подобно процедуре Halt.

Контрольные вопросы

1.С какой целью оформляются и где описываются процедуры и функции?

2.В каком случае подпрограмма оформляется как процедура и в каком случае как функция?

3.Что такое спецификация подпрограммы?

4.Каков синтаксис описания процедуры? Какой вид имеет заголовок процедуры?

5.Каков синтаксис описания функции?

6.Каковы особенности реализации функций?

7.Как выполняются обращения к процедуре и к функции?

8.Какие переменные подпрограмм называются локальными и какова область их действия? Какие переменные называются глобальными?

9.Какие параметры используются для передачи данных между подпрограммами, какими способами осуществляется эта передача?

10.Что такое формальные параметры подпрограммы и как они описываются? Что такое фактические параметры подпрограммы?

11.Какие существуют виды формальных параметров?

12.Как передаются в подпрограмму параметры-значения, что может использоваться в качестве фактического параметра для параметразначения?

13.Как передаются в подпрограмму параметры-переменные, что может использоваться в качестве фактического параметра для пара- метра-переменной?

14.Как передаются в подпрограмму параметры-константы, что может использоваться в качестве фактического параметра для параметраконстанты?

15.Каким образом можно осуществить досрочный выход из подпрограммы?

57

Тема 10. МОДУЛИ

1.Назначения модулей

Наличие модулей в Турбо Паскале позволяет:

1)создавать библиотеки программных элементов – подпрограмм, констант, типов и переменных;

2)практически неограниченно увеличивать кодовую часть программы;

3)использовать подпрограммы, константы, типы и переменные, содержащиеся в стандартных модулях (поставляемых в составе системы программирования) и в модулях других программистов;

4)программировать и отлаживать программу по частям.

Модуль состоит из следующих частей:

заголовок модуля;

секция интерфейса;

секция реализации;

секция инициализации.

Все разделы модуля, за исключением секции инициализации, являются обязательными. Обязательна также указанная последовательность разделов.

2. Заголовок модуля

Заголовок модуля состоит из зарезервированного слова unit и идентификатора. Идентификатор модуля должен быть уникальным. Пример заголовка:

unit MyModule;

Модуль должен быть помещен в файл, имя которого совпадает с именем модуля, а его расширение должно быть .PAS. После компиляции файл с модулем получает расширение .TPU.

3.Секция интерфейса

Секции интерфейса выполняет представительскую функцию, – в

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

Секция начинается зарезервированным словом interface. Далее могут размещаться: 1) предложение uses, в котором перечисляются имена модулей, используемых данным модулем; 2) раздел описания констант; 3) раздел описания типов; 4) раздел описания переменных; 5) раздел описания процедур и функций. Порядок следования разделов

58

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

Вразделе объявления процедур и функций указываются лишь заголовки подпрограмм. Сами подпрограммы (их блоки) размещаются в секции реализации.

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

4.Секция реализации модуля

Назначение секции реализации – реализация подпрограмм, заяв-

ленных в секции интерфейса.

Секция начинается зарезервированным словом implementation. Далее могут размещаться: 1) предложение uses, в котором перечисляются имена модулей, используемых данным модулем, но не упомянутые в предложении секции uses интерфейса; 2) раздел описания меток; 3) раздел описания констант; 4) раздел описания типов; 5) раздел описания переменных; 6) раздел описания процедур и функций.

Легко заметить, что структурно секция реализации отличается от секции интерфейса только тем, что разрешено наличие раздела описаний меток. Как и в секции интерфейса: 1) порядок следования разделов описаний может быть произвольным; 2) возможны повторения разделов; 3) действует правило: используемое сейчас должно быть описано выше; 4) любой из подразделов может отсутствовать; 5) допустима пустая секция реализации.

Модули с пустой секцией реализации не так уж и бесполезны, более того, они часто используются. Естественно, что при этом в секции интерфейса не должно содержаться описаний подпрограмм, допустимы только константы, типы и переменные.

Раздел описания подпрограмм обязательно должен содержать описания подпрограмм, заявленных (описанных) в секции интерфейса. В описаниях этих подпрограмм допустимо использовать сокращенные заголовки без списков формальных параметров. Описания каждой подпрограмм обязательно содержит её блок (тело), состоящее из раздела описаний и раздела операторов.

В отличие от интерфейсов модулей в секциях реализации модулей допустимо циклическое обращение друг к другу, т.к. взаимодействие модулей осуществляется через интерфейсы, и здесь не возникает проблемы с установлением необходимых связей.

59

Важно понимать, что все метки, константы, типы, переменные и подпрограммы, описанные в секции реализации, кроме подпрограмм из секции интерфейса, являются локальными элементами данного модуля, они не видны из других программ и модулей и создаются только с одной целью – реализовать подпрограммы секции интерфейса!

5.Секция инициализации

Секция инициализации – факультативная часть модуля. В ней раз-

мещаются операторы, которые внедряются в раздел операторов той программы, которая использует данный модуль. Если программа использует несколько модулей, то содержимое их секций инициализации внедряется в программу в порядке перечисления имён модулей в предложении uses.

Эта секция начинается словом begin, после которого идут операторы, а затем размещается слово end. (с точкой), например:

begin

Assign(F1, 'FILE1.DAT'); end.

Если секция инициализация модуля не нужна, то после секции реализации сразу же размещается слово end. (с точкой).

6.Использование модуля в основной программе

Чтобы использовать подпрограммы, константы, типы, переменные,

описанные в интерфейсной секции модуля, в основной программе следует записать слово uses, после которого указать имя (имена) модуля (модулей). После этого в основной программе можно использовать идентификаторы, указанные в интерфейсных секциях перечисленных модулей.

7.Использование идентификаторов элементов модуля

Как правило, идентификаторы объектов модуля (имена констант,

типов, переменных, процедур и функций) используются в основной программе (или другом модуле) обычным образом. Однако может оказаться, что используемый идентификатор элемента модуля совпадает с идентификатором использующей его программы. Чтобы различить их, при обращении к элементу модуля указывается имя модуля, а затем через точку – идентификатор объекта (аналогично использованию полей записи).

Пример.

{ Главная программа

}

program Example2;

 

 

uses Unit1;

 

 

var

 

 

X: Real;

{ переменная X программы

}

begin

 

 

Read(X);

{ чтение значения переменной X программы

}

60

Read(Unit1.X);

{ чтение значения переменной X модуля

}

{ использование одноименных переменных программы и модуля

}

Writeln(X, Unit1.X);

 

 

end.

 

 

{ Модуль

 

}

unit Unit1;

 

 

interface

 

 

var

 

 

X: Real;

{переменная X модуля

}

implementation

 

 

end.

 

 

8. Компиляция модулей

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

Откомпилированные модули программы обязательно должны размещаться на диске. Для этого в команде меню Compile|Destination необходимо установить параметр Disk.

Для проверки синтаксической правильности отдельного модуля можно выполнить его компиляцию с помощью команды меню Compile|Compile (комбинация клавиш Alt+F9).

Программу, использующую модули, можно компилировать либо с помощью команды меню Compile|Make (клавиша F9) либо Compile|Build.

При использовании команды Compile|Make наряду с компиляцией главной программы компилируются и те используемые программой модули, у которых к моменту компиляции был изменен текст.

При использовании команды Compile|Build все используемые программой модули перекомпилируются безусловно.

9. Стандартные модули

Как указывалось выше, модули можно использовать для создания библиотек стандартных подпрограмм и данных. В Турбо Паскале в настоящее время имеется большое количество стандартных подпрограмм и данных, объединенных в несколько стандартных модулей. Они позволяют упростить процедуру написания программ, более полно использовать возможности компьютеров типа IBM PC, возможности операционной системы MS DOS.

Каждый стандартный модуль содержит константы, переменные и подпрограммы, предназначенные для решения определенного класса задач.

В библиотеке Турбо Паскаля имеются следующие стандартные модули.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]