Исключительная (или особая) ситуация представляет собой сигнал о произошедшей в приложении ошибке. Для обработки исключительных ситуаций используются две конструкции:
try try
защищаемый код защищаемый блок
finally except
код завершения обработчик исключения
end; end;
В первом варианте блок finally выполняется независимо от того, возникла ли ошибка в процессе выполнения защищаемых операций.
Блок try except используется для обработки исключительных ситуаций. В Object Pascal исключительные ситуации представляют собой объекты, содержащие информацию, идентифицирующую ошибку и место ее возникновения. Внутри части except создаются обработчики особых ситуаций для классов исключительных ситуаций. Обработчик особой ситуации имеет следующий формат:
try
защищаемый блок except
on E: ESomeException do <обработчик исключениям end;
Для обработки особой ситуации Delphi предоставляет возможность создания временных объектов особой ситуации (Е), которые могут использоваться в обработчике исключения. Временный объект особой ситуации имеет тот же тип, что и объект исключения, который он обозначает (ESomeException).
|
|
Существуют предопределенные классы исключительных ситуаций для обработки стандартных ошибок, таких, как нехватка памяти, деление на нуль, числовое переполнение, ошибки ввода-вывода и другие. Перечислим некоторые из них:
EMathError класс-предок исключений, случающихся при выполнении операций с плавающей точкой;
EInvalidArgument значение параметра выходит за диапазон значений
EInvalidOp передача математическому сопроцессору ошибочной конструкции;
EOverflow переполнение разрядов при работе со слишком большими величинами;
EUnderflow потеря разрядов при работе со слишком малыми величинами;
EZeroDivide деление на ноль;
EIntError класс-предок исключений, случающихся при выполнении целочисленных операций;
EDivByZero деление на ноль;
EIntOverflow выполнение операций, приводящих к переполнению целых переменных;
ERangeError значение целочисленного выражения выходит за пределы установленного целочисленного типа. Попытка обращения к элементу массива по индексу, выходящему за пределы массива;
EListError обращение к элементу списка (String, List, TStringList) по индексу, выходящему за пределы допустимых значений;
EInOutError ошибки при операциях с файловой системой. Код ошибки возвращается в локальной переменной ErrorCode, которая может принимать следующие значения:
2 файл не найден
3 неверное имя файла
4 слишком много открыто файлов
5 отказ в доступе
100 конец файла
101 диск полон
106 неверная операция ввода;
EConvertErrorошибки преобразования типов (простых, объектных).
Например, для создания устойчивого к ошибкам приложения, записывающего данные в файл, необходимо написать следующий код:
|
|
begin
assignfile (f, 'data.dan1); try
append(f); try
writeln(f,s); finally
closefile(f); end; except
on E: EInOutError do if E. ErrorCode = 2 then
if MessageDlg('Файл не найден. Создать его?', mtError, [mbYes, mbNo],0)=mrYes
then FileCreate('data.dan');
end;
end;
В данном листинге внутренний блок try finally используется для того, чтобы файл был закрыт в любом случае, т. е. независимо от того, была ошибка или нет.
Внешний блок try except используется для обработки исключительной ситуации, которая может произойти в программе. После закрытия файла во внутреннем блоке finally блок except использует временный объект Е для определения типа произошедшей ошибки ввода/вывода.
Упражнение 5.2.1. Модифицируйте приложение, созданное в упр. 5.1.1, так, чтобы при повторном запуске программы данные, введенные в предыдущем сеансе, отображались на страницах блокнота.
Решение
Напишем метод, который все странички блокнота будет сохранять в отдельных файлах в каталоге, указанном в переменной dir. В разделе public описания класса TNoteBookF опишите метод SaveAll и переменную dir:
public
{ Public declarations } dir: string; procedure SaveAll;
В разделе Implementation модуля опишите программный код метода:
procedure TNoteBookF.SaveAll;
var i: integer;
TempComponent: TListBox; begin
InputQuery('Введите полное имя каталога','',dir);
for i:=0 to 11 do
begin
NoteBookl.Pagelndex:=i; TempComponent:=
TListBox(FindComponent('ListBox'+IntToStr(i+1))); TempComponent.Items.SaveToFile(dir+Month1+intToStr(i + 1));
{Строки компонента ListBox сохраняются в соответствующем файле}
end;
end;
Эксперимент. Сохраните и запустите приложение. Убедитесь в работоспособности приложения для существующих каталогов. Попробуйте сохранить файлы в несуществующий каталог, например c:\NoteBook\Month\. ♦
Для несуществующего каталога операционная система возбуждает исключительную ситуацию, результатом которой отображается сообщение об ошибке, изображенное на рис. 5.2.1: «Приложение Projectl.exe возбудило исключительную ситуацию типа EFCreateError с сообщением 'Невозможно создать
файл C:\NoteBook\Month\Monthl1. Процесс остановлен. Воспользуйтесь командами Step или Run для продолжения.»
Чтобы обезопасить приложение от подобного вида ошибок, добавим блок обработки исключительной ситуации EFCreateError (рис. 5.2.1), возникшей при сохранении файла:
begin
InputQuery('Введите полное имя каталога','',dir); if dir[length(dir)]<>'\'
then dir:=dir+'\';
{добавляем разделитель подкаталогов в конец строки}
for i:=0 to 11 do begin
NoteBookl.Pagelndex:=i;
TempComponent:=
TListBox(FindComponent('ListBox'+IntToStr(i+1)));
try
TempComponent.Items.SaveToFile(dir+'Month'+intToStr(i+1)); {Строки компонента ListBox сохраняются в соответствующем файле} except
on EFCreateError do
begin
{класс исключений, возникающих при неудачных попытках
создания файла}
makedir (dir); {процедура создания каталога (смотри ниже)} TempComponent.Items.SaveToFile(dir+'Month'+intToStr(i+1)); end; end; end; end;
Рассмотрим процедуру создания подкаталогов:
procedure MakeDir{dir: string); var d: string;
k: byte; begin
k:=pos('\',dir); d:=copy(dir,1,k); delete(dir,1,k);
{выделяем название корневого каталога из dir, запоминаем в переменной d}
while DirectoryExists(d) do begin
{пока каталог с именем, указанным в переменной d, существует} k:=pos ('\',dir); d:=d+copy(dir,1,k); delete(dir,1,k);
{выделяем имя очередного подкаталога из переменной dir} end;
{в переменной d хранится имя несуществующего каталога} CreateDir(d);
{стандартная функция создания подкаталога с именем d} while (pos('\',dir)<>0) do begin
k:=pos('\',dir); d:=d+copy(dir,1,k); delete(dir,1,k); CreateDir(d); end; end;
Эксперимент. Запустите приложение. Убедитесь, что при вводе неправильного имени каталога происходит обработка исключительной ситуации и создается каталог с заданным именем. ♦
Задания для самостоятельного выполнения
1. Сохранение данных блокнота. При нажатии кнопки 'Закрыть', если были внесены изменения в блокноте, появляется диалоговое окно с текстом 'Сохранить изменения?' и двумя кнопками 'Да' и 'Нет'. При нажатии на 'Да' данные сохраняются в файлах, при нажатии на 'Нет' — приложение закрывается без сохранения изменений.
|
|
2. Модифицируйте код приложения так, чтобы вопрос «Сохранить изменения?» появлялся только, если данные блокнота были изменены.
3. После щелчка на системной кнопке закрытия формы (крестик в правом верхнем углу формы), форма закрывается без предупреждения о необходимости сохранить данные блокнота. Исправьте этот недостаток.
4. Считывание данных в блокнот.
а) При запуске приложения страницы заполняются данными из файлов.
b) Создайте модальное окно выбора папки для сохранения (и считывания) данных блокнота. Модифицируйте код приложения так, чтобы при запуске появлялось модальное окно для выбора папки, в которой хранятся данные. Примечание. Используйте компоненты DriveComboBox, Directory ListBox, FileListBox, FilterComboBox со страницы Win 3.1 палитры компонентов.
5. Данные блокнота хранятся в двенадцати файлах — это не является рациональным с точки зрения компактности данных. Продумайте структуру файла для хранения записей блокно та и внесите необходимые изменения в программный код.
Примечание. Для работы с файловым типом данных в языке Object Pascal используются следующие процедуры:
AssignFile(<файловая переменная>, <имя файла>) — устанавливает соответствие между внешним файлом и файловой переменной.
Reset (<файловая переменная>) — открывает на чтение существующий внешний файл, ассоциированный с файловой переменной Append (<файловая переменная>) —подготавливает существующий файл, ассоциированный с файловой переменной, для добавления записей в конец.
Rewrite {<файловая переменная>) — создает новый файл с именем, соответствующим файловой переменной, и устанавливает его в режим записи элементов.
CloseFile (<файловая переменная>) — разрывает установленное соответствие между файловой переменной и внешним файлом.
6. Игра «Виселица». В файле содержатся слова русского алфавита. Приложение случайным образом выбирает одно из слов и предлагает его отгадать. Каждая буква загаданного слова отображается звездочкой. Игрок пытается отгадать слово, выбирая буквы из алфавита. Если выбранная буква в слове есть, она (или они, если таких букв несколько) отображается вместо звездочки в слове и удаляется из алфавита. Если выбранной буквы в слове нет, появляется очередной элемент виселицы (горизонтальная балка, перекладина, веревка, го лова, туловище, правая рука, левая рука, правая нога, левая нога) и буква удаляется из алфавита. Игра заканчивается победой, если слово отгадано, проигрышем, если появились все элементы виселицы.
|
|
7. Используя компонент RadioGroup, напишите приложение-тест. Первое окно: приложение предлагает ввести имя тестируемого. Далее даются вопросы теста по одному:
1. В компании кто-то рассказывает историю, которую вы уже слышали. Вы
а) улыбаясь, спокойно выслушиваете до конца;
б) отворачиваетесь или выходите из комнаты;
в) слушаете, но всем своим видом выражаете недовольство;
г) перебиваете рассказчика.
2. Кто-то высказывает мнение в корне противоречащее вашему. Вы:
а) выслушиваете и продолжаете заниматься своим делом;
б) стараетесь выйти;
в) говорите, что не желаете обсуждать с ним это;
г) защищаете свои убеждения.
3. Вы считаете, что
а) люди как правило на добро отвечают добром;
б) многие быстро забывают доброе к ним отношение;
в) люди корыстны;
г) многие неблагодарны и пользуются вашим добрым отношением к ним.
4. Настоящий друг
а) помогает тому, кого считает своим другом;
б) старается помочь;
в) в любых ситуациях поддержит;
г) всегда разделяет точку зрения того, кого считает другом.
1. В отношениях лучше, когда
а) никто из партнеров ни от кого не зависит;
б) оба партнера друг от друга во многом зависят;
в) кто-то зависит от вас;
г) вы зависите от партнера, зато он многое берет на себя.
2. Когда кто-то часто допускает речевые ошибки, вы
а) не обращаете внимания;
б) стараетесь лишь изредка поправлять его;
в) предлагаете ему взять уроки русского языка;
г) не можете удержаться от того, чтобы постоянно не поправлять его.
3. Встречаясь с новыми людьми, вы
а) ведете себя естественно;
б) бываете остроумны, чтобы произвести впечатление;
в) стремитесь быть настороже, чтобы ничто не прошло мимо вашего внимания;
г) постоянно помните, что подвергаетесь оценке окружающих.
4. Вы
а) любите обсуждать комические ситуации, в которых сами побывали;
б) любите когда подшучивают над вами;
в) очень любите подшучивать над другими;
г) не позволяете, чтобы другие подшучивали над вами.
5. Когда вас приглашает в гости кто-то из близких друзей, а вы уже собрались в другое место, то вы
а) говорите об этом;
б) не называете причины отказа;
в) прикидываетесь, что больны;
г) говорите, что у вас работа.
6. Вы считаете совершенно необходимым
а) быть с собой в ладу в любых ситуациях;
б) всегда соответствовать общему духу компании;
в) чтобы окружающие считались с вашим настроением;
г) держаться с достоинством и не показывать своих чувств.
Для перехода на следующий вопрос теста необходимо обязательно выбрать один из предлагаемых ответов. После ответа на последний вопрос теста предлагается интерпретация полученного результата:
Если общая сумма ответов «а» составляет 7 и более, то большинство людей относятся к вам с симпатией. Умение быть искренним и в то же время не обижать позволяет вам сохранять мир с самыми разными людьми. Вы умеете, оставаясь собой, позволять и другим быть собою. Вы не подстраиваетесь под чужое мнение, но и не требуете к себе особого отношения, проявляя терпимость и способность понять другого. Если общая сумма ответов «б» составляет 7 и более, то у вас, в общем, хорошие отношения с людьми. Вы достаточно терпимы. Иногда, правда, вы слишком «подыгрываете» окружающим, вплоть до неискренности. От этого сами, бывает, чувствуете дискомфорт. Тем не менее вам не чужды прагматизм и некоторое недоверие к окружающим. Поверьте, они это чувствуют.
Если общая сумма ответов «в» составляет 7 и более, то лишь немногие относятся к вам с симпатией. Со многими у вас возникают проблемы. Вы недостаточно терпимы к окружающим, вас многое раздражает. Вы предпочитаете иногда слишком дистанцироваться или, наоборот, чересчур давить на людей, если что-то вам не по вкусу. Ваше недоверие и подозрительность не могут оставаться незамеченными и отталкивают людей.
Если общая сумма ответов «г» составляет 7 и более, то вам никто не симпатизирует.
Если в ваших ответах самые разные варианты, то люди к вам относятся по-разному. Одни — с симпатией, а кому-то вы антипатичны. Но в любом случае, чем больше в ваших ответах вариантов «а», тем больше у вас шансов на взаимопонимание и взаимную симпатию в общении.