Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс DELPHI_2003.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
530.71 Кб
Скачать

Функции работы с символами

В практике часто приходится обрабатывать отдельные символы. Переменным символьного типа Char можно присваивать значения таким образом:

var

c,b : Char;

begin

c := 'a';

b := c;

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

if b > c then ShowMessage('Истина!')

else ShowMessage('Ложь!');

При работе с символьными переменными часто используют функции Chr() и Ord(). Функция Chr() принимает в качестве параметра число, и возвращает символ, который соответствует этому числу в таблице ANSI:

function Chr ( X: Byte ): Char;

Функция Ord() совершает прямо противоположное действие, она принимает в качестве параметра символ, и возвращает число, под которым этот символ хранится в таблице ANSI:

function Ord ( C: Char ): Byte;

Символьные переменные можно использовать с этими функциями:

a := Chr(200);

i := Ord(a);

i := Ord('f');

В первой строке в переменную a мы записали символ "И", которому в таблице символов соответствует номер 200. Во вторую, целую переменную, мы записали число 200, так как символ с этим номером был записан в переменную a, которую мы передали в качестве параметра. Наконец, в третьей строке мы в целую переменную записали число 102, этот номер соответствует символу "f".

Строка

Строка – это набор символов. Строку можно представить в виде статичного или динамичного массива символьных данных. Типы строк мы уже разбирали в 4 лекции: AnsiString – строка из ANSI – символов, и WideString – строка из UNICODE – символов.

Тип String не является отдельным типом, по умолчанию он равен AnsiString. Однако его можно перенастроить и на WideString, хотя в этом нет необходимости. Поэтому смело указывайте строковые переменные, как String:

var

s : String;

begin

s := 'Это многострочная' + #13 + 'строка';

ShowMessage(s);

Как видно из примера, строку можно составлять из нескольких подстрок, и даже добавлять в нее отдельные символы. В примере мы добавили символ под номером 13, это символ перехода на новую строку. В результате выполнения этого кода процедура ShowMessage() выведет на экран сообщение, разбитое на две строки:

Это многострочная

строка

ShortString – короткая строка из ANSI – символов. Может содержать от 0 до 255 символов. Используется нечасто. Собственно, вы можете объявить тип String с заранее указанным размером:

var

s : String[100];

Как видите, строка объявляется с числовым индексом, почти как массив. Собственно, строка символов и есть массив символьных данных, и обращаться с ней можно также. Индексация символов в строке начинается с единицы, то есть, индексу 1 соответствует 1-й символ строки.

var

stroka : String;

begin

stroka := 'Привет';

stroka[5] := 'а'; //изменили 5-й символ строки

ShowMessage(stroka); //результат: строка "Приват"

PChar

Это тоже строка, и в будущем нам придется с ней сталкиваться. Эта строка работает совершенно иначе, чем String. Строка String представляет собой массив символов, в нулевом элементе которого содержится количество байт, отводимых под эту строку. А переменная типа PChar – это не сама строка, а указатель на начало строки, то есть переменная указывает на первый символ строки в памяти компьютера. А где же тогда PChar хранит количество байт в строке?! А нигде! Мы уже говорили о таблице символов ANSI, и выяснили, что нулевой символ – пустой. Вот последний символ PChar как раз и хранит этот символ, и компьютер, найдя его, считает, что строка окончена.

Со строками PChar работать очень неудобно, однако нам придется это делать, когда мы будем работать с функциями WinAPI напрямую. Функции WinAPI – это функции самой Windows, а не Delphi. Однако Delphi позволяет использовать их. Иногда это бывает необходимо, например, когда средств Delphi недостаточно для выполнения намеченной задачи. Использование таких функций не всегда удобно, однако они выполняются процессором намного быстрее, так как содержатся в самой операционной системе. Пример – функция MessageBox().

Вы уже привыкли выводить сообщения с помощью функции Delphi ShowMessage()? Привыкайте к новой функции!

Application.MessageBox('строка 1', 'строка 2',[ кнопки + тип_окна]);

Здесь:

  • строка 1 - выводит текст внутри окна.

  • строка 2 – текст в заголовке окна.

Если не указывать [кнопки + тип_окна] то выйдет простое окно с кнопкой ОК, как в функции ShowMessage().

Таблица 10.1. Типы кнопок

