Error Handling problem, need help

Good morning everyone. I have been working on the following program but I can't get the invalid argument to work. Every function works execept when I enter a date that is out of range. It returns a runtime error.

Can someone look at it and tell me what is wrong with it?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

#include <iostream>
#include <string>
#include "DATE.h"

using namespace std;

const int Date::days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

//Date Constructor
Date::Date(int month, int day, int year)
{
	setDate(month, day, year);
}

void Date::setDate(int mm, int dd, int yy)
{
	if (mm >= 1 && mm <=12)
		month = mm;
	else
		throw invalid_argument("Month must be 1-12");

	if(yy >= 1900 && yy <= 2100)
		year = yy;
	else
		throw invalid_argument("Year must be >= 1900 and <= 2100");
	
	if ((month == 2 && leapYear(year) && dd >= 1 && dd <= 29) ||
		(dd >= 1 && dd <= days[month]))
		day = dd;
	else
		throw invalid_argument(
		"Day is out of range for current month and year");
}

//overloaded postfix increment operator
Date Date::operator++(int)
{
	Date temp = *this;
	nextDay();

	//return unincremented, saved, temporary object
	return temp;
}

//add specified number of days to date
const Date &Date::operator+=(int additionalDays)
{
	for (int i = 0; i < additionalDays; ++i)
		nextDay();

	return *this;
}

//if year is leap year, return true; otherwise, return false
bool Date::leapYear(int testYear)
{
	if (testYear % 400 == 0 ||
	   (testYear % 100 != 0 && testYear % 4 == 0))
		return true;

	else
		return false;

}//end function leapYear

//determine whether the day is the last day of the month
bool Date::endOfMonth(int testDay) const
{
	if (month == 2 && leapYear(year))
		return testDay == 29;
	else
		return testDay == days[month];
}

void Date::nextDay()
{
	if (!endOfMonth(day))
		++day;
	else
		if (month < 12) //day is end of the month and month < 12
		{
			++month;
			day = 1;
		}
		else
		{
			++year;
			month = 1;
			day = 1;
		}
}

//overloaded output operator
ostream &operator<<( ostream &output, const Date &d)
{
	static string monthName[13] = { "", "January", "February", "March", "April",
		"May", "June", "July", "August", "September", "October", "November", "December"};
	output << monthName[d.month]<< ' ' << d.day << ", " << d.year;
	return output;
}

void Date::print ()
{
	cout << month << '/' << day << '/' << year << endl;
}
It returns a runtime error.


I'm guessing your runtime error says something like "unhandled exception".

That's because you're throwing an exception. When an exception is thrown and never caught, it will cause the program to crash.

If that's not the behavior you want then you'll have to either not throw an exception, or catch it after it's thrown.
Disch,

I thought that lines 21, 26, and 33 would return the invalid argument. I have not yet reach the handling exception chapter in my class so I have to work with what I have.

Any sugestions on how I can modify those three lines to return the exception?
I thought that lines 21, 26, and 33 would return the invalid argument.



An exception is not returned in the same way that a normal return value is. When an exception is thrown, the function it is it effectively ends at that point, and then the function that called that function, and then the next one, and the next, and so on and so on until somewhere there is a catch that you have set (with an associated try), which will catch that exception and execution of your programme carries on from that catch.

Your code has no suitable catch, so the setDate function is left and then the Date is left and then whatever called that is left and then eventually your main function is left as the stack unwinds and then the operating system hands you the runtime error.

If you're going to use exceptions, you have to catch them if you intend to make them meaningful. The real issue here, though, is that you're using an exception for a circumstance that really doesn't require it. I suggest that your function returns a value indicating success or failure, and the caller deals with that appropriately.

There are a million opinions about when to use exceptions, but for me the clue is in the name; they are for exceptional circumstances. This is a case where you can quite easily handle bad input using return values.
Last edited on
Moschops,

thanks for the advice. I looked at the code and I made this smaller modification to the setDate class:
Now, if I bad date is entered the program terminates. Any advice on how can I handle the bad dates and still be able to display the corrrect ones without using the try/catch block?

I am testing this class using the following three dates:

1
2
3
4

	Date date1(1, 4, 2004);
	Date date3(15, 31, 1995);
	Date date4(12, 31, 2011);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Date::setDate(int mm, int dd, int yy)
{
	if (mm >= 1 && mm <=12)
		month = mm;
	else
		cout << "Month must be 1-12" << endl;

	if(yy >= 0 && yy <= 2100)
		year = yy;
	else
		cout << "Year must be greater than 0" << endl;
	
	if ((month == 2 && leapYear(year) && dd >= 1 && dd <= 29) ||
		(dd >= 1 && dd <= days[month]))
		day = dd;
	else
		cout << "Day is out of rage." << endl;

}
What do you want to happen when bad input is entered? How will this input be gathered? If it's from a user, the user can be prompted to enter the data again. If from a file, then it can be identified as bad and the code simply moves on to the next one.
Mochops,

I would like to tell the user to re enter the wrong date. Or at least that it would skip that particular date and move on to the next one.

I am using the following test program. I don't need to enter values from the keyboard but I can always modify it if I needed.

This is my testFile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <iomanip>
#include "Date.h" //include definition of class Date from Date.h
#include <stdexcept>

using namespace std;

int main()
{
	Date date1(1, 4, 2004);
	Date date2;//default construtor
	Date date3(15, 31, 1995);
	Date date4(12, 31, 2011);


	cout << "Here is Date 1:\n";
	date1.print();
	
	cout << "Here is Date 2 using the default constructor:\n";
	date2.print();

	cout << "Here is Date 3:\n";
	date3.print();

	cout << "Here is Date 3 after using nextDay function:\n";
	date3++;
	date3.print();

	cout << "Here is Date 4 set at December 31, 2011:\n";
	date4.print();

	cout << "Here is Date 4 after using nextDay to change into the new year:\n";
	date4++;
	date4.print();

}

Well then something like this springs to mind:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int Date::setDate(int mm, int dd, int yy)
{
        int failed = 0;

	if (mm >= 1 && mm <=12)
		month = mm;
	else
		failed = 1;

	if(yy >= 0 && yy <= 2100)
		year = yy;
	else
		failed = 1;
	
	if ((month == 2 && leapYear(year) && dd >= 1 && dd <= 29) ||
		(dd >= 1 && dd <= days[month]))
		day = dd;
	else
		failed = 1;

return failed;

}


Now the setDate function returns 0 if everything was fine, and 1 is it isn't.
Moschops,

I tried your block and still give me the same run time error. I changed int failed = 0; for a
string failed = "Wrong values entered" and send it to the console as a result.

With the string failed, I am able to eliminate the runtime error but I can't get the correct dates to show.
I can't get the correct dates to show.


So now that your setDate function returns a value that you can use to decide if the date is correct or not, you can then use that returned value to choose to call date.print only if it was successful.
Topic archived. No new replies allowed.