Основы Object Pascal (Основы Object Pascal)

Посмотреть архив целиком

А.В. Старков, А.В.Федоров Современные методы программирования

МОСКОВСКИЙ АВИАЦИОННЫЙ ИНСТИТУТ

(ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ)


АЭРОКОСМИЧЕСКИЙ ФАКУЛЬТЕТ


Кафедра «СИСТЕМНЫЙ АНАЛИЗ И УПРАВЛЕНИЕ»












А.В.Федоров, А.В.Старков


Программирование на языке Object Pascal

в среде DELPHI


Учебное пособие по дисциплине


«Современные методы программирования»



УТВЕРЖДЕНО

На заседании кафедры


«____»____________2007 г.











МОСКВА 2007


Глава 1


ВВЕДЕНИЕ В Object Pascal


Модуль и его структура

Список uses

Интерфейс

Реализация

Инициализация и завершение

Ключевые слова

Ключевое слово const

Ключевое слово type

Ключевое слово var

Комментарии

Переменные

Типы данных и переменные

Совместимость типов

Знаки операций

Константы

Массивы

Одномерные массивы

Многомерные массивы

Функции Low и High

Динамические массивы

Строки

Короткая строка

Длинная строка

Расширенная строка

Строка с терминальным нулем

Операции со строками

Управляющие символы

Сравнение строк

Строковые функции

Форматирование строк

Множества

Совместимость типов

Указатели

Статические и динамические переменные

Размещение динамических переменных

Разыменование указателя

Прежде чем использовать возможности Delphi, надо познакомиться с основами языка программирования Object Pascal.


Новый термин. Объект и компонент – это фрагменты программы, которые выполняют конкретные функции. (Компонент это объект, но не всякий объект является компонентом).


Объект дает пользователю (программисту, использующему объект) только те функции, которые действительно необходимы; следовательно, использовать объекты достаточно просто. Все внутренние механизмы, знать о которых пользователю необязательно, скрыты. Это и составляет концепцию объектно–ориентированного программирования – ООП.

ООП поддерживает модульный подход к программированию. Функциональность любого компонента может быть расширена с помощью механизма наследования. Важно то, что компоненты скрывают от программиста свою сложность и дают возможность сосредоточиться на главном.


Модуль


Программирование – это нечто большее, чем написание исходного кода. Прежде всего, программирование есть разработка концепции решения задачи, а уже затем – написание исходного кода, выполнение которого и приведет к желаемому результату.

Код, который вы пишете, заносится в текстовый файл. Компилятор преобразует текст в машинный код – последовательность слов, которые «понимает» процессор.

Текстовый файл, который Delphi компилирует в машинный код, называется модулем (unit).


Новый термин. Модуль это текстовый файл, который может быть откомпилирован в модуль машинного кода. Откомпилированный модуль записывается файл с расширением имени DCU.



Любая программа с графическим интерфейсом пользователя (Graphical User Interface, GUI) состоит, как минимум, из двух модулей – модуля проекта и модуля формы.

Модуль проекта содержит код, который обеспечивает подготовку программы к выполнению и затем запускает ее. Файл модуля проекта имеет расширение имени DPR. Исходный код проекта можно просмотреть, выбрав в главном меню команду Project | View Source. Обычно нет никакой необходимости редактировать этот файл. Более того, его нельзя изменять до тех пор, пока вы не разберетесь в деталях. Если вы случайно модифицируете исходный код модуля проекта недопустимым образом, скорее всего программа не будет работать.

Второй тип модулей это модуль формы. Модуль формы содержит исходный код, который отвечает за правильное поведение соответствующего окна в процессе работы программы. Файлы модулей этого типа имеют расширение имени PAS. Именно с модулями форм вы будете иметь дело чаще всего.

Любая программа (проект) в Delphi имеет, по крайней мере, один модуль формы, но их может быть и больше. Например, приложение, которое способно показать сообщение «О программе…» в ответ на команду Help | About будет иметь в своем составе два модуля: модуль формы главного окна и модуль формы информации о программе.

К третьему типу относятся модули, которые содержат только исходный текст. В модулях этого типа размещают объявления типов, констант процедур и функций, которые будут необходимы для реализации алгоритма прикладной программы.


Структура модуля


Структура модуля стандартна. Модуль проекта в Delphi имеет заголовок, состоящий из ключевого слова program, за которым следует имя модуля и блок кода, ограниченный ключевыми словами begin и end. вы можете просмотреть исходный код модуля проекта. Для этого выберите в главном меню View | Project Source. Типичный текст модуля проекта приведен на листинге 1.1.


Замечание. Номера строк на листинге 1.1 добавлены ради наглядности. В исходном тексте строки программ не нумеруются


Листинг 1.1. Стандартный текст модуля проекта Delphi.


01: program Project1;

02:

03: uses

04: Forms,

05: Unit1 in 'Unit1.pas' {Form1};

06:

07: {$R *.RES}

08:

09: begin

10: Application.Initialize;

11: Application.CreateForm(TForm1, Form1);

12: Application.Run;

13: end.



В первой строке ключевое слово program идентифицирует модуль проекта. Его имя (Project1) следует за ключевым словом program. Delphi всегда присваивает проекту имя по умолчанию, но вы можете сохранить проект и под другим именем. Новое имя автоматически заменит собой старое в строке 1).

