Глава 7. Операторы
Операторы описывают те алгоритмические действия, которые
должны выполняться. Операторам могут предшествовать метки, кото-
рые можно использовать для ссылок в операторах перехода goto.
оператор --T--------------------T-------------------------->
¦ ------¬ ----¬ ^ ¦ -----------------¬ ^
L->¦метка+-->¦ : +-- +-->¦простой оператор+--+
L------ L---- ¦ L----------------- ¦
¦ -----------------¬ ¦
L-->¦ структурный +---
¦ оператор ¦
L-----------------
Метка - это последовательность цифр в диапазоне от 0 до 9999
или идентификатор.
Существует два основных вида операторов: простые операторы и
структурные операторы.
Простые операторым
Простым оператором является такой оператор, который не со-
держит в себе других операторов.
----------------------¬
простой оператор ----T--->¦оператор присваивания+------->
¦ L---------------------- ^
¦ ----------------------¬ ¦
+--->¦ оператор процедуры +---+
¦ L---------------------- ¦
¦ ----------------------¬ ¦
L--->¦ оператор перехода +----
L----------------------
Оператор присваивания
Оператор присваивания заменяет текущее значение переменной
новым значением, которое определяется выражением, или определяет
выражение, значение которого должно возвращаться функцией.
------------¬ ---¬ ----------¬
оператор -----T-->¦ссылка на +------>¦:=+-->¦выражение+-->
присваивания ¦ ¦переменную ¦ ^ L--- L----------
¦ L------------ ¦
¦ --------------¬ ¦
L-->¦идентификатор+--
¦ функции ¦
L--------------
Выражение должно быть совместимо по присваиванию с типом пе-
ременной или типом значения, возвращаемого функцией в качестве
результата (см. раздел "Совместимость типов" в Главе 4).
Приведем некоторые примеры операторов присваивания:
X := Y + Z
Done := (I >= 1) and (I < 100);
Huel := [blue, Succ(C)];
I := Sqr(J) - I * K;
Присваивания объектного типа
Правила совместимости по присваиванию объектных типов позво-
ляют присваивать экземпляру объекта экземпляр любого из его до-
черних типов. Такое присваивание представляет собой проекцию
потомка на пространство его предка. В примере исходного кода в
Главе 4 с учетом экземпляра F типа TField и экземпляра Z типа
TZipField присваивание F := Z копирует только поля X, Y, Len и
Name.
Присваивание экземпляру объектного типа не инициализирует
экземпляр. Например, в предыдущем примере присваивание F := Z оз-
начает, что вызов конструктора для F можно опустить.
Операторы процедуры
Оператор процедуры определяет активизацию процедуры, обозна-
ченную с помощью идентификатора процедуры. Если соответствующее
описание процедуры содержит список формальных параметров, то опе-
ратор процедуры должен содержать в себе соответствующий ему спи-
сок фактических параметров (параметры, список которых приводится
в определении, являются формальными параметрами, а в операторе
вызова процедуры они являются фактическими параметрами). При вы-
зове происходит передача фактических параметров формальным пара-
метрам.
--------------¬
оператор --T->¦идентификатор+-TT-------------------------->
процедуры ¦ ¦ процедуры ¦ ¦¦ -------------------¬ ^
¦ L-------------- ¦L->¦список фактических+--
¦ --------------¬ ¦ ¦ параметров ¦
+->¦ десигнатор +-+ L-------------------
¦ ¦ метода ¦ ¦
¦ L-------------- ¦
¦ --------------¬ ¦
+->¦ уточненный +-+
¦ ¦ десигнатор ¦ ¦
¦ ¦ метода ¦ ¦
¦ L-------------- ¦
¦ --------------¬ ¦
L->¦ ссылка на +--
¦ переменную ¦
L--------------
Приведем некоторые примеры операторов процедур:
PrintHeaing;
Transpose(A,N,M);
Fin(Name,Address);
Операторы перехода
Оператор перехода goto вызывает передачу управления операто-
ру, которому предшествует метка, указанная в данном операторе пе-
рехода. Синтаксическая схема оператора перехода имеет следующий
вид:
-----¬ ------¬
оператор перехода --->¦goto+--->¦метка+--->
L----- L------
При использовании оператора перехода должны соблюдаться сле-
дующие правила:
1. Метка, которая указывается в операторе перехода, должна
находиться в том же блоке или модуле, что и сам оператор
перехода. Другими словами, не допускаются переходы из
процедуры или функции или внутрь нее.
2. Переход извне внутрь структурного оператора (то есть пе-
реход на более глубокий уровень вложенности) может выз-
вать непредсказуемые эффекты, хотя компилятор не выдает
сообщения об ошибке. Например, вы не должны переходить в
тело цикла for.
Примечание: Хорошая практика программирования требует
минимального использования переходов.
Структурные операторы
Структурные операторы строятся из других операторов, порядок
выполнения которых должен быть последовательным (составные опера-
торы и операторы над записями), определяемым условной передачей
управления (условные операторы) или повторяющимся (операторы цик-
ла).
------------------------¬
структурный ----T---->¦ составной оператор +------->
оператор ¦ L------------------------ ^
¦ ------------------------¬ ¦
+---->¦ условный оператор +---+
¦ L------------------------ ¦
¦ ------------------------¬ ¦
+---->¦ оператор цикла +---+
¦ L------------------------ ¦
¦ ------------------------¬ ¦
L---->¦ оператор над записями +----
L------------------------
Составные операторы
Составные операторы задают порядок выполнения операторов,
являющихся их элементами. Они должны выполняться в том порядке, в
котором они записаны. Составные операторы обрабатываются, как
один оператор, что имеет решающее значение там, где синтаксис
Паскаля допускает использование только одного оператора. Операто-
ры заключаются в ограничители begin и end, и отделяются друг от
друга точкой с запятой.
------¬ ---------¬ ----¬
составной ---->¦begin+------>¦оператор+----T-->¦end+-->
оператор L------ ^ L--------- ¦ L----
¦ ----¬ ¦
L-----+ ; ¦<-------
L----
Приведем пример составного оператора:
begin
Z := X;
X := Y;
Y := Z;
end;
Условные операторы
Условные операторы позволяют выбрать для выполнения один из
составных операторов (или не выбрать ни одного).
----------------¬
условный оператор --T-->¦ оператор if +------->
¦ L---------------- ^
¦ ----------------¬ ¦
L-->¦ оператор case +----
L----------------
Оператор условия (if)
Синтаксис оператора if можно представить следующим образом:
---¬ ----------¬ -----¬ ---------¬
оператор if ->¦if+-->¦выражение+-->¦then+-->¦оператор+--T--¬
L--- L---------- L----- L--------- ¦ ¦
-------------------------- ¦
¦ -----¬ ---------¬ v
L-->¦else+-->¦оператор+--------->
L----- L---------
В выражении должен получаться результат, имеющий стандартный
булевский тип. Если результатом выражения является истинное зна-
чение (True), то выполняется оператор, следующий за ключевым сло-
вом then.
Если результатом выражения является значение False и при-
сутствует ключевое слово else, то выполнятся оператор, следующий
за ключевым словом else. Если ключевое слово else отсутствует, то
никакой оператор не выполняется.
Синтаксическая неоднозначность, возникающая в конструкции:
if e1 then e2 else e3
разрешается путем следующей интерпретации этой конструкции:
if e1 then
begin
if e2 then
s1
else
s2
end
Примечание: В предшествующем операторе else двоеточие
не указывается.
В общем случае ключевое слово else связывается с ближайшим
ключевым словом if, которое еще не связано с ключевым словом
else.
Приведем два примера оператора if:
if X < 1.5 then
Z := X+Y
else
Z := 1.5;
if P1 <> nil then
P1 := P1^.father;
Оператор варианта (case)
Оператор варианта (casе) состоит из выражения (переключате-
ля) и списка операторов, каждому из которых предшествует одна или
более констант (они называются константами выбора) или ключевое
слово else. Переключатель (селектор) должен иметь порядковый тип
(размером в байт или слово). Таким образом, строковый тип и длин-
ный целый тип являются недопустимыми типами переключателя. Все
константы выбора должны быть уникальными и иметь порядковый тип,
совместимый с типом переключателя.
-----¬ ----------¬ ---¬ -----¬
оператор case ->¦case+-->¦выражение+-->¦of+----->¦case+--T--¬
L----- L---------- L--- ^ L----- ¦ ¦
¦ -----¬ ¦ ¦
L---+ ; ¦<-- ¦
L----- ¦
-----------------------------------------
¦ ----¬
L-T--------------------T---------->¦end+-->
¦ -----------¬ ^ ¦ ----¬ ^ L----
L-->¦ветвь else+--- L->¦ ; +---
L----------- L----
---------------------¬
----------¬ ¦ ---¬ ----------¬ v ----¬ ---------¬
case -->¦константа+-+->¦..+->¦константа+--T->¦ : +->¦оператор+->
^ L---------- L--- L---------- ¦ L---- L---------
¦ ----¬ ¦
L-----------------+ , ¦<--------------
L----
-----¬ ---------¬
ветвь else ---->¦else+--->¦оператор+--->
L----- L---------
Оператор варианта case приводит к выполнению оператора, ко-
торому предшествует константа выбора, равная значению переключа-
теля или диапазону выбора, в котором находится значение переклю-
чателя. Если такой константы выбора или такого диапазона выбора
не существует и присутствует ветвь else, то выполнятся оператор,
следующий за ключевым словом else. Если же ветвь else отсутству-
ет, то никакой оператор не выполняется.
Приведем некоторые примеры оператора варианта:
case Operator of
plus: X := X+Y;
minus: X := X-Y;
times: X := X*Y;
end;
case I of
0, 2, 4, 6, 8: Writeln('Четная цифра');
1, 3, 5, 7, 9: Writeln('Нечетная цифра');
10..100: Writeln('Между 10 и 100');
end;
Оператор цикла
Оператор цикла задает повторное выполнение определенных опе-
раторов.
------------------¬
оператор цикла ---T-->¦ оператор repeat +------>
¦ L------------------ ^
¦ ------------------¬ ¦
+-->¦ оператор while +--+
¦ L------------------ ¦
¦ ------------------¬ ¦
L-->¦ оператор for +---
L------------------
Если число повторений заранее известно, то подходящей конс-
трукций является оператор for. В противном случае следует исполь-
зовать операторы while или repeat.
Для управления повторением операторов можно использовать
стандартные процедуры Break и Continue. Break завершает оператор
цикла, а Continue продолжает со следующей итерации этого операто-
ра. Подробности вы можете найти в Главе 1 "Справочного руководс-
тва программиста".
Оператор цикла с постусловием (repeat)
В операторе цикла с постусловием (начинающимся со слова
repeat) выражение, которое управляет повторным выполнением после-
довательности операторов содержится внутри оператора repeat.
-------¬ ---------¬ ------¬ ----------¬
оператор ->¦repeat+---->¦оператор+--T->¦until+-->¦выражение+-->
repeat L------- ^ L--------- ¦ L------ L----------
¦ ----¬ ¦
L----+ ; ¦<-----
L----
Результат выражения должен быть булевского типа. Операторы,
заключенные между ключевыми словами repeat и until, выполняются
последовательно до тех пор, пока результат выражения не примет
значение True. Последовательность операторов выполнится по край-
ней мере один раз, поскольку вычисление выражения производится
после каждого выполнения последовательности операторов.
Приведем примеры оператора цикла с постусловием:
repeat
K := I mod J;
I := J;
J := K;
until J = 0;
repeat
Write('Введите значение (0..9):');
Readln(I);
until (I >= 0) and (I <= 9);
Операторы цикла с предусловием (while)
-----------------------------------------------------------------
Оператор цикла с предусловием (начинающийся с ключевого сло-
ва while) содержит в себе выражение, которое управляет повторным
выполнением оператора (который может быть составным оператором).
------¬ ----------¬ ---¬ ---------¬
оператор --->¦while+-->¦выражение+-->¦do+-->¦оператор+-->
while L------ L---------- L--- L---------
Выражение, с помощью которого осуществляется управление пов-
торением оператора, должно иметь булевский тип. Вычисление его
производится до того, как внутренний оператор будет выполнен.
Внутренний оператор выполнятся повторно до тех пор, пока выраже-
ние принимает значение Тruе. Если выражение с самого начала при-
нимает значение False, то оператор, содержащийся внутри оператора
цикла с предусловием, не выполняется.
Примерами операторов цикла с предусловием могут служить сле-
дующие операторы:
while Data[I] <> X do I := I + 1;
While I > 0 do
begin
if Odd(I) then Z := Z * X;
I := I div 2;
X := Sqr(X);
end;
while not Eof(InFile) do
begin
Readln(InFile,Line);
Process(Line);
end;
Операторы цикла с параметром (for)
Операторы цикла с параметром (которые начинаются со слова
for) вызывает повторяющееся выполнение оператора (который может
быть составным оператором) пока управляющей переменной присваива-
ется возрастающая последовательность значений.
----¬ ------------¬ ---¬ ---------¬
оператор --->¦for+-->¦управляющая+-->¦:=+-->¦исходное+---¬
for L---- ¦переменная ¦ L--- ¦значение¦ ¦
L------------ L--------- ¦
--------------------------------------------------
¦ ---¬
¦ -->¦to+-----¬ ---------¬ ---¬ ---------¬
L---+ L--- +-->¦конечное+-->¦do+-->¦оператор+--->
¦ -------¬ ¦ ¦значение¦ L--- L---------
L->¦downto+-- L---------
L-------
-------------------------¬
управляющая переменная --->¦идентификатор переменной+--->
L-------------------------
----------¬
исходное значение ---->¦выражение+--->
L----------
----------¬
конечное значение ---->¦выражение+--->
L----------
В качестве управляющей переменной должен использоваться
идентификатор переменой (без какого-либо квалификатора), который
обозначает переменную, объявленную локальной в блоке, в котором
содержится оператор for. Управляющая переменная должна иметь пе-
речислимый тип. Начальное и конечное значения должны иметь тип,
совместимый по присваиванию с перечислимым типом.
Примечание: О локальности и области действия рассказы-
вается в Главе 8.
Когда начинает выполняться оператор for, начальное и конеч-
ное значения определяются один раз, и эти значения сохраняются на
протяжении всего выполнения оператора for.
Оператор, который содержится в теле оператора for, выполня-
ется один раз для каждого значения в диапазоне между начальным и
конечным значением. Управляющая переменная всегда инициализирует-
ся начальным значением. Когда работает оператор for, значение уп-
равляющей переменной (счетчика циклов) увеличивается при каждом
повторении на единицу. Если начальное значение превышает конечное
значение, то содержащийся в теле оператора for оператор не выпол-
нятся. Когда в операторе цикла используется ключевое слово
downto, значение управляющей переменной уменьшается при каждом
повторении на единицу. Если начальное значение в таком операторе
меньше, чем конечное значение, то содержащийся в теле оператора
цикла оператор не выполнятся.
Если оператор, содержащийся в теле оператора for, изменяет
значение управляющей переменной, то это является ошибкой. После
выполнения оператора for значение управляющей переменной стано-
вится неопределенным, если только выполнение оператора for не бы-
ло прервано с помощью оператора перехода.
Если принять во внимание эти ограничения, то оператор
for V := Expr1 to Expr2 do Body;
эквивалентен оператору:
begin
Temp1 := Expr1;
Temp2 := Expr2;
if Temp1 <= Temp2 then
begin
V := Temp1;
Body;
while V <> Temp2 do
begin
V := Succ(V);
Body;
end;
end;
end;
и оператор цикла:
for V := Expr1 downto Exp2 do Body;
эквивалентен операторам:
begin
Temp1 := Expr1;
Temp2 := Expr2;
if Temp1 >= Temp2 then
begin
V := Temp1;
Body;
while V <> Temp2 o
begin
V := Pred(V);
Body;
end;
end;
end;
где Temp1 и Temp2 - вспомогательные переменные, тип которых сов-
падает с основным типом переменной V и которые не встречаются в
другом месте программы.
Приведем примеры оператора цикла с параметром:
for I := 2 to 63 do
if Data[I] > Max then Max := Data[I]
for I := 1 to 10 do
for J := 1 to 10 do
begin
X := 0;
for K := 1 to 10 do
X := X + Mat1[I,K]*Mat2[K,J];
Mat[I,J] := X;
end;
for C := red to blue do Check(C);
Оператор with
В операциях над записями оператор with удобно использовать
для краткого обращения к полям записи. В операторе with к полям
одной или более конкретных переменных типа запись можно обращать-
ся, используя только идентификаторы полей. Оперaтор with имеет
следующий синтаксис:
-----¬ ----------------¬ ---¬ ---------¬
оператор -->¦with+----->¦ ссылка на +--T->¦do+-->¦оператор+>
with L----- ^ ¦переменную типа¦ ¦ L--- L---------
¦ ¦ запись ¦ ¦
¦ ¦ или объект ¦ ¦
¦ L---------------- ¦
¦ ----¬ ¦
L--------+ , ¦<---------
L----
ссылка на переменную ---------------------¬
типа запись или объект --->¦ссылка на переменную+-->
L---------------------
Возьмем следующее описание:
type
TDate = record
Day : Integer:
Month : Integer;
Year : Integer:
end;
var OrderDate: TDate;
С учетом данного описания приведем пример оператора with:
with OrderDate do
if Month = 12 then
begin
Month := 1;
Year := Year + 1
end else
Month := Month + 1;
Это эквивалентно следующему:
if OrderDate.Month = 12 then
begin
OrderDate.Month := 1;
OrderDate.Year := TDate.Year + 1
end
else
Date.month := TDate.Month + 1;
В операторе with сначала производится проверка каждой ссылки
на переменную, а именно: можно ли ее интерпретировать, как поле
записи. Если это так, то она всегда интерпретируется именно таким
образом, даже если имеется доступ к переменной с тем же именем.
Допустим описаны следующие переменные:
type
TPoint = record
x,y: Integer;
end;
var
x: Point;
y: Integer;
В этом случае и к x, и к y можно обращаться, как к перемен-
ной или как к полю записи. В операторе:
with x do
begin
x := 10;
y := 25;
end;
x между ключевыми словами with и dо относится к переменной типа
указатель, а в составном операторе x и y ссылаются на x.x и y.y.
Оператор:
with V1,V2,...Vn do s;
эквивалентен операторам:
with V1 do
with V2 do
...
with Vn do
S;
В обоих случаях, если Vn является полем и v1, и v2, то она
интерпретируется как v2.Vn, а не как v1.Vn.
Если выборка переменной типа запись связана с индексировани-
ем массива или разыменованием указателя, то эти действия произво-
дятся до того, как будет выполняться составной оператор.
Назад | Содержание | Вперед