TURBO PASCAL |
Новости
|
2.2.2. Тестовая программаВ следующей программе осуществляется ввод произвольного вещественного числа и находится частное от деления единицы на корень квадратный из этого числа. В программе возможно возникновение исключительной ситуации при вводе числа (ошибочный символ в записи вещественного числа), извлечении корня (число меньше нуля) и делении (делитель равен нулю). Все три критические точки запоминаются в переменной Jump, которая используется в исключительной ситуации. Программа повторяет описанные действия до тех пор, пока не будет введена единица. _+———————---—————————————————————+ Программа иллюстрирует механизм выхода из процедуры [ завершения в нужную точку программы. В программе \ осуществляется ввод произвольного целого числа, затем ¦ вычисляется корень квадратный из него и находится \ обратная ему величина. Для завершения работы программы \ следует ввести единицу. \ +————————————————————————-—————————+^ Uses F Jump; var OldExit: Pointer; {Старое значение переменной ExitProc} Jump : JumpRec; {Сохранение точки выхода} г : Real; {Вспомогательная переменная} label Loop; Procedure MyExit; Far; {Эта процедура обрабатывает исключительную ситуацию} begin Long Jump(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(r); Set Jump(Jump); {Контролируем извлечение корня} if ErrorAddr <> NIL then begin WriteLn('Ошибка при извлечении корня'); Goto Loop end else r := sqrt(r); SetJump(Jump); {Контролируем деление} if ErrorAddr <> NIL then begin WriteLn('Ошибка при делении чисел'); Goto Loop end else r := 1/r; WriteLn(r:20:10) until r = 1; ExitProc := OldExit {Нормальный выход} end. Как нетрудно заметить, процедура обработки исключительной ситуации MyExit в рассмотренном примере просто возвращает управление в нужную точку программы. Разумеется, в реальной программе ее можно сделать более сложной. Однако для большей «прозрачности» программы я рекомендую все дополнительные действия, связанные с обработкой исключительной ситуации, размещать в теле основной программы — ведь в критических точках обычно используются условные операторы вида if ErrorAddr о NIL then ... Отмечу одну особенность: непосредственно перед передачей управления в пользовательскую процедуру выхода Турбо Паскаль автоматически помещает в переменную ExitProc значение NIL. По этой причине оператор ExitProc := SMyExit помещен в тело цикла Repeat... Until. Если разместить его перед оператором Repeat, то после первой же ошибки программа перестанет обрабатывать исключительные ситуации, поэтому повторная ошибка приведет к аварийному завершению программы. При использовании описанного средства обработки исключительных ситуаций в сложных программах с несколькими модулями следует учесть, что при передаче управления в подпрограмму другого модуля обычно изменяется значение сегмента кода. Если Вы использовали процедуру обработки ошибки в одном модуле, а ошибка возникла в процедуре из другого модуля, управление передается в процедуру обработки ошибки со значением сегмента кода, соответствующим модулю, в котором произошла ошибка. В результате процедура LongJump не сможет установить правильный NEAR— адрес переменной Jump и программа «зависнет». Чтобы этого не произошло, LongJump должна использовать FAR— адрес переменной Jump. Проще всего этого можно достичь, если поместить переменную Jump в интерфейсную часть любого модуля и использовать эту переменную для организации обработки исключительных ситуаций. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |