3 Replies - 12221 Views - Last Post: 20 July 2010 - 12:32 PM Rate Topic: -----

#1 oonamas  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • 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  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 966
  • View blog
  • 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

Was This Post Helpful? 0
  • +
  • -

#3 c0dy  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • 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

Was This Post Helpful? 0
  • +
  • -

#4 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • 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;
   int reply = cin.get();
   cin.sync();
   return !(reply == 'n' || reply == 'N');
}


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

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1