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 <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({}); 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("")); } #elif defined(TEST4) // ---------------- Unit-Testing for Exercise 4 #include <cassert> #include <memory> #include <sstream> #include "clock.h" #include "observer_container.h" class MockedTimer : public ObserverContainer { public: using ObserverContainer::ObserverContainer; void Tick(std::ostream& os) { Notify(os); } }; struct ExpectStream : public std::ostringstream { auto operator()(const char* s) { auto result = (str() == s); str({}); 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("")); } #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 timer 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 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 ObserverContainer, public ThreadBase { public: void Tick(std::ostream& os); void Start(); #ifdef THREAD void Execute() override; #endif }; #endif // include guard
#include "timer.h" void Timer::Tick(std::ostream& os) { Notify(os); } void Timer::Start() { Create(); } #ifdef THREAD #include <iostream> void Timer::Execute() { while (IsEnabled()) { Delay(kDelayTimeMs); Tick(std::cout); } } #endif
#ifndef OBSERVER_CONTAINER_H #define OBSERVER_CONTAINER_H #include <iosfwd> #include <list> #include <memory> #include "iobserver.h" class ObserverContainer { private: using ObserverRef = std::shared_ptr<IObserver>; using ObserverRefList = std::list<ObserverRef>; ObserverRefList observers_{}; public: void Attach(std::shared_ptr<IObserver> observer); void Detach(std::shared_ptr<IObserver> observer); void Notify(std::ostream& os); protected: ObserverContainer() = default; ~ObserverContainer() = default; }; #endif // include guard
#include "observer_container.h" #include <algorithm> #include <iosfwd> void ObserverContainer::Attach(const std::shared_ptr<IObserver> observer) { // avoid duplicates already on insertion: if (!observer) return; const auto it = std::find(observers_.cbegin(), observers_.cend(), observer); if (it != observers_.cend()) return; observers_.emplace_back(observer); } void ObserverContainer::Detach(const std::shared_ptr<IObserver> observer) { // no worries about duplicates as such are avoided on insertion if (!observer) return; const auto it = std::find(observers_.cbegin(), observers_.cend(), observer); if (it == observers_.cend()) return; observers_.erase(it); } void ObserverContainer::Notify(std::ostream& os) { // NOTE: not safe against concurrent `Attach` or `Detach` !!! for (const auto &e : observers_) { e->Update(os); } }
#ifndef THREAD_BASE_H #define THREAD_BASE_H #include <thread> class ThreadBase { private: std::thread thread_; volatile bool is_enabled_{}; public: virtual ~ThreadBase() = default; void Create(); static void Delay(unsigned time_ms); void Stop(); void Wait(); virtual void Execute() = 0; protected: bool IsEnabled() const; }; #endif // include guard
#include "thread_base.h" #include <chrono> void ThreadBase::Create() { if (!is_enabled_) { is_enabled_ = true; thread_ = std::thread([this]() { this->Execute(); }); } } void ThreadBase::Delay(const unsigned time_ms) { const std::chrono::milliseconds delay_time(time_ms); std::this_thread::sleep_for(delay_time); } void ThreadBase::Stop() { is_enabled_ = false; } void ThreadBase::Wait() { // the thread may be invalid (not started) if (thread_.joinable()) { thread_.join(); } } bool ThreadBase::IsEnabled() const { return is_enabled_; }
#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