Кнопки

Описание

MB_OK

(ОК)

MB_OKCANCEL

(ОК и Отмена)

MB_RETRYCANCEL

(Повторить и Отмена)

MB_YESNO

(Да и Нет)

MB_YESNOCANCEL

(Да, Нет и Отмена)

MB_ABORTRETRYIGNORE

(Прервать, Повтор и Пропустить)

Таблица 10.2. Типы окон

Тип окна

Описание

MB_ICONWARNING

(желтый треугольник с "!")

MB_ICONINFORMATION

(белый шарик с "i")

MB_ICONQUESTION

(белый шарик с "?")

MB_ICONERROR

(красный круг с белым крестиком)

Эта функция, помимо вывода сообщения, также возвращает значение – идентификатор кнопки, которую нажал пользователь:

Таблица 10.3. Возвращаемое функцией значение

Значение

Нажатая кнопка

IDOK

ОК

IDCANCEL

Отмена

IDABORT

Прервать

IDRETRY

Повтор

IDIGNORE

Пропустить

IDYES

Да

IDNO

Нет

Пример использования:

Application.MessageBox('Ошибка копирования файла!', 'Ошибка',

MB_ABORTRETRYIGNORE+MB_ICONERROR)

В результате выполнения этой функции программа выведет окно:

Рис. 10.1.  Окно функции MessageBox()

Давайте сразу попробуем эту функцию на примере. Создайте новое приложение. На форму установите компонент Label для вывода результата, и кнопку. В свойстве Caption компонента Label удалите весь текст. Создаем обработчик нажатия кнопки. Поскольку функция возвращает перечисляемое значение, мы можем использовать case. Пишем такой код:

case Application.MessageBox('Ошибка копирования файла!', 'Ошибка',

MB_ABORTRETRYIGNORE+MB_ICONERROR) of

IDABORT : Label1.Caption := 'Прервать';

IDRETRY : Label1.Caption := 'Повтор';

IDIGNORE: Label1.Caption := 'Пропустить';

end; //case

В примере в качестве селектора для case мы указали саму функцию. Когда пользователь нажмет одну из кнопок, функция вернет числовое значение, соответствующее константе одной из кнопок. В результате, выполнится нужный код, и в свойство Caption компонента Label запишется, какая из кнопок была нажата.

Сохраните пример, откомпилируйте и посмотрите, как он работает. Попробуйте изменить тип окна на другой, например на MB_ICONQUESTION.

Функции работы со строками

Используя операции сравнения =, <, >, <=, >= строки можно сравнивать между собой. При этом большей считается та строка, в одинаковой позиции которой находится символ с большим кодом. Если все символы одинаковы, строки считаются равными. Примеры:

Таблица 10.4. Примеры сравнения строк

Строка 1

Строка 2

Результат сравнения

Иванов

Иванов

Строки равны

васильев

Васильев

Строка 1 > Строки 2

Алексеев

Петров

Строка 1 < Строки 2

Иванова

Иванов

Строка 1 > Строки 2

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

Length()

Очень полезная, и часто используемая функция. Она возвращает длину строки (количество символов). Примерыиспользования:

Var

s : String;

i : Integer;

begin

s := ‘Иванов’;

i := Length(s); //результат – 6

i := Length(‘Иванова’); // результат - 7

Процедура Delete

Процедура принимает в качестве параметра строку и удаляет какую-то ее часть. Синтаксис процедуры такой:

Delete(Строка, p, n);

Где:

  • Строка – переменная строкового типа.

  • p – номер символа, с которого начинается удаление.

  • n – количество удаляемых символов.

Пример использования:

s := 'Город Санкт-Петербург';

Delete(s, 7, 6);

В результате выполнения данного кода в строке s останется текст "Город Петербург".

Функция Pos()

Функция находит подстроку Substr в строке S и возвращает индекс первого символа найденной подстроки. Если S не содержит указанную подстроку, то функция возвращает 0:

Функция Pos ( Substr: string; S: string ): Integer;

Пример использования:

var

S: string;

I: Integer;

begin

S:= 'Влесуродиласьелочка';

I:= Pos( 'лес', S); // I = 3

end;

Функция Copy()

