It is useful to take a close look at Program 5.21 and make a list of the things that could go wrong with its execution:
MaxNum
(for example, the user could
enter a 0, a negative number, or a number greater than 10). In this case, the
program would terminate with a Constraint_Error
, Ada's usual
exception for out-of-range conditions.
ABC
or A1
. In this case, the program would
terminate with Ada.Text_IO.Data_Error
, because the input/output
system would complain about bad data.
Factorial
,
could produce a result that is simply too large. Some Ada systems, for example,
on IBM-PC-type computers, use the value 32767
for
Integer'Last
because this is the largest integer that will fit in
a 16-bit word. Because Factorial(8)
is 40320
, trying
to compute it will cause Constraint_Error
to be raised.
As written, Program 5.21 will terminate if any of these conditions arises, and the Ada "run-time system" will display a message. Generally the name of the exception will be displayed, but otherwise the form of the message depends upon the compiler.
Ada provides a useful mechanism called exception handling, which allows the programmer to "catch" the exception before it goes to the Ada run-time system. The programmer can supply, at the bottom of the program, procedure, or function, a set of statements, called exception handlers, indicating what is to be done in case an exception is raised. Later chapters, beginning with Chapter 6, will introduce exception handling systematically; for now, Program 5.22 shows you the general idea.
Program 5.22
WITH Ada.Text_IO; WITH Ada.Integer_Text_IO; WITH Useful_Functions; PROCEDURE Robust_Sum_Fact IS ------------------------------------------------------------------------ --| Prompts the user for an integer N from 1 to 10 --| and displays the sum and factorial of all integers from --| 1 to N. Sum and Factorial are gotten from package Useful_Functions. --| This version incorporates an exception handler part. --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ SUBTYPE OneToTen IS Positive RANGE 1..10; MaxNum: OneToTen; -- input - a value from 1-10 SumToCount: Positive; -- output - sum of integers from 1-Count ProdToCount: Positive; -- output - product of integers from 1-Count BEGIN -- Robust_Sum_Fact Ada.Text_IO.Put (Item => "Please enter an integer from 1 to 10 > "); Ada.Integer_Text_IO.Get (Item => MaxNum); Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item => " N Sum Factorial"); Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item => " ----------------------"); Ada.Text_IO.New_Line; FOR Count IN 1..MaxNum LOOP SumToCount := Useful_Functions.Sum (N => Count); ProdToCount := Useful_Functions.Factorial (N => Count); Ada.Integer_Text_IO.Put (Item => Count, Width => 3); Ada.Integer_Text_IO.Put (Item => SumToCount, Width => 7); Ada.Integer_Text_IO.Put (Item => ProdToCount, Width => 9); Ada.Text_IO.New_Line; END LOOP; EXCEPTION WHEN Constraint_Error => Ada.Text_IO.Put (Item => "The input value is out of range."); Ada.Text_IO.New_Line; WHEN Ada.Text_IO.Data_Error => Ada.Text_IO.Put (Item => "The input value is not well formed."); Ada.Text_IO.New_Line; END Robust_Sum_Fact;Sample Run
Please enter an integer from 1 to 10 > 11 The input value is out of range.
Notice that at the bottom of the program, there is a section:
EXCEPTION WHEN Constraint_Error => Ada.Text_IO.Put(Item => "The input value is out of range."); Ada.Text_IO.New_Line; WHEN Ada.Text_IO.Data_Error => Ada.Text_IO.Put (Item => "The input value is not well formed."); Ada.Text_IO.New_Line; END RobustSumFact;
Each
group of statements beginning with WHEN
is called an exception
handler. If the program executes normally, execution stops at the "normal"
last statement (the last line before the word EXCEPTION
); it is as
though the exception-handling section were not there. However, if an exception
is raised anywhere in the program, execution of the statement causing the
exception is halted, and control is passed immediately to the appropriate
exception handler. Once the handler's statements have been executed (in this
case, displaying a message), the program terminates normally. There is no
message dispayed by the run-time system; because the program handled its own
exception, the run-time system has no need to do so.
How useful is this? We will see in Chapter 6 how exception handling can make programs much less prone to terminate with error messages from the run-time system and also how exception handling can be used to ensure the validity of user input. In the simple case considered here, the usefulness of exception handling is that it allows the programmer to control the form of the message displayed when the program terminates. This is better than leaving it to the run-time system, the form of whose messages depends on the compiler.
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.