Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Osman Zakir
- // 9 / 7 / 2017
- // Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
- // Chapter 17 Exercises 11-13
- #include <iostream>
- #include <stdexcept>
- #include <memory>
- #include <vld.h>
- #include "../../cust_std_lib_facilities.h"
- struct God
- {
- God(const std::string &name, const std::string &myth, const std::string &vehicle, const std::string &weapon)
- : m_name{ name }, m_myth{ myth }, m_vehicle{ vehicle }, m_weapon{ weapon } { }
- std::string name() const { return m_name; }
- std::string myth() const { return m_myth; }
- std::string vehicle() const { return m_vehicle; }
- std::string weapon() const { return m_weapon; }
- void set_name(const std::string &name) { m_name = name; }
- void set_myth(const std::string &myth) { m_myth = myth; }
- void set_vehicle(const std::string &vehicle) { m_vehicle = vehicle; }
- void set_weapon(const std::string &weapon) { m_weapon = weapon; }
- private:
- std::string m_name;
- std::string m_myth;
- std::string m_vehicle;
- std::string m_weapon;
- };
- class Link
- {
- public:
- Link(God *god, Link *p = nullptr, Link *n = nullptr)
- : m_god{ god }, m_prev{ p }, m_succ{ n }
- {
- }
- Link *insert(Link *n); // insert n before this object
- Link *add(Link *n); // insert n after this object
- Link *erase(); // remove this object from list
- Link *find(const std::string &name); // find node matching passed in name in list
- const Link *find(const std::string &name) const; // find node matching passed in name in const list
- Link *find_if_myth(const std::string &myth); // find node matching passsed in myth in list
- const Link *find_if_myth(const std::string &myth) const; // find node matching passsed in myth in const list
- Link *advance(int n) const; // advance n positions in list
- Link *add_ordered(Link *n); // insert n in its correct lexicographical position
- Link *operator()(God*) { return this; }
- God *god() const { return m_god; }
- Link *next() const { return m_succ; }
- Link *previous() const { return m_prev; }
- private:
- God *m_god;
- Link *m_prev;
- Link *m_succ;
- };
- void print_all(std::unique_ptr<Link> &p);
- int main()
- {
- try
- {
- std::unique_ptr<Link> gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
- "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Thor", "Norse",
- "Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Baldr", "Norse",
- "A giant ship called Hringorni", "None" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Frejya", "Norse",
- "Chariot pulled by two cats", "Magic called seidr" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Ares", "Greek",
- "War chariot", "Sword and spear" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Zeus", "Greek",
- "A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Apollo", "Greek",
- "Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Hera", "Greek",
- "A chariot drawn by peacocks", "Her intelligence" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Poseidon", "Greek",
- "A chariot pulled either by a hippocampus or by four horses that can ride on the seas",
- "A three-pronged spear called Trident" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Athena", "Greek", "",
- "Allowed to use Zeus's Thunderbolt and the Aegis" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Amaterasu", "Japanese", "",
- "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Izanagi", "Japanese", "",
- "Sword of Totsuka (later given to Susanoo)" } })));
- gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Bishamonten", "Japanese", "", "A spear" } })));
- std::unique_ptr<Link> norse_gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
- "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
- std::unique_ptr<Link> greek_gods = std::make_unique<Link>(new Link{ new God{ "Zeus", "Greek",
- "A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } });
- std::unique_ptr<Link> jap_gods = std::make_unique<Link>(new Link{ new God{ "Amaterasu", "Japanese", "",
- "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
- std::unique_ptr<Link> trav = std::make_unique<Link>(std::move(gods->find("Odin")));
- if (trav)
- {
- if (trav == gods)
- {
- gods = std::make_unique<Link>(std::move(trav->next()));
- }
- trav->erase();
- }
- std::cout << "gods list:\n";
- print_all(gods);
- }
- catch (const std::runtime_error &rte)
- {
- std::cerr << "Runtime error: " << rte.what() << '\n';
- keep_window_open();
- return 1;
- }
- catch (const std::bad_alloc &ba)
- {
- std::cerr << "Bad allocation error: " << ba.what() << '\n';
- keep_window_open();
- return 2;
- }
- catch (const std::overflow_error &ofe)
- {
- std::cerr << "Overflow error: " << ofe.what() << '\n';
- keep_window_open();
- return 3;
- }
- catch (const std::exception &e)
- {
- std::cerr << "Exception: " << e.what() << "\n";
- keep_window_open();
- return 4;
- }
- catch (...)
- {
- std::cerr << "An unknown exception occurred\n";
- keep_window_open();
- return 5;
- }
- keep_window_open();
- }
- Link *Link::insert(Link *n)
- {
- if (n == nullptr)
- {
- error("Node to add cannot be null");
- }
- n->m_succ = this;
- if (m_prev)
- {
- m_prev->m_succ = n;
- }
- n->m_prev = m_prev;
- m_prev = n;
- return n;
- }
- Link *Link::add(Link *n)
- {
- if (n == nullptr)
- {
- error("Node to add cannot be null");
- }
- n->m_prev = this;
- if (m_succ)
- {
- m_succ->m_prev = n;
- }
- n->m_succ = m_succ;
- m_succ = n;
- return n;
- }
- Link *Link::erase()
- {
- Link *trav = this;
- if (trav == nullptr)
- {
- return this;
- }
- if (trav->m_succ)
- {
- trav->m_succ->m_prev = trav->m_prev;
- }
- if (trav->m_prev)
- {
- trav->m_prev->m_succ = trav->m_succ;
- }
- return trav->m_succ;
- }
- Link *Link::find(const std::string &name)
- {
- Link *trav = this;
- while (trav != nullptr)
- {
- if (trav->m_god->name() == name)
- {
- return trav;
- }
- trav = m_succ;
- }
- return this;
- }
- const Link *Link::find(const std::string &name) const
- {
- const Link *c_trav = this; // const pointer
- Link *nc_trav = const_cast<Link*>(c_trav); // non-const pointer
- while (c_trav != nullptr && nc_trav != nullptr)
- {
- if (c_trav->m_god->name() == name)
- {
- return c_trav;
- }
- nc_trav = m_succ;
- }
- return this;
- }
- Link *Link::find_if_myth(const std::string &myth)
- {
- Link *trav = this;
- while (trav != nullptr)
- {
- if (trav->m_god->myth() == myth)
- {
- return trav;
- }
- trav = trav->m_succ;
- }
- return this;
- }
- const Link *Link::find_if_myth(const std::string &myth) const
- {
- const Link *c_trav = this; // const pointer
- Link *nc_trav = const_cast<Link*>(c_trav); // non-const pointer
- while (c_trav != nullptr && nc_trav != nullptr)
- {
- if (c_trav->m_god->myth() == myth)
- {
- return c_trav;
- }
- nc_trav = nc_trav->m_succ;
- }
- return this;
- }
- Link *Link::advance(int n) const
- {
- Link *trav = const_cast<Link *>(this);
- if (trav == nullptr)
- {
- return const_cast<Link*>(this);
- }
- if (n > 0)
- {
- while (n--)
- {
- if (trav->m_succ == nullptr)
- {
- return const_cast<Link*>(this);
- }
- trav = trav->m_succ;
- }
- }
- else if (n < 0)
- {
- while (n++)
- {
- if (trav->m_prev == nullptr)
- {
- return const_cast<Link*>(this);
- }
- trav = trav->m_prev;
- }
- }
- return trav;
- }
- Link *Link::add_ordered(Link *n)
- {
- if (!n)
- {
- error("Node to insert cannot be null");
- }
- Link *trav = this;
- if (!trav)
- {
- return this;
- }
- // to make sure to start at head of the list
- while (trav->m_prev != nullptr)
- {
- trav = trav->m_prev;
- }
- while (trav->m_god->name() < n->m_god->name() && trav->m_succ)
- {
- trav = trav->m_succ;
- }
- if (n->m_god->name() < trav->m_god->name())
- {
- trav = trav->insert(n);
- }
- else
- {
- trav = trav->add(n);
- }
- return trav;
- }
- void print_all(std::unique_ptr<Link> &p)
- {
- if (p->previous() != nullptr)
- {
- while (p->previous() != nullptr)
- {
- p = std::make_unique<Link>(std::move(p->previous()));
- }
- }
- std::cout << "{\n";
- while (p)
- {
- std::cout << "Name: " << p->god()->name()
- << "; Myth: " << p->god()->myth();
- if (p->god()->vehicle() != "")
- {
- std::cout << "; Vehicle: " << p->god()->vehicle();
- }
- else
- {
- std::cout << "; Vehicle: N/A";
- }
- std::cout << "; Weapon: " << p->god()->weapon();
- if ((p = std::make_unique<Link>(std::move(p->next()))))
- {
- std::cout << "\n";
- }
- }
- std::cout << "\n}\n";
- }
Add Comment
Please, Sign In to add comment