Со строки 3 расположен раздел, текст которого начинается с ключевого слова uses. Здесь приводится список модулей, которые требуется откомпилировать в порядке их перечисления. Назначение ключевого слова uses более подробно рассмотрено в разделе "Список uses."

В строке 7 вы видите директиву. В данном случае это есть указание подключить файл ресурсов проекта. Назначение файла ресурсов объясняется в разделе "Создание прикладных программ"

В строке 9 записано ключевое слово begin, а в строке 13 – ключевое слово end. Обратите внимание на точку после слова end. Модуль в общем случае может содержать несколько блоков, ограниченных парой «begin – end», но только одно заключительное слово end с точкой.

Код в сроках 10, 11 и 12 выполняет инициализацию программы, создает ее главную форму и запускает программу на выполнение. Вникать в подробности этого кода нет никакой необходимости.



Теперь рассмотрим типовой Pascal–модуль.

В
главном меню выберите команду File | New.

В диалоговом окне New Items найдите значок Unit и дважды щелкните на нем. Delphi создает заготовку нового модуля и помещает ее в окно редактора кода. Текст модуля приведен на листинге 1.2.









Листинг 1.2. Заготовка модуля


01: unit Unit2;

02:

03: interface

04:

05: implementation

06:

07: end.




У модулей на листингах 1.1 и 1.2 есть что–то общее.

Во-первых, это имя Unit2 в первой строке (имя модуля создала Delphi). Но код на листинге 1.1 начинается словом program, а здесь – словом unit.

Во–вторых, это слово end в конце. Общим правилом является то что в начале любого Pascal–модуля стоит либо ключевое слово program, либо unit, с помощью которых модулю присваивается то или иное имя, а в конце модуля стоит слово end с точкой.

Код на листинге 1.2 отличается от кода на листинге 1.1 тем что здесь есть разделы, отмеченные ключевыми словами interface и implementation. Любой модуль, который не является модулем проекта, должен иметь раздел интерфейса (interface) и раздел реализации (implementation). Назначение этих разделов мы рассмотрим позже. Другим отличием листинга 1.2 от листинга 1.1 состоит в том, что здесь нет слова begin. Главный модуль программы обязательно содержит блок «begin – end», а обычный модуль – только end с точкой в конце.

Рассмотрим назначение ключевых слов, которые используются в Pascal–модуле.


Список uses


Новый термин. В разделе uses перечислены внешние модули, на которые ссылается данный модуль. Иными словами, данный модуль не удастся откомпилировать без использования модулей, которые перечислены в списке uses.


Обратимся к листингу 1.1. Слово uses в строке 3 открывает список модулей, которые необходимы для выполнения прикладной программы. Например, в строке 11 листинга 1.1 написано:


Application.CreateForm(TForm1, Form1);


В этой строке используются идентификаторы, которые в данном модуле не объявлены. Так, описание процедуры Application.CreateForm находится в модуле с именем Forms.pas, а идентификаторы TForm1 и Form1 описаны в модуле формы приложения Unit1.pas. Видите связь? Список uses сообщает Delphi где искать дополнительную информацию, необходимую для компиляции модуля. Рассмотрим список uses подробнее:


uses

Forms,

Unit1 in 'Unit1.pas' {Form1};


В этом списке присутствуют имена двух модулей: Forms и Unit1. В некотором смысле это неудачный пример, поскольку второй модуль описан необычно. Так, его описание содержит дополнительный текст (Unit1 in 'Unit1.pas' {Form1}). Этот текст показывает что модуль содержит описание формы. Такой синтаксис описания применяется только в модуле проекта. Текст в фигурных скобках – это комментарий.


Необходимо запомнить два правила составления списка uses:


Имена модулей в списке разделяются запятыми.

Список заканчивается символом «;».

Способ оформления списка не имеет никакого значения. Например, следующие два списка uses абсолютно верны:


uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;


uses

Windows,

Messages,

SysUtils,

Classes,

Graphics,

Controls,

Forms,

Dialogs,

StdCtrls;



ПРИМЕЧАНИЕ: В некоторых случаях Delphi может добавлять ссылки на модули в список uses. Это делается с помощью команды меню File | Use Unit.


Интерфейс


Раздел интерфейса в модуле начинается с ключевого слова interface.

Этот раздел предназначен для объявления идентификаторов, которые «экспортирует» данный модуль. Экспортируемый идентификатор доступен в любом другом модуле проекта, который ссылается на данный модуль в своем списке uses.

Большинство модулей содержат объявления классов, процедур, функций, типов и т.д, которые будут использоваться в других модулях. Любые объекты, которые должны быть доступны другим модулям, следует объявить в разделе интерфейса. Раздел интерфейса заканчивается перед словом implementation.



Реализация


Новый термин: Раздел реализации (implementation) модуля содержит детальный код модуля.


Раздел реализации начинается словом implementation и заканчивается либо итоговым end., либо перед ключевым словом initialization. Ключевое слово initialization используется для создания в модуле раздела инициализации. Пока что мы ограничимся сказанным, ибо прежде чем объяснять тонкости создания модулей необходимо рассмотреть другие аспекты языка Pascal.

Рассмотрим пример, иллюстрирующий использование разделов interface и implementation.


Допустим, нам надо создать модуль с процедурой DoSomething. причем эта процедура должна быть доступна всем модулям проекта. В этом случае мы должны описать процедуру DoSomething в разделе interface и затем написать код этой процедуры в разделе implementation. Вцелом модуль будет выглядеть так, как показано на листинге 1.3.