Функция возвращает подстроку размером Count символов, начиная с символа Index. Параметр S – передаваемая в функцию строка; Index и Count – целые числа. Если Index больше длины строки, то функция возвращает пустую строку. Если значение параметра Count больше, чем может быть возвращено функцией, то возвращаются символы или элементы, начиная с Index и до конца S.

Функция Copy ( S, Index, Count ): string;

Пример использования:

var

S: string;

begin

S:= 'Победа';

S:= Copy( S, 3, 4); // S = 'беда'

end;

На начальном этапе обучения этих функций вам будет вполне достаточно. С их помощью можно решить практически любую задачу по обработке символов и строк.

До сих пор мы создавали программы, не задумываясь о том, какие файлы при этом создаются, для чего они нужны. Нам понятно, что файл проекта с расширением *.exe – это сама программа, которая получилась после компиляции проекта. Файлы с расширением *.pas – файлы модулей, содержащих исходный код программы. Настало время подробней изучить структуру проекта, из каких файлов он состоит, для чего они нужны, какова их внутренняя структура.

Занятие 11

Модуль

Проект в Delphi представляет собой набор программных единиц – модулей. Модуль на английском языке называется Unit. Когда мы разрабатываем форму, мы одновременно обрабатываем модуль этой формы. Модуль – это файл с расширением *.pas. Это расширение – сокращение от языка программирования Pascal, на котором строилась Delphi. Иначе говоря, модуль – исходный код программы, или исходник. Как только мы создаем новую форму, сразу же создается и модуль для нее. Delphi заполняет этот модуль необходимым кодом, а нам остается создавать код для обработки кнопок и различных событий.

Давайте на примере уже рабочей программы посмотрим, из чего состоит проект. Откройте проект MyNotebook из лекции 8. Перейдите на редактор кода.

На самом верху вы видите строку

unit Main;

Unit – это зарезервированное слово, обозначающее Модуль формы. Зарезервированными называются служебные слова, которые уже имеют собственные названия в компиляторе, и такие названия нельзя давать переменным, константам, массивам, компонентам, функциям или процедурам. Зарезервированные слова в коде всегда выделяются жирным шрифтом, вы можете это видеть на примере таких слов, как unit, interface, uses, begin или end, и так далее:

Рис. 11.1.  Фрагмент редактора кода

Когда мы создавали форму, то сразу дали ей имя (свойство Name) fMain. А когда сохраняли проект, Delphi прежде всего запросила имя для модуля формы. Мы назвали модуль также как форму, но без начальной буквы f - Main. Вот почему наверху кода unit (Модуль) этой формы имеет имя Main. Теперь вы понимаете, как важно соблюдать правила наименования форм и модулей? Когда в проекте будет много форм, то и модулей будет много, и если вы не будете соблюдать эти правила, то запросто запутаетесь в названиях. И также важно давать формам и модулям осмысленные имена. В сложных проектах таких форм и модулей может быть сотни!

Но вернемся к проекту MyNotebook. Взгляните на код. Далее идет служебное слово interface. Эта директива сообщает компилятору, что начинается раздел интерфейса. В этом разделе, прежде всего, указываются модули, подключенные к данному модулю. Они описываются после служебного слова uses. Когда мы вводим какую-либо функцию или процедуру, мы не задумываемся, откуда она берется. А эта функция описана в одном из подключенных модулей! Давайте в этом убедимся. Спустите курсор в нижнюю часть модуля. Последней у нас описана процедура вызова модального окна fAbout. Ниже этого вызова введите строку:

ShowMessage('Привет!');

Она тут совершенно не нужна, и потом мы ее удалим. А пока что установите курсор внутри самого слова ShowMessage, и нажмите <Ctrl>+<F1>. Тем самым, вы вызываете контекстную подсказку именно об этой команде. И в самом начале справки вы видите указание, в каком модуле описана данная процедура:

Unit

Dialogs or QDialogs

Теперь вернитесь к разделу uses, в котором описаны подключенные модули. Вы можете убедиться, что модуль Dialogs в списке присутствует. Если бы это было не так, то при попытке вызвать процедуру ShowMessage компилятор сразу сообщил бы нам об ошибке, он просто не нашел бы описания этой процедуры и не знал, откуда ее вызвать. Данный раздел подключенных модулей Delphi генерирует самостоятельно, и добавлять сюда другие модули вручную приходится лишь в том случае, когда вы хотите воспользоваться процедурой, описанной в модуле, которого в списке нет. Вы точно знаете, что такая процедура или функция существует, но компилятор выдает ошибку. Тогда вы устанавливаете курсор на имя процедуры и вызываете контекстную подсказку. И смотрите, в каком модуле описана данная процедура. Если этого модуля в списке нет, а процедура вам нужна позарез, добавьте модуль в список.

