Exception Handling in C++: Understanding Try, Catch, and Throw, Study notes of Programming Languages

An introduction to exception handling in c++ programming. It explains what exceptions are, how to use try, catch, and throw keywords to handle abnormal program behavior, and how to write and catch local exceptions. The document also covers catching multiple exceptions and includes examples of exception handling for division by zero and user input validation.

Typology: Study notes

2010/2011

Uploaded on 09/06/2011

vrunda
vrunda 🇮🇳

4.1

(21)

76 documents

1 / 8

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Foundations of Exceptions
Introduction
During the execution of a program, the computer will face two types of situations: those
it is
prepared to deal with and those it doesn’t like. Imagine you write a program that asks the
user to
supply two numbers to perform a calculation. Here is such a program:
#include <iostream>
using namespace std;
int main(){
double a, b, c; // Request two numbers from the user
cout << "Please provide two numbers\n";
cout << "First Number: ";
cin >>a;
cout << "Second Number: ";
cin >> b; // Multiply the numbers and display the
result c = a * b;
cout << "\n" << a << " * " << b << " = " << c << "\n\n";
return 0;
}
This is a classic easy program. When it comes up, the user is asked to simply type two
numbers; the program would use them to perform a multiplication and display the result.
Imagine that a user, thanks to his infinite creativity or because of just a mistake, decides
to type the name of a country or somebody’s telephone number as one of the requested
values. Since a program such as this one is not prepared to multiply two strings or one
number to a string (actually, using operator overloading, you can tell the compiler how to
perform almost any type of operation on the values of your program), it would not know
what to do. The only alternative the compiler would have is to send the problem to the
operating system, hoping that the OS would know what to do. What actually happens is
that, whenever the compiler is handed a task, it would try to perform the assignment. If it
can’t perform the assignment, for any reason it is not prepared for, it would throw an
error. As a programmer, if you can anticipate the type of error that could occur in your
program, you can catch the error yourself and deal with it by telling the compiler what to
do when this type of error occurs.
Exceptional Behaviors
An exception is a situation that would be unusual for the program that is being processed. As a
programmer, you should anticipate any abnormal behavior that could be caused by the user entering
wrong information that could otherwise lead to unpredictable results.
An error result or an unpredictable behavior on your program not caused by the operating system
but that occurs in your program is called an exception. The ability to deal with a program’s
pf3
pf4
pf5
pf8

Partial preview of the text

Download Exception Handling in C++: Understanding Try, Catch, and Throw and more Study notes Programming Languages in PDF only on Docsity!

Foundations of Exceptions Introduction During the execution of a program, the computer will face two types of situations: those it is prepared to deal with and those it doesn’t like. Imagine you write a program that asks the user to supply two numbers to perform a calculation. Here is such a program: #include using namespace std; int main(){ double a, b, c; // Request two numbers from the user cout << "Please provide two numbers\n"; cout << "First Number: "; cin >>a; cout << "Second Number: "; cin >> b; // Multiply the numbers and display the result c = a * b; cout << "\n" << a << " * " << b << " = " << c << "\n\n"; return 0; } This is a classic easy program. When it comes up, the user is asked to simply type two numbers; the program would use them to perform a multiplication and display the result.

Imagine that a user, thanks to his infinite creativity or because of just a mistake, decides to type the name of a country or somebody’s telephone number as one of the requested values. Since a program such as this one is not prepared to multiply two strings or one number to a string (actually, using operator overloading, you can tell the compiler how to perform almost any type of operation on the values of your program), it would not know what to do. The only alternative the compiler would have is to send the problem to the operating system , hoping that the OS would know what to do. What actually happens is that, whenever the compiler is handed a task, it would try to perform the assignment. If it can’t perform the assignment, for any reason it is not prepared for, it would throw an error. As a programmer , if you can anticipate the type of error that could occur in your program, you can catch the error yourself and deal with it by telling the compiler what to do when this type of error occurs.

Exceptional Behaviors

An exception is a situation that would be unusual for the program that is being processed. As a programmer, you should anticipate any abnormal behavior that could be caused by the user entering wrong information that could otherwise lead to unpredictable results.

An error result or an unpredictable behavior on your program not caused by the operating system but that occurs in your program is called an exception. The ability to deal with a program’s

eventual abnormal behavior is called exception handling. C++ provides three keywords to handle an exception.

  1. Trying the normal flow: To deal with the expected behavior of a program, use the try keyword as in the following syntax:

try { Behavior }

The try keyword is required. It lets the compiler know that you are anticipating an abnormal behavior and will try to deal with it. The actual behavior that needs to be evaluated is included between an opening curly bracket “{“ and a closing curly bracket “}”. Inside of the brackets, implement the normal flow that the program should follow, at least for this section of the code.

  1. Catching Errors: During the flow of the program as part of the try section, if an abnormal behavior occurs, instead of letting the program crash or instead of letting the compiler send the error to the operating system, you can transfer the flow of the program to another section that can deal with it. The syntax used by this section is:

