1. Описание процедур и функций

advertisement
Процедуры и функции. Способы передачи параметров.
Использование модулей
Проектируя алгоритм решения конкретной задачи, полезно выделить
подзадачи, каждую из которых можно решать независимо от остальных. Для
выделенных
подзадач
составляются
свои
алгоритмы,
называемые
вспомогательными. Каждая из подзадач может детализироваться далее с
использованием вспомогательных алгоритмов. Такой механизм называется
нисходящим проектированием или методом пошаговой детализации.
Обычно проектировщик старается довести разбиение до таких подзадач,
решение
которых
применяется
либо
готовый
реализуется
стандартным
вспомогательный
образом
алгоритм),
(например,
либо
легко
программируется. Например, отделяют друг от друга этап (подзадачу)
начального ввода данных, следующий этап обработки данных и, наконец,
вывод результатов.
При переходе к программированию в конкретной системе, подзадачи
обычно оформляются как подпрограммы – именованные последовательности
инструкций, реализующие некоторые действия. Подпрограмма может быть
многократно
вызвана
из
разных
частей
программы.
Использование
подпрограмм позволяет сделать основную программу более наглядной,
понятной, а в случае, когда одна и та же последовательность команд
встречается в программе несколько раз, даже более короткой и эффективной.
Применение
метода
пошаговой
детализации
делает
программу
более
структурированной и легко читаемой, такая программа менее подвержена
ошибкам, которые зачастую являются неотъемлемой частью процесса
модернизации программы.
1.
Описание процедур и функций
В языке Паскаль существует два вида подпрограмм: процедуры и
функции, определяемые программистом.
Описание функции или процедуры располагается в разделе описания
процедур и функций программы. Процедуры и функции, используемые в
1
программе, должны быть соответствующим образом описаны до первого их
упоминания.
Синтаксическая диаграмма описания процедуры изображена на рис. 1.
Рис. 1. Синтаксическая диаграмма описания процедуры.
Синтаксическая диаграмма описания функции изображена на рис. 2.
Рис. 2. Синтаксическая диаграмма описания функции.
За заголовком следует тело подпрограммы, которое состоит из раздела
описаний и раздела исполняемых операторов.
Раздел описаний внутри процедуры или функции может иметь такие же
подразделы, как и раздел описаний основной программы (описание процедур и
функций в том числе). Раздел исполняемых операторов представляет собой
составной оператор.
В отличие от процедуры функция, завершив свою работу, должна вернуть
основной программе (или другой вызвавшей ее подпрограмме) ровно одно
значение, причем его тип нужно явным образом указать уже при объявлении
функции.
Для
возвращения
результата
функции
применяется
специальная
переменная, имеющая имя, совпадающее с именем самой функции. Оператор
присваивания значения этой переменной обязательно должен встречаться в
2
теле функции хотя бы один раз. Но использовать ее в левой части оператора
присваивания можно только внутри самой функции.
Пример 1.1. Написать функцию вычисления тангенса.
Function tan(a:real):real; {тип возвращаемого результата – Real}
Begin
tan:=sin(a)/cos(a)
{tan
–
специальная
переменная,
которой
присваивается результат выполнения функции}
End;
Вызов процедуры и функции
Вызов процедуры или функции производится по их имени.
Вызов процедуры осуществляется отдельной командой, то есть вызов
внутри операторов присваивания и вывода недопустим. Обращение к
процедуре производится по схеме, указанной на рис. 3.
Рис. 3. Синтаксическая диаграмма вызова процедуры.
После выполнения процедуры работа программы продолжится с
оператора, который следует за оператором вызова процедуры.
Вызов функций, созданных пользователем, производится аналогично
вызову стандартных функций, то есть внутри выражений, либо в правой части
оператора присваивания, либо в операторе вывода. Синтаксическая диаграмма
вызова функции показана на рис. 4.
Рис. 4. Синтаксическая диаграмма вызова функции.
Пример 1.2. Используя функцию вычисления тангенса в Пример 1.1,
написать программу вычисления суммы тангенсов трех чисел.
Program tangens;
3
Var x,y,z:real; {глобальные переменные}
Function tan(a:real):real;
Begin
tan:=sin(a)/cos(a)
End;
Begin
ReadLn(x,y,z);
WriteLn((tan(x)+tan(y)+tan(z)):8:2)
{функция
tan
вызывается
3
раза в операторе вывода }
End.
Область действия описания процедур и функций
При использовании процедур и функций в Паскале допускается их
описание не только внутри основной программы, но и внутри других процедур
и функций. Описание объекта, как правило, должно предшествовать его
первому появлению в других программных фрагментах1.
Кроме того,
внутренняя подпрограмма не может вызывать подпрограмму, по отношению к
которой она является вложенной.
Рассмотрим схему условного описания подпрограмм в некоторой
программе на Рис. 5.
1
Использование forward может решить проблему (см. справочник по языку)
4
Основная программа
Процедура А
Процедура А1
Процедура А2
Процедура В
Процедура В1
Процедура В2
Процедура В21
Процедура В22
Рис. 5. Условное описание структуры программы.
Из основной программы можно обратиться к A и B. Обращение к
внутренним процедурам невозможно, так как они являются локальными по
отношению к тем процедурам, внутри которых описаны, и не видны из
основной программы.
Из A можно обратиться к A1 и A2. Обращение к процедуре B в данном
случае недопустимо, так как она описана позже процедуры A.
Из процедуры B можно обратиться к её внутренним процедурам B1 и B2,
а также к процедуре A, так как её описание предшествует вызову.
Из процедуры B2 можно вызвать B21 и B22, а также процедуры A и B1.
Из процедуры B22 можно вызвать A, B1 и B21.
Рекурсивные вызовы мы здесь пока не учитываем, о них речь пойдет
позже.
Задание. Каким процедурам можно обратиться из B1? А к каким из B21?
Локальные и глобальные переменные
Глобальные переменные объявляются в разделе описания переменных
основной программы, до описания всех процедур и функций. Их область
5
видимости – вся программа. Все объекты, описанные внутри процедур и
функций, являются локальными, т.е. "видимыми" лишь в этих подпрограммах.
Основной программе локальные переменные недоступны.
Пример 1.3. Локальные и глобальные переменные.
Program PRIMER;
Procedure f1;
Begin
A:=3; Write(a,‘ ‘);
End;
Procedure f2;
Var a:integer;
Begin
A:=4; Write(a,‘ ‘);
End;
Begin
A:=1; Write(a,‘ ‘);
F1; Write(a,‘ ‘);
F2; writeLn(a);
End.
В результате выполнения программы будет выведено: 1 3 3 4 3. Объясните
почему.
Формальные и фактические параметры
Параметры, заданные при описании процедуры или функции, называются
формальными. Они служат для обеспечения передачи параметров в
подпрограмму и возврата результатов из неё. Формальные параметры могут
использоваться
внутри
процедур и функций
аналогично переменным,
описанным в них.
Из синтаксической диаграммы описания формальных параметров на
рис. 6 видно, что формальные параметры в заголовке процедур и функций
отделяются друг от друга точкой с запятой. Ключевое слово var может
отсутствовать (об этом далее). Если параметры однотипны, то их имена можно
перечислять через запятую, указывая общее для них имя типа.
6
Рис. 6. Синтаксическая диаграмма описания формальных параметров.
Формальные параметры вместе с обрамляющими их скобками могут
отсутствовать.
Во всех реализациях языка Паскаль за исключением Паскаль АВС типы
формальных параметров должны обязательно обозначаться идентификатором,
т.е. при описании параметров можно использовать только стандартные имена
типов, либо имена типов, определенные с помощью ключевого слова type.
Например, недопустимы следующие записи:
1) Procedure S(a:1..100).
Возможен следующий вариант:
Type c = 1..100;
Procedure S(a:c);
2) Procedure S(m:Array[1..12] Of Integer);
Правильным является вариант:
Type Tarray=[1..12] Of Integer;
Procedure S(a:Tarray);
Значения, передаваемые в процедуру или функцию, называются
фактическими
параметрами.
При
вызове
фактические
параметры
подставляются вместо формальных, стоящих на тех же местах в заголовке.
Желательно, чтобы имена фактических параметров не совпадали с
именами формальных во избежание путаницы, хотя совпадение не запрещается.
Задание. Назовите в Пример 1.12 имена формальных и фактических
параметров.
2.
Способы передачи параметров
И в процедурах, и в функциях формальные параметры делятся на два
типа:
7
1) параметры, передаваемые по значению (параметры-значения),
2) параметры, передаваемые по ссылке (параметры-переменные).
Перед описанием параметра, передаваемого по ссылке, в списке
формальных параметров ставится ключевое слово var. В описании формальных
параметров, передаваемых по значению, var не ставится. Действие слова var
распространяется до ближайшей точки с запятой. Например, в описании
Procedure Proc(a,b,c:integer; var x,y:real; z:char);
a, b, c, z – параметры-значения, x, y – параметры, передаваемые по ссылке.
Рассмотрим отличие этих двух способов.
Параметры-значения
Тип параметра-значения может быть любым за исключением файлового.
При вызове подпрограммы для параметра, передаваемого по значению,
выделяется новая область памяти. Для переменной создаётся ее копия, которая
получает начальное значение, равное значению фактического параметра. В
качестве фактических параметров могут использоваться не только переменные,
но и константы и выражения. Для константы или выражения результат
вычисления выражения также отправляется во вновь созданную область
памяти. После этого никакой связи между фактическим и формальным
параметром не существует. Внутри подпрограммы возможны любые действия с
данным параметром, но это никак не отражается на значениях переменных,
переданных в качестве параметров-значений.
Пример 2.1. Определить, что будет выведено на экран в результате
работы программы.
Program a2;
Var b,c:integer;
Procedure Q(X,Y:integer); {передача параметров по значению}
Begin
X:=5;
Y:=10
End;
8
Begin
b:=1; c:=2;
Q(b,c);
Write(b,’ ‘,c)
End.
При выполнении данной программы на экран будет выведено: 1 2. Схема
передачи параметров по значению показана на рис. 7.
X
Y
b
c
Рис. 7. Схема передачи параметров по значению.
Пример 2.2. Вычислить площадь четырёхугольника со сторонами a, b, c,
d и диагональю e.
Чтобы
вычислить
площадь
такого
b
a
четырёхугольника, необходимо вычислить площади
e
двух треугольников, из которых он состоит, а
затем
сложить.
отдельного
Для
вычисления
треугольника
площади
c
d
воспользуемся
формулой
Герона:
S  p(p  a )(p  b)(p  c) , где a, b, c – стороны треугольника, p=(a+b+c)/2 –
полупериметр треугольника.
Program geron;
Var a,b,c,d,e:real; {глобальные переменные}
Function S(x,y,z:real):real; {x, y, z – формальные параметры}
{используется передача параметров по значению}
Var p:real; {локальная переменная. Память выделяется тогда,
когда
функции
функция
эта
начинает
часть
свою
памяти
работу.
После
освобождается,
будет снова не определено}
Begin
9
и
завершения
значение
работы
переменной
p:=(x+y+z)/2;
{вычисление полупериметра треугольника}
S:=sqrt(p*(p-x)*(p-y)*(p-z)) {вычисление площади треугольника}
End;
Begin
Readln(a,b,c,d,e);
Writeln(’S=’,(S(a,b,e)+S(c,d,e)):8:2)
{a,
b,
c,
d,
e
–
фактические параметры}
End.
Внутри функции мы использовали локальную переменную p, которая
видна только внутри этой функции и не оказывает никакого влияния на
переменные, описанные в основной программе. Переменные a, b, c, d являются
глобальными.
Параметры-переменные
Параметр-переменная указывается в заголовке подпрограммы аналогично
параметру-значению, но только перед именем параметра записывается
зарезервированное слово var.
В процедуру или функцию передается адрес фактического параметра,
ссылка на ячейку памяти, где он находится, а не его значение. То есть
формальный и фактический параметр являются именами одной и той же ячейки
памяти. Поэтому в качестве фактического параметра, передаваемого по ссылке
может выступать только переменная того же типа, какой имеет формальный
параметр, константой или выражением формальный параметр, передаваемый
по ссылке быть не может. При передаче параметра по ссылке изменения
формального
параметра
внутри
процедуры
приводят
к
аналогичному
изменению фактического параметра.
Пример 2.3. Определить, что будет выведено на экран в результате
работы программы.
Var b, c:integer;
10
Procedure
Q(Var
X,Y:integer);
{Передача
параметров
по
ссылке}
Begin
X:=5;
Y:=10
End;
Begin
b:=1; c:=2;
Q(b,c);
Write(b,’ ‘,c)
End.
При выполнении данной программы на экран будут выведены значения:
5 10. При передаче параметров по ссылке из основной программы в процедуру
каждая ячейка памяти используется для работы с переменными, имеющими
два разных имени (см. рис. 8).
X/b
Y/c
Рис. 8. Передача параметров по ссылке.
Обычно параметры-значения используются для передачи в подпрограмму
исходных данных, а параметры-переменные – для возврата результата. Но это
не означает, что параметры-переменные нельзя использовать для передачи в
подпрограмму значений.
Пример 2.4. Вычислить площадь четырёхугольника со сторонами a, b, c,
d и диагональю e. Для вычисления площади треугольника по формуле Герона
написать процедуру (см. пример 2.2). Глобальные переменные в процедуре не
использовать.
Var a,b,c,d,e,s1,s2:real;
Procedure
Square(x,y,z:Real;
Var
S:Real);
{параметры
передаются по значению, параметр S – по ссылке}
Var p:Real;
11
x,
y,
z
Begin
p:=(x+y+z)/2;
S:=sqrt(p*(p-x)*(p-y)*(p-z))
End;
Begin
ReadLn(a,b,c,d,e);
Square(a,b,e,S1);
Square(c,d,e,S2);
WriteLn(‘S=’,S1+S2)
End.
В качестве параметров-значений можно передавать переменные,
константы и выражения. В качестве параметров-переменных – только
переменные.
Например,
будет
ошибочной
запись:
Square(5,6,8,13).
Оператор Square(5,6,8,S1) является правильным.
Что лучше использовать для решения этой задачи: процедуру или
функцию?
Функции используются в том случае, когда в основную программу
должна
быть
возвращена
скалярная
величина,
а
процедуры
удобнее
использовать в следующих случаях:
 если в основную программу должна быть возвращена величина
