Day Number Program Adjusting for Leap Year

Page 1 of 1

3 Replies - 28334 Views - Last Post: 20 July 2010 - 12:32 PMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'http://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=182251&amp;s=9d417d7b38ca5cacba1e31882c1d7953&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

#1 oonamas

Reputation: 0
• Posts: 4
• Joined: 18-July 10

Day Number Program Adjusting for Leap Year

Posted 19 July 2010 - 02:37 PM

I just turned in this working executable for my beginning C++ class, but I'm sure there's an easier way to do it without the long list of if statements that I used. Any tips? Thanks!

```#include <iostream>
using namespace std;

//functions used
bool leapYear(int);
int dayNumber(int, int, int);

int main ()
{
int month;
int day;
int year;
int leap;
int number;

//get the date
cout << "Enter a date in integer form (month day year): ";
cin >> month >> day >> year;

//determine if leap year is true or false using function
leap = leapYear(year);
//compute the day number using function
number = dayNumber(month, day, leap);

//display results
cout << "The day number on the given date is: " << number << endl;

//display if leap year is true or false
if (leap == 1)
cout << "The year entered is a leap year: true" << endl;

if (leap == 0)
cout << "The year entered is a leap year: false" << endl;

system ("pause");

return 0;
}

//function to determine if leap year is true or false, using integers 1 or 0
bool leapYear(int year)
{
if (year % 400 == 0)
{
return true;
}
if (year % 100 == 0)
{
return false;
}
if (year % 4 == 0)
{
return true;
}
if (year % 4 !=0)
{
return false;
}
}

//compute day number, adjusting for leap years
int dayNumber(int month, int day, int leap)
{
if (month == 1)
{
return day;
}
if (month == 2)
{
return 31 + day;
}
if (month == 3)
{
return 59 + day + leap;
}
if (month == 4)
{
return 90 + day + leap;
}
if (month == 5)
{
return 120 + day + leap;
}
if (month == 6)
{
return 151 + day + leap;
}
if (month == 7)
{
return 181 + day + leap;
}
if (month == 8)
{
return 212 + day + leap;
}
if (month == 9)
{
return 243 + day + leap;
}
if (month == 10)
{
return 273 + day + leap;
}
if (month == 11)
{
return 304 + day + leap;
}
if (month == 12)
{
return 334 + day + leap;
}
}
```

Is This A Good Question/Topic? 0

Replies To: Day Number Program Adjusting for Leap Year

#2 sarmanu

• D.I.C Lover

Reputation: 967
• Posts: 2,362
• Joined: 04-December 09

Re: Day Number Program Adjusting for Leap Year

Posted 19 July 2010 - 03:08 PM

Well, the leap year function could be simply rewritten in one line, like this:
```bool leapYear(int year)
{
return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0));
}

```

Now, a more elegant approach would be to use a struct. Here's how I'd do it:
```#include <iostream>
using namespace std;

//functions used
bool leapYear(int);
int dayNumber(int, int, int);

// Yes, only one data member.
struct Days
{
int days;
};

// Basically, there are 12 month. month 0 = 0 days
// month 1 = 31 days
// ...
// month 11 = 334
const Days d[12] = {
{ 0 }, { 31 }, { 59 }, { 90 }, { 120 },
{ 151 }, { 181 }, { 212 }, { 243 }, { 273 },
{ 304 }, { 334 }
};

// Assume that month is a valid month (range 1 - 12).
int getDayNumber(const int month)
{
// Since d is an array of structs with index starting
// from 0, use d[month - 1].
// e.g when month = 1, it will be: d[0].days which is 0 ...
return d[month - 1].days;
}

int main ()
{
int month;
int day;
int year;
int leap;
int number;

//get the date
cout << "Enter a date in integer form (month day year): ";
cin >> month >> day >> year;

//determine if leap year is true or false using function
leap = leapYear(year);
//compute the day number using function
number = dayNumber(month, day, leap);

//display results
cout << "The day number on the given date is: " << number << endl;

//display if leap year is true or false
if (leap)
cout << "The year entered is a leap year: true" << endl;
else
cout << "The year entered is a leap year: false" << endl;

system ("pause");

return 0;
}

//function to determine if leap year is true or false, using integers 1 or 0
bool leapYear(int year)
{
return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0));
}

//compute day number, adjusting for leap years
int dayNumber(int month, int day, int leap)
{
return day + getDayNumber(month) + (month > 2 ? leap : 0);
}

```

