http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h
Chapter 9 // Exercise 10
Implement leapyear() from section 9.8.
dateclass.h
dateclass.cpp
dateclass.h
//dateclass.h
#ifndef _DATECLASS_H_
#define _DATECLASS_H_
#include "std_lib_facilities.h"
enum class Month
{
jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};
//forward declaration
Month returnMonth(int month);
//9.8 The Date Class
class Date
{
public:
Date();
~Date();
Date(int y, Month m, int d); //check for valid date & initialise
//non-modifying operations:
int day() const { return d; };
Month month() const { return m; }
int year() const { return y; }
//modifying operations:
void add_day(int n);
void add_month(int n);
void add_year(int n);
private:
int y;
Month m;
int d;
bool lastDay = false;
bool endYear = false;
};
//helper functions
bool is_date(int y, Month m, int d); //true for valid date
bool leapyear(int y); //true if y is leap year
ostream& operator<<(ostream& os, Date& d);
istream& operator>>(istream& is, Date& dd);
bool operator==(const Date& a, const Date& b);
bool operator!=(const Date& a, const Date& b);
#endif // !_DATECLASS_H_
dateclass.cpp
//dateclass.cpp
#include "dateclass.h"
//default Date Constructor
Date::Date()
{
y = 2001;
m = Month::jan;
d = 1;
}
//deconstructor
Date::~Date() {}
//Date Constructor - initialise the day
Date::Date(int y, Month m, int d)
{
//check that y m d is a valid date
if (!is_date(y, m, d))
cout << "Error, invalid date." << endl;
else
{
//if date is valid, initalise the date
Date::y = y;
Date::m = m;
Date::d = d;
}
return;
}
//increment date by n days
void Date::add_day(int n)
{
//if day goes above 31, increase month, set day to 1
//if month goes above 12, increase year, set month to 1
for (int i = 0; i < n; ++i)
{
//wrap days
if (Date::d == 31)
lastDay = true;
Date::d = (Date::d == 31) ? 1 : ++Date::d; //if day is equal to 31, make it 1, otherwise ++
if (lastDay)
{
//wrap month
lastDay = false;
int mon = (static_cast<int>(Date::m) == 12) ? 1 : (static_cast<int>(Date::m) + 1); //if month is equal to 12, make it 1, otherwise ++
Date::m = returnMonth(mon);
if (static_cast<int>(Date::m) == 12)
endYear = true;
if (endYear)
{
//just increase year by one
endYear = false;
++Date::y;
}
}
}
}
void Date::add_month(int n)
{
for (int i = 0; i < n; ++i)
{
//if month is equal to 12, make it 1, otherwise ++
int mon = (static_cast<int>(Date::m) == 12) ? 1 : (static_cast<int>(Date::m) + 1);
Date::m = returnMonth(mon);
if (static_cast<int>(Date::m) == 12)
endYear = true;
if (endYear)
{
//just increase year by one
endYear = false;
++Date::y;
}
}
}
void Date::add_year(int n)
{
for (int i = 0; i < n; ++i)
++Date::y;
}
//switch to return correct type of Month
Month returnMonth(int month)
{
switch (month)
{
case 1:
return Month::jan;
break;
case 2:
return Month::feb;
break;
case 3:
return Month::mar;
break;
case 4:
return Month::apr;
break;
case 5:
return Month::may;
break;
case 6:
return Month::jun;
break;
case 7:
return Month::jul;
break;
case 8:
return Month::aug;
break;
case 9:
return Month::sep;
break;
case 10:
return Month::oct;
break;
case 11:
return Month::nov;
break;
case 12:
return Month::dec;
break;
default:
cout << "Bad month" << endl;
}
}
//true for valid date
bool is_date(int y, Month m, int d)
{
//check that y is valid
if (y < 1900 || y > 2018)
{
cout << "Error, invalid year." << endl;
return false;
}
//check that m is valid
if (m < Month::jan || m > Month::dec)
return false;
//check that d is valid
if (d <= 0)
return false; //d must be positive
int daysInMonth = 31; //most months have 31 days
switch (m)
{
case Month::feb:
//if leapyear, make it 29, if not make it 28
daysInMonth = (leapyear(y)) ? 29 : 28;
break;
case Month::apr: case Month::jun: case Month::sep: case Month::nov:
daysInMonth = 30; //the rest have 30 days
break;
}
if (daysInMonth < d)
return false;
return true;
}
//checks for leap year (gregorian calender)
bool leapyear(int y)
{
//if divisible by 4 but not 100 - then leap year
if (y % 4 == 0 && y % 100 != 0)
return true;
//if divisible by 4, 100 and 400 - then leap year
if (y % 4 == 0 && y % 100 == 0 && y % 400 == 0)
return true;
else
return false;
}
//compares dates
bool operator==(const Date& a, const Date& b)
{
return a.year() == b.year()
&& a.month() == b.month()
&& a.day() == b.day();
}
bool operator!=(const Date& a, const Date& b)
{
return !(a == b);
}
//print to screen
ostream& operator<<(ostream& os, Date& d)
{
return os << d.day() << ", " << static_cast<int>(d.month()) << ", " << d.year() << endl;
}
//write into Date
istream& operator>>(istream& is, Date& dd)
{
int y, m, d;
char ch1, ch2, ch3, ch4;
is >> ch1 >> y >> ch2 >> m >> ch3 >> d >> ch4;
if (!is)
return is;
if (ch1 != '(' || ch2 != ',' || ch3 != ',' || ch4 != ')')
{
//format error
is.clear(ios_base::failbit); //set the failbit
return is;
}
dd = Date(y, Month(m), d); //update dd
return is;
}
main.cpp
//main.cpp
#include "std_lib_facilities.h"
#include "dateclass.h"
int main()
{
//intialise dates
Date today(2016, Month::feb, 29);
Date tomorrow(today);
//increase day by one
tomorrow.add_day(1);
tomorrow.add_month(2);
tomorrow.add_year(2);
//print out results
cout << "Today: " << today << endl;
cout << "Tomorrow: " << tomorrow << endl;
keep_window_open();
return 0;
}
At first I wasn't sure how to go about this. However after googling "what determines a leap year" there is some very handy psuedocode on wikipedia to determine whether a year is a leap year or not.
https://en.wikipedia.org/wiki/Leap_year
Turns out a leap year can be determined if the year is divisible by 4 or 100. However centurial years must be divisible by 400 to be a leap year.
Please be aware in this exercise though that the add_day() function still only wraps at 31 days as a later exercise instructs us to create this function so I haven't fixed it yet.
https://en.wikipedia.org/wiki/Leap_year
Turns out a leap year can be determined if the year is divisible by 4 or 100. However centurial years must be divisible by 400 to be a leap year.
Please be aware in this exercise though that the add_day() function still only wraps at 31 days as a later exercise instructs us to create this function so I haven't fixed it yet.
No comments:
Post a Comment