
- •1.Алфавит языка паскаль
- •9.6.Функции определения порядка
- •10.Тип вещественный
- •12.Операторы
- •12.1.Простые операторы
- •13.2.Вывод данных на монитор
- •13.3.Форматирование при выводе данных
- •17.1.Объявление и вызов подпрограмм
- •19.Блоки (модули) в паскале
- •19.1.Блок Crt (Unit Crt)
- •23.1.Работа с текстовыми файлами
- •24.Динамическая память
- •640 Кбайт ┌───────────────────┐
- •26.Динамические библиотеки
- •28.Тип объект (класс)
- •30.Встроенный ассемблер
- •30.1.Объявление операндов
- •31.Основы работы в графическом режиме
- •34.Многоугольники
- •35.Криволинейные фигуры
- •39.Команды работы редактора
17.1.Объявление и вызов подпрограмм
а)Объявление подпрограмм
Структура подпрограммы почти полностью совпадает со структурой
программы. Действительно:
=>Заголовок подпрограммы:
Procedure <имя>[(<список формальных параметров>)];
Function <имя>[(<список формальных параметров>)]:<тип резу-
льтата>;
Отметим, что в отличии от заголовка программы заголовок у под-
программы должен быть обязательно, поскольку иначе нельзя объявить
имя подпрограммы, отделить ее текст от всей программы и обратиться
к ней в программе.
=>Раздел описаний. Он, как в программе, может включать в себя
несколько секций, но не может быть секции Uses. Как правило, отсут-
ствует секция подключения процедур и функций из внешних файлов.
=>Операторная часть. Она аналогична операторной части програм-
мы, только в конце ставится ;.
Пример 36. ┌─ заголовок подпрограммы (в данном случае-процедуры)
Procedure P1(X,Y,Z:Integer;C:Char;Var B:Byte;Var K:ShortInt);
Const N=10; ─┐
Type Ar=Array[1..5] Of String[10]; ├─ раздел описания
Var Ari:Ar; ─┘ локальные переменные
Begin ─┐
... ├─ операторная (исполняемая) часть
End; ─┘
Function F1(X,Y,Z:Integer;C:Char;Var K:ShortInt):Byte;
Const=10;
Type Ar=Array[1..5] Of String[10];
Var Ari:Ar;
Begin
...
F1:=<результат: 0..255 (байт)>;
End;
Примечания:
->Тип результата функции может быть стандартным или ранее объ-
явленным пользовательским типом, который должен быть только
простым, строковым, указателем или PChar.
->Начиная с версии TP 6.0, возможен вызов функции без присвое-
ния результата соответствующей переменной (так называемый
расширенный синтаксис). Для его реализации необходимо испо-
льзовать директиву компилятору {$X+}. Рекомендуется исполь-
зовать расширенный синтаксис в объектно-ориентированном про-
граммировании.
->Нельзя выйти из подпрограммы иначе, как через конец подпрог-
раммы, и нельзя войти в подпрограмму иначе, как через нача-
ло, т.е. нельзя по метке выйти наружу или войти внутрь.
->Идентификатор функции в теле подпрограммы может несколько
раз использоваться слева от оператора присваивания. Если не-
обходимо его подставить справа от знака :=, то следует ис-
пользовать идентификатор функции совместно со <списком пара-
метров>.
->Локальные переменные размещаются в сегменте стека.
Пример 37. {возведение в целочисленную степень}
X=1, N=0
X=1/Xn, N<0
X=Xn, N>0
Function Pow(X:Real;N:Integer):Real;
Begin
If N=0 Then Pow:=1.0
Else If N<0 Then Pow:=1/Pow(X,Abs(N))
Else Pow:=X*Pow(X,N-1);
End;
Приведенный в примере прием называется рекурсией, но о ней бу-
дет сказано позднее.
б)Расположения текста подпрограмм
=>В небольших программах текст подпрограмм обычно располагают
в секции описаний программ, как было сказано в 3.
=>При большом числе подпрограмм и в больших программах, текст
подпрограмм может быть размещен в отдельном файле, который подклю-
чается при компиляции, как сказано в 3, через {$I <имя файла>.Pas}.
=>Подпрограммы могут быть оформлены в виде модуля-блока и пре-
дварительно откомпилированы для получения файла с <имя файла>.Tpu,
который подключается в разделе описаний в секции Uses, но об этом
позднее.
=>Подпрограммы могут быть оформлены в виде модуля-блока, кото-
рый при компиляции подключается не к Exe файлу, а в виде Ovl-файла.
Для этого в программе надо указать {$O <имя файла>.Ovl}. Этот спо-
соб рассматривать не будем.
=>Подпрограммы могут быть написаны на другом языке, чаще всего
это ассемблер. Тогда они подключаются в виде Obj-кода с помощью ди-
рективы компилятору {$L <имя файла>.Obj}. В этом случае говорят о
внешних подпрограммах, и для их подключения используется зарезерви-
рованное слово External.
в)Вызов подпрограмм
Пользовательские подпрограммы вызываются также как и стандарт-
ные.
Пример 38. {на основе примера 36}
Const Ic='d';
Var V:Byte;A,M:Integer;
B1:Byte;K1:ShorInt;
Begin
...
A:=10;
P1(A,-15,Sqr(4),Ic,B1,K1);
V:=F1(A,-15,A+4,Ic,K1);
...
End.
17.2.Объявление и передача параметров
Переменные, поступающие для обработки в подпрограмму, могут
передаваться в нее и обратно, а, следовательно, и описываться, тре-
мя различными способами.
а)Как глобальные переменные (плохой способ). При таком способе
переменные, которые передаются в подпрограмму и поступают из нее,
описываются в разделе описания головной программы. Если таким обра-
зом передаются все переменные, то в подпрограмме может вообще отсу-
тствовать <список формальных параметров>. Глобальные переменные ра-
змещаются в сегменте данных, размер которого не более 65520 байт.
Пример 39.
Procedure P2;
Var I:Byte; поступают извне
Begin │ │
For I:=1 To 10 Do WriteLn(I:4,X:4:2,St);
End;
Function F2:String;
Var S:String[15];
Begin
ReadLn(S);S:=S+St+' ';
F2:=S; └ поступает извне
End;
б)Как параметры-значения. Такие переменные только передаются в
подпрограмму. По окончании работы значения таких переменных не оп-
ределены и не могут быть использованы. В примере 36 к таким пере-
менным относятся: X,Y,Z,C.
в)Как параметры-переменные. Такие переменные не только переда-
ются в подпрограммы, но и сохраняют при выходе из нее те значения,
которые присваиваются им внутри подпрограммы. Описываются они с ис-
пользованием зарезервированного слова Var в <списке параметров> по-
дпрограммы. В примере 36 к таким переменным относятся B и K.
Примечания:
->Переменные, которые описаны в <списке параметров> при объяв-
лении подпрограммы, называются формальными. Они нужны лишь
для того, что бы показать: сколько переменных передается в
подпрограмму, какого они типа и как они обрабатываются внут-
ри подпрограммы.
->Если идентификаторы типов, констант, переменных, объявленных
в разделе описания подпрограммы, или идентификаторы перемен-
ных, объявленные в <списке формальных параметров>, совпадают
с какими-нибудь идентификаторами в головной программе, то
они имеют приоритет внутри подпрограммы. Для обращения к пе-
ременной из головной программы следует использовать состав-
ное имя: <имя программы>.<имя переменной>. Однако на началь-
ном этапе создания программ на ТР будем избегать этого.
->Параметры, которые подставляются вместо объявленных в <спис-
ке формальных параметров>, называются фактическими.
->Если параметры описаны в <списке формальных параметров>, как
параметры-значения, то вместо них можно подставлять как пере-
менные, описанные в головной программе, например, A вместо X
в программах P1 и F1, так и конкретные значения (-15) вместо
Y, или константы, как Ic вместо C, или выражения, Sqr(4) или
математическое выражение A+4 вместо Z.
->Если параметры описаны в <списке формальных параметров> как
параметры-переменные, то вместо них можно подставлять толь-
ко переменные, описанные в головной программе, например, B1
и K1 вместо B и K.
->Количество фактических параметров должно совпадать с объяв-
ленным, как и их типы и места расположения.
->Скобки для объявления формальных параметров круглые.
->Нельзя в скобках объявлять пользовательский т.е. ранее неиз-
вестный тип данных. Так нельзя объявить новый тип - массив:
Procedure P(X:Array[1..5] Of Real);
->В процедурах и функциях могут быть использованы нетипизиро-
ванные параметры-переменные со словом Var.
->В процедурах и функциях могут быть использованы открытые па-
раметры: строки и массивы различных размеров.
17.3.Особенности и виды подпрограмм, директивы подпрограмм
а)Рекурсия
Рекурсия - это такой способ организации вычислительного проце-
сса, при котором функция (реже процедура) в ходе выполнения состав-
ляющих ее операторов обращается сама к себе. При этом идентификатор
функции стоит справа от оператора присваивания и используется вмес-
те с формальными параметрами. Один из примеров рассмотрен нами в 36.
Пример 40.
->Function Fac(N:Byte):LongInt; {факториал N!}
Begin
If N=0 Then Fac:=1
Else Fac:=N*Fac(N-1);
End;
->Procedure Bin(N:Integer); {10-ое в 2-ое}
Begin
If N<2 Then Write(N) │2 {целочисленное}
Else Begin 19└── 2 {деление 19 Div 2}
Bin(N Div 2); │ 9 └── 2
Write(N Mod 2); │ │ 4 └── 2
End; │ │ │ 2 └── ответ
End; │ │ │ │ 1 0 0 1 1
помещаются в стек │ │ │ │
│ │ │ 2 Mod 2 │ │ │
│ │ 4 Mod 2 ───┘ │ │
9 Mod 2 ────────┘ │
19 Mod 2 ────────────┘
Рекурсия придает программам изящность, но пользоваться надо ос-
торожно, ибо программа выполняется медленнее и при большом числе
операций происходит переполнение сегмента данных и "зависание" ЭВМ.
б)Опережающее описание - директива
Хотя и редко, но бывают случаи, когда подпрограммы обращаются
друг к другу. Для того, чтобы обойти требование ТР, заключающееся в
том, что все используемые идентификаторы должны быть описаны ранее
их применения можно воспользоваться опережающим описанием: Forward.
Пример 41.
Procedure A(J:Byte);
...
Begin
...
B(J);
...
End;
Procedure B(I:Byte);
...
Begin
...
A(I);
...
End;
Достаточно перед описанием процедуры A записать:
Procedure B(I:Byte); Forward;
При описании же процедуры B в ее заголовке формальные парамет-
ры можно уже не указывать.
в)Процедура Inline (встроенная процедура) - директива
Procedure DeleteCursor; {удаление курсора с экрана}
Begin
Inline($B4/1/$B9/$2000/$CD/$10);
End; $0607 -{восстановление курсора на экране}
По существу это включение ассемблерного текста в программы на
ТР, но в виде кодов. В ТР версии 6.0 и выше можно уже непосредствен-
но включать текст на ассемблере. Ассемблерный текст в виде кодов
можно вставить в текст программы и непосредственно в виде Inline-
оператора.
Пример 42.
->Inline($B4/0/$CD/$16); - Стоп до нажатия любой клавиши.
->Inline($B8/$0600/$B7/$07/$B9/$0000/$BA/$184F/$CD/$10); - Очи-
стка окна заданным цветом.
$07 - Цвет фона (0) и цвет символов (7);
$0000 - Координаты левого верхнего угла окна (первые две циф-
ры - строка, вторые - столбец);
$184F - Координаты правого нижнего угла окна (первые две циф-
ры - строка, вторые - столбец).
г)External - внешняя процедура - директива
д)Interrupt - процедура прерывания - директива
е)Assembler - директива, позволяющая использовать язык assemb-
ler для написания кода подпрограмм.
ж)Export - директива, позволяющая сделать процедуры и функции
доступными для других модулей кода. Обязательно при
заимствовании процедур и функций для Windows-приме-
нений, при включении в библиотеки *.Dll.
з)В TP версии 7.0 в качестве параметров-переменных можно испо-
льзовать массивы и строки открытого типа (размеры не задаются). В
качестве фактического параметра в этом случае можно использовать
строку или массив любого размера, однако массив должен состоять из
тех же компонент, что и объявленный. Фактический размер массива в
этом случае может быть определен с помощью функции High. Отметим,
что нумерация компонентов в открытом массиве всегда начинается с 0.
Для объявления открытой строки введен тип OpenString. Ее можно объ-
явить и через обычную строку типа String, указав опцию {$P+}.
Пример 43.
Function Max(Var Mas:Array Of Integer):Integer;
Var M:Integer;
I:Byte;
Begin
M:=Mas[0];
For I:=1 To High(Mas) Do If M < Mas[I] Then M:=Mas[I];
Max:=M;
End;
Procedure FillString(Var St:OpenString;C:Char);
Begin
St[0]:=Chr(High(St));
FillChar(St(1),High(St),C);
End;
18.ПРОЦЕДУРНЫЙ ТИП
В ТР, начиная с версии 5.0, допускается использовать процедуры
и функции как элементы языка, которые могут выступать в качестве
переменных, а также параметров-значений, передаваемых в подпрограм-
мы. Для этого введен процедурный тип.
Рассмотрим проблему использования переменных и параметров-зна-
чений процедурного типа на примере вычисления суммы F(K) членов ря-
да с номера L по номер N, где F(K)=1/K.
1.Для этого необходимо:
а)В секции Type описать пользовательский процедурный тип: про-
цедуру или/и функцию. Например:
Type Proc=Procedure(Var L,N:Integer); {процедурный тип}
Func=Function(K:Integer):Real;
По существу описывается целый класс (набор) процедур и функций
подобного типа.
б)В секции Var можно объявить переменные введенного типа фун-
кции или/и процедуры и другие необходимые переменные.
Var Fu1:Func; {объявлена переменная функция}
Pr1:Proc; {объявлена переменная процедура}
I,J,P:Byte;
R:Real;
в)Описать процедуру и/или функцию, передаваемую в качестве па-
раметра, в разделе описания с ключом-опцией: {$F+} - дальний вызов.
Пример 44.
{$F+}
Procedure Vvod(Var L,N:Integer);
Begin
Write('Укажите номер начального элемента ряда ');
ReadLn(L);
Write('Укажите номер последнего элемента ряда ');
ReadLn(N);
End;
Function S(K:Integer):Real;
Begin
S:=1/K;
End;
2.Как все это использовалось?
Если не использовать передачу функции и процедуры в качестве
параметра, то мы записали бы головную программу следующим образом:
Begin
R:=0;
Vvod(I,J);
For P:=I To J Do R:=R+S(P);
WriteLn('Сумма интересуемых членов ряда = ',R:5:2);
End.
Для того, чтобы передать функцию и процедуру в качестве пара-
метра, необходимо определить подпрограмму, в которую они передаются.
В нашем случае можем ввести такую процедуру:
┌──────┬─ процедура и функция -параметры-значения
Function Sum(P:Proc;F:Func):Real;
Var L,N,R:Integer;
Rv:Real;
Begin
Rv:=0;
P(L,N);
For R:=L To N Do Rv:=Rv+F(R);
Sum:=Rv;
End;
После этого в головной программе мы можем записать:
Begin
R:=Sum(VVod,S);
WriteLn('Сумма интересующих членов ряда = ',R:5:2);
End.
Можно также и через переменные процедуры и функции решить за-
дачу. Этот способ предпочтительнее в тех случаях, когда несколько
процедур и/или функции необходимо передавать.
Begin
Pr1:=Vvod; {в этих случаях Pr1 и Fu1 присваиваются адреса,}
Fu1:=S; {по которым размещаются подпрограммы Vvod и S}
R:=Sum(Pr1,Fu1);
WriteLn('Сумма интересуемых членов ряда = ',R:5:2);
End.
Примечания:
->Нельзя передавать в качестве параметра стандартные процедуры
и функции. Если это необходимо, то следует на их основе сде-
лать свою.
->Передаваемые процедуры и функции не могут быть встроенными в
другие процедуры и функции.
->Нельзя передавать подпрограммы, включающие прерывания.
->В памяти этот тип занимает 4 байта (двойное слово).
->Переменной процедурного типа можно присваивать значение Nil,
значение переменной процедурного типа или идентификатор под-
программы. Возможен оператор If @Pr1<>Nil Then Pr1(I,J);
->Процедурные типы являются совместимыми, если у них совпадает
число параметров и они имеют в одноименных позициях одинако-
вый тип. У функций должен совпадать и возвращаемый результат.
->Могут быть объявлены константы-процедуры или функции, напри-
мер, Const ConstProc:Proc=Vvod;