нескалярного типа (например, массив),
 если в основную программу должно быть возвращено несколько
значений,
 если в основную программу ничего не должно возвращаться.
При вызове процедур и функций необходимо соблюдать следующие
правила:

количество фактических параметров должно совпадать с количеством
формальных;

соответствующие фактические и формальные параметры должны
совпадать по порядку следования и по типу.
12
Пример 2.5. В программе сделаны следующие описания:
Const A=15; var X: integer; Y: real; C: char;
а также описана процедура, заголовок которой имеет вид:
procedure PR(Var A:real; B:integer; C:real; Var D:integer; E:char);
Определить, какой из приведенных ниже операторов будет верным
вызовом процедуры PR.
1 X:= PR(Y,A,0.5,X,C);
2 PR(Y,A,A*2,X,‘X’);
3 PR(0.5,2,Y,X,C);
4 PR(Y,X,Y/2,A+1,C);
5 PR(Y,A,0.5,X,‘ABCDE’);
Рассмотрим поочередно все варианты ответов.
Ответ 1 не является правильным, т.к. PR является процедурой, а не функцией,
Ответ
2.
Типы
формальных
параметров
и
способы
передачи
соответствуют фактическим параметрам, указанных при вызове процедуры.
Это правильный ответ.
Ответ 3. Здесь в качестве первого параметра передается константа,
что недопустимо для параметров, передаваемых по ссылке.
Ответ 4. Для четвертого параметра передается выражение, что так
же недопустимо для параметров-переменных.
Ответ 5. Ошибка при описании пятого параметра, который является
строкой: ‘ABCDE’. Из заголовка процедуры видно, что пятый параметр
должен быть символом. Ошибка – несоответствие типов.
Пример 2.6. Найти наибольший общий делитель (НОД) для значений x, y,
x+y.
Идея решения состоит в следующем математическом факте: если х, у, z —
три натуральных числа, то НОД(х, у, z) = НОД(НОД(х, у), z) – иначе говоря,
нужно найти НОД двух величин, а затем НОД полученного значения и третьего
числа.
13
Будем использовать функцию для вычисления наибольшего общего
делителя двух произвольных чисел. Для этого воспользуемся алгоритмом
Эвклида: для того, чтобы найти наибольший общий делитель двух чисел X и Y,
нужно большее из чисел заменять их разностью до тех пор, пока X не станет
равно Y. Наибольший общий делитель – это то число, к которому
преобразуются X и Y.
Проверим это алгоритм на числах 24 и 40.
НОД(24,40)=НОД(24,16)=НОД(8,16)=НОД(8,8)=8
Программа:
Program NOD;
Var x,y,Rez:integer;
Function Evklid(M,N:integer):Integer;
Begin
While M<>N do
If M>N Then M:=M-N
Else N:=N-M;
Evklid:=N
End;
Begin
ReadLn(x,y);
Rez:=Evklid(Evklid(x,y),x+y);
Writeln(‘НОД=’,Rez)
End.
Пример 2.7. Написать функцию, определяющую, является ли заданное
число простым.
Простое число – это число, которое делится только на 1 и само на себя.
Для того чтобы проверить, является ли число N простым, необходимо
последовательно делить его на все числа, начиная с 2 до числа N-1. Если
окажется, что ни на одно из чисел N не делится, то оно простое.
14
В действительности, можно написать более эффективную программу по
времени выполнения, если учесть следующие факты:
1) Если число N четное и не равно двум, то оно не является простым.
Поэтому выполнение деления для четных чисел не требуется.
2) Для нечетных чисел процесс последовательного деления надо начинать
с числа 3 и выполнять его с шагом 2, т.е. делить N на числа 3, 5, 7 и т.д.
3) Достаточно делить N на числа от 3 до
Учитывая
данные
положения,
N.
напишем
функцию,
которая
будет
возвращать логическое значение true (истинна), если число простое и false
(ложь) – в противном случае.
Program prime;
Var K:integer;
Function isprime(N:integer):Boolean;
Var j:integer;
is: boolean;
Begin
If N=2 Then
{Число 2 является простым}
isprime:=true
Else
IF N div 2 =0 Then
{Четное число, не равное 2}
isprime:=false
Else Begin
{Проверка только нечетных чисел}
is:= true;
j:=3;
While (j<=trunc(sqrt(N)) and is Do
Begin
is:=(N mod j <> 0) and is;
j:=j+2
End;
isprime:=is;
End;
End;
Begin
Readln(K);
{Ввод исходного числа}
15
If isprime(K) Then WriteLn(‘Простое’)
Else WriteLn(‘Не простое’)
End.
Пример 2.8. Написать программу, запрашивающую 5 целых чисел
(N<=999999) и выводящих в текстовый файл все цифры этих чисел через
запятую в обратном порядке.
Program number;
Var a:longint;
i:byte;
f:text;
procedure cifra(x:longint); {вывод цифр числа в файл в обратном
порядке}
Var k:byte;
Begin
While x<>0 Do
Begin
k:=x mod 10;
{определение последней цифры числа}
write(f,k,’,’); {вывод цифры в файл через запятую}
x:=x div 10
{«зачеркивание» последней цифры числа}
End;
WriteLn(f)
{переход в следующую строку в файле}
End;
Begin
Assign(f,’f.dat’);
ReWrite(f);
For i:=1 To 5 Do
Begin
Read(a);
{ввод целого числа}
cifra(abs(a))
{процедура вывода в файл цифр очередного числа}
End;
Close(f)
End.
16
Пример 2.9. Требуется определить, что получится в результате
работы программы?
Var a,b,c:Integer;
Procedure One(x,y:Integer; Var z:Integer);
Begin
x:=y+2; y:=z*3; z:=5;
Writeln(x,’ ‘,y,’ ‘,z)
End;
Procedure Two(x:Integer; Var z,y:Integer);
Begin
x:=y+z; y:=y+10;
WriteLn(x,’ ‘,y,’ ‘,z)
End;
Begin
a:=1; b:=2; c:=3;
Two(b,a,c); writeln(b,’ ‘, a,’ ‘,c);
One(a,b,c); writeln(a,’ ‘,b,’ ‘c)
End.
Решение показано в таблице 1.
Таблица 1. Решение примера 2.9.
в основной программе в процедуре Two в процедуре One
a
b
C
1
2
3
1
2
3
x
z
y
x
y
команды
z
a:=1; b:=2; c:=3;
2
Two(b,a,c)
4
x:=y+z
13
y:=y+10
WriteLn(x,’ ’,y,’ ’,z)
{выводим 4 13 1}
WriteLn(b,’ ’,a,’ ’,c)
17
{выводим 2 1 13}
1
2
13
1
Оne(a,b,c)
2
4
x:=y+2
39
y:=z*3
5
z:=5
WriteLn(x,’ ’,y,’ ’,z)
{выводим 4 39 5}
WriteLn(а,’ ’,b,’ ’,c)
{выводим 1 2 5}
Ответ:
4 13 1
2 1 13
4 39 5
125
Область действия переменных при работе с процедурами и
функциями
1. Имена переменных, описанных в начале некоторой программы,
считаются известными в пределах данной программы, включая и все
вложенные подпрограммы.
Program Demo1;
Var
i:Integer;
{описание
переменной
i
–
глобальная
переменная;
будет «видна» в подпрограмме}
Procedure Print; {процедура печати значения переменной i}
Begin
WriteLn(i) {используется переменная i, объявленная в основной
программе}
End;
Begin
For i:=1 To 5 Do {изменение переменной i происходит в основной
программе}
Print;
end.
18
В результате работы программы Demo1 будут напечатаны цифры от 1
до 5. Переменная i, используемая и в основной программе, и в подпрограмме –
одна и та же переменная.
Использование в подпрограмме глобально описанных переменных часто
считается плохим стилем программирования, т.к. повторно использовать такую
подпрограмму затруднительно из-за того, что нужно помнить, какое количество
параметров неявно было передано в подпрограмму и что они означают. Лучше
всего осуществлять явную передачу параметров в подпрограмму, используя
механизм формальных и фактических параметров.
2. Имена переменных, описанных в основной программе, могут совпадать
с именами переменных из других подпрограмм, а так же с именами
формальных
параметров. При
этом для
одноименных
переменных в
большинстве случаев, за исключением передачи параметров по ссылке, будут
использоваться различные участки памяти, т.е. это будут разные переменные.
В программе Demo2 используются две различные переменные с одним и
тем же именем i:
Program Demo2;
Var i:Integer;
Procedure Print(i:Integer);
Begin
i:=2 * i;
Write(i,’ ’)
End;
Begin
For i:=1 To 5 Do Begin
Print (i);
write(i,’ ’);
End
End.
В результате выполнения этой программы будет выведено:
2 1 4 2 6 3 8 4 10 5
19
3. Пусть вторая подпрограмма вызывается из первой. Во второй
подпрограмме описана переменная с именем, которое существует в первой
подпрограмме. Тогда переменная из второй подпрограммы делает "невидимой"
(недоступной) переменную из первой подпрограммы.
Program Demo3;
Var i,S:Integer;
function f(N1:Integer);
var
S:Integer;
{локальная
переменная,
доступна
только
в
подпрограмме}
begin
S:=0;
While N1 <> 0 Do Begin
S:=S + N1 mod 10; N1:=N1 div 10;
end;
WriteLn(S);
end;
Begin
S:=0;
For i:=123 To 132 Do
S:=S+f(i);
WriteLn(S);
End;
Из анализа приведенной программы можно сделать вывод, что
переменная
S,
расположенная
в
подпрограмме,
делает
недоступной
аналогичную переменную, расположенную в основной программе.
3.
Использование модулей
Часто возникает необходимость использования одних и тех же процедур
или функций различными программами. Для таких случаев удобно выделить
эти процедуры и функции в отдельную библиотеку, доступ к которой будет
возможен из любой программы. Подобные библиотеки называют модулями.
Модуль – это совокупность программных ресурсов, предназначенных для
использования другими модулями и программами. Модуль, по определению,
20
считается
отдельной
программой.
Если
обычная
процедура
является
структурным элементом программы и не может существовать вне её, то модуль
представляется собой отдельно хранимую и независимо компилируемую
единицу. Один модуль может содержать
любое количество процедур,
функций, а также других программных ресурсов (переменных, констант,
типов), доступ к которым будет возможен из любой программы. Сам по себе
модуль не является выполнимой программой. Имя файла, в котором хранится
модуль, должно обязательно совпадать с заголовком модуля.
Раздел подключаемых модулей
Для оформления раздела подключаемых модулей в разделе описаний
используется ключевое слово uses, синтаксис данного раздела представлен на
рис. 9.
Рис. 9. Синтаксическая диаграмма для раздела подключаемых модулей.
Модуль представляет собой библиотеку процедур и функций, обращение
к которым в программе становится возможным, если имя данного модуля было
указано в предложении uses. Существует ряд стандартных модулей,
реализованных разработчиками системы программирования, кроме того,
имеется возможность создать модуль самостоятельно.
Создание модуля
Все программные ресурсы модуля можно разбить на две части:
1)
объекты,
прямо
предназначенные
для
использования
другими
программами или модулями,
2) объекты рабочего характера. В соответствии с этим модуль, кроме
заголовка, имеет две основные части: интерфейсную и реализации.
Интерфейсная часть содержит описания объектов, доступных из других
программ. Их называют объектами, видимыми вне модуля.
21
В
части реализации
помещаются
рабочие объекты,
называемые
невидимыми или скрытыми.
Кроме
этого,
модуль
может
содержать
раздел
инициализации,
предназначенный для установки начальных значений переменных модуля
перед их использованием в программах. Этот раздел начинается со слова begin
и содержит последовательность операторов присваивания. Не рекомендуется
делать инициирующую часть пустой, лучше ее опустить.
Общая структура модуля:
unit имя
interface
<описания видимых объектов>
implementation
<описания скрытых объектов>
begin
<операторы инициализации объектов модуля>
end.
Если в модуле содержатся процедуры и функции, то её заголовок
считается интерфейсной частью, а тело – реализацией. В соответствии с этим в
интерфейсной части модуля должны быть представлены только заголовки
процедур и функций, а их полные описания должны содержаться в разделе
реализации. При этом в разделе реализации можно писать сокращённый
заголовок (без описания параметров). Но, если параметры будут описаны, то
они должны полностью совпадать с заголовком в интерфейсной части.
Для того чтобы можно было воспользоваться объектами модуля, нужно в
программе после заголовка указать: uses <имя модуля>.
Пример 3.1. Реализовать в виде модуля набор подпрограмм для
выполнения следующих операций:
а) проверка существования треугольника с заданными сторонами,
б) вычисления площади треугольника по трём сторонам.
С помощью данного модуля решить задачу: ввести стороны трёх
существующих треугольников и вывести их площади в порядке возрастания.
22
Описание модуля для всех реализаций, кроме Паскаля АВС, приведены
ниже.
Unit Treug;
Interface {Интерфейсная часть. Описание видимых объектов}
Procedure Prav(x,y,z:Real; Var l:Boolean);
Function Square(x,y,z:Real):Real;
Implementation {Раздел реализации}
Procedure prav; {Проверка существования треугольника}
Begin
l:=(x<y+z) and (y<x+z) and (z<x+y)
End;
Function Square; {Вычисление площади треугольника}
Var p:real;
Begin
p:=(x+y+z)/2;
square:=sqrt(p*(p-x)*(p-y)*(p-z))
end;
End.
После создания текста модуля, его необходимо сохранить под именем
Treug.pas. Затем пишем текст основной программы:
Program;
Uses Treug; {Подключение модуля Treug}
Var a,b,c,x:Real;
s:Array [1..3] Of Real;
flag:Boolean;
i:Integer;
Begin
For i:=1 To 3 Do Begin
flag:=false; {признак существования треугольника}
While not flag Do
Begin
ReadLn(a,b,c); {ввод сторон треугольника}
Prav(a,b,c,flag); {проверка существования треугольника}
If not flag Then
WriteLn(‘Треугольник не существует’)
23
Else
s[i]:=square(a,b,c) {вычисление площади треугольника}
End
End;
If
s[1]>s[2]
then
begin
{Упорядочение
площадей
по
возрастанию}
x:=s[1]; s[1]:=s[2]; s[2]:=x end;
if s[2]>s[3] then begin
x:=s[2]; s[2]:=s[3]; s[3]:=x end;
if s[1]>s[2] then begin
x:=s[1]; s[1]:=s[2]; s[2]:=x end;
writeln(s[1],’ ‘,s[2],’ ‘,s[3])
end.
При компиляции модуля создается одноименный файл с некоторым
зарезервированным
расширений
для этих целей
откомпилированных
расширением. Список возможных
модулей
для
различных
систем
программирования приведен в таблице 2.
Таблица 2. Расширения файлов откомпилированных модулей
Расширение
Система программирования
откомпилированного модуля
.tpu
Turbo Pascal
.tpu, .tpp, .tpw
Borland Pascal
.dcu
Delphi
.ppu
Free Pascal, Lazarus
Поскольку система Pascal ABC не создает кода на диске, модули
являются аналогом включаемых файлов. В частности, они компилируются
всякий раз при компиляции основной программы. Описание аналогичного
модуля в Паскале АВС будет иметь вид:
Unit Treug;
Var x,y,z:Real; l:Boolean; {раздел описаний}
Procedure Prav(x,y,z:Real; Var l:Boolean);
Begin
l:=(x<y+z) and (y<x+z) and (z<x+y)
24
End;
Function Square(x,y,z:Real):Real;
Var p:real;
Begin
p:=(x+y+z)/2;
square:=sqrt(p*(p-x)*(p-y)*(p-z));
end;
initialization {раздел инициализации}
Prav(x,y,z,l);
Square(x,y,z);
end.
За более подробной информацией для работы с модулями воспользуйтесь
справкой системы программирования.
Различные системы программирования имеют неодинаковые наборы
стандартных модулей. Например, в Turbo Pascal и Borland Pascal часто в
программах используются модули CRT и Graph. В модуле Crt сосредоточены
процедуры и функции, обеспечивающие управление текстовым режимом
работы экрана. С его помощью можно перемещать курсор в любую точку
экрана, менять цвет выводимых символов и фона, создавать окна. Модуль
GRAPH содержит набор типов, констант, процедур и функций для управления
графическим режимом работы экрана. Этот модуль позволяет создавать
различные
графические
изображения
и
выводить
стандартными или созданными программистом шрифтами.
25
на
экран
надписи
26
27
28
Related documents
Download