Step 6 of 9
Challenge: a Clock class
This challenge is about designing a small class from a description. Here's the process professionals use:
- Decide the data. What's the smallest set of members that represents the state? For a timer, a single number of seconds remaining is enough. Minutes and seconds can be computed from it when needed, so they shouldn't be stored separately (two copies of the same information can get out of sync).
- Write the constructor so every object starts valid.
- Write each method, keeping the data valid (here: never below 0).
- Mark reading methods
const.
Formatting with padding
M:SS needs the seconds padded to two digits: 1:05, not 1:5. Building the string yourself is simple: if the seconds are below 10, add a "0" before them.
#include <iostream>
#include <string>
class Stopwatch {
public:
void add(int seconds) {
if (seconds > 0) total_ += seconds;
}
std::string display() const {
int h = total_ / 3600;
int m = (total_ / 60) % 60;
int s = total_ % 60;
return std::to_string(h) + "h" + two(m) + "m" + two(s) + "s";
}
private:
static std::string two(int n) {
return (n < 10 ? "0" : "") + std::to_string(n);
}
int total_ = 0;
};
int main() {
Stopwatch w;
w.add(3725);
std::cout << w.display() << "\n";
w.add(-50);
w.add(40);
std::cout << w.display() << "\n";
}
1h02m05s
1h02m45s
two is a private static helper: it doesn't need an object, and it's an implementation detail, so it's hidden from users of the class.
Default arguments work on member functions too: void tick(int s = 1) lets callers write tick() or tick(5).
Your turn: write a class Clock representing a round timer in seconds:
Clock(int seconds)creates itvoid tick(int s = 1)subtracts seconds but never goes below 0bool expired() constis true at 0std::string display() constreturnsM:SS, like1:55or0:07