Lab 02

Exceptions

You will need to deal with three things to utilize exceptions in your code:

1. Define your own exception class (which can be a sub-class of one of the existing exception classes as explained below).

2. Throw your exception in your code when the error conditions have been met.

3. Catch your thrown exception and deal with in in a try / catch statement.

More information for each of these steps is given here.

You will want to create one or more files to define your exceptions. The easiest way to create a new exception class in C++ is by defining a sub-class of the existing exceptions in the stdexcept / exception library.

Example Exception:

  
    #include<stdexcept>
    #include <string>
    using namespace std;

    class NewException : public out_of_range
    {
    public:

      NewException(const string & message ="")
        : out_of_range(message.c_str())
      {} //Don't Forget these brackets!

    }
  

Description

This defines a NewException class which is a sub-class of out_of_range. In this class we have a default constructor which assigns the string parameter to the message private variable of the out_of_range class. (the function c_str() converts the string to a c-style string i.e. a character array.) The new constructor is needed because sub-classes do not inherit the constructor and destructor of the parent class.

The public keyword in the class definition indicates that functions that were previously public in the parent class should remain public in the child class. Because of this we can call the what() function as we will see below.

Exception use

To make use of an exception such as the example above, one could create a header file called “Exceptions.h” and place this class definition inside this file. Make sure to use the #ifndef set-up in this header file to avoid multiple inclusions of this exception header.

Then if were used by a particular class, Exceptions.h would first be included in that classes header file.

Then the function definition of the function that threw this exception would be modified to include this information. Here is an example:
Matrix Matrix::inverse( ) const throw(NewException);

Inside this function, the exception would be thrown like this:
throw NewException("error: message");

This thrown exception would need to be caught somewhere. Usually this occurs in the method that has called the function. For lab 2, these exceptions will be caught in the main method of the program.

Example – catching of an exception:

  
    try {
      m.inverse()
      catch(NewException e)
      {
        cout << e.what() << endl;
      }
  

e is the NewException object created by the throw. It contains the error message string.

The what() method is part of the parent class out_of_range and returns the value of the message variable which we assign to be the error message for the exception in the exception header file.

Standard Exception classes

Here are the classes in the stdexcept. These are in the namespace std. Indention indicates sub-classing.

  
    logic_error
        domain_error
        invalid_argument
        length_error
        out_of_range
    runtime_error
        range_error
        overflow_error
        underflow_error
  

You could sub-class any of these exception class.

Also, all of these classes are sub-classes of the exception class, which you could sub-class directly.

More information on these exceptions

Pointers

Remember, pointers store the address of a value stored somewhere else on the computer memory. Pointers point to strings / numbers / objects, but aren’t actually any of those things.

Syntax

Here are the common usages of pointers.

Creation


    int *p;      //-- creates a pointer that can point to integers
    
    string *s;   //-- creates a pointer that can only point to string objects
    

Assigning an Address

  
    int x = 7;   //-- x is just a normal integer
    
    p = &x;      //-- indicates that the pointer p now 
                 //   contains the memory address of the variable x.
                 //   So p points to x.
  

Assigning Values using Pointers

  
    *p = 2;      //-- this changes the value stored in the address held by p. 
                 //   Meaning *p and x will change.     
  

Using Multiple Pointers

  
    int *q;		   //-- q is another integer pointer.
    
    q = p;       //-- q and p point to the same thing.  
                 //   Meaning, p and q now contain the same memory address.
  

Checking if Filestream is Open

Here is some more code you’ll want to add to the error checking portion of your main function

  
    // Attempt to open the specified input file and confirm that it has been opened correctly
  	ifstream in(argv[1]);
  	if (in.bad())
  	{
  		cerr << "Error: Failed to open input file." << endl;
  		return 1;
  	}
  

The new portion is the if statement. It calls the bad() method of the ifstream instance. This you can find more information about on the reference site, but essentially it will return true if there was an error opening the file. You’ll probably want to add similar code for the output file.

Detecting End of File

Two ways I have found to work for this project.

Simpler & Cleaner way

  
    ifstream inputFile (argv[1]);
    
    while(!inputFile.eof())
    {
      //... 
    }
  

This seems to work for the sample file, and so will probably work fine for this project.

Problems with this method:

More Confusing, Less Elegant but perhaps better way

  
    ifstream inputFile (argv[1]);
    string command;

    while(1)
    {
      inputFile >> command;

      if(inputFile.fail())   
      {					 
          break;
      }
      
      // ...
    }
  

So, This method breaks out of the while loop when the fail method of the inputFile returns true. It returns true if an input operation doesn’t succeed for any reason. This is usually because of an illegal character or the end of file.