Lab 9 Assignment - Exceptions

This assignment will familarize you with C++ exeception

Introduction

Read through: http://www.ozzu.com/cpp-tutorials/tutorial-exceptions-t86515.html

Also: http://www.cplusplus.com/doc/tutorial/exceptions/

The date class

Consider the following Date Class interface:

//**************************************** 
// SPECIFICATION File for a Date ADT 
//**************************************** 
class MonthError 
{}; 
class DayError 
{}; 
class YearError 
{}; 
class Date 
{ 
public: 
  Date(); 
  Date(int initMonth, int initDay, int initYear); 
  // Knowledge Responsibilities 
  int GetMonth() const; 
  int GetDay() const; 
  int GetYear() const; 
  bool operator<(const Date& otherDate) const; 
  bool operator>(const Date& otherDate) const; 
  bool operator==(const Date& otherDate) const; 
private: 
  int month; 
  int day; 
  int year; 
};

Note the three new empty classes at the top. These was used to signal bad date elements.

Date Implementation

//**************************************** 
// IMPLEMENTATION File for a Date ADT 
// Month, day, and year are kept as integers 
//**************************************** 
 
#include <iostream> 
#include "Date.h" 
bool IsLeapYear(int year); 
using namespace std; 
Date::Date() 
{  
  month = 1; 
  day = 1; 
  year = 1582; 
} 
 
//**************************************** 
 
Date::Date(int initMonth, int initDay, int initYear) 
{ 
  static int daysInMonth[12] =  
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  if (initMonth <= 0 || initMonth > 12) 
    throw MonthError(); 
  else month = initMonth; 
  if (!(initDay > 0 && initDay <= daysInMonth[initMonth-1])) 
    throw DayError(); 
  else 
    if (month == 2 && day == 29 && !IsLeapYear(initYear)) 
      throw DayError(); 
  else 
    day = initDay; 
  if (initYear < 1582) 
    throw YearError(); 
  else 
    year = initYear; 
} 
 
//***************************************** 
 
int Date::GetMonth() const 
{ return month; } 
 
//***************************************** 
 
int Date::GetDay() const 
{ return day; } 
 
//**************************************** 
 
int Date::GetYear() const 
{ return year; }  
 
//**************************************** 
 
bool Date::operator<(const Date& otherDate) const 
{ 
  if (year < otherDate.year) 
    return true; 
  else if (year > otherDate.year) 
    return false; 
  else if (month < otherDate.month) 
    return true; 
  else if (month > otherDate.month) 
    return false; 
  else if (day < otherDate.day) 
    return true; 
  else return false; 
} 
 
//***************************************** 
 
bool Date::operator>(const Date& otherDate) const 
{ 
  return otherDate < *this; 
} 
 
//***************************************** 
 
bool Date::operator==(const Date& otherDate) const 
{ 
  return (month==otherDate.month) && (day==otherDate.day) 
          && (year==otherDate.year);   
} 
 
//********************************************************** 
  
bool IsLeapYear(int year) 
// IsLeapYear returns true if year is a leap year and 
// false otherwise.  
{ 
  if (year % 4 != 0)    // Is year not divisible by 4? 
    return false;       // If so, can't be a leap year 
                        // Must be divisible by 4 at this point 
  if (year % 100 != 0)  // Is year not a multiple of 100? 
    return true;        // If so, is a leap year 
                        // Must be divisible by 100 at this point 
  if (year % 400 != 0)  // Is year not a multiple of 400? 
    return false;       // If so, then is not a leap year 
                        // Must be divisible by 400 at this point 
  return true;          // Is a leap year 
}

Note how this code checks for valid Day, Month, and Year, and throws the appropriate exception.

Date Driver Program

//****************************************** 
// Test driver for class Date, which 
// is the Date class with exception handling 
//****************************************** 
#include <iostream> 
#include "Date.h" 
using namespace std; 
int main()  
{ 
  int month; 
  int day; 
  int year; 
   
  cout << "Enter month. Negative month stops test." << endl; 
  cin >> month; 
  while (month >=  0) 
  { 
    cout << "Enter day and year" << endl; 
    cin >> day >> year; 
    try 
    { 
      Date date1(month, day, year); 
      cout << "Valid date." << endl; 
    } 
    catch (MonthError error) 
    { 
      cout << "Attempt to create date with invalid month." << endl;   
    } 
    catch (DayError error) 
    { 
      cout << "Attempt to create date with invalid day." << endl; 
    } 
    catch (YearError error) 
    { 
      cout << "Attempt to create date with invalid year." << endl; 
    } 
    cout << "Enter month.  Negative month stops test." << endl; 
    cin >> month; 
  } 
  return 0; 
}      

Experiment

Create a program from the above code. Test it out, checking each of the exceptions.

Making Exceptions Smart

The above exceptions provide no information about the error the occured. An exception can be made into a full class, and store information about the error, and return this information as required.

Consider a general "date" class exception:

class DateException {
 
protected:
   
    int number;
 
public:
    DateException( int date ) {number = date;}; 
    std::string getMessage(); 
};

Note that this is a generic error exception for a day, month, or year integer. Now consider a day exception based on this:

class DayError : public DateException 
{
private:
 
public:
    DayError( int theday ) : DateException::DateException(theday){};
   
    // Override the getMessage() method
    std::string getMessage() {
        if (number == 0)
           return "Day can't be 0";
        else if (number < 0)
           return "Day can't be negative";
        else 
           return "Day too large";
    }
   
    // note: all other member data and methods are inherited!
};

Note that this is a allows the day exception to return a specfic error to the caller avout the nature of the error.

Below see how the throw now passes the day to the exception constructor:

Date::Date(int initMonth, int initDay, int initYear) 
{ 

  cout << initMonth << " " << initDay << " " << initYear << endl; 
  if (initMonth <= 0 || initMonth > 12) 
    throw MonthError(); 
  else month = initMonth; 
  if (!(initDay > 0 && initDay <= daysInMonth[initMonth-1])) 
    throw DayError(initDay); 
  else 
    if (month == 2 && day == 29 && !IsLeapYear(initYear)) 
      throw DayError(initDay); 
  else 
    day = initDay; 
  if (initYear < 1582) 
    throw YearError(); 
  else 
    year = initYear; 
}

Finally see how the test program can use this information to print more information about the error:

catch (DayError error) 
    { 
      cout << "Attempt to create date with invalid day!" << endl;
      cout << error.getMessage() << endl; 
    }

Experiment 2

Add the above day error exception processing to you code, test it out.

Now try to add informational exceptions for Months and Years.

What to turn in on =BlackBoard=

The laboratory report should include the following elements:

  1. Brief statement of the objectives of the lab and a description of what you did during the lab session (1/2 – 1 page).
  2. Lab results such as program listings, input and/or output files, tables of data produced, answers to specific questions posed, etc. as appropriate to the lab assignment. If there were no results, indicate this with “No Results.”
  3. Discussion of any difficulties you encountered and what you did to resolve them (1/2 – 1 page).
  4. Discussion of what you learned or how the lab experience reinforced things you already knew (1/2 – 1 page).
  5. Your overall rating of the lab on a scale of 1-4 and an explanation of your rating. Ratings are as follows:
1 = poor
2 = fair
3 = good
4 = excellent

- JimSkon - 2010-04-21

Topic revision: r7 - 2011-05-12 - JimSkon
 
This site is powered by the TWiki collaboration platformCopyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback