Исключительные ситуации
Исключительная ситуация (exception) — это прерывание нормального хода работы программы из-за невозможности правильно выполнить последующие действия. Для обработки исключений в Delphiпредусмотрен механизм защищенного блока. Защищенный блок начинается зарезервированным словом try(попытаться) и завершается словом end. Внутри блока располагается часть программы, в которой может возникнуть исключительная ситуация (ошибка). Существует два вида защищенных блоков: первый - в случае возникновения ошибок выполняются предусмотренные программистом действия и второй блок – независимо от того, была ошибка или нет, выполнить те или иные действия.
Первый блок завершается зарезервированым словом except (исключить), после которого следуют операторы обработки исключительной ситуации:
try
// защищаемые от ошибок операторы
except
// операторы обработки исключительной ситуации
end;
Между словами try и except помещаются защищаемые от ошибок операторы. Если при выполнении любого из этих операторов возникает исключительная ситуация, то управление передается операторам между словами exceptи end, образующими блок обработки исключительных ситуаций. При нормальном (безошибочном) выполнении программы блок except...end пропускается. При написании программы можно использовать вложенные защищенные блоки, чтобы организовать локальную и глобальную обработку исключительных ситуаций.
Если в защищаемом блоке может возникнуть несколько ошибок, и программист желает распознать их и назначить на каждую ошибку свое действие, то в секции обработки исключительных ситуаций через точку с запятой записываются классы исключительных ситуаций:
try
{ вычисления с вещественными числами }
except
on EZeroDivide do {обработка ошибки деления на нуль};
on EMathError do {обработка других ошибок
вещественной математики }
else {обработка всех остальных ошибок (обработчик по
умолчанию };
end;
Порядок операторов onв данном случае имеет значение, так как обработка ошибки деления на нуль является частным случаем любых ошибок вещественной математики. Если поменять местами эти два оператора, то ошибки деления на нуль никогда не будут обрабатываться, все ошибки будут квалифицироваться ошибками первого оператора.
Второй блок завершается зарезервированным словом finally (окончательно). Этот блок используется в том случае, когда программа распределяет некоторый ресурс (например, связывает файловую переменную с ресурсом на диске), но исключительная ситуация прерывает ее действие, а связь остается. Блок записывается следующим образом:
// запрос ресурса
try
// защищаемые операторы, которые используют ресурс
finally
// освобождение ресурса
end;
Если программа использует сразу несколько ресурсов, то блок try.. finally.. end может быть вложенным столько раз, сколько потребуется.
В таблице 9 представлены часто используемые в данном курсе классы исключительных ситуаций:
Таблица 9
Класс исключительных ситуаций | Описание |
EInOutError | Ошибка доступа к файлу или устройству ввода-вывода. |
EIntError | Общий класс исключительных ситуаций целочисленной арифметики, от которого порождены классы EDivByZero, ERangeError и EIntOverflow. |
EDivByZero | Попытка деления целого числа на нуль. |
ERangeError | Выход за границы диапазона целого числа или результата целочисленного выражения. |
EIntOverflow | Переполнение в результате целочисленной операции. |
EMathError | Общий класс исключительных ситуаций вещественной математики, от которого порождены классы EInvalidOp, EZeroDivide, EOverflow и EUnderflow. |
EZeroDivide | Попытка деления вещественного числа на нуль. |
EOverflow | Потеря старших разрядов вещественного числа в результате переполнения разрядной сетки. |
EUnderflow | Потеря младших разрядов вещественного числа в результате переполнения разрядной сетки. |
EConvertError | Ошибка преобразования данных с помощью функций IntToStr, StrToInt, StrToFloat, StrToDateTime. |
При возникновении исключительной ситуации во время тестирования приложения в среде Delphi, ошибка перехватывается отладчиком, поэтому сначала мы видим стандартное диалоговое окно с видом ошибки, а только потом ту часть программы, которую написали сами. Если приложение будет запускаться через исполняемый файл, то в случае возникновения ошибки, программа сразу выдаст результат специально написанной для этой ошибки.
Пример 17. Программа деления двумерного массива на число.
Положите на форму компоненты, как показано на рисунке 34.
Рисунок 34 - Внешний вид приложения на этапе конструирования
Последовательность действия пользователя при работе приложения предполагается такой: на форме видны только два компонента для ввода размера массива и две кнопки для ввода значений и для выхода из приложения. После правильного ввода размерности массива, появляются компоненты сетка, кнопка для ввода массива, компонент для ввода числа и кнопка для ввода этого числа. После этого, если все значения были введены правильно, становится видна сетка с результатом расчета.
Текст программы:
const
Nmax=255;
Mmax=255;
var
n,m:integer;
A,B:array [1..Nmax,1..Mmax] of real;
procedure TForm1.LabeledEdit1KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['0'..'9',#8,'-',
DecimalSeparator]) then key:=#0;
end;
procedure TForm1.BitBtn1Click(Sender: TObject); //Ввод m,n
begin
try // пользователь может ввести не целое число
n:=StrToInt(Form1.LabeledEdit1.Text);
m:=StrToInt(Form1.LabeledEdit2.Text);
Except
begin
MessageDlg('Ошибка ввода размерности!',
mtError,[mbOK],0);
exit;
end;
End;
if (n<=0) or (m<=0) then
begin
MessageDlg('неправильно введена размерность
массива!',mtError,[mbOK],0);
exit;
end;
Form1.StringGrid1.RowCount:=m;
Form1.StringGrid1.ColCount:=n;
Form1.StringGrid1.Width:=
Form1.StringGrid1.DefaultColWidth*n+10;
Form1.StringGrid1.Height:=
Form1.StringGrid1.DefaultRowHeight*m+10;
Form1.StringGrid1.Show;
Form1.BitBtn2.Show;
Form1.Label2.Caption:='Заполните массив';
Form1.Label2.Show;
end;
procedure TForm1.FormShow(Sender: TObject);
// метод «Показ формы» - установка начальных значений
begin
//эти методы и свойства можно установить в Инспекторе объектов
{реакция нажатия на клавишу для всех следующих компонентов одинакова:можно вводить только вещественные числа}
Form1.LabeledEdit2.OnKeyPress:=
Form1.LabeledEdit1.OnKeyPress;
Form1.LabeledEdit3.OnKeyPress:=
Form1.LabeledEdit1.OnKeyPress;
Form1.StringGrid1.OnKeyPress:=
Form1.LabeledEdit1.OnKeyPress;
{для первой сетки разрешен ввод значений с клавиатуры. Т.к. свойство Options является множеством, то следует перечислить все поля данного свойства, которые равны True}
Form1.StringGrid1.Options:=
[goFixedVertline,goFixedHorzLine,
goVertLine,goHorzLine,goEditing];
Form1.StringGrid1.FixedCols:=0;
Form1.StringGrid1.FixedRows:=0;
Form1.StringGrid1.Hide;
Form1.StringGrid2.FixedCols:=0;
Form1.StringGrid2.FixedRows:=0;
//---------------------
Form1.StringGrid2.Hide;
Form1.Label1.Hide;
Form1.Label2.Hide;
Form1.LabeledEdit3.Hide;
Form1.BitBtn2.Hide;
Form1.BitBtn4.Hide;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);//Ввод массива
var
i,j:integer;
begin
Try
for i:=0 to n-1 do
for j:=0 to m-1 do
A[i+1,J+1]:=
FloatToStr (Form1.StringGrid1.Cells[i,j]);
Except
on EConvertError do
begin
MessageDlg('Ошибка! Это не число', mtError,
[mbOK],0);
exit;
end;
End;
Form1.BitBtn4.Show;
Form1.LabeledEdit3.Show;
end;
procedure Dividion;
//Процедура деления. Написана самим программистом
var
k,i,j:integer;
begin
Form1.StringGrid2.RowCount:=m;
Form1.StringGrid2.ColCount:=n;
Form1.StringGrid2.Width:=
Form1.StringGrid2.DefaultColWidth*n+10;
Form1.StringGrid2.Height:=
Form1.StringGrid2.DefaultRowHeight*m+10;
Try
k:=StrToInt(Form1.LabeledEdit3.Text);
for i:=1 to n do
for j:=1 to m do
begin
B[i,j]:=A[i,j] / k;
Form1.StringGrid2.Cells[i-1,j-1]:=
FloatToStr (B[i,j]);
end;
Except
on EConvertError do
begin
MessageDlg(' Ошибка! Это не число',
mtError,[mbOK],0);
exit;
end;
on EZeroDivide do
begin
MessageDlg('Деление на нуль!',
mtError,[mbOK],0);
exit;
end;
end;//try
Form1.StringGrid2.Show;
Form1.Label1.Show;
Form1.LabeledEdit3.EditLabel.Caption:=
'Введенное число';
end;
procedure TForm1.BitBtn4Click(Sender: TObject);
begin
Form1.Label2.Caption:='Введенный массив';
Dividion;
end;
Пример 18. Расчет факториала. В данном примере использован целый тип данных результата вычисления.
Для того, чтобы включить проверку на переполнение, следует выбрать в главном меню Delphi пункт Project/Options. Откроется окно, в котором нужно выбрать вкладку Compilerи установить флаги проверок ошибок во время выполнения приложения (Runtime errors). Окно представлено на рисунке 35.
.
Рисунок 35 - Установка проверки ошибок
Текст программы:
var
f:integer;
function fact (n:integer):Integer;
begin
if n=1 then Result:=1
else
Result:=Fact(n-1)*n;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Try
f:=StrToInt(Form1.Edit1.Text);
Form1.Edit1.Text:=IntToStr(fact(f));
Except
on EConvertError do MessageDlg('Неправильно
введено число!',mtError,[mbOK],0);
on EIntOverFlow do MessageDlg
('Переполнение!',mtError,[mbOK],0);
End;
end;
Пример 19. Процедура записи в файл. При нажатии на кнопку происходит расчет функции с заданным шагом и в заданном диапазоне. Результаты расчета записываются в файл.
procedure TForm1.BitBtn1Click(Sender: TObject);
var
f:TextFile;
begin
Try
{файл с расчетами называется Test.txt и будет лежать в том же месте, что и исполняемый файл данного приложения (имя у этого приложениям Project1),у вас может быть другое имя}
AssignFile(f,ExtractFilePath('Project1.exe')
+'Test.txt');
ReWrite(f);
x:=x0;
repeat
y:=a*X*X+b*X+c;
WriteLn(f,FloatToStr(x)+' '+FloatToStr(y));
x:=x+h
until x>xk;
Дата добавления: 2015-04-10; просмотров: 1007;