I know this is already solved, I just wanted to chime in with a style thing...
These are largly personal preferences... but maybe they'll give you some insight:
1) if statements that are bogged down with tons of || and && are very hard to follow. Try to avoid large chains of those
2) You can use your functions in other functions. Specifically, you already wrote code to check for a leap year in your IsLeapYear function. No need to duplicate that code in IsValidDay... just call the function you already wrote.
3) when you have situations where you have several items that each need to be treated differently, you can simplify it by finding a way to treat them all the same way. This can often be accomplished by using a switch and assigning different things for each case, or by using a look up table. For example... since months all have a different number of days, and there's no clear pattern to them, you can make a lookup table or a switch to find the number of days, and then use the number of days as a single value.
I'd recommend something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
bool IsValidDay( int year, int month, int day)
{
// this is an example of a look up table
static const int dayspermonth[] = {31,29,31,30,31,30,31,31,30,31,30,31};
// make sure the month and year are
if(!IsValidMonth(month)) return false;
if(!IsValidYear(year)) return false;
// month and year are OK, make sure the day is valid
if(day < 1) return false;
if(day > dayspermonth[month-1]) return false;
// special case for leap year
if( (month == 2) && (day == 29) ) return IsLeapYear(year); // Feb 29 is only valid on leap years
// everything checks out
return true;
}
|
See how much simpler and cleaner it is?
Alternatively, here's the switch approach:
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
|
bool IsValidDay( int year, int month, int day)
{
int daysinthismonth;
// find out how many days are in this month
switch(month)
{
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
daysinthismonth = 31;
break;
case 4: case 6: case 9: case 11:
daysinthismonth = 30;
break;
case 2:
daysinthismonth = IsLeapYear(year) ? 29 : 28;
break;
default:
return false; // invalid month
}
// make sure the year is valid
if(!IsValidYear(year)) return false;
// make sure date is valid
if(day < 1) return false;
if(day > daysinthismonth) return false;
// otherwise everything checks out
return true;
}
|
Not quite as clean... granted. But it's useful in other situations.
EDIT: I just saw you had IsValidYear and IsValidMonth functions. I changed the above to use those functions.