// simple_time.cpp #include #include using namespace std; constexpr int MINUTES_PER_HOUR = 60; /* * Track time in hours and minutes, where minutes always in the range 0..59 * but hours can be any value, positive or negative. Has an operation to * advance time by one minute. */ class Time { public: Time(int hours, int minutes) { hrs = hours; // alternatively: this->hrs = hours; min = minutes; normalize(); } // advance by one minute, rolling over the hours as necessary void tick() { min += 1; normalize(); } // returns time as a string using the format H:MM string toString() { stringstream result; result << hrs << ":"; if (min < 10) result << "0"; result << min; return result.str(); } // returns number of hours; assumes time is normalized int hours() { return hrs; } // return number of minutes; assumed time is normalized int minutes() { return min; } private: int hrs, min; // ensure 0 <= min <= 59, adding to/borrowing from hrs as necessary // hrs can be any value void normalize() { if ( min >= 0 ) { hrs += min / MINUTES_PER_HOUR; min = min % MINUTES_PER_HOUR; } else if ( min % MINUTES_PER_HOUR == 0 ) { // special case: go back several hours hrs -= abs(min) / MINUTES_PER_HOUR; min = 0; } else { // go back at least one hour, possibly more hrs -= 1 + abs(min) / MINUTES_PER_HOUR; // move minutes to between 0 and 59 min = MINUTES_PER_HOUR + (min % MINUTES_PER_HOUR); } } }; // do not forget this semicolon! //#################################################################### // normally all includes would be at the top of the file, but in this // case I wanted more code than normal in a single file for // simplicity #include // test code void testBasicTime(); void testTick(); void testToString(); void testNegativeTime(); int main() { testBasicTime(); testTick(); testToString(); testNegativeTime(); cout << "All tests passed." << endl; return 0; } // test creating times void testBasicTime() { Time one(1, 0); assert(one.hours() == 1); assert(one.minutes() == 0); Time two(23, 59); assert(two.hours() == 23); assert(two.minutes() == 59); } void testTick() { Time start(9, 58); assert(start.hours() == 9 && start.minutes() == 58); start.tick(); assert(start.hours() == 9 && start.minutes() == 59); start.tick(); assert(start.hours() == 10 && start.minutes() == 0); for(int i = 0; i < 120; ++i) start.tick(); assert(start.hours() == 12 && start.minutes() == 0); // now ensure don't roll over hours for(int i = 0; i < 60; ++i) start.tick(); assert(start.hours() == 13 && start.minutes() == 0); } void testToString() { Time early(4, 5); assert(early.toString() == "4:05"); Time late(13, 59); assert(late.toString() == "13:59"); late.tick(); assert(late.toString() == "14:00"); } void testNegativeTime() { Time a(18, -1); assert(a.toString() == "17:59"); a = Time(0, -18); assert(a.toString() == "-1:42"); a = Time(3, -100); assert(a.toString() == "1:20"); a = Time(20, -300); assert(a.toString() == "15:00"); }