#include #include #include #include #include #include #include "date.h" using namespace std; const struct { const char *name; int length; } a[] = { {0, 0}, //Dummy element so that January will have subscript 1 {"January", 31}, {"February", 28}, {"March", 31}, {"April", 30}, {"May", 31}, {"June", 30}, {"July", 31}, {"August", 31}, {"September", 30}, {"October", 31}, {"November", 30}, {"December", 31} }; const size_t nmonths = sizeof a / sizeof a[0] - 1; struct trio { //Argument for constructor for class trio. struct init { int month; int day; int year; }; int year; int month; int day; date d; trio(const init& initial) : year(initial.year), month(initial.month), day(initial.day), d(month, day, year) {} }; inline ostream& operator<<(ostream& ost, const trio& s) { return ost << a[s.month].name << " " << s.day << ", " << s.year; } inline bool t_equals(const trio& s1, const trio& s2) { return s1.year == s2.year && s1.month == s2.month && s1.day == s2.day; } inline int t_dist(const trio& s1, const trio& s2) { int d = 365 * (s1.year - s2.year) + s1.day - s2.day; const int begin = min(s1.month, s2.month); for (int m1 = begin; m1 < s1.month; ++m1) { d += a[m1].length; } for (int m2 = begin; m2 < s2.month; ++m2) { d -= a[m2].length; } return d; } inline const date& t_min(const trio& s1, const trio& s2) { return s1.year < s2.year || s1.year == s2.year && (s1.month < s2.month || s1.month == s2.month && s1.day < s2.day) ? s1.d : s2.d; } inline date t_midpoint(const trio& s1, const trio& s2) { div_t dist = div(t_dist(s1, s2), 2); if (dist.rem < 0) { --dist.quot; } div_t d = div(dist.quot, 365); if (d.rem < 0) { d.rem += 365; --d.quot; } int year = s2.year + d.quot; int day = s2.day + d.rem; int month = s2.month; while (day > a[month].length) { day -= a[month].length; if (++month > 12) { month = 1; ++year; } } return date(month, day, year); } string getprint(const date& d); template bool test(const trio& s1, const trio& s2, const string& name, T (*p1)(const date& d1, const date& d2), T (*p2)(const trio& s1, const trio& s2)) { const T t = p1(s1.d, s2.d); const T correct = p2(s1, s2); if (t == correct) { return true; } cout << name << "(" << s1 << ", " << s2 << ")\n" << "should have returned " << correct << ",\n" << "but it returned " << t << ".\n" << "Your print function prints the 2 arguments as \"" << getprint(s1.d) << "\" and \"" << getprint(s2.d) << "\".\n\n"; return false; } inline ostream& operator<<(ostream& ost, const date& d) { return ost << getprint(d); } inline bool operator==(const date& d1, const date& d2) { return getprint(d1) == getprint(d2); } int main(int argc, char **argv) { const time_t t = time(0); const int this_year = localtime(&t)->tm_year + 1900; const size_t nyears = 3; const size_t ndays = 3; //first, last, and middle day of each month const size_t ndates = ndays * nmonths * nyears; trio::init initial[ndates]; trio::init *p = initial; for (int year = this_year - nyears + 1; year <= this_year; ++year) { for (int month = 1; month <= nmonths; ++month) { for (int day = 1;;) { p->month = month; p->day = day; p->year = year; ++p; if (day == 1) { day = a[month].length / 2; } else if (day == a[month].length / 2) { day = a[month].length; } else { break; } } } } const vector v(initial, initial + ndates); /* The above definition of v fails to compile in some versions of Microsoft, because Microsoft demands that the two pointer arguments be pointers to the data type stored in each element of the vector. If this is the case, change the above definition to the following. vector v; for (size_t i = 0; i < ndates; ++i) { v.push_back(trio(initial[i])); } Microsoft may also have to remove the const in lines 116-117 to avoid a warning. */ for (vector::const_iterator it1 = v.begin(); it1 != v.end(); ++it1) { const trio& s1 = *it1; for (vector::const_iterator it2 = v.begin(); it2 != v.end(); ++it2) { const trio& s2 = *it2; //cout << "testing " << s1 << " " << s2 << "\n"; if ((!test(s1, s2, "equals", equals, t_equals) || !test(s1, s2, "dist", dist, t_dist) || !test(s1, s2, "min", ::min, t_min) || !test(s1, s2, "midpoint", midpoint, t_midpoint))) { return EXIT_FAILURE; } } } cout << "equals, dist, min, and midpoint passed all tests.\n"; return EXIT_SUCCESS; } //Return the standard output of the print member function of this object. string getprint(const date& d) { ostringstream ostr; streambuf *const p = cout.rdbuf(); //Save the standard output. cout.rdbuf(ostr.rdbuf()); //Redirect standard output, like C freopen. d.print(); //The standard output of this print goes into ostr. cout.rdbuf(p); //Restore the standard output. return ostr.str(); }