В этой статье ознакомимся с общей структурой программы на языке Паскаль. Это необходимо, чтобы понимать как собственно организована программа на Паскале, с чего ее обязательно начинать, какими командами заканчивать и т.д. Итак, в состав любой программы на Паскале входит:
Заголовок - это имя программы.
Пример:
program Proga;
Раздел описаний содержит в себе следующие разделы:
1) раздел подключаемых модулей (библиотек), определяющийся через служебное слово uses. Данный раздел включает имена подключаемых модулей (библиотек), которые либо написаны пользователем, либо уже содержаться в системе Turbo Pascal. Раздел uses должен находится в самом начале раздела описаний (помните об этом). Имена библиотек и модулей разделяются запятыми.
Пример:
uses Graph,Math,CRT;
2) в разделе описания меток должны быть перечислены все метки, которые пользователь использует в программе. При этом любой оператор мы можем пометить меткой, имя которой задается по правилам образования идентификаторов в Турбо Паскаль. Метками могут быть любые числа, но только без знака, содержащие не более 4-х цифр. Метка всегда устанавливается перед оператором и отделена от него двоеточием.
Пример:
label 5, 342, 75, metka;
3) раздел описания констант дает возможность использовать имена в качестве синонимов констант.
Пример:
const y = 14; min = 456;
4) В разделе описания переменных var указываются все переменные (определяя их тип), которые впоследствии будут использованы в программе.
Пример:
var t,w,k: integer;
m,n: char;
l,p: boolean;
Что же касается описания типов, процедур и функций, то это будет изучено в дальнейшем, а пока, рассмотрим еще один раздел - раздел операторов.
Раздел операторов - это ничто иное как составной оператор, содержащий между служебными словами begin и end последовательность неких операторов, которые разделяются символом ";". Исходный текст программы оканчивается символом ".".
Внизу представлена программа, вычисляющая сумму 2-х чисел:
program Summa; {в этом разделе называем нашу программу именем Summa}
uses Crt; {подключение модуля для очистки экрана и задержки}
var {раздел описания переменных, определяем их тип}
x1,x2,sum: integer;
begin
clrscr; {очищаем экран}
writeLn('Вводим два числа: ');
readLn(x1,x2);
sum:= x + y;
writeLn('Сумма чисел x1 и x2 равна ',sum);
readkey; {ожидание нажатия клавиши}
end.
Исходник программы на Паскале может содержать ключи компиляции, с помощью которых можно управлять процессом компиляции. Ключ компиляции представляются в виде комментариев; содержит символ "$" с буквой ключом с последующим знаком"-" (т.е. выключить режим) или "+" (т.е. включить режим).
Пример:
{$F+} - формировать дальний тип вызова процедур и функций;
{$R+} - проверять выход за границы диапазонов.
Можно также включить в текст компилируемой программы какой-то файл. Это достигается с помощью ключа компиляции {$I имя подключаемого файла}.
7…
Директивы компилятора Почему-то мало кто пользуется директивами компилятора в полном масштабе... Еще {$M} {$N} {$E} {$I} приходится видеть, но вот такие: {$ifdef}...{$else}...{$endif} - почти никогда; несмотря на то, что они открывают довольно широкие возможности для программиста, а именно: позволяют писать код, успешно компилируемый на разных компиляторах Паскаля, в том числе и 32 битных, включая FPC и TMT.
Еще одно удобство на мой взгяд - широкие возможности при отладке приложений.
Общий синтаксис этих команд таков: {$define <условный_символ>} - установить условный_символ. {$ifdef <условный_символ>} - код следующий после этой директивы компилируется только в том случае, если условный_символ был установлен. {$else} - эта директива обозначает начало альтернативного участка кода. {$endif} - ограничивает действие директив {$ifdef} и {$else}.
Режимы компиляции. Отладка. Предположим, что в программе необходимо на этапе отладки выводить какие-то данные для тестирования алгоритма... Можно, конечно, в окончательном варианте кода закомментировать такие отладочные выводы, или удалить, но лучше заключить "отладочные операторы" в такую конструкцию, с использованием директив:
Код
{$define debug} var x:byte; begin x:=1; inc(x); {$ifdef debug} writeln(x); {$endif} end.
Таким образом, при работе программы на экран будет выведено значение "2". Если отладку надо отменить, мы можем убрать символ "$" из директивы {$define debug} - и теперь это будет просто коментарий, и следовательно на экран ничего не будет выведено.
Универсальность кода Хорошо, когда мы берем старый код из TP и он компилируется, и программа правильно работает в компиляторе постарше... А почему бы не реализовать совместимость наоборот или напрямую? Часто при компиляции, возникают ошибки только из-за того, что код оптимизирован под конкретный компилятор, например под BP, и в TP отказывается компилироваться... Выходом из такой ситуации является правильное написание кода, а именно отладка кода под различные компиляторы (конечно если это требуется). Для примера рассмотрим программу для построения графиков некоторых функций (в полярной системе координат) скачать архив
{$ifdef Win32}
{$APPTYPE GUI}
{$else}
{$E+} {$N+}
{$endif}
Uses
{$ifdef Win32}
WinCrt,Windows,
{$else}
CRT,
{$endif}
Graph;
Var{GLOBAL}
Gd,Gm:Integer;
a,b:Longint;
g:byte;
Procedure INIT;
Begin
{$ifdef Win32}
gd:=d8bit; gm:=m800x600;
{$else}
gd:=Vga; Gm:=VgaHi;
{$endif}
InitGraph(gd,gm,'');
SetColor(11);
SetBkColor(8);
End; {INIT}
Procedure Graphic;
Function Ro(Fi:Double):Double;
Begin
case g of
1:ro:=fi; {бЇЁа «м аеЁҐ¤ }
2:ro:=Sin(7*fi); {ᥨ«ҐЇҐбвЄ(r)ў п а(r)§ }
3:ro:=1-cos(fi); {Є а¤Ё(r)Ё¤ }
4:ro:=5*cos(fi)+2; {г«ЁвЄ Џ бЄ «п}
5:if cos(2*fi)>=0 then ro:=sqrt(2*cos(2*fi)); {‹ҐЁбЄ в ЃҐаг««Ё}
end;
end;
Const
c=2*pi; step=0.0005;
r=220;
{$ifdef Win32}
x0=400; y0=300;
{$else}
x0=320; y0=220;
{$endif}
Var
k,max,fi:Double;
Begin
fi:=0; max:=0.0001;
Repeat
if max<abs(ro(fi)) then max:=abs(ro(fi));
fi:=fi+0.01
until fi>c;
fi:=0;
Repeat
k:=ro(fi)/max;
if k<1 then putpixel(x0+Round(r*cos(a*fi)*k),
y0+Round(r*sin(b*fi)*k),15);
If Keypressed then Exit else fi:=fi+step
until fi>c
end; {graphic}
Begin
INIT;
Repeat
clearViewPort;
Outtextxy(20,14,'Case graphic:');
Outtextxy(20,22,'1. Spiral Arhimeda');
Outtextxy(20,30,'2. seeds petal rose');
Outtextxy(20,38,'3. Kardioida');
Outtextxy(20,46,'4. Snail Pascal');
Outtextxy(20,54,'5. Lemniskatta Bernuli');
g:=ord(readkey)-48;
a:=5; b:=5;
clearViewPort;
Graphic;
Outtextxy(20,450,'Esc-exit, Enter-repeat')
until readkey=#27;
CloseGraph
end.
Этот код можно скомпилировать вот в этих компиляторах: FPC(target: Win32, DOS), TP7, BP7, BPW (target:real, protected mode), TMT. Неплохо, правда? И везде он будет работать одинаково правильно! Конечно при компиляции в FPC под Win32, это будет windows приложение, а в остальных случаях консольное DOS (16 битное) приложение... Прокоментирую первые строчки программы (а дальше я думаю все понятно)
Код
{$ifdef Win32} {- если компилируем под Win32 } { (это срабтает только в FPC, TMT)} {$APPTYPE GUI} {- режим компиляции: графическое windows приложение.} {$else} {- компилируем в 16 битных компиляторах.} {$E+} {$N+} {-включаем эмуляцию сопсроцессора, т.к. в } { программе используются тип double} {$endif} {-конец условного участка кода.} Uses {$ifdef Win32} {-если компилируем под Win32 } WinCrt,Windows,{ подключаем соотв. модули.} {$else} {- иначе компиляция в 16 битных компиляторах} CRT, {$endif} {- конец условного куска кода.} Graph; {- а этот модуль подключается в любом случае.}
Эмуляция сопроцессора Очень часто у многих возникает вопрос - почему при компиляции у меня возникает ошибка Error 116: Must be in 8087 mode to compile this. Ответ: Вы используете один из следующих вещественных типов: Single, Double, Extended, Comp Для работы с этими типами, необходима эмуляция сопроцессора. Просто добавьте в начало программы директивы: {$E+, $N+}
Оптимизация Для уменьшения размера программ желательно добавить следующие директивы: {$B-} - быстрое вычисление логических условий;
Но с оптимизацией будьте очень осторожны !! Например, вот такой пример будет компилироваться, но выдаст неверный результат (попробуйте запустить программу без ключей {$B-} и {$B+}...):
Код
var x, y: integer;
function do_it: boolean; begin x := 5; { Здесь меняется значение глобальной переменной } do_it := true; end;
begin x := 2; {$B-} if (x > 5) and do_it then y := x else y := 2 * x; {$B+}
{ При "быстром" вычислении логических условий результат будет неверный } writeln('y = ', y); writeln('x = ', x) end.
Добавлено: Volvo
{$D-} - отключить информацию для отладки (пропадает возможность отлаживать программу!!! (через F7)). При этом размер сократится на 100-150 байт...