- •Часть I. Язык Borland Pascal...................................12
- •Глава 1. Что такое программа Borland Pascal?...................12
- •Глава 2. Лексемы...............................................22
- •Глава 3. Константы.............................................32
- •Глава 4. Типы..................................................34
- •Глава 5. Переменные и типизированные константы.................72
- •Глава 6. Выражения.............................................93
- •Глава 7. Операторы............................................117
- •Глава 8. Блоки, локальность и область действия................133
- •Глава 9. Процедуры и функции..................................139
- •Глава 10. Программы и модули..................................170
- •Глава 11. Динамически компонуемые библиотеки..................180
- •Глава 12. Библиотеки исполняющей системы......................194
- •Глава 13. Стандартные процедуры и функции.....................199
- •Глава 14. Ввод и вывод........................................215
- •Глава 15. Использование сопроцессора 80x87....................248
- •Глава 16. Модуль Dоs..........................................259
- •Глава 17. Программирование в защищенном режиме dos............270
- •Глава 18. Строки с завершающим нулем..........................297
- •Глава 19. Использование графического интерфейса Borland.......308
- •Глава 20. Использование оверлеев..............................329
- •Часть III. В среде Borland Pascal.............................348
- •Глава 21. Использование памяти................................348
- •Глава 22. Вопросы управления..................................388
- •Глава 23. Автоматическая оптимизация..........................405
- •Часть IV. Использование Borland Pascal с языком ассемблера....411
- •Глава 24. Встроенный ассемблер................................411
- •Глава 25. Компоновка с программами на языке ассемблера........437
- •Часть II "Библиотеки исполняющей системы" содержит информа-
- •Часть I. Язык Borland Pascal
- •Глава 1. Что такое программа Borland Pascal?
- •Глава 2. Лексемы
- •Глава 3. Константы
- •Глава 4. Типы
- •Глава 5. Переменные и типизированные константы
- •Глава 6. Выражения
- •Глава 7. Операторы
- •Глава 8. Блоки, локальность и область действия
- •Глава 9. Процедуры и функции
- •Глава 10. Программы и модули
- •Глава 11. Динамически компонуемые библиотеки
- •Часть II. Глава 12. Библиотеки исполняющей системы
- •Глава 13. Стандартные процедуры и функции
- •Глава 14. Ввод и вывод
- •Глава 15. Использование сопроцессора 80x87
- •Глава 16. Модуль Dоs
- •Глава 17. Программирование в защищенном режиме dos
- •Глава 18. Строки с завершающим нулем
- •Глава 19. Использование графического интерфейса Borland
- •Глава 20. Использование оверлеев
- •Часть III. В среде Borland Pascal
- •Глава 21. Использование памяти
- •Глава 22. Вопросы управления
- •Глава 23. Автоматическая оптимизация
- •Часть IV. Использование Borland Pascal с языком ассемблера
- •Глава 24. Встроенный ассемблер
- •Глава 25. Компоновка с программами на языке ассемблера
Глава 7. Операторы
─────────────────────────────────────────────────────────────────
Операторы описывают те алгоритмические действия, которые
должны выполняться. Операторам могут предшествовать метки, кото-
рые можно использовать для ссылок в операторах перехода goto.
оператор ──┬────────────────────┬──────────────────────────>
│ ┌─────┐ ┌───┐ ^ │ ┌────────────────┐ ^
└─>│метка├──>│ : ├─┘ ├──>│простой оператор├──┤
└─────┘ └───┘ │ └────────────────┘ │
│ ┌────────────────┐ │
└──>│ структурный ├──┘
│ оператор │
└────────────────┘
Метка - это последовательность цифр в диапазоне от 0 до 9999
или идентификатор.
Существует два основных вида операторов: простые операторы и
структурные операторы.
Простые операторы
─────────────────────────────────────────────────────────────────
Простым оператором является такой оператор, который не со-
держит в себе других операторов.
┌─────────────────────┐
простой оператор ────┬───>│оператор присваивания├───────>
│ └─────────────────────┘ ^
│ ┌─────────────────────┐ │
├───>│ оператор процедуры ├───┤
│ └─────────────────────┘ │
│ ┌─────────────────────┐ │
└───>│ оператор перехода ├───┘
└─────────────────────┘
B.Pascal 7 & Objects/LR - 118 -
Оператор присваивания
─────────────────────────────────────────────────────────────────
Оператор присваивания заменяет текущее значение переменной
новым значением, которое определяется выражением, или определяет
выражение, значение которого должно возвращаться функцией.
┌───────────┐ ┌──┐ ┌─────────┐
оператор ─────┬──>│ссылка на ├──────>│:=├──>│выражение├──>
присваивания │ │переменную │ ^ └──┘ └─────────┘
│ └───────────┘ │
│ ┌─────────────┐ │
└──>│идентификатор├─┘
│ функции │
└─────────────┘
Выражение должно быть совместимо по присваиванию с типом пе-
ременной или типом значения, возвращаемого функцией в качестве
результата (см. раздел "Совместимость типов" в Главе 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 можно опустить.
B.Pascal 7 & Objects/LR - 119 -
Операторы процедуры
─────────────────────────────────────────────────────────────────
Оператор процедуры определяет активизацию процедуры, обозна-
ченную с помощью идентификатора процедуры. Если соответствующее
описание процедуры содержит список формальных параметров, то опе-
ратор процедуры должен содержать в себе соответствующий ему спи-
сок фактических параметров (параметры, список которых приводится
в определении, являются формальными параметрами, а в операторе
вызова процедуры они являются фактическими параметрами). При вы-
зове происходит передача фактических параметров формальным пара-
метрам.
┌─────────────┐
оператор ──┬─>│идентификатор├─┬┬──────────────────────────>
процедуры │ │ процедуры │ ││ ┌──────────────────┐ ^
│ └─────────────┘ │└─>│список фактических├─┘
│ ┌─────────────┐ │ │ параметров │
├─>│ десигнатор ├─┤ └──────────────────┘
│ │ метода │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
├─>│ уточненный ├─┤
│ │ десигнатор │ │
│ │ метода │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
└─>│ ссылка на ├─┘
│ переменную │
└─────────────┘
Приведем некоторые примеры операторов процедур:
PrintHeaing;
Transpose(A,N,M);
Fin(Name,Address);
B.Pascal 7 & Objects/LR - 120 -
Операторы перехода
─────────────────────────────────────────────────────────────────
Оператор перехода goto вызывает передачу управления операто-
ру, которому предшествует метка, указанная в данном операторе пе-
рехода. Синтаксическая схема оператора перехода имеет следующий
вид:
┌────┐ ┌─────┐
оператор перехода ───>│goto├───>│метка├───>
└────┘ └─────┘
При использовании оператора перехода должны соблюдаться сле-
дующие правила:
1. Метка, которая указывается в операторе перехода, должна
находиться в том же блоке или модуле, что и сам оператор
перехода. Другими словами, не допускаются переходы из
процедуры или функции или внутрь нее.
2. Переход извне внутрь структурного оператора (то есть пе-
реход на более глубокий уровень вложенности) может выз-
вать непредсказуемые эффекты, хотя компилятор не выдает
сообщения об ошибке. Например, вы не должны переходить в
тело цикла for.
Примечание: Хорошая практика программирования требует
минимального использования переходов.
Структурные операторы
─────────────────────────────────────────────────────────────────
Структурные операторы строятся из других операторов, порядок
выполнения которых должен быть последовательным (составные опера-
торы и операторы над записями), определяемым условной передачей
управления (условные операторы) или повторяющимся (операторы цик-
ла).
┌───────────────────────┐
структурный ────┬────>│ составной оператор ├───────>
оператор │ └───────────────────────┘ ^
│ ┌───────────────────────┐ │
├────>│ условный оператор ├───┤
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
├────>│ оператор цикла ├───┤
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
└────>│ оператор над записями ├───┘
└───────────────────────┘
B.Pascal 7 & Objects/LR - 121 -
Составные операторы
─────────────────────────────────────────────────────────────────
Составные операторы задают порядок выполнения операторов,
являющихся их элементами. Они должны выполняться в том порядке, в
котором они записаны. Составные операторы обрабатываются, как
один оператор, что имеет решающее значение там, где синтаксис
Паскаля допускает использование только одного оператора. Операто-
ры заключаются в ограничители begin и end, и отделяются друг от
друга точкой с запятой.
┌─────┐ ┌────────┐ ┌───┐
составной ────>│begin├──────>│оператор├────┬──>│end├──>
оператор └─────┘ ^ └────────┘ │ └───┘
│ ┌───┐ │
└─────┤ ; │<──────┘
└───┘
Приведем пример составного оператора:
begin
Z := X;
X := Y;
Y := Z;
end;
Условные операторы
─────────────────────────────────────────────────────────────────
Условные операторы позволяют выбрать для выполнения один из
составных операторов (или не выбрать ни одного).
┌───────────────┐
условный оператор ──┬──>│ оператор if ├───────>
│ └───────────────┘ ^
│ ┌───────────────┐ │
└──>│ оператор case ├───┘
└───────────────┘
B.Pascal 7 & Objects/LR - 122 -
Оператор условия (if)
─────────────────────────────────────────────────────────────────
Синтаксис оператора if можно представить следующим образом:
┌──┐ ┌─────────┐ ┌────┐ ┌────────┐
оператор if ─>│if├──>│выражение├──>│then├──>│оператор├──┬──┐
└──┘ └─────────┘ └────┘ └────────┘ │ │
┌────────────────────────┘ │
│ ┌────┐ ┌────────┐ v
└──>│else├──>│оператор├─────────>
└────┘ └────────┘
В выражении должен получаться результат, имеющий стандартный
булевский тип. Если результатом выражения является истинное зна-
чение (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;
B.Pascal 7 & Objects/LR - 123 -
Оператор варианта (case)
─────────────────────────────────────────────────────────────────
Оператор варианта (casе) состоит из выражения (переключате-
ля) и списка операторов, каждому из которых предшествует одна или
более констант (они называются константами выбора) или ключевое
слово else. Переключатель (селектор) должен иметь порядковый тип
(размером в байт или слово). Таким образом, строковый тип и длин-
ный целый тип являются недопустимыми типами переключателя. Все
константы выбора должны быть уникальными и иметь порядковый тип,
совместимый с типом переключателя.
┌────┐ ┌─────────┐ ┌──┐ ┌────┐
оператор case ─>│case├──>│выражение├──>│of├─────>│case├──┬──┐
└────┘ └─────────┘ └──┘ ^ └────┘ │ │
│ ┌────┐ │ │
└───┤ ; │<─┘ │
└────┘ │
┌───────────────────────────────────────┘
│ ┌───┐
└─┬────────────────────┬──────────>│end├──>
│ ┌──────────┐ ^ │ ┌───┐ ^ └───┘
└──>│ветвь else├──┘ └─>│ ; ├──┘
└──────────┘ └───┘
┌────────────────────┐
┌─────────┐ │ ┌──┐ ┌─────────┐ v ┌───┐ ┌────────┐
case ──>│константа├─┴─>│..├─>│константа├──┬─>│ : ├─>│оператор├─>
^ └─────────┘ └──┘ └─────────┘ │ └───┘ └────────┘
│ ┌───┐ │
└─────────────────┤ , │<─────────────┘
└───┘
┌────┐ ┌────────┐
ветвь else ────>│else├───>│оператор├───>
└────┘ └────────┘
Оператор варианта case приводит к выполнению оператора, ко-
торому предшествует константа выбора, равная значению переключа-
теля или диапазону выбора, в котором находится значение переклю-
чателя. Если такой константы выбора или такого диапазона выбора
не существует и присутствует ветвь else, то выполнятся оператор,
следующий за ключевым словом else. Если же ветвь else отсутству-
ет, то никакой оператор не выполняется.
B.Pascal 7 & Objects/LR - 124 -
Приведем некоторые примеры оператора варианта:
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;
B.Pascal 7 & Objects/LR - 125 -
Оператор цикла
─────────────────────────────────────────────────────────────────
Оператор цикла задает повторное выполнение определенных опе-
раторов.
┌─────────────────┐
оператор цикла ───┬──>│ оператор repeat ├──────>
│ └─────────────────┘ ^
│ ┌─────────────────┐ │
├──>│ оператор while ├──┤
│ └─────────────────┘ │
│ ┌─────────────────┐ │
└──>│ оператор for ├──┘
└─────────────────┘
Если число повторений заранее известно, то подходящей конс-
трукций является оператор for. В противном случае следует исполь-
зовать операторы while или repeat.
Для управления повторением операторов можно использовать
стандартные процедуры Break и Continue. Break завершает оператор
цикла, а Continue продолжает со следующей итерации этого операто-
ра. Подробности вы можете найти в Главе 1 "Справочного руководс-
тва программиста".
Оператор цикла с постусловием (repeat)
─────────────────────────────────────────────────────────────────
В операторе цикла с постусловием (начинающимся со слова
repeat) выражение, которое управляет повторным выполнением после-
довательности операторов содержится внутри оператора repeat.
┌──────┐ ┌────────┐ ┌─────┐ ┌─────────┐
оператор ─>│repeat├────>│оператор├──┬─>│until├──>│выражение├──>
repeat └──────┘ ^ └────────┘ │ └─────┘ └─────────┘
│ ┌───┐ │
└────┤ ; │<────┘
└───┘
Результат выражения должен быть булевского типа. Операторы,
заключенные между ключевыми словами repeat и until, выполняются
последовательно до тех пор, пока результат выражения не примет
значение True. Последовательность операторов выполнится по край-
ней мере один раз, поскольку вычисление выражения производится
после каждого выполнения последовательности операторов.
B.Pascal 7 & Objects/LR - 126 -
Приведем примеры оператора цикла с постусловием:
repeat
K := I mod J;
I := J;
J := K;
until J = 0;
repeat
Write('Введите значение (0..9):');
Readln(I);
until (I >= 0) and (I <= 9);
B.Pascal 7 & Objects/LR - 127 -
Операторы цикла с предусловием (while)
─────────────────────────────────────────────────────────────────
Оператор цикла с предусловием (начинающийся с ключевого сло-
ва while) содержит в себе выражение, которое управляет повторным
выполнением оператора (который может быть составным оператором).
┌─────┐ ┌─────────┐ ┌──┐ ┌────────┐
оператор ───>│while├──>│выражение├──>│do├──>│оператор├──>
while └─────┘ └─────────┘ └──┘ └────────┘
Выражение, с помощью которого осуществляется управление пов-
торением оператора, должно иметь булевский тип. Вычисление его
производится до того, как внутренний оператор будет выполнен.
Внутренний оператор выполнятся повторно до тех пор, пока выраже-
ние принимает значение Т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;
B.Pascal 7 & Objects/LR - 128 -
Операторы цикла с параметром (for)
─────────────────────────────────────────────────────────────────
Операторы цикла с параметром (которые начинаются со слова
for) вызывает повторяющееся выполнение оператора (который может
быть составным оператором) пока управляющей переменной присваива-
ется возрастающая последовательность значений.
┌───┐ ┌───────────┐ ┌──┐ ┌────────┐
оператор ───>│for├──>│управляющая├──>│:=├──>│исходное├───┐
for └───┘ │переменная │ └──┘ │значение│ │
└───────────┘ └────────┘ │
┌────────────────────────────────────────────────┘
│ ┌──┐
│ ┌─>│to├─────┐ ┌────────┐ ┌──┐ ┌────────┐
└───┤ └──┘ ├──>│конечное├──>│do├──>│оператор├───>
│ ┌──────┐ │ │значение│ └──┘ └────────┘
└─>│downto├─┘ └────────┘
└──────┘
┌────────────────────────┐
управляющая переменная ───>│идентификатор переменной├───>
└────────────────────────┘
┌─────────┐
исходное значение ────>│выражение├───>
└─────────┘
┌─────────┐
конечное значение ────>│выражение├───>
└─────────┘
В качестве управляющей переменной должен использоваться
идентификатор переменой (без какого-либо квалификатора), который
обозначает переменную, объявленную локальной в блоке, в котором
содержится оператор for. Управляющая переменная должна иметь пе-
речислимый тип. Начальное и конечное значения должны иметь тип,
совместимый по присваиванию с перечислимым типом.
Примечание: О локальности и области действия рассказы-
вается в Главе 8.
Когда начинает выполняться оператор for, начальное и конеч-
ное значения определяются один раз, и эти значения сохраняются на
протяжении всего выполнения оператора for.
Оператор, который содержится в теле оператора for, выполня-
ется один раз для каждого значения в диапазоне между начальным и
конечным значением. Управляющая переменная всегда инициализирует-
ся начальным значением. Когда работает оператор for, значение уп-
равляющей переменной (счетчика циклов) увеличивается при каждом
повторении на единицу. Если начальное значение превышает конечное
значение, то содержащийся в теле оператора for оператор не выпол-
B.Pascal 7 & Objects/LR - 129 -
нятся. Когда в операторе цикла используется ключевое слово
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;
B.Pascal 7 & Objects/LR - 130 -
где 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);
B.Pascal 7 & Objects/LR - 131 -
Оператор with
─────────────────────────────────────────────────────────────────
В операциях над записями оператор with удобно использовать
для краткого обращения к полям записи. В операторе with к полям
одной или более конкретных переменных типа запись можно обращать-
ся, используя только идентификаторы полей. Оперaтор with имеет
следующий синтаксис:
┌────┐ ┌───────────────┐ ┌──┐ ┌────────┐
оператор ──>│with├─────>│ ссылка на ├──┬─>│do├──>│оператор├>
with └────┘ ^ │переменную типа│ │ └──┘ └────────┘
│ │ запись │ │
│ │ или объект │ │
│ └───────────────┘ │
│ ┌───┐ │
└────────┤ , │<────────┘
└───┘
ссылка на переменную ┌────────────────────┐
типа запись или объект ───>│ссылка на переменную├──>
└────────────────────┘
Возьмем следующее описание:
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;
B.Pascal 7 & Objects/LR - 132 -
В операторе 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.
Если выборка переменной типа запись связана с индексировани-
ем массива или разыменованием указателя, то эти действия произво-
дятся до того, как будет выполняться составной оператор.
B.Pascal 7 & Objects/LR - 133 -
───────────────────────────────────────────────────────────────────────