catch( Argument ) { WhatToDo } This section always follows the try section and there must not be any code between the try ’s closing bracket and the catch section. The catch keyword is required and follows the try section. The catch behaves a little like a function. It uses an argument that is passed by the previous try section. The argument can be a regular variable or a class. If there is no argument to pass, the catch must at least take a three-period argument as in catch(…). The behavior of the catch clause starts with an opening curly bracket “{“ and ends with a closing curly bracket “}”. The inside of the brackets is called the body of the catch clause. Therefore, use the body of the catch to deal with the error that was caused.

Combined with the try block, the syntax of an exception would be:

try { // Try the program flow } catch( Argument ){ // Catch the exception }

  1. Throwing an error: There are two main ways an abnormal program behavior is transferred from the try block to the catch clause. This transfer is actually carried by the throw keyword. Unlike the try and catch blocks, the throw keyword is independent of a formal syntax but still follows some rules.

#include using namespace std; int main(){ double Number1, Number2, Result;// Request two numbers from the user cout << "Please provide two numbers\n"; try { cout << "First Number: "; cin >> Number1; cout << "Second Number: "; cin >> Number2; if( Number2 == 0 ) throw; // Perform a division and display the result Result = Number1 / Number2; cout << "\n" << Number1 << " / " << Number2 << " = " << Result << "\n\n"; }

catch(...) { }

return 0;} Test the program and supply two valid numbers such as 126.45 and 5.

Return to your programming environment and test the program again. This time, type 0 for the second number.

Predicting Exceptions

Writing Local Exceptions

Imagine you write a program that requests a student’s age from the user. As we know, everybody’s age is positive. Therefore, we need to figure out what to do if the user types a negative number. The expression that checks whether the number entered is positive can be written as:

if(StudentAge < 0)

If the condition is true, the minimum you can do is to send the produced error away. This is done with the throw keyword:

try { if(StudentAge < 0) throw;}

Whenever an exception occurs, and whenever you use the try keyword to try an expression, you must transfer control to a catch block. This is where you should display your own message for the

error. Here is an example:

#include <iostream.h> int main(){ int StudentAge; try { cout << "Student Age: "; cin >> StudentAge; if(StudentAge < 0) throw "Positive Number Required"; cout << "\nStudent Age: " << StudentAge << "\n\n"; } catch(const char* Message) { cout << "Error: " << Message; } cout << "\n"; return 0; }

This program starts with the try block that asks the user to enter a positive number. If the user enters an invalid value, the program examines the throw keyword. This throw appears to display a string. The compiler registers this string and since there was an exception, the program exits the try block (it gets out of the try block even if the rest of the try block is fine) and looks for the first catch block it can find. If it finds a catch that doesn’t take an argument, it would still use the catch. Otherwise, you can use the catch block to display the error string that was sent by the throw keyword. In the example above, the catch uses a string as a pseudo-argument and displays it using a cout extractor.

In the example above, the catch block is configured to display a string. Let’s consider the classic division by zero operation. The division by zero is dealt with at different levels. The processor (Intel, AMD, etc) is configured not to allow it. The operating system is also prepared for it. Finally, the compiler has its own interpretation of this operation. Nevertheless, if you suspect it to occur in your program, you can take appropriate measures. When preparing to deal with division by zero, the main idea is to compare the denominator with 0. This comparison should be performed in a try block. If the comparison renders true, you should avoid the operation and hand the error (exception) to a catch. The catch is usually used to display a message as in the last code. Here is an example:

#include using namespace std; int main(){ double Operand1, Operand2, Result; // Request two numbers from the user cout << "This program allows you to perform a division of two numbers\n"; cout << "To proceed, enter two numbers: "; try { cout << "First Number: "; cin >> Operand1;

One Exception }catch( Arg2 ) { Another Exception }

The compiler would proceed in a top-down as follows:

  1. Following the normal flow control of the program, the compiler enters the try block.
  2. If no exception occurs in the try block, the rest of the try block is executed. If an exception occurs in the try block, the try displays a throw that specifies the type of error that happened. a. The compiler gets out of the try block and examines the first catch b. If the first catch doesn’t match the throw n error, the compiler proceeds with the next catch. This continues until the compiler finds a catch that matches the throw n error. c. If one of the catches matches the thrown error, its body executes. If no catch matches the thrown error, you have (or the compiler has) two alternatives. If there is no catch that matches the error (which means that you didn’t provide a matching catch), the compiler hands the program flow to the operating system (which calls the terminate() function). Another alternative is to include a catch whose argument is three periods: catch(…). The catch(…) is used if no other catch , provided there was another, matches the thrown error. The catch(…) , if included as part of a catch clause, must always be the last catch , unless it is the only catch of the clause.

Multiple catches are written if or when a try block is expected to throw different types of errors. Imagine a program that requests some numbers from the user and performs some operation on the numbers. Such a program can be written as follows:

#include <iostream.h> int main(){ double Operand1, Operand2, Result; char Operator; cout << "This program allows you to perform an operation on two numbers\n"; cout << "To proceed, enter a number, an operator, and a number:\n"; cin >> Operand1 >> Operator >> Operand2; switch(Operator) { case '+': Result = Operand1 + Operand2; break; case '-': Result = Operand1 - Operand2; break; case '*': Result = Operand1 * Operand2; break; case '/': Result = Operand1 / Operand2; break; default: cout << "Bad Operation"; } cout << "\n" << Operand1 << " " << Operator << " " << Operand2 << " = " << Result;

cout << "\n\n"; return 0; }