Листинг 1.3. Модуль с экспортируемой процедурой


unit Unit2;


interface


procedure DoSomething;


implementation


procedure DoSomething;

begin


{ Алгоритм процедуры DoSomething. }


end;


end.

Обратите внимание на то, что процедура DoSomething объявлена в разделе интерфейса, а затем определена (т.е. дан ее подробный код) в разделе implementation. Правда, мы несколько опередили события, ибо не объяснили еще ни понятие «процедура», ни понятие «функция». Процедуры и функции мы рассмотрим позже.


Инициализация и завершение

Разделы инициализации и завершения предназначены для размещения в них кода, который должен быть выполнен в начале (initialization) и при завершении работы программы (finalization). Код раздела инициализации выполняется когда модуль загружается в оперативную память. Код раздела завершения выполняется перед выгрузкой модуля из памяти. Модуль может содержать только раздел инициализации, однако раздел завершения может быть только в паре с разделом инициализации. Разделы initialization и finalization в модулях необязательны.


Ключевые слова


Помимо обязательных разделов интерфейса и реализации модуль может содержать ряд других разделов. Каждый раздел начинается тем или иным ключевым словом. Некоторые ключевые слова могут употребляться в различных контекстах (т.е. не только как идентификаторы разделов модуля). Здесь мы рассмотрим как некоторые ключевые слова используются в модулях.


Ключевое слово const


Любой модуль может содержать один и более разделов объявления констант. Такой раздел начинается с ключевого слова const.

Если в программе много раз используется одно и то же численное значение или определенная строка текста появляется в нескольких местах, стоит объявить повторяющееся значение как константу.


Новый термин. Константа – это имя фиксированного значения, на которое вы часто ссылаетесь в своих программах. Объявление константы позволяет обращаться в программе к соответствующему значению по имени вместо написания величины.


Допустим, что имеется несколько значений, которые будут встречаться в программе много раз. Возможно, эти значения понадобятся другой программе. Тогда их можно (и нужно!) объявить как константы. В качестве примера добавим раздел констант к тексту модуля на листинге 1.3. Один раздел констант поместим в интерфейсную секцию модуля, а другой – в секцию реализации. Константы, объявления которых находятся в интерфейсной секции модуля, будут доступны в других модулях. Константы, объявленные в секции реализации, доступны только в данном модуле. На листинге 1.4 показан модуль с двумя разделами объявления констант.

Константы AppCaption, EarthMeanRadius, EarthGravitation, объявленные в интерфейсной секции модуля Unit2, могут быть в будущем использованы в любом из модулей, который в своем uses – списке содержит имя Unit2.

Константы, обозначенные идентификаторами BaseX и BaseY, будут доступны только в данном модуле, поскольку их объявления размещены в секции implementation.

Ключевое слово const используется и других контекстах исходного кода. Об этом – в разделе «Переменные, константы и параметры–переменные».


Листинг 1.4. Разделы объявления констант в модуле

unit Unit2;

interface

const

AppCaption = 'My Cool Program 1.0';

EarthMeanRadius = 6371.21; {km}

EarthGravitation = 0.398603e6; {km^3/s^2}

procedure DoSomething;

implementation

const

BaseX = 20;

BaseY = 200;

procedure DoSomething;

begin

{ Здесь должен быть код процедуры DoSomething. }

end;

end.



Ключевое слово type


Новый термин: Ключевое слово type используется для объявления нового типа данных.


Объявление нового типа данных – изощренная технология программирования, суть которой на данном этапе объяснить трудно. Все же, давайте рассмотрим пример. Допустим, что для хранения данных в некоторой программе необходима коллекция величин (массив), каждый элемент которой имеет размер в один байт, а общее количество элементов равно 20. Если ссылки на подобный массив в программе будут встречаться часто, можно (и нужно!) объявить новый тип данных. В данном случае объявление нового типа данных имеет вид


type

TMyArray = array [0..19] of Byte;


Теперь любой контекст вида «array [0..19] of byte» можно будет заменить словом TMyArray. Далее мы увидим много примеров использования объявлений типов данных.



Ключевое слово var


Новый термин: Ключевое слово var обозначает секцию модуля, в которой объявляются переменные.


Ключевое слово var используется для объявления переменных (понятие «переменная» подробно рассматривается в разделе «Переменные»). Секции объявления переменных могут присутствовать в модулях, в процедурах и в функциях. В модуле может быть несколько секций объявления переменных.

На листинге 1.5 показан текст модуля с секциями объявлений типов и переменных.


Листинг 1.5. Модуль с объявлениями типов и переменных

unit Unit2;


interface


type

TMyArray = array [0..19] of Byte;

TMyOrbit = record A,e,u,w,i,O : real; end;


const

AppCaption = 'My Cool Program 1.0';

EarthMeanRadius = 6371.21; {km}

EarthGravitation = 0.398603e6; {km^3/s^2}


var

X : Integer;

MyArray : TMyArray;

MyOrbit : TOrbit;


procedure DoSomething;


implementation


const

BaseX = 20;

BaseY = 200;

procedure DoSomething;

begin

{ Code for DoSomething goes here. }

end;

end.




ПРИМЕЧАНИЕ: Начало секции объявления типов, констант или переменных идентифицируется одним из ключевых слов var, const, или type. Окончание секции – перед следующим ключевым словом



Комментарии