Should work. PS: it's 1 AM, and I hope there aren't any logical mistakes.
EDIT: as it is, the program is prone to errors. What happens if the user enters a non-valid month, like 100? Or a non-valid day, like -1, or 394? You should check for valid user input first.

This post has been edited by sarmanu: 19 July 2010 - 03:13 PM

#3 c0dy

Reputation: 3
• Posts: 34
• Joined: 29-June 10

Re: Day Number Program Adjusting for Leap Year

Posted 19 July 2010 - 03:17 PM

Something like:
```enum { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };

inline bool leapYear(int y) { return !(y%4) && (y%400 || !(y%100)); }

int daysInMonth(int m, int y) {
switch (m) {
case feb:
return 28 + leapYear(y);
case apr: case jun: case sep: case nov:
return 30;
case jan: case mar: case may: case jul: case aug: case oct: case dec:
return 31;
default:
// Error would be here.
}
}

```

This post has been edited by c0dy: 20 July 2010 - 04:50 AM

#4 David W

• DIC supporter

Reputation: 298
• Posts: 1,839
• Joined: 20-September 08

Re: Day Number Program Adjusting for Leap Year

Posted 20 July 2010 - 12:32 PM

You may be wondering how to write code so that your program will not crash or go off into some crazy (infinite?) loop ...

Validating input ... is often the solution.

User comments may greatly assist 'seeing' the logic flow.

Note the simple 'top down' logic flow ...

Firstly ... get a good year.
Only then ... get a good month ...
Only then ... get a good day for that month and year.

Note that if the cin stream is maintained 'clean' ... 'as we go',
that this prevents having to deal with (sometimes) unwanted remaining whitespace char's in the cin stream ... after cin input of data.

```// get valid month, day (and year in range 1600..3000)
// and return values by reference ...
void getValid( int& m, int& d, int& y )
{
for( ; ; ) // loop forever ... until break/return
{
cout << "Enter date as month day year "
<< "(for example 2 29 2000 ) : "
<< flush;
if( cin >> m >> d >> y ) // i.e. if no error flag
{
if( y < 1600 || y > 3000 ) // use suitable limits
{
cout << "Valid year range here is "
<< "1600..3000\n";
cin.sync(); // 'flush' cin stream ...
continue; // from top of 'for' right now ...
}

if( m < 1 || m > 12 )
{
cout << "Valid month range is 1..12\n";
cin.sync();
continue;
}

int dsInMn = daysInMonth( m, y );
if( d < 1 || d > dsInMn )
{
cout << "Valid day range is 1.."
<< dsInMn << " for month "
<< m << " and year " << y
<< endl;
cin.sync();
continue;
}
else // valid data input ... so ...
{
cin.sync();
return;
}
}
else // loop again ... but first ...
{
cout << "Integers only please ...\n";
cin.clear(); // clear cin stream error flags
cin.sync(); // 'flush' cin stream ...
}
}
}

```

Note that the above function uses ...

```// valid m (1..12) passed in ... and valid y
int daysInMonth( int m, int y )
{
int num = DAYS[m-1];
if( m == 2 && isLeapYear( y ) )
++num;
return num;
}

```

... and that this above function uses ...

```const int DAYS[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
```

and ...
```inline bool isLeapYear( int y )
{
return !(y%4) && (!(y%400) || (y%100));
}
```

Now ... we are almost done. All that's left is ...

