online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
// Main Program and Application for ALL five Exercises // =================================================== // What this program does is configured by enabling // one or more of #define-s in file `config.h` // #include "config.h" #if defined(TEST1) // ------------------ Unit-Testing for Exercise 1 #include <cassert> #include <iostream> int main() { Clock c{23, 59, 58}; std::ostringstream expect; // should only step up the seconds here c.Update(expect); assert(expect.str() == "Clock [hh:mm:ss] 23:59:59\n"); expect.str(""); // should step up the seconds which resets and in turn // steps up the minutes which resets and in turn steps // up the hours which resets. // NOTE: This test will FAIL if LimitCounter::Count is // not virtual and properly overwritten in // OverflowCounter::Count c.Update(expect); assert(expect.str() == "Clock [hh:mm:ss] 00:00:00\n"); expect.str(""); // should only step up the seconds here c.Update(expect); assert(expect.str() == "Clock [hh:mm:ss] 00:00:01\n"); expect.str(""); // should only step up the seconds here c.Update(expect); assert(expect.str() == "Clock [hh:mm:ss] 00:00:02\n"); expect.str(""); c.SetHours(3); c.SetMinutes(59); c.SetSeconds(59); // should reset seconds and minutes, stepping up hours // NOTE: This one will FAIL if LimitCounter::Count uses // plain Reset() to set value_ to zero. Correct // implementation must use LimitCounter::Reset() // to avoid the whole counter chain uop to hours // is reset to zero c.Update(expect); assert(expect.str() == "Clock [hh:mm:ss] 04:00:00\n"); expect.str(""); c.Reset(); c.Update(expect); // Note: // c.Update() FIRST increments the Clock and only then // shows "hh:mm:ss" so the expection is not "00:00:00" assert(expect.str() == "Clock [hh:mm:ss] 00:00:01\n"); expect.str(""); std::cout << "passed all tests of clock functionality\n"; } #elif defined(TEST2) // ---------------- Unit-Testing for Exercise 2 #include <cassert> int main() { try { LimitCounter lc{0, 10}; lc.SetValue(11); assert(!"LimitCounter exeception expected"); } catch (LimitCounter::ValueOutOfRange &ex) {} catch (...) { assert(!"not the expected exception"); } } #elif defined(TEST3a) // -------- Unit-Testing for Exercise 3 Part 1 #include <cassert> #include <initializer_list> #include <type_traits> #include "array.h" int main() { Array<int, 5> test_obj{0}; // ------------------------------------------------------------- assert((std::is_same<decltype(test_obj)::value_type, int>{})); // -----------------------------------------^^^^^^^^^^---------- // -------------------------------- assert(test_obj.max_size() == 5); // ----------------^^^^^^^^^^------ for (auto v : { 7, 14, 12, 2, 5 }) { test_obj.Insert(v); } // ------------------------ assert(test_obj[0] == 7); assert(test_obj[1] == 14); assert(test_obj[2] == 12); assert(test_obj[3] == 2); assert(test_obj[4] == 5); // ---------------^^^------ // ------------------------------------- assert(test_obj.Insert(111) == false); // ^^^^^^ ^^^^^ test_obj.Erase(12); assert(test_obj.Insert(111) == true); // ----------------^^^^^^---------^^^^ // ----------------------------------------------------- assert((std::is_same<decltype(test_obj[0]), int&>{})); // ---------------------^^^^^^^^---------^^^---^^^^------ // ---------------------------------------------------------------- auto const& const_test_obj = test_obj; // ^^^^^ assert((std::is_same<decltype(const_test_obj[0]), int const&>{})); // ---------------------^^^^^^^^---------------^^^---^^^^^^^^^^----- // ------------------------ assert(test_obj[6] == 0); test_obj[6] = 999; assert(test_obj[6] == 0); // ---------------!!!------ } #elif defined(TEST3b) // -------- Unit-Testing for Exercise 3 Part 2 #include <cassert> #include <iostream> #include <memory> #include <sstream> #include "clock.h" #include "observer_array.h" class MockedTimer : public ObserverArray<3> { public: using ObserverArray<3>::ObserverArray; void Tick(std::ostream& os) { Notify(os); } }; struct ExpectStream : public std::ostringstream { auto operator()(const char* s) { auto result = (str() == s); str(""); // <--- empty current content return result; } }; int main() { MockedTimer test_obj{}; ExpectStream expect{}; test_obj.Notify(expect); assert(expect("")); auto clk1 = std::make_shared<Clock>(0, 1, 59); auto clk2 = std::make_shared<Clock>(11, 59, 58); test_obj.Attach(clk1); test_obj.Notify(expect); assert(expect("Clock [hh:mm:ss] 00:02:00\n")); test_obj.Attach(clk2); test_obj.Notify(expect); assert(expect("Clock [hh:mm:ss] 00:02:01\n" "Clock [hh:mm:ss] 11:59:59\n")); test_obj.Detach(clk1); test_obj.Notify(expect); assert(expect("Clock [hh:mm:ss] 12:00:00\n")); test_obj.Detach(clk2); test_obj.Notify(expect); assert(expect("")); std::cout << "*** ALL TESTS PASSED ***" << std::endl; } #elif defined(TEST4) // ---------------- Unit-Testing for Exercise 4 // ... TBD #else // ----------------------------------- Manual Testing selected // ============================================= // Support functions ShowValue and GetCommand // (may go into their own compilation unit // support.cpp with a corresponding header file // support.h but are included directly for // convenient use in onlineGDB) #include <cctype> #include <iostream> void ShowValue() { std::cout << std::endl; } template <typename T> void ShowValue(T text) { std::cout << text << std::endl; } template <typename T, typename... Other> void ShowValue(T text, Other... other) { std::cout << text << " "; ShowValue(other...); } char GetCommand() { std::cout << "::> " << std::flush; char cmd; while (std::cin.get(cmd)) { if (cmd == '\n') continue; std::cin.ignore(99999, '\n'); if (std::isupper(cmd = std::toupper(cmd))) { return cmd; } } return 'Q'; } // ============================================= // DEFINITION of Actual Application (usually has // its own application.h file but is included // directly for convenient use with onlineGDB) #include <memory> #include <string> #include "clock.h" #include "iclock_factory.h" #include "timer.h" class Application { private: IClockFactory& clock_factory_; std::shared_ptr<Clock> clock_; std::shared_ptr<Timer> timer_; public: explicit Application(IClockFactory& clock_factory) : clock_factory_{clock_factory} { } void SetClock(const std::shared_ptr<Clock>& clock) { using namespace std::string_literals; if (clock == nullptr) throw "no clock service available"s; clock_ = clock; } void SetTimer(const std::shared_ptr<Timer>& timer) { using namespace std::string_literals; if (timer == nullptr) throw "no clock service available"s; timer_ = timer; } void Run(); }; // ============================================= // System Manager Services (usually has its own // header and implementation file but included // directly for convenient use with onlineGDB) #include "iclock_factory.h" #include "timer.h" constexpr unsigned kStartHours = 23; constexpr unsigned kStartMinutes = 59; constexpr unsigned kStartSeconds = 55; class SystemManager : public IClockFactory { private: std::shared_ptr<Clock> clock_{}; std::shared_ptr<Timer> timer_{}; std::shared_ptr<Application> application_{}; public: SystemManager() { Create(); BuildRelations(); } void Execute() const { ShowValue("Clock Observer ..."); application_->Run(); } #ifdef THREAD timer_->Wait(); #endif std::shared_ptr<Clock> GetNewClock(unsigned hours, unsigned minutes, unsigned seconds) override { return std::make_shared<Clock>(hours, minutes, seconds); } private: void Create() { clock_.reset(new Clock{kStartHours, kStartMinutes, kStartSeconds}); timer_.reset(new Timer{}); application_.reset(new Application{*this}); } void BuildRelations() const { application_->SetClock(clock_); application_->SetTimer(timer_); } }; // ============================================= // IMPLEMENTATION of Actual Application (usually // has its own application.cpp file but included // directly for convenient use with onlineGDB) void Application::Run() { while (true) { ShowValue("\n"); #ifndef OBSERVER #ifndef CONTAINER ShowValue("'A': Tick clock"); ShowValue("'B': Reset clock"); #ifdef EXCEPTION ShowValue("'C': Set IClock-Pointer to nullptr"); #endif #endif #endif #if defined(OBSERVER) || defined(CONTAINER) ShowValue("'A': Tick all clocks"); ShowValue("'B': Attach a clock"); ShowValue("'C': Detach a clock"); ShowValue("'D': Reset clock"); ShowValue("'E': Attach five different initialized clocks"); #endif #ifdef THREAD ShowValue("'F': Start the timer thread"); #endif ShowValue("'Q': Quit this program"); ShowValue(); switch (GetCommand()) { #ifndef OBSERVER #ifndef CONTAINER case 'A': clock_->Update(std::cout); break; case 'B': clock_->Reset(); break; #ifdef EXCEPTION case 'C': SetClock(nullptr); break; #endif #endif #endif #if defined(OBSERVER) || defined(CONTAINER) case 'A': timer_->Tick(std::cout); break; case 'B': timer_->Attach(clock_); break; case 'C': timer_->Detach(clock_); break; case 'D': clock_->Reset(); break; case 'E': timer_->Attach(clock_factory_.GetNewClock(1, 0, 0)); timer_->Attach(clock_factory_.GetNewClock(2, 0, 0)); timer_->Attach(clock_factory_.GetNewClock(3, 0, 0)); timer_->Attach(clock_factory_.GetNewClock(4, 50, 40)); timer_->Attach(clock_factory_.GetNewClock(5, 59, 50)); break; #endif #ifdef THREAD case 'F': timer_->Start(); break; #endif case 'Q': #ifdef THREAD timer_->Stop(); #endif return; default: break; } } } #include <string> int main() { const std::unique_ptr<SystemManager> system_manager{new SystemManager}; try { system_manager->Execute(); } catch (const std::string &ex) { std::clog << "Execution Terminated (details: " << ex << ")\n"; } catch (const char *ex) { std::clog << "Execution Terminated: " << ex << ".\n"; } catch (const std::exception &ex) { std::clog << "Execution Terminated by '" << ex.what() << "' exception\n"; } catch (...) { std::clog << "Execution Terminated by unknkwon exception\n"; } } #endif
#include "limit_counter.h" #include <string> #include <stdexcept> LimitCounter::LimitCounter (const unsigned value, const unsigned limit) : value_{value}, limit_{limit} { } void LimitCounter::SetValue (const unsigned value) { value_ = value; } unsigned LimitCounter::GetValue () const { return value_; } bool LimitCounter::Count () { const auto temp_value = GetValue () + 1; if (temp_value >= limit_) { LimitCounter::Reset (); return true; } SetValue (temp_value); return false; } void LimitCounter::Reset () { value_ = 0; }
#ifndef LIMIT_COUNTER_H #define LIMIT_COUNTER_H #include <stdexcept> class LimitCounter { private: unsigned value_; const unsigned limit_; public: LimitCounter(unsigned value, unsigned limit); virtual ~LimitCounter() = default; void SetValue(unsigned value); unsigned GetValue() const; virtual bool Count(); virtual void Reset(); }; #endif // include guard
#include "overflow_counter.h" OverflowCounter::OverflowCounter(const unsigned value, const unsigned limit, LimitCounter& next_counter) : LimitCounter{value, limit}, next_counter_{next_counter} { } void OverflowCounter::Reset() { LimitCounter::Reset(); next_counter_.Reset(); } bool OverflowCounter::Count() { const auto is_overflow = LimitCounter::Count(); if (is_overflow) { next_counter_.Count(); } return is_overflow; }
#ifndef OVERFLOW_COUNTER_H #define OVERFLOW_COUNTER_H #include "limit_counter.h" class OverflowCounter : public LimitCounter { private: LimitCounter& next_counter_; public: OverflowCounter(unsigned value, unsigned limit, LimitCounter& next_counter); void Reset() override; bool Count() override; }; #endif // include guard
#ifndef CLOCK_H #define CLOCK_H #include <iosfwd> #include "iobserver.h" #include "limit_counter.h" #include "overflow_counter.h" class Clock : public IObserver { private: LimitCounter hours_; OverflowCounter minutes_; OverflowCounter seconds_; public: Clock(unsigned hours, unsigned minutes, unsigned seconds); void SetHours(unsigned hours); void SetMinutes(unsigned minutes); void SetSeconds(unsigned seconds); unsigned GetHours() const; unsigned GetMinutes() const; unsigned GetSeconds() const; void Reset(); void Update(std::ostream &os); void Show(std::ostream&) const; }; #endif // include guard
#include "clock.h" #include <iomanip> #include <iostream> Clock::Clock(const unsigned hours, const unsigned minutes, const unsigned seconds) : hours_{hours, 24}, minutes_{minutes, 60, hours_}, seconds_{seconds, 60, minutes_} { } void Clock::SetHours(const unsigned hours) { hours_.SetValue(hours); } void Clock::SetMinutes(const unsigned minutes) { minutes_.SetValue(minutes); } void Clock::SetSeconds(const unsigned seconds) { seconds_.SetValue(seconds); } unsigned Clock::GetHours() const { return hours_.GetValue(); } unsigned Clock::GetMinutes() const { return minutes_.GetValue(); } unsigned Clock::GetSeconds() const { return seconds_.GetValue(); } void Clock::Reset() { seconds_.Reset(); } void Clock::Update(std::ostream& os) { seconds_.Count(); Show(os); } void Clock::Show(std::ostream& os) const { os << "Clock [hh:mm:ss] " << std::setfill('0') << std::setw(2) << GetHours() << ":" << std::setfill('0') << std::setw(2) << GetMinutes() << ":" << std::setfill('0') << std::setw(2) << GetSeconds() << "\n"; }
#ifndef ICLOCK_FACTORY_H #define ICLOCK_FACTORY_H #include <memory> #include "clock.h" class IClockFactory { public: virtual ~IClockFactory() = default; virtual std::shared_ptr<Clock> GetNewClock(unsigned hours, unsigned minutes, unsigned seconds) = 0; }; #endif // include guard
#ifndef IOBSERVER_H #define IOBSERVER_H #include <iosfwd> class IObserver { public: virtual ~IObserver() = default; virtual void Update(std::ostream& os) = 0; }; #endif // include guard
#ifndef ARRAY_H #define ARRAY_H #include <type_traits> template <typename T, unsigned N> class Array { public: using value_type = T; static constexpr auto max_size() { return N; } private: T init_value_; // if this value is held by `array` then it is "free slot" T array_[N]{}; // fixeds siz (limits the number of entries that can be held) public: explicit Array(T init_value); virtual ~Array() = default; bool Insert(T element); void Erase(T element); T& operator[](unsigned index); const T& operator[](unsigned index) const; }; template <typename T, unsigned N> Array<T, N>::Array(T init_value) : init_value_{init_value} { for (auto &e : array_) { e = init_value; } } template <typename T, unsigned N> bool Array<T, N>::Insert(T element) { for (auto &e : array_) { if (e == init_value_) { e = element; return true; } } // caller my look at this if interested if successful return false; } template <typename T, unsigned N> void Array<T, N>::Erase(T element) { for (auto &e : array_) { if (e == element) { e = init_value_; // remove just one or all(?) ... hmm, all (hope that's ok) } } // no indication: if not found then it's not there - finito! } template <typename T, unsigned N> T& Array<T, N>::operator[](unsigned index) { static_assert(std::is_unsigned<decltype(index)>::value, "for signed argument types add test for >= 0 below"); if (index < max_size()) { return array_[index]; } static value_type dummy_result = init_value_; dummy_result = init_value_; return dummy_result; } template <typename T, unsigned N> const T& Array<T, N>::operator[](unsigned index) const { return const_cast<Array*>(this)->operator[](index); } #endif // include guard
#ifndef OBSERVER_ARRAY_H #define OBSERVER_ARRAY_H #include <iosfwd> #include <memory> #include "array.h" #include "iobserver.h" template <unsigned ArrayLength> class ObserverArray { private: Array<std::shared_ptr<IObserver>, ArrayLength> observers_; public: ObserverArray(const ObserverArray& other) = delete; ObserverArray(ObserverArray&& other) = delete; ObserverArray& operator=(const ObserverArray& other) = delete; ObserverArray& operator=(ObserverArray&& other) = delete; virtual void Attach(std::shared_ptr<IObserver> observer); virtual void Detach(std::shared_ptr<IObserver> observer); virtual void Notify(std::ostream& os); protected: ObserverArray(); ~ObserverArray() = default; }; template <unsigned ArrayLength> ObserverArray<ArrayLength>::ObserverArray() : observers_{std::shared_ptr<IObserver>{}} { } template <unsigned ArrayLength> void ObserverArray<ArrayLength>::Attach( std::shared_ptr<IObserver> observer) { if (observer) { observers_.Insert(observer); } } template <unsigned ArrayLength> void ObserverArray<ArrayLength>::Detach( std::shared_ptr<IObserver> observer) { if (observer) { observers_.Erase(observer); } } template <unsigned ArrayLength> void ObserverArray<ArrayLength>::Notify(std::ostream& os) { for (auto i = 0U; i < ArrayLength; i++) { if (observers_[i] != nullptr) { observers_[i]->Update(os); } } } #endif // include guard
#ifndef TIMER_H #define TIMER_H #include "config.h" //#include "thread_base.h" #ifdef OBSERVER #ifndef CONTAINER #include "observer_array.h" #endif #endif #ifdef CONTAINER #include "observer_container.h" #endif constexpr unsigned kMaxObservers = 10; constexpr unsigned kDelayTimeMs = 1000; class Timer : public ObserverArray<kMaxObservers> { public: void Tick(std::ostream& os); #ifdef THREAD void Execute() override; #endif }; #endif // include guard
#include "timer.h" void Timer::Tick(std::ostream& os) { Notify(os); } #ifdef THREAD #include <iostream> void Timer::Execute() { while (IsEnabled()) { Delay(kDelayTimeMs); Tick(std::cout); } } #endif
#ifndef CONFIG_H #define CONFIG_H // // Exercise 1: Manual Testing: no #define-s enabled // Unit-Testing: enable #define TEST1 // Exercise 2: Manual Testing: #define-s EXCEPTION // Unit-Testing: enable #define TEST2 // Exercise 3: Manual Testing: #define-s OBSERVER // Part 1 Unit-Testing: enable #define TEST3a // Part 2 Unit-Testing: enable #define TEST3b // Exercise 4: Manual Testing: #define-s CONTAINER // Unit-Testing: enable #define TEST4 // Exercise 5: Manual Testing: enable THREAD // Unit-Testing: (none provided) // NOTE: #define-s for manual testing accumulate, i.e. // they are meant to be enabled and stay enabled // as the exercise progresses. But if ANY of // TEST1, TEST2, TEST3, TEST4 is enabled ONLY // the respective unit-testing takes place. // enable manual test cases // --------------------------------------------- #define EXCEPTION #define OBSERVER //#define CONTAINER //#define THREAD // enable/disable unit tests // --------------------------------------------- //#define TEST1 //#define TEST2 //#define TEST3a //#define TEST3b //#define TEST4 #endif // include guard

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