Комментарий – это текст, который объясняет назначение того или иного фрагмента программы. Комментарии к программе можно рассматривать как один из способов документирования программного обеспечения.

Вот примеры комментариев к программе:


{

SPACE SYSTEM TOOLBOX 1.0

Copyright (c) Moscow State Aviation Institute 1998–2000

}


{ Cоздаем объект – систему ГЛОНАСС}

{ Не забыть освободить выделенную здесь память! }

GLONASS := TGLONASS.Create;


{ Освобождаем память }

GLONASS.Free;


(* Исправить ошибки в этом месте модуля *)


Имеется несколько способов комментирования. Наиболее типичным является использование фигурных скобок. Открывающая фигурная скобка начинает комментарий, а закрывающая – заканчивает. Другой способ использует символы (* как начало, а символы *) – как окончание комментария. Различие этих двух способов состоит в том, что с помощью символов (*/*) можно «заблокировать» фрагменты текста, которые содержат комментарии. Итак, два вида символов позволяют написать от одной до нескольких строк комментария к тексту программы.


ПРИМЕЧАНИЕ: Фигурные скобки в языке Pascal также используются для задания директив. В тексте директивы сразу за открывающей фигурной скобкой следует знак доллара. Например, чтобы дать компилятору указание отменить вывод диагностических сообщений, в исходный код программы надо поместить строку:


{$HINTS OFF}


Когда компилятор встречает в тексте программы такую строку, он прекращает генерацию диагностических сообщений до тех пор пока не обнаружит директиву {$HINTS ON}. Директивы мы будем рассматривать далее по мере необходимости.


Третий способ комментирования – использование пары символов //. Часто это называют «комментарий в стиле C», ибо так принято в языках С и С++. Данный тип комментария допустим во всех версиях Delphi старше первой.




ПРИМЕЧАНИЕ: Рекомендуется использовать комментарии в фигурных скобках для документирования программы, т.е. того текста, который вы сдаете заказчику. Для блокирования фрагментов кода в процессе отладки используйте С-стиль комментариев или (*/*). А вообще-то это дело вкуса.


Компилятор игнорирует все комментарии. Если вы используете стандартные параметры настройки Delphi, все строки–комментарии будут выделены курсивом синего цвета. Это позволяет быстро находить комментарии в программе.


ПРИМЕЧАНИЕ. Если вы – член коллектива, работающего над большим проектом, то вам наверняка придется читать тексты, написанные коллегами по работе. В свою очередь, кто–то будет разбираться в тексте, который написали вы. Исчерпывающие комментарии к программе помогут сэкономить часы работы любого программиста, который должен сопровождать чужой программный продукт. Даже если вы работаете «на себя», комментирование кода – отличный стиль программирования. вы удивитесь, как быстро забывается, зачем вы написали тот или иной код. Исчерпывающие комментарии в программе позволят Вам не тратить понапрасну время на восстановление в своей памяти «что к чему».




Переменные


Прежде чем использовать в программе переменные их надо объявить. Объявления переменных размещаются в секции модуля, которая идентифицируется словом var . Например,


var

X : Integer; { переменная X объявлена как целочисленная }

Y : Integer; { переменная Y объявлена как целочисленная }


Ранее мы обсудили использование ключевого слова var в терминах модуля. Так, было сказано, что все переменные, используемые в модуле, должны быть объявлены в var–секции. Это действительно так, но вы можете иметь секцию объявления переменных и внутри процедуры, и внутри функции.

Вот пример объявления переменных в процедуре:


procedure TForm1.Test;

var

S : string;

begin

S := 'Hello World!';

Label1.Caption := S;

end;


Объявленную переменную можно использовать в программе для хранения и модификации данных. Рассмотрим несколько примеров. В следующем фрагменте кода используются переменные X и Y, объявленные ранее. Комментарий в конце каждой строки кода поясняет то, что произойдет при выполнении этого кода:


X := 100; { 'X' принимает значение числа 100 }

X := X + 50; { 'X' теперь содержит значение 150 }

Y := 150; { 'Y' содержит значение 150 }

X := X + Y; { 'X' содержит значение 300 }

Inc(X); { Приращение. 'X' теперь содержит значение 301 }


Переменная это область (ячейка) памяти компьютера, которая хранит некоторое значение.

Дадим ряд пояснений к этому коду.

Во–первых, надо ясно понимать, что значение переменной X изменяется только в результате той или иной операции над ней. (Предусмотренные языком Object Pascal операции, функции и процедуры для манипуляции переменными мы рассмотрим позже). Здесь мы видим, что переменным можно присваивать значения, складывать, давать приращение и т.д.


Во–вторых, обратите внимание на то, что каждый сегмент кода заканчивается символом «;». Символ «точка с запятой» используется как символ окончания фразы, выраженной на языке Pascal. Законченные фразы, которые вы пишете на языке Pascal, называются операторами.



ПРИМЕЧАНИЕ. С незапамятных времен, подающий надежды программист обязан был выучить, в чем разница между выражением (expression) и оператором (statement). Официальное определение понятия «оператор» гласит: оператором называется любое выражение, за которым следует символ «;». Выражением называется единица кода, которая вычисляет некоторое значение. Рассмотрим следующий оператор:


c := a + b;