Кстати, количество подключенных к форме модулей объясняет, почему, казалось бы, небольшой проект имеет достаточно большой размер *.exe файла. Ведь подключенные модули содержат множество описаний функций и процедур, и даже если мы их не используем, они все равно доступны. Однако беспокоиться по этому поводу не стоит – нам едва ли придется писать программы, для которых критичен размер исполняемого файла. Это, как правило, драйверы или вирусы, и хотя на Delphi можно написать и то, и другое, для этих задач больше подходит чистый С. А если вы будете использовать Borland C++ Builder или Microsoft C++ Visual, то и они имеют множество подключенных модулей, и размер даже маленькой программки окажется большим.

Вернемся к нашему коду. Далее идет служебное слово type, которое описывает форму – какие в ней находятся компоненты, как они называются, и какие процедуры используются. В этом блоке вы видите разделы:

private

{ Private declarations }

public

{ Public declarations }

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

Далее идет описание глобальных записей, констант и переменных. Здесь у нас есть только одна глобальная переменная:

var

fMain: TfMain;

Это – форма. Да, да, не удивляйтесь, форма – это переменная типа TForm. Точнее, не просто переменная, а объект со своими свойствами, событиями и методами.

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

В этом разделе глобальных переменных мы можем создать собственную переменную:

var

fMain: TfMain;

adres: String; //для адреса, откуда запущена программа

Затем выделить главную форму, перейти на вкладку Events (События) и двойным щелчком мыши сгенерировать событие OnCreate, которое происходит однажды, при создании формы, или же OnActivate, которое происходит, когда форма становится активной. В этом событии прописать такую строку:

adres := ExtractFilePath(Application.ExeName);

Переменную adres в процедуре описывать не нужно – она глобальная, и мы ее уже описали. Функция Application.ExeName вернет полное имя файла нашей программы, а функция ExtractFilePath() вычленит из этого имени адрес, и вернет его. В дальнейшем, в любой процедуре или функции модуля, где будет необходимо обратиться к файлу, например, myparam.ini, который находится там же, откуда запущена программа, достаточно указать:

... adres + 'myparam.ini' ...

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

Далее идет раздел implementation. Это раздел реализации. Он содержит сами процедуры и функции, которые поддерживают работу этой формы. Кроме того, в этом разделе также может присутствовать директива uses, в которой объявлены модули, подключенные к данной форме. Данный раздел необязателен – если в вашем проекте только одна форма, то раздела не будет вовсе. Если есть еще одна форма, как в нашем примере – форма fAbout, модуль которой называется About, то этот раздел добавляется автоматически, как только вы воспользуетесь командой File -> Use Unit. Сразу под ключевым словом implementation у нас есть строка

uses About;

которая говорит о том, что к данной форме подключен модуль About. Можно модули добавлять и вручную, однако лучше все-таки делать это с помощью команды меню – так вы будете застрахованы от возможных ошибок. Однако если вы создали ошибочную связь с другой формой, то удалить эту связь можно вручную.

Далее вы видите такую строку, выделенную зеленым цветом:

{$R *.dfm}

Это не комментарий, как можно было бы подумать, а директива компилятору, что в процессе компиляции следует использовать файл описания формы. Файлы, которые составляют проект, мы рассмотрим чуть позже.

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

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

Закройте этот проект, сохранять его не нужно, команда ShowMessage, которую мы дали для примера, в программе не нужна. Создайте новый проект и перейдите в редактор кода. Сразу после директивы компилятора вы видите строку

end.

Обратите внимание, что слова begin перед ней нет, и быть не должно! Это – единственное исключение из правила скобок begin..end. Собственно, это даже не исключение, потому что эта end не является закрывающей скобкой, это завершение модуля.

Теперь, если мы будем устанавливать на форму компоненты, и обрабатывать для них события, будут формироваться процедуры между директивой компилятору и завершающей end.

Занятие 12