Введение
Любые данные, т. е. константы, переменные и выражения, в Object Pascal характеризуются
своими типами.
Тип определяет множество допустимых значений, которые может иметь тот или иной объект,
а также множество допустимых операций применимых к нему. Кроме того, тип определяет
формат внутреннего представления данных в памяти компьютера.
Язык Object Pascal поддерживают строгую типизацию данных. Всем переменным и
константам в программе обязательно сопоставлены типы и компилятор строго отслеживает
чтобы операции совершаемые над переменными соответствовали их типу. Например, для
следующего выражения компилятор сгенерирует ошибку.
var x, y, z:integer;
...
x:=y/z;
Тип результата после вычисления выражения будет вещественным, а переменная в которую
должен быть записан результат, имеет целочисленный тип, поэтому компилятор сгенерирует
ошибку.
Описание типов
Все типы делятся на две группы: встроенные и пользовательские. К встроенным типам
относятся такие простые типы как Integer, Real и др. Пользовательские типы строятся на
основе встроенных. К пользовательским типам данных относятся: тип диапазон,
перечисляемый тип. К пользовательским типам данных также относятся все структурные
типы: множество, массив, запись, файл (будут рассмотрены в последующих лабораторных
работах).
Как уже было сказано выше, тип указывается при описании переменных, например
var x: real;
При создании пользовательского типа можно либо полностью привести его после двоеточия,
либо объявить его отдельно, в секции type, например
type MyReal = real;
var x:MyReal;
В данном примере объявлен псевдоним типа real – MyReal, который эквивалентен типу real.
Целые
Логические
Символьный
Перечисляемый
Тип-диапазон
Рисунок 1 – Простые типы данных
Порядковые типы
Порядковые типы отличаются тем, что каждый из них имеет конечное число возможных
значений. Эти значения можно определенным образом упорядочить и, следовательно,
сопоставить некоторое целое число – порядковый номер значения.
Функции, предназначенные для работы с порядковыми типами, приведены в таблице 1.
Целые типы
Диапазон возможных значений целых типов зависит от их внутреннего представления,
которое может занимать один, два, четыре или восемь байт. В таблице 2 приведены основные
целочисленные типы.
Логические типы
Переменная логического типа может принимать только два значения True (истина) и False
(ложь). Логические типы приведены в таблице 4.
Для работы с логическими типами используйте тип Boolean, остальные типы были
добавлены в Object Pascal для совместимости с программами написанными на других
языках программирования.
Символьный тип
Символьный тип, как следует из его названия, предназначен для хранения кода символа.
Внутренняя структура типа совпадает с внутренней структурой беззнаковых целых чисел.
Object Pascal поддерживает два символьных типа AnsiChar и WideChar. Характеристики
этих типов приведены в таблице 5.
1 В Object Pascal тип Char является основным. В следующих версиях тип Char может стать псевдонимом для
типа WideChar.
function ord(X:char):byte;
Константу символьного типа можно задать двумя способами. Задать символ в одинарных
кавычках или указать код символа. Следующие две записи эквивалентны.
ch:='A';
ch:=#97; //97 – код символа "A".
Например
var ch:char;
code: byte;
begin
ch:='A';
code:=ord(ch);
ch:=chr(32); //32 — соответствует коду клавиши пробел
end.
Перечисляемый тип
Перечисляемый тип задается перечислением тех значений, которые он может получать.
Каждое значение именуется некоторым идентификатором и располагается в списке,
обрамлённом круглыми скобками.
<имя типа> = (id, id, id,...);
Здесь «имя типа» – идентификатор Object Pascal,
«id» – идентификатор Object Pascal.
Например, тип описывающий некоторый фиксированный набор цветов
type TColors = (red, green, white, yellow);
Применение перечисляемых типов делает программы более наглядными и повышает
надежность программ. Пусть определены следующие типы:
type TColors = (red, green, white, yellow);
TDays=(monday, tuesday, wednesday);
Определены переменные
var col:TColors;
day:TDays;
то допустимы следующие операторы
col:=white;
col:=Succ(green);
day:=Pred(tuesday);
но не допустимы
col:=monday;
day:=col;
Максимальное количество перечисляемых значений зависит от реализации. В настоящее
время размер переменной перечисляемого типа равен 4 байта, что соответствует 2 32
различных значений, т. е. во внутреннем представлении перечисляемый тип представляет
собой тип LongWord.
Как говорилось выше, можно поместить определение типа сразу, после двоеточия, например
var col: (red, green, white, yellow);
day: (monday, tuesday, wednesday);
Тип-диапазон
Тип диапазон представляет собой подмножество некоторого базового порядкового типа. Тип-
диапазон задается границами своих значений.
<мин. зн.> .. <макс. зн.>
Например
type TDigits = '0'..'9';
TMonth = 1..12;
TMyColors = green .. yellow;
При задании типа-диапазона следует иметь ввиду, что символы '..' нельзя разделять
пробелами и что левая граница диапазона не должна превышать правую границу.
Вещественные типы
Вещественные типы предназначены для работы с вещественными числами в формате с
плавающей и фиксированной точкой.
Для представления вещественных чисел используются следующие типы приведенные в
таблице 6.
Тип дата-время
Тип дата-время предназначен для хранения даты и времени. Тип дата-время определяется
идентификатором TDateTime и предназначен для одновременного хранения даты и времени.
Во внутреннем представлении переменная этого типа соответствует типу Double. Для работы
с данным типом используются функции приведенные в таблице 73.
2 Начиная с версии Delphi 5.0 тип real соответствует типу double. Для совместимости со старыми
программами введен тип real48 соответствующий типу real из таблицы 6. При использовании директивы
компилятора {$REALCOMPATIBILITY ON} компилятор под типом real будет подразумевать именно тип
real48. По умолчанию {$REALCOMPATIBILITY OFF}
3 Для использования функций из таблицы 7 необходимо подключить модуль SysUtils. (uses SysUtils;)
Подпрограмма Назначение
function DateToStr( Преобразует дату в строку символов
D: TDateTime):string
function DateTimeToStr( Преобразует дату и время в строку символов
D: TDateTime):string;
function Time: TDateTime; Возвращает текущее время
function TimeToStr ( Преобразует время в строку
T: TDateTime):string;
Для использования подпрограмм из таблицы 7 необходимо подключить модуль SysUtils, как
показано ниже.
program Test;
uses SysUtils;
Строковые типы
В Object Pascal определено несколько типов строк, таблица 8.
4 Длина строки ограничивается лишь доступной памятью, для 32 разрядных ОС это 4 Гб (в Windows 2 Гб).
Таблица 95 – Подпрограммы для работы со строками
Подпрограмма Описание
function Copy (Source: string; Копирует из строки Source Count символов,
Index, Count: Integer):string; начиная с символа с номером Index.
procedure Delete ( Удаляет Count символов из строки Source,
var Source: string; начиная с символа с номером индекс.
Index, Count: Integer);
procedure Insert (SubSt: string; Вставляет подстроку SubSt в строку St,
var St: string; начиная с символа с номером Index.
Indext: Integer);
function Length Возвращает текущую длину строки.
(S:string):integer;
function Pos ( Отыскивает в строке St первое вхождение
SubSt, St:string):integer; подстроки SubSt и возвращает номер
позиции с которой она начинается. Если
подстрока не найдена возвращается ноль.
Преобразование типов
При написании программ часто бывает необходимым преобразовать тип переменной.
Близкие типы можно преобразовывать с помощью следующей конструкции.
<идентификатор типа>(<переменная>)
Например преобразование типа переменной Integer к типу Word выглядит следующим
образом
var i: Integer;
j: Word;
...
j:=Word(i);
В таблице 10 приведены стандартные функции преобразования типов.
Приведение типов
Приведение типов – это способность компилятора рассматривать переменную одного типа
как переменную другого типа. В отличие от функций преобразования типов, таких как,
Round, Trunc и т. п при приведении типа не происходит изменения данных, т. е. нет потери
производительности. Приведение типа записывается следующим образом
имя типа(имя переменной)
Например,
var b:Boolean;
begin
b:=True;
writeln(b);
writeln(integer(b));
writeln(Single(integer(b)));
end.
Будет выведено
TRUE
1
1.401298464E-45
Приведение типа используется когда необходимо работать со внутренним
представлением переменной. Это опасная операция и её, по возможности, нужно
избегать. При приведении типа, размер типа должен быть не больше чем
действительный тип переменной.
Операторы
Все операторы условно можно разделить на три группы:
• арифметические операторы,
• логические операторы,
• специальные операторы.
Арифметические операторы
Арифметические операторы применяются при построении арифметических выражений. К
арифметическим операторам относятся +, -, *, /, () и некоторые другие, см. таблицу 13.
Результатом вычисления арифметических операторов является целочисленный или
вещественный тип.
Логические операторы
Логические операторы применяются при вычислении логических выражений. К логическим
операторам относятся >, <, <>, =, in, and, not, or. Результат вычисления логического
выражения имеет логический тип.
Оператор присваивания
Оператор присваивания имеет следующий синтаксис
<идентификатор переменной>:=<выражение>;
Следует отметить, что между символами ":=" недопустимы пробелы. Тип переменной
которой осуществляется присваивание и тип результата вычисления выражения должны
совпадать.
Оператор SizeOf
Этот оператор возвращает размер переменной в байтахю Он имеет следующий синтаксис:
SizeOf(X):Integer;
Здесь X – переменная или имя типа. Оператор возвращает размер переменной заданного типа
в байтах.
Пример:
var i:Integer;
x:real;
i:=SizeOf(x);
...
i:=SizeOf(Single);
Операторы ввода-вывода
Для операций ввода-вывода данных в Object Pascal используется пара операторов read и
write. Эти операторы ввода-вывода универсальны и используются при работе с любыми
устройствами ввода-вывода такими как, клавиатура, консоль, накопители, порты ввода-
вывода и др. Следует также отметить, что эти операторы обрабатываются компилятором
особым образом и поэтому идентификаторы read и write не рекомендуется использовать для
именования собственных объектов.
Оператор write
С помощью оператора write осуществляется вывод данных. По умолчанию устройством
вывода служит консоль. Синтаксис оператора write имеет следующий вид:
write (<выражение>, <выражение>, ... <выражение>);
Выражение может состоять из одной константы или переменной, например
write('x=', x);
Первое выражение равно 'x=' – это строковая константа. Второе выражение равно x. Это
переменная любого простого типа. Следует отметить, что стандартный оператор вывода
может работать с переменными только простых и строковых типов. Оператор write после
вывода не осуществляет перевод курсора на следующую строку. Для того чтобы после
вывода данных курсор переводился на следующую строку необходимо использовать
оператор writeln.
writeln (<выражение>, <выражение>, ... <выражение>);
Оператор writeln без параметров переведет курсор на новую строку.
Операторы write и writeln позволяют производить форматированный вывод. Для этого
применяется расширенная форма операторов.
writeln (<выражение>:Width, ...);
write (<выражение>:Width, ...);
With – определяет общее число символов отведенных на значение. Значение всегда
выводится целиком, даже если оно не помещается в отведенное ему число символов. Эта
возможность бывает полезна вывода таблиц. В этом случае параметр Width задает ширину
колонки в символах. Пример:
Оператор read
С помощью оператора read осуществляется ввод данных. По умолчанию устройством ввода
служит клавиатура. Синтаксис оператора read имеет следующий вид:
read (<переменная>, < переменная >, ... < переменная >);
Оператор read может работать только с переменными простого и строкового типа. При вводе
нескольких переменных с помощью оператора read они должны разделяться пробелом.
После ввода всех переменных необходимо нажать клавишу «Enter». Если «Enter» был нажат
до ввода всех переменных, то курсор будет переведен на следующую строку и, система будет
ожидать ввода оставшихся данных, например
Листинг 5
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}
program InOutPrg;
var x, y, z: Integer;
begin
read(x, y, z);
end.
Попробуйте ввести переменные сначала через пробел, а затем используя клавишу ввод для
каждой переменной. Аналогично оператору write у оператора read существует форма с
переводом на следующую строку после окончания ввода данных.
readln (<переменная>, < переменная >, ... < переменная >);
Оператор readln без параметров приостановит выполнение программы до нажатия клавиши
«Enter».
В листинге 6 приведена программа осуществляющая ввод и вывод данных.
begin
write('Enter first number: ');
read(x1);
write('Enter second number: ');
read(x2);
sum:=x1+x2;
writeln('Summa ', x1, 'and', x2, ' =', sum);
writeln('Press Enter to exit');
readln;
end.
Комментарии в программах
Комментарий это часть текста которая игнорируется компилятором и служит лишь для
описания логики работы программы или других целей. Object Pascal поддерживает два вида
комментариев: однострочные и многострочные.
Однострочные комментарии задаются двумя обратными слешами без пробела (//). Все
символы введенные после этого символа комментария до конца строки считаются
комментарием и не учитываются компилятором, например
writeln('Vvedite n');
readln(n);
x:=n*n+5; //вычисление выражения
Многострочные комментарии могут располагаться на нескольких строках. Символом начала
многострочного комментария является символ «{». Все символы идущие после считаются
комментарием и игнорируются компилятором. Конец комментария отмечается символом «}»,
например
writeln('Vvedite n');
readln(n);
x{здесь будет результат}:=n*n+5;
{это многострочный
комментарий }
Обратите внимание, что многострочный комментарий может находиться внутри
выражения, но не внутри идентификатора.
Директивы компилятора
Если многострочный комментарий начинается с символа ‘$’, то компилятор рассматривает
введенную строку как директиву компилятора
Все директивы условно можно разделить на две группы:
• директивы условной компиляции;
• директивы задающие режимы работы компилятора.
С одной из директив задающих работу компилятора вы уже знакомы – это директива
APPTYPE, которая задает тип создаваемого приложения консольное (значение CONSOLE) или
графическое (GUI). Все директивы задающие режимы работы компилятора делятся на
локальные и глобальные. Глобальные имеют область действия всю программу, их работа не
зависит от местоположения директивы, например директива APPTYPE является глобальной.
Локальные директивы имеют локальную область действия, например директива {$Q},
рассмотренная выше. Её область действия распространяется до строки с такой же
директивой, но с другим значением, например
{$Q+}
{$Q-}
Листинг 7
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}
{$DEFINE DEBUG}
program Dirr;
var j, n, summa :integer;
begin
writeln('Vvedite n');
readln(n);
j:=n+5;
{$IFDEF DEBUG}
writeln('j= ', j);
{$ENDIF}
summa:=n + j;
writeln('summa= ', summa);
readln;
end.
Для того чтобы отменить объявление имени DEBUG необходимо просто стереть символ
«$»(или поставить передним точку или пробел) и компилятор пропустит все символы в
фигурных скобках, т. к. будет считать его комментарием. Код, находящийся между
директивами IFDEF и ENDIF, будет пропущен и не попадет в исполняемый модуль. Для
включения этого кода в программу достаточно просто восстановить символ «$» (стереть
точку).
Кроме директив DEFINE, UNDEF, IFDEF и ENDIF существует еще две директивы условной
компиляции это
IFNDEF <имя>
действие обратное директиве IFDEF, если имя не объявлено, то фрагмент включается в
текст.
ELSE
применяется в паре с директивой IFDEF либо директивой IFNDEF, например
{$IFDEF DEBUG}
если объявлено DEBUG включаем этот фрагмент
{$ELSE}
иначе включаем этот фрагмент
{$ENDIF}
Рассмотрим еще одну часто используемую директиву компилятора. Это директива INCLUDE.
Она не относится к директивам условной компиляции, но часто применяется совместно с
ними.
INCLUDE <имя файла>
В то место где указана эта директива вставляется все содержимое указанного файла.
Допускается сокращенная запись этой директивы {$I <имя файла>}
Поместим в файл с именем deb.inc следующую строку writeln('j= ', j);
Перепишем предыдущий пример в следующем виде
Листинг 8
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}
{$DEFINE DEBUG}
program Dirr;
var j, n, summa :integer;
begin
writeln('Vvedite n');
readln(n);
j:=n+5;
{$IFDEF DEBUG}
{$INCLUDE deb.inc}
{$ENDIF}
summa:=n + j;
writeln('summa= ', summa);
readln;
end.
Эта директива применяется для сокращения листинга или включения часто используемого
кода.
Разберем для чего нужны следующие директивы компилятора в начале каждой программы
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}
Директива MODE переключает Free Pascal в режим совместимости с Delphi. Так как
директивы MODE в Delphi нет, то при попытке откомпилировать программу получим
ошибку – неизвестная директива компилятора. Чтобы этого не происходило поместим эту
директиву между директивами условной компиляции IFDEF и ENDIF. Имя (переменная)
FPC определена в компиляторе Free Pascal и не определена в Delphi, следовательно
компилятор Delphi просто не увидит неизвестную ему директиву MODE, а компилятор
Free Pascal увидит.
Директива APPTYPE задает консольный тип приложения. В Free Pascal по умолчанию
генерируется именно консольное приложение, поэтому ее можно было бы и не указывать, но
в Delphi по умолчанию создается графическое приложение. Поэтому лучше явно указать тип
создаваемого приложения. Таким образом, программы, написанные в лабораторной работе,
можно без правок компилировать как компилятором Free Pascal, так и компилятором Delphi.