В этом примере фрагмент кода справа от знака присваивания (:=), т.е. a + b, есть выражение. Вся строка целиком – оператор. Можно сказать, что выражение – это часть оператора. Один оператор может содержать несколько выражений. Возможно, сейчас это все же остается запутанным, но вскоре все прояснится. Сейчас просто запомните: оператор заканчивается «точкой с запятой». (Существуют ситуации когда «точка с запятой» в конце оператора не ставится. Такого рода исключения из общих правил будут оговорены особо).



Имена переменных должны удовлетворять правилам построения идентификаторов. Идентификаторы используются также для именования функций, процедур, полей в записях, модулей и других объектов программы. В идентификаторах можно использовать строчные или заглавные буквы английского алфавита, цифры и символ подчеркивания (_). Идентификатор не может содержать ни пробелов, ни специальных символов. Первым символом идентификатора должна быть либо буква, либо символ подчеркивания. Количество символов в идентификаторе не ограничено, но все, что следует после 255-го символа, – игнорируется. Практически же все что длиннее 20 символов, вряд ли полезно. Вот примеры допустимых имен переменных:


aVeryLongVariableName : Integer; { «длинный» идентификатор }

my_variable : Integer; { идентификатор с подчеркиванием }

x : Integer; { одиночный символ в качестве имени }

X : Integer; { это то же самое имя что и предыдущее }

Label2 : string; { имя содержит цифру }



ПРИМЕЧАНИЕ. Язык Pascal не чувствителен к регистру. (т.е. не чувствует разницу между строчными и прописными буквами). Так, в следующих операторах используется одна и та же переменная:


var

XPos : Integer;

{ ...далее }

XPos := 20;

XPOS := 200;

xpos := 110;

XpoS := 40;


Если раньше вы имели дело с языком, который различает заглавные и строчные буквы (C или C++), нечувствительность Object Pascal к регистру может показаться странной, но скоро вы привыкните и к этому.

Несмотря на то, что Pascal не чувствителен к регистру, старайтесь использовать заглавные буквы для того чтобы придать Вашим идентификаторам выразительность. Согласитесь, что идентификаторы EarthMeanRadius или Earth_Mean_Radius привлекательней чем earthmeanradius.




Типы данных и переменные


НОВЫЙ ТЕРМИН. В Object Pascal тип данных информирует компилятор как размещать информацию в памяти.


Некоторые языки программирования допускают присваивание переменной значения любого типа. Например, рассмотрим следующие примеры кода на языке BASIC:


X = -1;

X = 1000;

X = 3.14;


Интерпретатор BASIC заботится о выделении подходящего размера памяти для хранения соответствующего значения.

В программе на Object Pascal все переменные, используемые в программе надо объявить, например


var

X1 : Integer;

X : Integer;

Y : Double;

Z : Byte;

{ ...далее }

X1 := -1;

X := 1000;

Y := 3.14;

Z := 27;


Компилятор использует объявления переменных для проверки корректности присваиваемых им значений. Некорректность использования типов данных приведет либо к ошибке компиляции, либо к предупреждению, на которое следует обратить внимание, проанализировать и исправить ошибку. Строгий контроль за использованием типов данных обеспечивает надежность программы.

Некоторые из типов являются беззнаковыми, т.е. данные такого типа могут принимать только положительные значения. В таблице 1.1 приведены основные типы данных Object Pascal, размер памяти для размещения одного значения соответствующего типа, а так же диапазон допустимых значений. В этой таблице не представлены строковые типы, обсуждение которых вынесено в раздел «Строки»



Таблица 1.1. Типы данных Object Pascal


Тип

Размер, байт

Диапазон значений

ShortInt

1

-128 …127

Byte

1

0 … 255

Char

1

0 … 255

WideChar

2

0 … 65 535

SmallInt

2

32 768 … 32 767

Word

2

0 … 65 535

LongInt

4

2 147 483 648 … 2 147 483 647

Int64

8

от –9 223 372 036 854 775 808

до 9 223 372 036 854 775 807

Integer

4

см. LongInt

Cardinal

4

0 … 2 147 483 647

Single

4

1.5 10-45 … 3.4 1038

Double

8

5.0 10-324 … 1.7 10308

Real

8

как Double

Extended

10

3.4 10-4932 … 1.1 104932

Comp

8

от –9 223 372 036 854 775 808

до 9 223 372 036 854 775 807

Currency

8

от –922 337 203 685 477.5808

до 922 337 203 685 477.5807

Boolean

1

True или False

Variant

16



Как следует из таблицы 1.1, типы Integer и LongInt эквивалентны. Это сделано для совместимости на уровне исходных текстов с программами, подготовленными на 16–разрядных компьютерах. На 16–разрядной версии тип Integer требует 2 байта памяти, а тип LongInt – 4 байта.

В 32-разрядной версии оба типа имеют размер 4 байта и, следовательно, одинаковые диапазоны значений.

Кроме того, можно заметить, что типы Int64 и Comp (computational) также имеют одинаковые диапазоны значений. Различие между ними в том как трактует их компилятор. Так, Int64 относится к целочисленным, а тип Comp – к вещественным. В инженерных приложениях тип Comp вряд ли Вам понадобится.

Далее, отметим идентичность типов Real и Double. В Delphi 1.0 (и в Turbo Pascal) тип Real был 6-байтным. Теперь он стал 8-байтным. Дело в том, что 6-байтный вещественный тип противоречит 32-разрядной архитектуре современных процессоров.

