#include "Clock.h"
#include <iostream>
#include <sstream>
#define SHOW_(expect, ...)\
do {\
std::ostringstream result;\
result.copyfmt(std::cout);\
result << (__VA_ARGS__);\
std::cout << __FILE__ << ':' << __LINE__ << '\t'\
<< #__VA_ARGS__ << " --> " << result.str();\
if (result.str() != expect) {\
std::cout << " != " << expect;\
}\
std::cout << std::endl;\
}\
while (0)
int main()
{
std::cout.setf(std::ios::boolalpha);
Clock c{}; SHOW_("00:00:00", c);
c.TickUp(); SHOW_("00:00:01", c);
c.TickUp(); SHOW_("00:00:02", c);
c.TickUp(); SHOW_("00:00:03", c);
c.Set(0, 0, 58); SHOW_("00:00:58", c);
c.TickUp(); SHOW_("00:00:59", c);
c.TickUp(); SHOW_("00:01:00", c);
c.TickUp(); SHOW_("00:01:01", c);
c.TickUp(60); SHOW_("00:02:01", c);
c.TickUp(100); SHOW_("00:03:41", c);
c.TickUp(1000); SHOW_("00:20:21", c);
Clock c2{23, 59, 58}; SHOW_("23:59:58", c2);
c2.TickUp(); SHOW_("23:59:59", c2);
c2.TickUp(); SHOW_("00:00:00", c2);
c2.TickUp(); SHOW_("00:00:01", c2);
}
#ifndef CLOCK_H
#define CLOCK_H
#include <iosfwd>
#include "Counter.h"
class Clock {
Counter hours_;
Counter minutes_;
Counter seconds_;
public:
Clock(int hours = 0, int minutes = 0, int seconds = 0)
: hours_{24}
, minutes_{60, &hours_}
, seconds_{60, &minutes_}
{
Set(hours, minutes, seconds);
}
Clock(const Clock&) =delete;
Clock& operator=(const Clock&) =delete;
void Set(int hours, int minutes, int seconds) {
hours_.SetValue(hours);
minutes_.SetValue(minutes);
seconds_.SetValue(seconds);
}
void TickUp(int ticks = 1) { seconds_.Count(ticks); }
friend std::ostream& operator<<(std::ostream&, const Clock&);
};
#endif
#include "Clock.h"
#include <iostream>
#include <iomanip>
std::ostream& operator<<(std::ostream& lhs, const Clock& rhs) {
std::ostream os{lhs.rdbuf()};
os.fill('0');
os << std::setw(2) << rhs.hours_.GetValue() << ':'
<< std::setw(2) << rhs.minutes_.GetValue() << ':'
<< std::setw(2) << rhs.seconds_.GetValue();
return lhs;
}
#ifndef COUNTER_H
#define COUNTER_H
class Counter {
private:
int value_{};
const int max_value_{};
Counter* next_counter_{};
public:
Counter(const Counter&) =delete;
Counter& operator=(const Counter&) =delete;
Counter(int max_value, Counter* next_counter = nullptr)
: value_{0}
, max_value_{max_value}
, next_counter_{next_counter}
{}
void SetValue(int value) { value_ = value; }
int GetValue() const { return value_; }
void Count();
void Count(int amount);
void Reset();
};
#endif
#include "Counter.h"
void Counter::Count() {
if (++value_ >= max_value_) {
value_ = 0;
if (next_counter_) {
next_counter_->Count(1);
}
}
}
#ifdef SIMPLE_IMPLEMENTATION
void Counter::Count(int steps) {
while (steps-- > 0) {
Counter::Count();
}
}
#else
#include <cassert>
void Counter::Count(int steps) {
assert(max_value_ > 0);
if (steps <= 0) return;
const auto tmp = value_ + steps;
value_ = tmp % max_value_;
const auto next_steps = tmp / max_value_;
if (next_steps && next_counter_) {
next_counter_->Count(next_steps);
}
}
#endif
void Counter::Reset() {
value_ = 0;
if (next_counter_) {
next_counter_->Reset();
}
}
clock-1x:
g++ -std=c++14 *.cpp -o $@
run: clock-1x
./clock-1x
clean:
-rm -f *.o a.out core clock-1x
zip:
zip ../clock-1x.zip *.txt *.cpp *.h