Алгоритмический язык Паскаль
Любая группа операторов, размещенных между словами BEGIN и END (иначе, операторные скобки), рассматривается как один - составной оператор. При выполнении составного оператора все его компоненты (операторы) выполняются в порядке их написания (линейно).
Составные операторы обрабатываются как единое целое, как один оператор, что имеет значение там, где синтаксис языка допускает использование одного оператора. Это имеет место практически во всех структурных операторах. Примеры использования составных операторов будут рассмотрены в соответствующих разделах данного пособия.
Наряду с понятием "составной оператор" в языке существует специфическое понятие - "пустой оператор". Пустой оператор - это оператор, который не предусматривает выполнения никаких действий.
Однако практика показывает, что иногда полезно иметь такое средство, например, при выполнении искусственной задержки выполнения программы:
FOR I:=1 TO 10000 DO;
При выполнении данного цикла машина переменной I последовательно присвоит значения от 1 до 10000. В теле цикла нет операторов, значит, кроме счета ничего не будет выполнено, однако время на это затрачивается, и, следовательно, некоторое время программа "висит" на данном операторе.
Существуют и другие примеры использования пустого оператора, когда по синтаксису оператор формально необходим, но никаких действий внутри него не производится.
4.2 Организация ветвлений. Операторы выбора
Оператор IF можно представить в виде следующей синтаксической диаграммы:
Конструкция "Условие" есть логическое выражение, которое принимает два значения типа BOOLEAN: TRUE, FALSE (истинно или ложно).
Само выражение (логическое) складывается из операций сравнения >, >=, <, <=, =, <>. Результат сравнения может быть TRUE или FALSE.
Логические выражения могут формироваться также и с помощью трех логических операций: NOT, AND, OR. Приоритеты операций:
Высший: ()
NOT *, /, DIV, MOD
AND
OR +, -
Низший: >, =, <, >=, <>, <=
В качестве условия может быть использована и логическая переменная.
Например:
I and J or K ---> (I and J) or K;
not X and Y ---> (not X) and Y,
где I, J, K, X, Y переменные типа BOOLEAN;
(A<B) or (B=0), где A,B - переменные простого типа.
В операторе IF всегда за словами THEN и ELSE должен следовать один оператор. Если хотя бы один из них является оператором IF, то полученную конструкцию называют вложением.
ПРИМЕР:
IF <условие1> THEN
<ветвь 1>
ELSE
IF <условие2> THEN
<ветвь 2>
ELSE
<ветвь 3>
Такое вложение используется для уменьшения числа необходимых проверок. Этот метод часто обеспечивает большую эффективность, чем составное условие, однако одновременно он уменьшает надежность программы. Не рекомендуется использовать более двух-трех уровней вложения IF. Вложения могут идти и после слова THEN. Ниже следуют два способа вложения конструкции IF в конструкцию IF:
1 способ
|
2 способ
|
|
|
|
|
IF c1 THEN
|
IF c1 THEN
|
|
s1
|
IF c2 THEN
|
|
ELSE IF c2 THEN
|
IF c3 THEN
|
|
s2
|
ELSE s2
|
|
ELSE IF c3 THEN
|
ELSE s3
|
|
ELSE s4
|
ELSE s4
|
|
|
Первый способ предпочтительнее, чем второй, т.к. конструкция THEN-IF менее удобна, чем ELSE-IF. С помощью конструкции ELSE-IF чаще всего осуществляется выбор одного из нескольких альтернативных путей. Заметим, однако, что иногда такое вложение лучше заменить на последовательность короткой формы оператора IF-THEN. Это видно на следующем примере:
program QUARD;
var A,B,C: real; DETER: real;
begin
read(A,B,C); DETER:= sqr(B)-4*A-C;
1 вариант
|
2 вариант
|
|
|
|
|
|
|
if DETER<0 then
|
if DETER<0 then
|
|
write('Не имеет корней');
|
write('Нет корней');
|
|
if DETER=0 then
|
else
|
|
|
write('Один корень');
|
if DETER=0 then
|
|
if DETER>0 then
|
write('Один корень');
|
|
write('Два корня');
|
else
|
|
|
|
|
write('Два корня');
|
|
|
end
однако в Паскале существует оператор, позволяющий сделать выбор из нескольких альтернатив - множественное ветвление.
Оператор варианта состоит из выражения и списка операторов, каждому из которых предшествует одна или более констант, называемых константами выбора, что видно из синтаксической диаграммы:
ОБЩАЯ ФОРМА ЗАПИСИ:
CASE <выражение> OF
константы: оператор;
константы: оператор
ELSE < оператор >
END.
Выражение, стоящее между CASE и OF, называется селектором.
Константы (значения выражения), предшествующие двоеточию, называются метками случаев. Порядок работы оператора - сначала вычисляется значение селектора, затем выполняется оператор, метка которого совпадает со значением селектора. Все остальные операторы не выполняются, управление передается на следующий после END оператор. Если же в операторе есть строка ELSE, то при несовпадении значения селектора ни с одной константой выполняется оператор, следующий за ELSE.
Выражение "селектор" может относиться к любому скалярному типу, кроме REAL. Метки случаев должны принадлежать тому же типу, что и селектор. Недопустимо, чтобы одна и та же метка появлялась более одного раза в операторе CASE.
Оператор CASE особенно удобно использовать, во-первых, когда характер действий определяется значениями, которые не попадают в последовательно расположенные интервалы, во-вторых, когда нескольким дискретным значениям селектора соответствует одно и то же действие.
ПРИМЕР 1. Печать названия десятичных цифр
program DICITS;
var DIGIT: integer;
label 1;
begin
1: writeln ('Введите цифру');
readln(DIGIT);
if (DIGIT < 0) or (DIGIT > 9) then
begin
writeln ('Это не цифра');
GOTO 1
end
else
case DIGIT of
0: writeln('нуль');
1: writeln('один');
9: writeln('девять');
end;
end.
ПРИМЕР 2. Печать номера квартала года
program NUMKVART;
var MESIATZ: 1..12;
begin
write('Введите номер месяца года - '"; read(MESIATZ);
case MESIATZ of
1,2,3: writeln('Первый квартал');
4,5,6: writeln('Второй квартал');
7,8,9: writeln('Третий квартал');
10,11,12: writeln('Четвертый квартал');
end;
end.
ПРИМЕР 3. Вывод на печать, является ли введенный с клавиатуры символ гласной буквой или знаком препинания
program SIMVOL;
var CH: char;
begin
write('Введите символ - '"; readln(CH);
write (CH,' есть ');
case CH of
'A','E','I','O','U': write('гласная');
'.',';',',',':','?','!': write('знак препинания');
end;
end.
ЗАМЕЧАНИЕ. В операторе CASE нет условий как таковых, однако проверка условий осуществляется в неявном виде. Действительно, строке
'A','E','I','O','U': WRITE('гласная')
примера 3 равносилен оператор
IF (ch='A") OR (ch='E') OR (ch='I') OR (ch='O') OR (ch='U')
THEN WRITE(' гласная').
4.3 Организация циклов. Операторы повторения
Оператор цикла задает повторное выполнение определенных операторов. Для реализации циклов в Паскале предусмотрены три различных структурных оператора: WHILE, REPEAT, FOR. Первые два используются, если число повторений (итераций) заранее не определено, но известно условие завершения цикла. Оператор FOR применяется тогда, когда число повторений тела цикла известно.
Этот оператор является наиболее мощным из всех трех, реализующих циклы. Два других оператора можно выразить с его помощью.
Логическое выражение, стоящее после WHILE, называется условием возобновления цикла и должно иметь булевский тип. Оператор, следующий за DO, является телом цикла. Он повторяется до тех пор, пока истинно условие возобновления цикла. Как только условие возобновления цикла становится ложным, управление переходит к оператору, стоящему за WHILE. Если условие возобновления не удовлетворяется до начала выполнения цикла, то тело цикла пропускается.
Из указанного описания видно, что оператор WHILE реализует базовую структуру "цикл - пока", т.к. здесь проверка условия идет до тела цикла. Поэтому оператор WHILE называют оператором цикла с предусловием.
Рассмотрим пример программы вычисления для данного а0 по известной итерационной формуле:
Здесь надо организовать циклический процесс и остановиться тогда, когда
,
где Е - заданная точность приближения.
program SQUR;
var A,X,EPS: real;
begin
write('Введите число ');
readln(A);
write('Введите точность ');
readln(EPS);
X:=(A+1)/2;
while abs(sqr(X)-A) >= EPS do
X:=0.5*(X+A/X);
write('Корень из ',A,' = ',X);
end.
ЗАМЕЧАНИЕ. Грамотное использование оператора WHILE предполагает умение правильно написать условие возобновления цикла. Здесь надо иметь в виду следующие рекомендации:
а) в условии, как в логическом выражении, должны обязательно фигурировать переменные, изменяющие свои значения в теле цикла;
б) во избежание зацикливания лучше сначала написать условие прекращения цикла и взять потом в оператор его отрицание;
в) переменные логического выражения должны получить свои исходные значения до входа в оператор WHILE.
Оператор REPEAT называют оператором цикла с постусловием, т.к. здесь выражение, управляющее повторным выполнением последовательности операторов, помещается после тела цикла.
В этом операторе тело цикла выполняется до тех пор, пока ложно условие, стоящее после UNTIL. Условием выхода из цикла является истинность выражения. Мы видим, что это есть форма "цикла-до".
ПРИМЕР. Даны числа A, B (A>1). Получить все степени числа A, меньшие числа B
program STEPENI;
var A,B,C: real;
begin
readln(A,B); C:=A;
repeat
writeln(C);
C:= C*A;
until C >= B;
end.
ПРИМЕЧАНИЕ. Между операторами WHILE и REPEAT существуют три основных различия:
1. В операторе REPEAT проверка условия выхода из цикла выполняется в конце, а не в начале цикла, как в операторе WHILE. Поэтому в операторе REPEAT тело цикла выполняется хотя бы один раз.
2. В REPEAT выход из цикла осуществляется по истинности условия, а в WHILE - по ложности.
3. В операторе WHILE тело цикла чаще всего имеет форму составного оператора, в операторе REPEAT для организации тела цикла операторные скобки не нужны.
Он предназначен для организации циклов, когда заранее известно, сколько раз должно повториться тело цикла. Здесь управление числом повторений осуществляется с помощью специальной переменной - параметра цикла (управляющей переменной), которой присваивается возрастающая (убывающая) последовательность значений.
Здесь "переменная" есть параметр цикла, "выражение 1" - начальное значение параметра, "выражение 2" - его конечное значение. В качестве управляющей переменной должен использоваться идентификатор переменной, объявленный локальной в блоке, который содержит данный оператор FOR. Управляющая переменная должна иметь ординальный тип. Начальное и конечное значения имеют тип, совместимый с типом параметра цикла.
Когда начинает выполняться оператор FOR, начальное и конечное значения определяются один раз, и эти значения сохраняются на протяжении всего выполнения оператора.
Оператор, который содержится в теле оператора FOR, выполняется один раз для каждого значения управляющей переменной в диапазоне между начальным и конечным значениями. Управляющая переменная всегда инициализируется начальным значением. Она принимает все свои значения из диапазона с шагом 1, если TO, и с шагом -1, если DOWNTO. В случае TO, если начальное значение превышает конечное, то тело цикла не выполняется.
Для случая DOWNTO это имеет место, когда начальное значение меньше, чем конечное. Отсюда заключаем, что оператор цикла FOR реализует, как и WHILE, схему цикла "пока".
ПРИМЕЧАНИЕ:
1. Если тело цикла в этом операторе состоит из более одного оператора, то они все заключаются в операторные скобки (реализуют конструкцию составного оператора).
2. В отличие от школьного алгоритмического языка, цикл FOR нельзя прервать путем присваивания управляющей переменной ее конечного значения. Изменения переменной цикла не влияют на число повторений тела цикла. Для досрочного выхода из цикла используют оператор GOTO.
3. После выполнения оператора значение управляющей переменной становится неопределенным, если только выполнение оператора FOR не было прервано с помощью оператора перехода.
Рассмотрим примеры использования оператора FOR для организации циклических процессов:
ПРИМЕР 1. Печать отсчета цифр при старте
program START;
var SEC: integer;
begin
writeln ('До старта осталось...');
for SEC:=10 downto 1 do
writeln (SEC:4);
writeln ('ноль'); writeln ('Старт !!')
END.
В данном примере управляющая переменная SEC принимает значения типа INTEGER, однако в Паскале она определена как переменная ординального типа, следовательно, может принимать значения типа CHAR или принадлежать перечислимому типу, как показано в следующем примере:
ПРИМЕР 2. Подсчет числа часов рабочей недели
program WORKTIME;
type DAYS = (MO,TU,WE,TH,FR,SA,SU);
var DEN: DAYS; WT: integer;
begin
WT:=0;
for DEN:= MO to SA do
if DEN <> SA then WT:= WT+8
else WT:= WT+7; writeln (WT)
end.
5. ОРГАНИЗАЦИЯ ПОДПРОГРАММ. ПРОЦЕДУРЫ И ФУНКЦИИ
Мы уже видели, что Паскаль-программа состоит из последовательности операторов (простых и структурных). Есть в языке также понятие функции. Система Turbo-Pascal имеет целый набор встроенных машинных функций. Однако Паскаль предоставляет возможность создавать новые операторы и функции на основе стандартных. Такие процедуры и функции принято называть пользовательскими.
В Паскале два типа подпрограмм - процедуры и функции. Создание процедур и функций является дальнейшим развитием идеи группирования, когда несколько операторов объединяются в программный блок, который имеет свое имя и к которому можно обратиться по этому имени с помощью соответствующих средств вызова. Процедура вызывается с помощью оператора процедуры с одноименным именем. Функция пользователя также имеет свое имя и ее активизация происходит при вычислении выражения, содержащего имя функции, и возвращаемое функцией значение подставляется в это выражение.
5.1 Процедуры и их типизация
Итак, процедура - это часть программы (подпрограмма), имеющая имя и предназначенная для решения некоторой частной задачи (подзадачи). Они делятся по способам описания и обращения к ним следующим образом:
Процедура встроенная (машинная) - процедура в программировании, описание которой считается известным транслятору, в связи с чем ее можно использовать без описания.
Процедура пользователя - процедура, которую создает (описывает) программист на основе имеющихся операторов и встроенных процедур и функций данного языка по определенным правилам данного компилятора.
Процедура без параметров - процедура, при обращении, к которой не требуется задания начальных установок, значений и после выполнения которой в основную программу не передаются результаты работы данной процедуры.
Процедура с параметрами-значениями - процедура, при обращении к которой требуются начальные значения. На выходе данные не передаются в основную программу.
Процедура с параметрами-переменными - процедура, не требующая начальных значений, однако передающая в основную программу результаты своей работы (передает значения некоторых переменных).
Комбинированная процедура - процедура, имеющая параметры-переменные и параметры-значения, т.е. входные и выходные данные.
Эти процедуры являются составной частью системы программирования. Среди этих процедур есть стандартные процедуры, которыми можно пользоваться в любом месте программы без какого-либо предварительного объявления. Сюда относятся уже ранее упомянутые процедуры ввода/вывода, управления работой программы, динамического распределения памяти, строковые процедуры и пр. Полный перечень встроенных процедур можно найти в справочнике для языка.
Помимо стандартных процедур в Паскале есть также стандартные модули, представленные в виде TPU - файлов, каждый из которых содержит в себе целый набор процедур и функций. Для того, чтобы использовать процедуры из модулей, необходимо вызвать нужный модуль в разделе USES. Система Turbo-Pascal имеет модули PRINTER, DOS, CRT, GRAPH и др.
CRT - позволяет использовать все возможности дисплея и клавиатуры, включая управление режимом экрана, расширенные коды клавиатуры, цвет, окна и звуковые сигналы.
DOS - поддерживает различные функции ДОС, включая установку и получение текущего значения даты и времени, поиск по каталогам файлов и выполнение программ.
PRINTER - позволяет легко организовать доступ к устройству печати.
GRAPH - мощный графический пакет с набором процедур и функций обработки графических объектов (точек, отрезков, прямоугольников, окружностей и пр.).
Рассмотрим несколько примеров встроенных процедур:
1) CLRSCR - процедура очистки экрана. Результатом работы является стирание всей информации с экрана. Данная процедура является примером процедур без параметров;
2) GOTOXY(A,B) - процедура позиционирования курсора на экране дисплея в точку с координатами (A,B). A и B являются входными данными, следовательно, это пример процедуры с параметрами-значениями;
3) WRITE([A],[B],.....,[Q]) процедура вывода информации на экран дисплея. Данная процедура - процедура с параметрами-значениями.
4) READ([A],[B],....,[Q]) процедуры ввода информации в ЭВМ.
При работе с процедурами пользователя необходимо уметь производить два вида деятельности: описание процедуры и обращение к ней в основной программе. Вызов процедуры пользователя осуществляется так же, как и вызов встроенной процедуры - с помощью оператора процедуры, имя которого совпадает с именем процедуры, с указанием списка параметров, если таковые имеются. Описание же процедуры включает в себя разработку подпрограммы и правильное оформление ее заголовка. Остановимся на нем подробнее.
В основной программе все процедуры (а также и функции) пользователя должны быть объявлены. Объявление процедур и функций осуществляется после объявления переменных и перед первым словом BEGIN программы.
Заголовок программы;
Описание модулей USES;
Описание меток LABEL;
Описание констант CONST;
Описание типа TYPE;
Описание переменных VAR;
Описание процедур и функций PROCEDURE/FUNCTION;
BEGIN
Тело программы (блок);
END.
Процедура, как видно из ее определения, оформляется так же, как и основная программа. Вообще процедуру нужно воспринимать как программу в миниатюре. В свою очередь основная программа может быть легко переделана в процедуру с заменой слова PROGRAM на PROCEDURE. Если процедура объявлена, ее можно использовать в последующих частях программы, просто задавая ее имя, за которым, если необходимо, следует список параметров. Вызов процедуры для основной программы становится новым оператором. Обращение к процедуре активизирует эту процедуру, то есть приводит к выполнению группу операторов, содержащихся в ее теле. После этого управление переходит к оператору, следующему за вызовом процедуры.
Описание процедур будем рассматривать по той же схеме, что и машинные процедуры, а именно: вначале без параметров, далее с параметрами - значениями, с параметрами - переменными и, наконец, комбинированные процедуры.
Заголовок процедуры без параметров можно описать в виде:
Вызываются же такие процедуры путем написания в основной программе имени этой процедуры. В виде процедуры без параметров оформляются такие подзадачи, у которых нет входных и выходных данных, или же эти данные удобнее передавать с помощью операторов присваивания, READ и WRITE.
Рассмотрим несколько примеров, в которых представлены эти варианты.
ПРИМЕР 1. Нарисовать три вертикальных квадрата 3х3 с помощью символа "*".
Очевидно, что в этой программе надо выделить рисование квадрата в виде процедуры без параметров, а затем трижды вызвать ее в основной программе:
program RISUNOK;
procedure KVADRAT;
begin
¦ writeln('***');
¦ writeln('* *');
¦ writeln('***');
end;
begin
¦ clrscr; KVADRAT;
¦ writeln; KVADRAT; writeln; KVADRAT;
end.
ПРИМЕР 2. Вычислить площадь четырехугольника ABCD
Зная длины сторон четырехугольника и длину одной из его диагоналей, например BD, можно найти по формуле Герона площади двух вспомогательных треугольников и сложить их. Отсюда следует, что в программе надо выделить процедуру вычисления площади треугольника:
program PLOCHAD_1;
var AB,BC,CD,AD,BD,S1,S,a,b,c,p:real;
procedure GERON_1;
begin p:=(a+b+c)/2;
S:=sqrt(p*(p-a)*(p-b)*(p-c));
end;
begin {*ОСНОВНАЯ ПРОГРАММА*}
read (AB,BC,CD,AD,AC);
a:=AB;b:=AD;c:=BD; GERON_1; S1:= S;
a:=BC;b:=CD;c:=BD; GERON_1; S1:= S1+S;
write(S1);
end.
Прежде чем переходить к рассмотрению процедур с параметрами, необходимо определить сами эти понятия. Сделаем это на примере программы вычисления площади четырехугольника (пример 2).
Рассмотренная программа имеет недостаток в том, что в основной ее части идет ряд присваиваний, которые предшествуют вызову процедуры. Чтобы избавиться от этих присваиваний, вводят процедуры с параметрами. С помощью параметров осуществляется передача информации в процедуру, а также и прием информации из процедуры в основную программу.
Различают формальные и фактические параметры. Формальные параметры - это имена переменных, фигурирующих в самой процедуре. Их описание производится в заголовке процедуры - после имени процедуры в скобках. Среди них имеются параметры-аргументы и параметры-результаты. Эти параметры называют формальными, потому что они служат только для фиксации числа параметров процедуры, их имена могут быть произвольными, смена имен не отражается на ее работе.
Фактические параметры задаются в вызове процедуры, т.е. они принадлежат основной части программы. В отличие от формальных параметров, которые всегда есть переменные, фактические параметры имеют вид:
параметры-аргументы - это константы, переменные, выражения;
параметры-результаты - это всегда переменные.
Рассмотрим заново программу вычисления площади четырехугольника. В ней все переменные объявлены в основной программе. Однако среди них есть переменные, которые задействованы только в процедуре. Это переменные A, B, C, P, S. Такие переменные принято называть локальными по отношению к процедуре. Остальные переменные называются глобальными. Среди локальных переменных можно выделить параметры-аргументы A, B, C и параметр-результат S. Принято формальные параметры описывать в заголовке процедуры с указанием их типа. Локальная же переменная P является вспомогательной и описывается в процедуре так же, как в основной программе.
Порядок следования формальных параметров в заголовке процедуры и фактических параметров в вызове процедуры важен, поскольку определяет, какому параметру будет присвоено то или иное значение.
Все переменные должны быть отнесены к какому-то типу, поэтому необходимо задать тип каждого параметра. Передаваемое значение и соответствующий ему параметр (фактический) должны быть одного и того же типа.
Новые варианты программы вычисления площади четырехугольника будут даны в следующих разделах, а пока рассмотрим подробнее понятия локальных и глобальных переменных в Паскаль-программах.
В предыдущем разделе уже было дано определение локальных и глобальных переменных. Уточним еще раз, что локальные переменные объявляются внутри блока процедуры и они бывают двух видов: формальные параметры заголовка процедуры и вспомогательные переменные в разделе VAR процедуры. Эти переменные неизвестны основной программе и их использование в основном блоке вызовет сообщение об ошибке.
Глобальные переменные объявляются в разделе VAR основной программы. Глобальные переменные называют глобальными, потому что они могут фигурировать не только в основной программе, но и в теле процедуры. Заметим, что иногда одна и та же переменная может быть и локальной, и глобальной. Например, если переменная J является одновременно локальной и глобальной, то локальная переменная J отличается от переменной J из главной программы. Изменения, происходящие с J в процедуре, не влияют на значение переменной J из главной программы, и наоборот. Это происходит потому, что, несмотря на сходство имен переменных, компилятор отводит локальной переменной J одну ячейку памяти, а глобальной переменной J - другую. Обычно стараются избегать совпадения имен переменных во избежание нежелательных посторонних эффектов, которые могут возникнуть из-за использования одних и тех же имен для разных переменных.
Для ясности рассмотрим пример, связанный с использованием локальных и глобальных переменных:
program NEST;
var A,B:integer;
procedure NESTEGG;
var A,X: char;
begin
A:= "!";
X:= "?";
B:= B+1;
end;
begin { ОСНОВНАЯ ПРОГРАММА }
A:= 0; B:= 100;
NESTEGG;{ ВЫЗОВ ПРОЦЕДУРЫ }
writeln(A,' ',B);
end.
В этой программе X - локальная переменная для процедуры NESTEGG, поэтому основная программа не может ни изменить ее значение, ни обратиться к ней. С другой стороны, переменная B (глобальная) известна и в программе, и в процедуре. Если переменная B является глобальной, т.е. объявлена в главной программе, то все входящие в состав этой главной программы процедуры могут ссылаться к ней, но только в том случае, если в них нет другого объявления для B. Любое объявление имени в процедуре делает недоступным объект, имеющий то же самое имя и объявленный в основной программе. Так, у нас A для основной программы есть INTEGER, но в процедуре есть A типа CHAR. Процедуре NESTEGG недоступна переменная A из главной программы. Все изменения, происходящие с A в процедуре, становятся несущественными при выходе из этой процедуры. Но, поскольку B известна в главной программе, то все изменения с B в процедуре важны и сохраняются после выхода из нее. Итак, будет напечатано: 0 101.
Как было сказано ранее, процедуры с параметрами-значениями требуют входных данных (смотри п. 5.1). Где они записываются и как задаются? На этот вопрос может ответить синтаксическая диаграмма заголовка процедуры:
Здесь под параметром понимают имя переменной, которая является "входной" для процедуры (формальный параметр-аргумент). Этот параметр с синтаксической точки зрения является параметром-значением, при его описании в заголовке процедуры не требуется писать слов VAR. Параметры-значения принимают из основной программы при вызове процедуры свои конкретные значения.
При обращении к процедуре с параметрами-значениями в основной программе фактическими параметрами могут служить как имена переменных (которые описаны и определены выше), так и конкретные значения (константы) и выражения. При обращении необходимо следить за соответствием списка параметров при обращении и описании. Кроме этого, следует строго соблюдать "типизацию" параметров.
Рассмотрим работу процедур такого типа на примерах.
ПРИМЕР 1. Нарисовать квадрат с произвольной длиной стороны в левом верхнем углу (длина стороны задается с клавиатуры).
В этой программе также надо оформить рисование квадрата в виде процедуры, но уже с входным параметром-аргументом - длиной стороны квадрата:
program RISUNOK_2;
var I: integer;
procedure KVADRAT(N: integer);
var J,K: integer;
begin
for J:=1 to N do write('*'); writeln;
for J:=1 to N-2 do
begin
write('*'); for K:=1 to N-2 do write(' ');
writeln('*');
end;
for J:=1 to N do write('*');
end;
begin { Основная программа }
write('Введите длину стороны - ');
readln(I); clrscr; KVADRAT(I);
end.
ПРИМЕР 2. Вычисление площади четырехугольника с применением процедуры с параметрами-значениями:
program PLOCHAD_2;
var AB,BC,CD,AD,AC,S1,S: real;
procedure GERON_2(a,b,c: real);
var P: real;
begin
P:= (a+b+c)/2; S:= sqrt(P*(P-a)*(P-b)*(P-c));
end;
begin {*ОСНОВНАЯ ПРОГРАММА*}
read (AB,BC,CD,AD,AC); GERON_2(AB,BC,AC); S1:= S;
GERON_2(AD,AC,CD); write ('S = ', S1+S)
end.
В данной программе определена процедура GERON_2 с тремя параметрами-значениями и локальной переменной P. Значение же площади треугольника помещается в глобальную переменную S. При вызове этой процедуры формальные параметры a, b, c замещаются на фактические параметры AB, BC, AC при первом обращении, и на AD, AC, CD - при втором.
Заметим также, что здесь фактические параметры представлены переменными, которые получают свое значение с помощью процедуры READ. Однако, если известны длины сторон треугольника, например, 6, 7, 4, то можно вычислить площадь этого треугольника, вызвав процедуру GERON_2(6,7,4), и получить ответ в переменной S.
В отличие от процедур с параметрами-значениями, данный тип не имеет входных параметров, т.е. из основной программы не передаются значения переменных в процедуру, за исключением глобальных переменных. Отличие в описании и обращении к процедурам с параметрами-переменными заключается в специфическом написании заголовка процедуры. В остальном все процедуры схожи. Итак, синтаксическая диаграмма заголовка процедуры с параметрами-переменными:
При детальном ознакомлении с синтаксической диаграммой видно, что параметрам-переменным должно предшествовать служебное слово VAR, причем оно пишется столько раз, сколько различных типов представлено в выходных данных.
Например:
PROCEDURE PRIMER(VAR a,b,c:INTEGER; VAR m:CHAR; VAR i,j:REAL);
При обращении к процедурам с параметрами-переменными фактическими параметрами должны являться имена переменных, которые описаны в основной программе.
ПРИМЕР 1. Обмен значениями переменных A и B
program ZERKALO;
var A,B: integer;
procedure OBMEN(var X,Y: integer);
begin X:= B; Y:= A end;
begin
A:= 1; B:= 2; writeln(A,B);
OBMEN(A,B); write(A,B);
end.
ПРИМЕР 2. Вычисление площади четырехугольника
program PLOCHAD_3;
var AB,BC,CD,AD,AC,S1,S2,a,b,c: real;
procedure GERON_3(var S: real);
var P: real;
begin
P:= (a+b+c)/2; S:= sqrt(P*(P-a)*(P-b)*(P-c));
end;
begin { Основная программа }
read (AB,BC,CD,AD,AC);
a:=AB; b:= BC; c:= AC; GERON_3(S1);
a:=AD; b:= AC; c:= CD; GERON_3(S2);
write ('S = ', S1+S2)
end.
Комбинированные процедуры включает в себя входные и выходные данные. В заголовке процедуры выходные параметры предваряются, словом VAR. Порядок следования параметров может быть произвольным.
НАПРИМЕР:
PROCEDURE PRIMER(VAR a,b,c:INTEGER; m:CHAR; VAR i,j:REAL);
Здесь a,b,c,i,j - параметры-результаты (переменные);
m - пераметр-аргумент (значение).
В качестве иллюстрации комбинированных процедур рассмотрим последний вариант вычисления площади четырехугольника:
program PLOCHAD_4;
var AB,BC,CD,AD,AC,S1,S2: real;
procedure GERON_4(a,b,c:real; var S: real);
var P: real;
begin
P:= (a+b+c)/2;
S:= sqrt(P*(P-a)*(P-b)*(P-c));
end;
begin {*ОСНОВНАЯ ПРОГРАММА*}
read (AB,BC,CD,AD,AC);
GERON_4(AB,BC,AC,S1);
GERON_4(AD,AC,CD,S2);
write ('S = ', S1+S2)
end.
ПРИМЕЧАНИЕ. Для более полного усвоения введенных ранее терминов перечислим на базе последнего примера все виды параметров и переменных:
- глобальные переменные AB, BC, CD, AD, AC, S1, S2;
- локальные переменные a, b, c, S, P;
- формальные параметры a, b, c, S;
a) параметры-значения (аргументы) a,b,c;
б) параметр-переменная (результат) S;
- фактические параметры AB, BC, CD, AD, AC, S1, S2;
a) параметры-значения (аргументы) AB, BC, CD, AD, AC;
б) параметры-переменные (результаты) S1,S2.
Попытка же описать выходной параметр в виде параметра-значения (без слова VAR в заголовке процедуры) приведет к тому, что результат работы процедуры не будет возвращен в основную программу. Это происходит потому, что характер "поведения" параметров-значений и параметров-переменных в процессе работы процедуры различен. Разница эта состоит в том, что преобразования, которые претерпевают формальные параметры-значения в процедуре, не вызывают изменения соответствующих им фактических параметров, в то время как изменения параметров-переменных может изменять значения соответствующих фактических параметров.
Причиной этого феномена является неодинаковое распределение памяти под хранение параметров процедуры. Формальному параметру-значению отводится некоторая область (ячейка) памяти, куда заносится значение соответствующего фактического параметра, вычисленного на момент обращения к процедуре. На этом связь между ними обрывается. Действительно, если фактическим параметром является константа или выражение, как изменения в формальном параметре-значении (а это есть всегда переменная) могут повлиять, например, на выражение.
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|