При переносе «старых» 16-разрядных программ на 32-разрядную платформу может возникнуть проблема совместимости по типу real. Так, если в Delphi – программе вы читаете с диска «старый» типизированный файл, объявленный как file of real, данные будут введены не верно. Для совместимости со «старым» типом real в Object Pascal есть тип real48, который соответствует 6–байтному вещественному числу.


ПРИМЕЧАНИЕ. Тип Int64 впервые появился в Delphi 4. Он предназначен для представления «очень больших» целочисленных значений. Его появление связано с тем, что объем жестких дисков далеко «перевалил» за гигабайт. В Windows API есть функция GetDiskFreeSpaceEx, которая вычисляет объем свободного пространства на жестком диске. Она может вернуть значение, которое гораздо больше верхней границы диапазона чисел типа Integer (2 147 483 647). Тип 64-битного целого и предназначен для решения подобных проблем.


Типы Single, Double, Extended, и Currency относятся к группе вещественных. К данным этого типа относятся числа, имеющие целую и дробную части. Каждое число вещественного типа может содержать конечное число десятичных цифр. Иначе данные этого типа называют числами с плавающей точкой.

Остальные типы данных относятся к целочисленным. Целочисленной переменной нельзя присвоить вещественное значение. Например, при компиляции следующего фрагмента будет зафиксирована ошибка:


var

X : Integer;

{ Далее... }

X := 3.75;


При написании кода программы, который отвечает за графический интерфейс, необходимость в переменных вещественного типа возникает очень редко.

С другой стороны, код реализации инженерных расчетов оперирует вещественными переменными на все 100%.







Преобразование типов


Если это не противоречит правилам, Object Pascal автоматически преобразует значения одного типа в значения других типов.

Рассмотрим следующий фрагмент кода:


var

Res : SmallInt;

Num1 : Integer;

Num2 : Integer;

{ далее... }

Num1 := 200;

Num2 := 200;

Res := Num1 * Num2;


Здесь результат умножения двух чисел типа Integer присваивается переменной типа SmallInt. Несмотря на смесь типов, Object Pascal способен выполнить преобразование.


Вопрос: Какое значение получит переменная Res?.

Ответ: -25536.

Почему?


В таблице 1.1 указано, что максимальным значением типа SmallInt является число 32767. При добавлении единицы к числу 32767 типа SmallInt мы получим –32768, что соответствует нижней границе диапазона чисел этого типа. Это в точности соответствует поведению счетчика километража на спидометре автомобиля когда при пробеге последнего из первой сотни тысяч километров показание 99 999 сбрасывается на 00 000.


Выполните следующие упражнение:


1. Создайте новый проект. Поместите на форму надпись и кнопку.

2. Дважды щелкните на кнопке формы чтобы перейти в режим редактирования обработчика события OnClick.

3. Придайте обработчику события OnClick такой вид :


procedure TForm1.Button1Click(Sender: TObject);

var

X : SmallInt;

begin

X := 32767;

X := X + 1;

Label1.Caption := IntToStr(X);

end;


4. Скомпилируйте программу и нажмите кнопку Button1.


Вы должны увидеть, что после щелчка на кнопке надпись показывает -32768 (функция IntToStr здесь преобразует целое значение в строковое). Итак, мы убедились в том, что 32767 + 1 = -32768 !

Данное упражнение иллюстрирует эффект целочисленного переполнения (overflow wrapping).

При использовании переменных целого типа всегда надо помнить об ограниченности диапазонов их значений.

Иногда преобразование данных одного типа в другой недопустимо. В такой ситуации вы увидите диагностику (сообщение об ошибке) вроде


Incompatible types: Integer and Real.


Это сообщение информирует о том, что была сделана попытка присвоить переменной значение, тип которого не соответствует типу этой переменной.

Если некорректность использования данных целочисленных типов может быть выявлена на этапе компиляции программы, вы увидите сообщение вроде «Range checking error»

Например, при компиляции фрагмента


var

X : Byte;

begin

X := 1000;

end;


будет выдано сообщение:

Constant expression violates subrange bounds.


Тем самым, компилятор информирует нас о том, что переменной X типа byte нельзя присвоить значение 1000, ибо переменные этого типа могут принимать любые значения только в диапазоне от 0 до 255.


ВНИМАНИЕ! Компилятор генерирует диагностические сообщения трех уровней серьезности: hint, warning и error.

  1. hint – подсказка. Это что-то вроде «Обратите внимание на …»

  2. warning – это предупреждение (серьезней чем hint)

  3. errorэто ошибка.

В первых двух случаях исполняемый файл все же создается, т.е. программа будет работать, но, возможно, некорректно. В последнем случае компилятор не сможет создать исполняемый файл.

Попробуйте заставить себя трактовать «hints» и «warnings» как сообщения о потенциальных ошибках в программе. Сообщениями этого типа компилятор «пытается» информировать вас о том, что в исходном тексте программы что-то не так, но это не страшно. Тем не менее, разберитесь в причине появления подсказки или предупреждения и устраните ее. Ситуации, когда предупреждения можно просто игнорировать, встречаются достаточно редко.


Знаки операций


С помощью знаков операций выполняют вычисления, сравнивают значения и т.д. Object Pascal предоставляет программисту большой набор операций над данными. Сначала рассмотрим те из них, которые применяются наиболее часто. Их список дан в таблице 1.2.


Таблица 1.2. Знаки операций


Символ

Описание

Пример

Математические

+

