try

Exceptions in C++

The most rudimentary way to handle problems encountered at runtime is to call abort(). The abort() function has its prototype in the cstdlib header file.

#include <iostream>
#include <cstdlib>

using namespace std;

int getInt(){
    int n;
    cout << "Please enter an integer: ";
    cin >> n;
    if(cin.fail()){
        abort();
    } else {
        return n;
    }
}

int main(void){

    cout << getInt() << endl;

    return 0;

}

Exceptions allow us to handle runtime problems. These problems are, ideally, not problems in the logic of the program itself, but issues that arise when handling data is brought into the program from outside it. Exceptions are for gracefully handling the “Murphy’s Law” aspect of running applications in the real world.

Exception handling in C++ involves the use of try blocks, that throw exceptions as needed with throw statements, that are then caught by catch blocks that handle the exception.

The classic introductory example to exceptions is the “divide by zero” program.

#include <iostream>
#include <string>

using namespace std;

int main(void){
    double x, y;

    //enter zero for the second number
    cout << "Enter two numbers to divide: " << endl;
    cin >> x >> y;

    //put code that might explode in a 
    //try block
    try
    {
        if(y > 0){
            cout << x << "/" << y << " = " << x / y << endl;
        } else {
            throw string("Divide by zero exception.");
        }
    } 
    catch(string s)
    {
        cout << "Warning! Warning! Danger, Will Robinson!" << endl;
        cout << s << endl;
    }

    return 0;
}

A try block begins with the try keyword followed by curly braces. If a problem is encountered in the try block, we will throw an exception using the throw statement. To handle the exception thrown, we will catch the exception in a catch block that is implemented with the catch keyword followed by parentheses containing the type of exception caught, then curly braces to delimit the catch block itself. We can throw a string, a char, or a number.

#include <iostream>
#include <iomanip>

using namespace std;

int main(void){

    double amount;

    //loop continues until value deposited.
    while(true){
        cout << "Please enter amount of money to deposit: ";
        cin >> amount;
        try{
            //wrong data type entered
            if(cin.fail()){
                throw int(2);
            //amount less than zero
            } else if(amount < 0.01){
                throw int(1);
            } else {    
                cout << fixed << setprecision(2) << "Depositing $" << amount << " in your account." << endl;
                break;
            }
        }
        catch(int errNo){
            if(errNo==1){
                cout << "Sorry, you must deposit a positive amount." << endl;
            } else if(errNo==2){
                cin.clear();
                string trouble;
                cin >> trouble;
                cout << "Sorry, there seems to be a problem with the amount you entered.";
                cout << "Please try again." << endl;
            } else {
                cout << "Sorry, there seems to be a problem. Please try again." << endl; 
            }
        }
    }

    return 0;

}

Using exceptions, we can have our program recover from problems that  otherwise might prove fatal. To handle exceptions, we place potentially problematic code in a try block, throw exceptions as needed with the throw statement, and handle those exceptions in catch blocks.

If the program throws an exception in a function and doesn’t catch it within the function, then control returns to the point immediately following the function call in the calling code, and the program looks for an appropriate catch block after that point.

We can indicate what type or types of exceptions a function can return when we define the function.

#include <iostream>
#include <cmath>
#include <iomanip>
#include <string>

using namespace std;

double divider(double x, double y) throw (string){
    if((abs(y) < 0.000000001)==false){
        return x / y;
    } else {
        throw string("Division by Zero.");
    }
}

int main(void){

    double x, y;

    cout << "Enter the two numbers to divide: " << endl;
    cin >> x >> y;
    try
    {
        cout << fixed << divider(x, y) << endl;
    } 
    catch (string s)
    {
        cout << "Error: " << s << endl;
    }

    return 0;

}

When we throw an exception in a function and don’t handle that exception in the function itself, control returns up the call stack, looking for an appropriate catch block. The call stack is used by the program to keep track of function calls, and when handling the exception, the program moves back up the call stack, searching for a catch block. Sometimes this is called unwinding the call stack.

#include <iostream>
#include <string>

using namespace std;

//errors thrown in this function will be caught in main()
void checkPassword(string passwd) throw (string)
{
    const int num_count = 10;
    char nums[num_count] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    
    bool flag = false;
    int i = 0;
    int temp;
    int stringLength = passwd.length();
    if(stringLength < 10)
    {
        throw string("Password must be longer than 10 characters.");
    }     

    //check if flag contains a number
    while(flag==false)
    {
        //find() member function returns string::npos
        //if it doesn't find a match
        if((passwd.find(nums[i]))!=string::npos)
        {
            flag = true;
            break;
        }
        //no match found yet, increment counter
        if(!(++i < num_count))
        {
            break;
        } 
    }
    //no match?
    if(flag==false)
    {
        throw string("Password must contain at least one number");
    }
    
    //check to make sure password contains a capital letter
    flag = false;
    for(i = 0; i < stringLength; i++)
    {
        temp = (int)passwd.at(i);
        if((temp > 64) && (temp < 91))
        {
            flag = true;
            break;
        }
    }
    if(flag==false)
    {
        throw string("Password must contain at least one capital letter.");
    }
}

    
//errors thrown in this function will be caught in main()
string getPassword() throw (string)
{
    string pwdOne, pwdTwo;
    cout << "Enter the new password: ";
    cin >> pwdOne;
    checkPassword(pwdOne);
    cout << "Confirm the password by reentering it: ";
    cin >> pwdTwo;

    if(pwdTwo.compare(pwdOne)!=0){
        throw string("Passwords not the same.");
    }
    return pwdOne;
}


int main(void){

    string passWd;

    try
    {
        passWd = getPassword();
        cout << "Your new password has been assigned!" << endl;
    }
    catch(string s)
    {
        cout << "Error: " << s << endl;
    }

    return 0;
}

I wrote a book on standard C, if you’re interested, please take a look: http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M