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