Сложение

x := y + z;

-

Вычитание

x := y - z;

*

Умножение

x := y * z;

/

Вещественное деление

x := y / 3.14;

div

Целочисленное деление

x := y div 10;

Присваивание

:=

Присвоить

x := 10;

Логические

and

Логическое «И»

if (x=1) and (y=2) then ...

or

Логическое «ИЛИ»

if (x=1) or (y=2) then ...

xor

Исключающее «ИЛИ»

if (x=1) xor (y<=2) then ..

Битовые

and

Поразрядное «И»

x := x and $02;

or

Поразрядное «ИЛИ»

x := x or $FF;

xor

Сложение по модулю 2

x := x xor $AB

Сравнения

=

Равно

if (x = 10) then ...

<>

Не равно

if (x <> 10) then ...

<

Меньше чем

if (x < 10) then ...

>

Больше чем

if (x > 10) then ...

<=

Меньше или равно

if (x <= 10) then ...

>=

Больше или равно

if (x >= 10) then ...

Одноместные

^

Разыменование ссылки

MyObject.Data^;

@

Адрес

ptr := @MyRecord;

not

Поразрядное отрицание

x := x and not $02;

not

Логическое отрицание

if not Valid then ...

Другие

$

Шестнадцатеричное число

X := $FF;

[]

Индекс элемента массива

X := MyArray[5];

.

Точка – соединение полей

X := Record.Data;



Список операций достаточно внушителен. Учить его наизусть нет необходимости. Все эти операции вы постепенно научитесь использовать в процессе создания различных программ. Необходимость применения ряда операций возникает очень редко. Но есть и такие, которые необходимы постоянно.

Обратите внимание на операции and, or, xor и not. Например, ключевое слово and можно применить и как знак логической операции «И», так и как знак поразрядной операции над битами (двоичными цифрами) машинного кода.

Логические операции участвуют в выражениях, результатом вычисления которых является либо true (истинно), либо false (ложно). Результаты логических вычислений либо присваиваются переменным булевого типа (boolean), либо принимают участие в управлении программой if. . . then . . . ; while . . . do ; until …; Например


if Assigned(MyObject) and (MyObject.Age >=10)

then MyObject.Run;


Битовые операции выполняются над битами целых чисел. При этом операция применяется к значению 0 или 1, так, как если бы это были false или true. Область применения битовых операций – формирование признаков ветвления программы, работа с цветом, масками закраски фона и т.п.

Следующая таблица обобщает логические операции


Операция

Результат

not a

true становится false и наоборот

a and b

true только когда оба операнда true

a or b

true когда один из операндов true

a xor b

true когда оба операнда имеют противоположную истинность, т.е. любое из двух true-false или false-true, но не true-true или false-false



Константы


Как было сказано выше, константа есть идентификатор, который обозначает постоянную величину. В процессе выполнения программы значение константы изменить невозможно. Термины «переменная» и «константа» выбраны неслучайно. Так, значения переменных могут изменяться в процессе работы программы, а значения констант – нет. Для объявления константы используется ключевое слово const. Чтобы объявить константы просто перечислите их имена и значения, например


const

DefaultWidth = 400;

DefaultHeight = 200;

Description = Динамическая модель атмосферы;


Обратите внимание на то, что объявление константы содержит знак «равно» (=), а не «присвоить» (:=). Кроме того, нет спецификации типа константы. Компилятор сам определяет тип константы по виду числового значения справа от знака (=). Имена констант в программе следует использовать вместо явного написания чисел или литералов.

Осмысленное применение констант обеспечивает надежность программы и является необходимым условием простоты ее модификации в будущем. Так, чтобы изменить поведение программы (размеры окон, элементов управления, реакции и т.п.), достаточно будет изменить объявления констант только в одном фрагменте исходного кода.


Массивы


Массивы относятся к структурированным типам данных.


Новый термин. Массив – структура, содержащая последовательность элементов (значений данных) одного и того же типа. Элементы массива упорядочены в непрерывной области памяти. Массивы могут быть одномерными, двумерными, трехмерными, а в общем случае, – многомерными.


Одномерные массивы


В одномерном массиве каждый элемент однозначно идентифицируется его порядковым номером в структуре. Такое понятие как «вектор» в программе представляют одномерным массивом.

Следующий пример показывает как объявить в программе одномерный массив с пятью элементами целого типа:


var

MyArray : array[0..4] of integer;


Для придания значений элементам массива надо использовать операцию «индекс» ([]):


MyArray[0] := -200;

MyArray[1] := -100;

MyArray[2] := 0;

MyArray[3] := 100;

MyArray[4] := 200;


Далее в программе можно обращаться к элементу одномерного массива по его индексу:


X := MyArray[3] + MyArray[4]; { результат Х = 300 }



Многомерные массивы


Массивы могут быть многомерными.

Рассмотрим пример объявления двумерного массива значений целого типа:


var

M2Array : array[0..2, 0..4] of Integer;


В данном случае компилятор выделяет в памяти место для 15 целых чисел (всего 60 байт). Для доступа к элементам двумерного массива надо записать два индексных выражения. Существуют два способа записи индексов, которые иллюстрируют следующие строки (они идентичны):


X := M2Array[1][1] + M2Array[2][1];

X := M2Array[1, 1] + M2Array[2, 1];


Порядок размещения элементов двумерного массива показан на рис 1.5. Здесь индекс по вертикали – первый, а по горизонтали – второй.