```/*
int daysBeforeMonth( int m, int y )
(
int sum = 0;
for( int i = m - 1; i > 0; --i )
sum += daysInMonth( m, y );
return sum;
)
*/

int dayNumber( int m, int d, int y )
{
int sumDaysBeforeMonth = 0;
for( int i = m - 1; i > 0; --i )
sumDaysBeforeMonth += daysInMonth( i, y );
return d + sumDaysBeforeMonth;
}

```

... where the unused function daysBeforeMonth is 'commented out' but left in to help the logic flow ... since that function is built into the dayNumber function.

Now ... putting it all together, you might code something like this:

```// dayNumInYear.cpp // with input validation

#include <iostream>
using namespace std;

const int DAYS[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };

// with easier to see logic ...
// and thus, more likely to see if correct logic
inline bool isLeapYear( int y )
{
return !(y%4) && (!(y%400) || (y%100));
/*
// deal with most probable input first ..
// this 1st test will return false for 3/4's of cases
if( y%4 ) return false;

// if reach here ... y is divided evenly by 4
// BUT ... before returning true ...
// deal with special cases ...
if( y%400 == 0 ) return true;

// if reach here ... and ...
if( y%100 == 0 ) return false;

// otherwise ...
return true;
*/
}

// valid m (1..12) passed in ... and valid y
int daysInMonth( int m, int y )
{
int num = DAYS[m-1];
if( m == 2 && isLeapYear( y ) )
++num;
return num;
}

/*
int daysBeforeMonth( int m, int y )
(
int sum = 0;
for( int i = m - 1; i > 0; --i )
sum += daysInMonth( m, y );
return sum;
)
*/

int dayNumber( int m, int d, int y )
{
int sumDaysBeforeMonth = 0;
for( int i = m - 1; i > 0; --i )
sumDaysBeforeMonth += daysInMonth( i, y );
return d + sumDaysBeforeMonth;
}

// get valid month, day (and year in range 1600..3000)
// and return values by reference ...
void getValid( int& m, int& d, int& y )
{
for( ; ; ) // loop forever ... until break/return
{
cout << "Enter date as month day year "
<< "(for example 2 29 2000 ) : "
<< flush;
if( cin >> m >> d >> y ) // i.e. if no error flag
{
if( y < 1600 || y > 3000 ) // use suitable limits
{
cout << "Valid year range here is "
<< "1600..3000\n";
cin.sync(); // 'flush' cin stream ...
continue; // from top of 'for' right now ...
}

if( m < 1 || m > 12 )
{
cout << "Valid month range is 1..12\n";
cin.sync();
continue;
}

int dsInMn = daysInMonth( m, y );
if( d < 1 || d > dsInMn )
{
cout << "Valid day range is 1.."
<< dsInMn << " for month "
<< m << " and year " << y
<< endl;
cin.sync();
continue;
}

// else (if reach here) valid data input so ...
cin.sync();
return;
}
else // loop again ... but first ...
{
cout << "Integers only please ...\n";
cin.clear(); // clear cin stream error flags
cin.sync(); // 'flush' cin stream ...
}
}
}

bool more() // defaults to yes ... more ...
{
cout << "\nMore (y/n) ? " << flush;
cin.sync();
}

int main()
{
int month, day, year;
do
{  // validated values returned by reference
getValid( month, day, year );

// display results ...
cout << "The day number for "
<< ( month < 10 ? "0" : "" )
<< month << "/"
<< ( day < 10 ? "0" : "" )
<< day << "/" << year << " is "
<< dayNumber( month, day, year )
<< " and ";

// display if is a leap ... or NOT
cout << year << " is"
<< ( isLeapYear( year) ? "" : " NOT" )
<< " a leap year." << endl;
}
while( more() );
}

```

P.S.

One of the fun and challenging things about programming is that there are usually many different ways to code to get the same results.

At DIC, you may see many different things, and some code, you may wish you didn't.

So ... be forewarned ... double - check all code you see ... by testing it out to see if it gives the desired output with all possible inputs ... and if it meets with the 'style standards' you may need or desire.

This post has been edited by David W: 20 July 2010 - 01:11 PM