Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Pascal: Общие вопросы > Обработка исключительных ситуаций


Автор: romtek 12.04.04, 20:44
Обработка исключительных ситуаций
Модуль с примером из книги Фаронова В.В.

Решает проблемы ошибки деления на ноль, критических ошибок ввода/вывода.

Пример использования
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    {+-------------------------------------------------------+
     | Программа иллюстрирует механизм выхода из процедуры   |
     |   завершения в нужную точку программы.В программе     |
     | осуществляется ввод произвольного целого числа, затем |
     |   вычисляется корень квадратный из него и находится   |
     | обратная ему величина.Для завершения работы программы |
     |             следует ввести единицу.                   |
     |+------------------------------------------------------+}
    Uses F_Jump;
    var
      OldExit: Pointer;  {Старое значение переменной ExitProc}
      Jump   : JumpRec;  {Сохранение точки выхода}
      rr      : Real;     {Вспомогательная переменная}
    label
      Loop;
    Procedure MyExit; Far;
      {Эта процедура обрабатывает исключительную ситуацию}
    begin
      LongJump(Jump)
    end;  {MyExit}
    begin
      OldExit := ExitProc;
      repeat
    Loop:                   {Точка повторения ввода}
        if ErrorAddr <> NIL then
          begin
            Write('Повторите ввод числа: ');
            ErrorAddr := NIL;
            ExitCode := 0
          end
        else
          Write('Введите число: ');
        ExitProc := @MyExit;        {Адрес процедуры выхода}
        SetJump(Jump);              {Контролируем ввод данных}
        if ErrorAddr <> NIL then
          begin
            WriteLn('Ошибка при вводе вещественного числа');
            Goto Loop
          end
        else
          ReadLn(rr);
        SetJump(Jump);             {Контролируем извлечение корня}
        if ErrorAddr <> NIL then
          begin
            WriteLn('Ошибка при извлечении корня');
            Goto Loop
          end
        else
          rr := sqrt(rr);
        SetJump(Jump);              {Контролируем деление}
        if ErrorAddr <> NIL then
          begin
            WriteLn('Ошибка при делении чисел');
            Goto Loop
          end
        else
          rr := 1/rr;
        WriteLn(r:20:10)
      until rr = 1;
      ExitProc := OldExit       {Нормальный выход}
    end.

Автор: AndNot 30.03.09, 14:50
Цитата SkyStar @
В Pascal нельзя никак отлавливать исключения.
Никогда не говори - никогда :D
Можно создать некий аналог try..except, несколько расширив стандартную возможность перехвата исключений - ExitProc:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    unit Except;
     
    interface
    type
      Try = record
        _sp, _bp: Word;
        _farptr: Pointer;
      end;
     
    procedure SetExcept(var dest: Try); inline (
    $5f/$07/$26/$89/$25/$26/$89/$6d/$02/
    $e8/$00/$00/$58/$05/$0c/$00/$26/$89/
    $45/$04/$26/$8c/$4d/$06);
     
    procedure ProceedExcept(var dest: Try); inline (
    $5f/$07/$26/$8b/$25/$26/$8b/$6d/$02/
    $26/$ff/$6d/$04);
     
    implementation
     
    end.

а это пример:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    uses dos, crt, except;
     
    var
      OldExit: Pointer;
      exc    : Try;
      r      : Real;
    label
      l;
     
    procedure NewExit; far;
    begin
      ExitProc := @NewExit;
      ProceedExcept(exc);
    end;
     
    begin
      OldExit := ExitProc;
      ExitProc := @NewExit;
      repeat
      l:
          Writeln;
          Write('Enter number: ');
          SetExcept(exc);
          Readln(r);
          ErrorAddr := NIL;
          SetExcept(exc);
          if ErrorAddr <> NIL then
            Goto l;
          Writeln('100/',r,'= ',100.0/r);
      until (r=1);
      ExitProc := OldExit;
    end.

Данный примерчик довольно трудно уронить, он вполне спокойно обруливает неверный ввод числа, а так же деление на ноль.
Но модуль except не идеален, его нужно немного дополнить, что бы иметь возможность восстанавливать программу даже в особо тяжелых случаях, когда важны значения всех регистров. Но для примера сойдет :)

Это сообщение было перенесено сюда или объединено из темы "как отлаливать исключение в турбо паскале 7.0"

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)