[0]

[1]

[2]

[3]

[4]

[0]

1

2

3

4

5

[1]

6

7

8

9

10

[2]

11

12

13

14

15


Рис.1.5. Размещение элементов двумерного массива в памяти


При включенной опции компилятора «Range checking» осуществляется автоматический контроль принадлежности индексов диапазонам, указанным при объявлении массива. Например, при компиляции следующего фрагмента кода


var

MyArray : array[0..4] of Integer;

X : Integer;

begin

X := MyArray[3] + MyArray[5]; { Ошибка! 5 вне диапазона. }

end;


будет выдано сообщение об ошибке :


Constant expression violates subrange bounds.


Диапазон индексов элементов массива, который указывается при его объявлении, может быть любым по усмотрению программиста. Так, нижняя граница не обязательно должна быть нулевой. Например, такое объявление одномерного массива допустимо:


var

MyArray : array[10..20] of Integer;


Теперь для доступа к элементам массива мы должны использовать индексы с 10 (первый элемент) по 20 (последний элемент).

Можно объявить массив констант и одновременной инициализировать его:


const

myArray:array[0..4] of Integer = (-200,-100, 0, 100, 200 );


При объявлении массива можно использовать имена ограниченных типов данных (отрезки, перечисления) при условии что эти типы уже где–то объявлены. Например:



type

WorkDays = (Monday,Tuesday,Wednesday,Thurthday,Friday);

WorkHours = 9..18;


WorkTime = array[WorkDays,WorkHours] of integer;


Здесь объявление типа массива WorkTime равносильно следующему


WorkTime = array[0..4,9..18] of integer;


Для доступа к элементам массива можно использовать значения перечисляемых типов, например


var

Days : WorkTime;


// Далее. . .

Days[Monday,10] := 56;

Days[Friday,17] := 100;

Функции Low и High


Функции Low и High предназначены для работы с массивами. Функция Low возвращает нижнюю, а функция High – верхнюю границу индексов массива :


var

X, I, Lower, Upper : Integer;

MyArray : array[10..20] of Integer;

begin

{ Code to initialize MyArray here. }

Lower := Low(MyArray); { Lower содержит 10 }

Upper := High(MyArray); { Upper содержит 20 }

X := 0;

for I := Lower to Upper do

X := X + MyArray[I];

{ продолжение кода . . . }

end;


Применение функций Low и High для работы с массивами – хороший способ избежать ошибок, связанных с выходом индекса за допустимые пределы.





Динамические массивы


При объявлении динамического массива достаточно указать только тип его элементов. Память для размещения его элементов на этом этапе не выделяется. Фактически массив создается только во время выполнения программы. Для этого используется функция SetLength. Как только необходимость в массиве отпадает, следует освободить память вызовом процедуры Finalize. Рассмотрим пример:


var

BigArray : array of Integer; {размер массива не указан }

X : Integer;

begin

X := GetArraySize; { Функция вычисляет размер массива }

SetLength(BigArray, X); { Динамическое размещение массива }

{ Теперь массив можно использовать}

. . . . . . . .

{ Массив больше не нужен }

Finalize(BigArray);

end;


Новый термин. Динамический массив размещается в оперативной памяти во время выполнения программы.

Размер динамического массива можно увеличивать или уменьшать во время выполнения. программы

По окончании использования его следует уничтожить.


Несомненное преимущество динамических массивов над статическими заключается в том, что в случае неопределенности потребного количеством элементов нам не надо объявлять массив «с запасом». Достаточно объявить динамический массив и управлять его размерами непосредственно из программы.

Для изменения размеров массива используют функцию Copy. Рассмотрим такой пример. Пусть динамический массив BigArray содержит 100 элементов. Нам необходимо увеличить его размер до 200 элементов. Для этого обращаемся к функции Copy:


Copy(BigArray, 200);


Предыдущее содержимое (значения элементов) массива остается неизменным, а его размер увеличен до 200 элементов.


Двумерные динамические массивы создаются аналогично. Объявление двумерного динамического массива имеет вид:


var

BigArray : array of array of Integer;

begin

SetLength(BigArray, 20, 20);

BigArray[0][0] := 200;

{ . . . . . . . . . . . . }


Finalize(BigArray);

end;



Строки


Строки в программах используются весьма интенсивно. Object Pascal дает нам три различных строковых типа: длинная строка, короткая строка и расширенная строка. Кроме того, есть строки с терминальным нулем.


Короткая строка


Короткая строка – это строка фиксированной длины с числом символов не более 255. Имеются два способа объявления строк фиксированной длины. В первом случае используется предопределенный тип ShortString, который объявляет строку длиной 255 байт. Во втором случае – ключевое слово string со спецификацией длины:


var

S1 : ShortString; { строка длиной 255 символов }

S2 : string[20]; { строка длиной 20 символов }


Так как объем памяти, выделяемой для строк этого типа, в процессе работы программы не изменяется, операции над строками фиксированной длины выполняются очень быстро. Однако, короткие строки – устаревший тип данных. В программах рекомендуется использовать длинные строки. Короткие строки называют строками с байтом длины, ибо первый ее элемент равен текущему числу символов в ней. Значение первого элемента можно прочесть и узнать сколько в строке символов, например,


Случайные файлы

Файл
шпора.doc
CBRR2776.DOC
2833-1.rtf
240-2350.DOC
4783.rtf