#include "Clock.h"
#include <iostream>
int main()
{
Clock c{}; std::cout << c << std::endl;
c.TickUp(); std::cout << c << std::endl;
c.TickUp(); std::cout << c << std::endl;
c.TickUp(); std::cout << c << std::endl;
c.Set(0, 0, 58);
c.TickUp(); std::cout << c << std::endl;
c.TickUp(); std::cout << c << std::endl;
c.TickUp(); std::cout << c << std::endl;
c.Set(0, 58, 37); std::cout << c << std::endl;
c.TickUp(60); std::cout << c << std::endl;
c.TickUp(100); std::cout << c << std::endl;
Clock c2{23, 59, 58}; std::cout << c2<< std::endl;
c2.TickUp(); std::cout << c2 << std::endl;
c2.TickUp(); std::cout << c2 << std::endl;
c2.TickUp(); std::cout << c2 << std::endl;
}
#ifndef CLOCK_H
#define CLOCK_H
#include <iosfwd>
class Clock {
int hours_{0};
int minutes_{0};
int seconds_{0};
public:
Clock() =default;
Clock(int hours, int minutes, int seconds)
: hours_{hours}
, minutes_{minutes}
, seconds_{seconds}
{}
Clock(const Clock&) =delete;
Clock& operator=(const Clock&) =delete;
void Set(int hours, int minutes, int seconds) {
hours_ = hours;
minutes_ = minutes;
seconds_ = seconds;
}
void TickUp(int seconds = 1);
friend std::ostream& operator<<(std::ostream&, const Clock&);
};
#endif
#include "Clock.h"
void Clock::TickUp(int n) {
while (n-- > 0) {
if (++seconds_ >= 60) {
seconds_ = 0;
if (++minutes_ >= 60) {
minutes_ = 0;
if (++hours_ >= 24) {
hours_ = 0;
}
}
}
}
}
#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_ << ':'
<< std::setw(2) << rhs.minutes_ << ':'
<< std::setw(2) << rhs.seconds_;
return lhs;
}
Simple example for building a clock
===================================
Everything goes into a single class.
Hours, minutes, and seconds are held by separate integers.
Overflow behavior is hard-coded within nested conditonals.
PRO-s:
quickly written
easily understood
CON-s:
no re-usable components from which the clock is built
best approach to build other clocks is
(a) copy & paste all of Clock source code
(b) then modify what needs to be changed
To advance to the next step apply the following changes:
NOTE: You may implement short functions consisting of just one
statement as inline functions in the class `Counter`.
Functions containing logic (like conditions and loops)
should rather have an implementation outside the class
(in a `cpp`-file that is compiled separately).
* Instead of plain integers use objects of a simple class
`Counter` with the following member data:
* an `int value_` holding the current counter value
* a `const int max_value_` holding the limit up to which the
counter can count until it gets reset to `0`;
* `Counter *next_counter_` pointing to anotherthe counter to
which and overflow is transferred when the current counter is
reset;
* for the last `Counter` in the chain that pointer should
be a `nullptr` and there needs to be a test for it before
the overflow gets transferred.
* Centrally implement the "reset logic" when the limit is reached
within the a member function `Count` in class `Counter`. (There
are several choices to do so, see "optional" section below.)
* Also implement member functions `SetValue` and `GetValue`
that the data members can be made `private`.
=================================================================
Optional:
* Consider the advantages and disadvantages for to implement the
feature stepping the clock several seconds at once:
* No arguments to `Count::Counter` it always counts just one
step up (and falls back to zero when the limit is reached).
=> `Clock::TickUp` needs to use a loop OR
=> `Clock::Tickup` no longer supports multiple steps
* ALTERNATIVELY: calculate the effective change of `value_`
AND the count steps `next_counter_` to h forwarded to.
* Discuss the advantages and disadvantages of adding more member
functions like:
* `GetLimit` - return the value of `limit_`
* `SetLimit` - change the value of `limit_`
* `Reset` - reset `value_` to `0` for the counter itself AND
the whole counter chain connected via `next_` (if any).
* Why is it a problem if a `Clock` object gets copy-constructed
or copy-assigned from an already existing ond and how can these
(automatically generated) operations be avoid?
=================================================================
Unrelated and/or Advanced:
* Devise a way to include the following information in the output
by using a macro (suggested name `SHOW`):
* The file name generating the output.
* The line number in that the macro was invoked.
* The expression evaluated to produce the output.
* Any other ideas for supporting something like very simple "TDD"
(= Test Driven Development) approach based on the `SHOW` macro?