online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
#define UNIT_TESTING #ifdef UNIT_TESTING #include <iostream> #include <sstream> #define SHOW_(expect, ...)\ do {\ std::ostringstream result;\ result.copyfmt(std::cout);\ result << (__VA_ARGS__);\ std::cout << __FUNCTION__ << ':' << __LINE__ << '\t'\ << #__VA_ARGS__ << " --> " << result.str();\ if (result.str() != expect) {\ std::cout << " != " << expect;\ }\ std::cout << std::endl;\ }\ while (0) #include "UpDownCounter.h" void single_counter_constructors() { SHOW_("3", UpDownCounter{3, 5, nullptr}.GetValue()); SHOW_("5", UpDownCounter{3, 5, nullptr}.GetLimit()); // SHOW_("3", UpDownCounter{3, 5, NULL}.GetValue()); // SHOW_("5", UpDownCounter{3, 5, NULL}.GetLimit()); SHOW_("3", UpDownCounter{3, 5}.GetValue()); SHOW_("5", UpDownCounter{3, 5}.GetLimit()); SHOW_("0", UpDownCounter{5, nullptr}.GetValue()); SHOW_("5", UpDownCounter{5, nullptr}.GetLimit()); // SHOW_("0", UpDownCounter{5, NULL}.GetValue()); // SHOW_("5", UpDownCounter{5, NULL}.GetLimit()); SHOW_("0", UpDownCounter{5}.GetValue()); SHOW_("5", UpDownCounter{5}.GetLimit()); SHOW_("0", UpDownCounter{}.GetValue()); SHOW_("0", UpDownCounter{}.GetLimit()); } #include <limits> void single_counter_setter() { UpDownCounter ud_0_max{}; SHOW_("0", ud_0_max.GetValue()); SHOW_("0", ud_0_max.GetLimit()); SHOW_("123", ud_0_max.SetValue(123), ud_0_max.GetValue()); SHOW_("0", ud_0_max.GetLimit()); } void single_counter_max_wrap() { const auto max = std::numeric_limits<UpDownCounter::value_type>::max(); std::ostringstream almost_max; almost_max << max-1; std::ostringstream exactly_max; exactly_max << max+0; UpDownCounter ud_0_max{}; SHOW_("0", ud_0_max.GetValue()); SHOW_("0", ud_0_max.GetLimit()); SHOW_(almost_max.str(), ud_0_max.SetValue(max-1), ud_0_max.GetValue()); SHOW_(exactly_max.str(), ud_0_max.UpCount(), ud_0_max.GetValue()); SHOW_("0", ud_0_max.UpCount(), ud_0_max.GetValue()); SHOW_("1", ud_0_max.UpCount(), ud_0_max.GetValue()); SHOW_("0", ud_0_max.DownCount(), ud_0_max.GetValue()); SHOW_(exactly_max.str(), ud_0_max.DownCount(), ud_0_max.GetValue()); SHOW_(almost_max.str(), ud_0_max.DownCount(), ud_0_max.GetValue()); } void single_counter_oflow() { UpDownCounter ud_3_5{3, 5}; SHOW_("3", ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("4", ud_3_5.UpCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("0", ud_3_5.UpCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("1", ud_3_5.UpCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("0", ud_3_5.DownCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("4", ud_3_5.DownCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); SHOW_("3", ud_3_5.DownCount(), ud_3_5.GetValue()); SHOW_("5", ud_3_5.GetLimit()); } void chained_counters_oflow() { UpDownCounter hi{3}; SHOW_("0", hi.GetValue()); SHOW_("3", hi.GetLimit()); UpDownCounter lo{4, &hi}; SHOW_("0", lo.GetValue()); SHOW_("4", hi.GetLimit()); SHOW_("1", lo.UpCount(), lo.GetValue()); SHOW_("0", hi.GetValue()); SHOW_("2", lo.UpCount(), lo.GetValue()); SHOW_("0", hi.GetValue()); SHOW_("3", lo.UpCount(), lo.GetValue()); SHOW_("0", hi.GetValue()); SHOW_("0", lo.UpCount(), lo.GetValue()); SHOW_("1", hi.GetValue()); SHOW_("1", lo.UpCount(), lo.GetValue()); SHOW_("1", hi.GetValue()); SHOW_("0", lo.DownCount(), lo.GetValue()); SHOW_("1", hi.GetValue()); SHOW_("3", lo.DownCount(), lo.GetValue()); SHOW_("0", hi.GetValue()); } void counter_tests() { single_counter_constructors(); single_counter_setter(); single_counter_max_wrap(); single_counter_oflow(); chained_counters_oflow(); } #include "Clock.h" void clock_tests() { Clock c{"myclock"}; SHOW_("myclock=0.00:00:00", c); SHOW_("true", c.IsZero()); SHOW_("myclock=0.00:00:01", c.TickUp()); SHOW_("false", c.IsZero()); SHOW_("myclock=0.00:00:02", c.TickUp()); SHOW_("myclock=0.00:00:03", c.TickUp()); SHOW_("myclock=0.00:00:58", c.Seconds(58)); SHOW_("myclock=0.00:00:59", c.TickUp()); SHOW_("myclock=0.00:01:00", c.TickUp()); SHOW_("false", c.IsZero()); SHOW_("myclock=0.00:01:01", c.TickUp()); SHOW_("myclock=0.00:59:59", c.Minutes(59).Seconds(59)); SHOW_("myclock=0.01:00:00", c.TickUp()); SHOW_("false", c.IsZero()); SHOW_("myclock=0.23:59:59", c.Hours(23).Minutes(59).Seconds(59)); SHOW_("myclock=1.00:00:00", c.TickUp()); SHOW_("false", c.IsZero()); SHOW_("myclock=123.00:00:00", c.Days(123)); SHOW_("myclock=122.23:59:59", c.TickDown()); SHOW_("myclock=122.23:00:01", c.Minutes().Seconds(1)); SHOW_("myclock=122.23:00:00", c.TickDown()); SHOW_("myclock=122.22:59:59", c.TickDown()); SHOW_("myclock=122.00:00:00", c.Hours().Minutes().Seconds()); SHOW_("false", c.IsZero()); SHOW_("myclock=0.00:00:00", c.Days()); SHOW_("true", c.IsZero()); } int main() { std::cout.setf(std::ios::boolalpha); counter_tests(); clock_tests(); } #else extern void appl(); int main() { appl(); } #endif
#include <iostream> void appl() { std::cout << "!!! application not yet developed !!!" << std::endl; }
#ifndef ICLOCK_H #define ICLOCK_H #include <iosfwd> class IClock { public: virtual ~IClock() =default; virtual void Print(std::ostream&) const =0; virtual bool IsZero() const =0; virtual IClock& TickUp() =0; virtual IClock& TickDown() =0; }; inline std::ostream& operator<<(std::ostream& lhs, const IClock& rhs) { rhs.Print(lhs); return lhs; } #endif
#ifndef CLOCK_H #define CLOCK_H #include <cstring> #include <iosfwd> #include "IClock.h" #include "UpDownCounter.h" class Clock : public IClock { const char* name_; UpDownCounter days_; UpDownCounter hours_; UpDownCounter minutes_; UpDownCounter seconds_; public: Clock(const char* name, UpDownCounter::value_type days = 0, UpDownCounter::value_type hours = 0, UpDownCounter::value_type minutes = 0, UpDownCounter::value_type seconds = 0) : name_{std::strcpy(new char[std::strlen(name)+1], name)} , days_{days} , hours_{hours, 24, &days_} , minutes_{minutes, 60, &hours_} , seconds_{seconds, 60, &minutes_} {} ~Clock() { delete[] name_; } Clock(const Clock&) =delete; // copy c'tor Clock& operator=(const Clock&) =delete; // copy assignment Clock(Clock&&) =delete; // move c'tor Clock& operator=(Clock&&) =delete; // move assignment Clock& Days(unsigned v = 0) { days_.SetValue(v); return *this; } Clock& Hours(unsigned v = 0) { hours_.SetValue(v); return *this; } Clock& Minutes(unsigned v = 0) { minutes_.SetValue(v); return *this; } Clock& Seconds(unsigned v = 0) { seconds_.SetValue(v); return *this; } virtual void Print(std::ostream&) const override; virtual bool IsZero() const override final; virtual IClock& TickUp() override final { seconds_.UpCount(); return *this; } virtual IClock& TickDown() override final { seconds_.DownCount(); return *this; } }; #endif
#include "Clock.h" #include <iostream> #include <iomanip> bool Clock::IsZero() const { return (seconds_.GetValue() == 0) && (minutes_.GetValue() == 0) && (hours_.GetValue() == 0) && (days_.GetValue() == 0); } void Clock::Print(std::ostream& s) const { std::ostream os{s.rdbuf()}; os.fill('0'); os << name_ << '=' << days_.GetValue() << '.' << std::setw(2) << hours_.GetValue() << ':' << std::setw(2) << minutes_.GetValue() << ':' << std::setw(2) << seconds_.GetValue(); }
#ifndef UP_DOWN_COUNTER_H #define UP_DOWN_COUNTER_H #include <cstdint> #include <type_traits> class UpDownCounter { public: using value_type = std::uint_fast8_t; static_assert(std::is_integral<value_type>::value && std::is_unsigned<value_type>::value, "designed to work with unsigned integral types only"); private: value_type value_{}; const value_type max_value_{}; UpDownCounter *next_counter_{}; public: UpDownCounter() =default; UpDownCounter(const UpDownCounter&) =delete; UpDownCounter(UpDownCounter&&) =delete; UpDownCounter& operator=(const UpDownCounter&) =delete; UpDownCounter& operator=(UpDownCounter&&) =delete; UpDownCounter(value_type value, value_type max_value, UpDownCounter* next_counter) : value_{value} , max_value_{max_value} , next_counter_{next_counter} {} UpDownCounter(value_type max_value, UpDownCounter* next_counter) : UpDownCounter(0, max_value, next_counter) {} UpDownCounter(value_type value, value_type max_value) : UpDownCounter(value, max_value, nullptr) {} UpDownCounter(value_type max_value) : UpDownCounter(0, max_value, nullptr) {} UpDownCounter(UpDownCounter* next_counter_) : UpDownCounter(0, 0, nullptr) {} void SetValue(value_type value) { value_ = value; } int GetValue() const { return value_; } int GetLimit() const { return max_value_; } void UpCount(); void DownCount(); }; #endif
#include "UpDownCounter.h" void UpDownCounter::UpCount() { if (++value_ == max_value_) { value_ = 0; if (next_counter_) { next_counter_->UpCount(); } } } void UpDownCounter::DownCount() { if (value_ == 0) { value_ = max_value_; if (next_counter_) { next_counter_->DownCount(); } } --value_; }
Back Down to Earth: An Up-Down Counter and Clock ------------------------------------------------ TBD
Review the code and maybe make some modifications ------------------------------------------------- Review the two classes: * `Clock` (files `Clock.h` and `Clock.cpp`) and * `UpDownCounter` (files `UpDownCounter.h and `UpDownCounter.cpp`) Run the tests for the `UpDownCounter` in `main`: * You may temporarily comment-out the call to`clock_tests()`. * Optionally also temporarily comment-out any testsFrom `counter_tests` you don't want for the moment, so that you get less output. Then answer the following questions: * How many ways exist to construct an `UpDownCounter` and what is their differrence? * Described the exact overflow behavior of an `UpDownCounter`, especially: * What is the maximum `value_` can reach if `max_value_` is any value other than zero and ... * ... to which value does a counter "wrap around" DOWNWARDS from zero in this case? * What is the maximum `value_` can reach if `max_value_` IS zero and ... * ... to which value does a counter "wrap around" DOWNWARDS from zero in this case? * Why is it so important that the type of the values held in a counter is an unsigned integral? * Which is the highest count that a `Clock` can reach? Some modifications ypu may want to make to the code: TBD

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue