DragonOsman

chapter17ex10-13

Oct 19th, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.62 KB | None | 0 0
  1. // Osman Zakir
  2. // 9 / 7 / 2017
  3. // Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
  4. // Chapter 17 Exercises 11-13
  5.  
  6. #include <iostream>
  7. #include <stdexcept>
  8. #include <memory>
  9. #include <vld.h>
  10. #include "../../cust_std_lib_facilities.h"
  11.  
  12. struct God
  13. {
  14.     God(const std::string &name, const std::string &myth, const std::string &vehicle, const std::string &weapon)
  15.         : m_name{ name }, m_myth{ myth }, m_vehicle{ vehicle }, m_weapon{ weapon } { }
  16.  
  17.     std::string name() const { return m_name; }
  18.     std::string myth() const { return m_myth; }
  19.     std::string vehicle() const { return m_vehicle; }
  20.     std::string weapon() const { return m_weapon; }
  21.  
  22.     void set_name(const std::string &name) { m_name = name; }
  23.     void set_myth(const std::string &myth) { m_myth = myth; }
  24.     void set_vehicle(const std::string &vehicle) { m_vehicle = vehicle; }
  25.     void set_weapon(const std::string &weapon) { m_weapon = weapon; }
  26. private:
  27.     std::string m_name;
  28.     std::string m_myth;
  29.     std::string m_vehicle;
  30.     std::string m_weapon;
  31. };
  32.  
  33. class Link
  34. {
  35. public:
  36.     Link(God *god, Link *p = nullptr, Link *n = nullptr)
  37.         : m_god{ god }, m_prev{ p }, m_succ{ n }
  38.     {  
  39.     }
  40.  
  41.     Link *insert(Link *n);                                            // insert n before this object
  42.     Link *add(Link *n);                                               // insert n after this object
  43.     Link *erase();                                                    // remove this object from list
  44.     Link *find(const std::string &name);                              // find node matching passed in name in list
  45.     const Link *find(const std::string &name) const;                  // find node matching passed in name in const list
  46.     Link *find_if_myth(const std::string &myth);                      // find node matching passsed in myth in list
  47.     const Link *find_if_myth(const std::string &myth) const;          // find node matching passsed in myth in const list
  48.     Link *advance(int n) const;                                       // advance n positions in list
  49.     Link *add_ordered(Link *n);                                       // insert n in its correct lexicographical position
  50.     Link *operator()(God*) { return this; }
  51.  
  52.     God *god() const { return m_god; }
  53.     Link *next() const { return m_succ; }
  54.     Link *previous() const { return m_prev; }
  55. private:
  56.     God *m_god;
  57.     Link *m_prev;
  58.     Link *m_succ;
  59. };
  60.  
  61. void print_all(std::unique_ptr<Link> &p);
  62.  
  63. int main()
  64. {
  65.     try
  66.     {
  67.         std::unique_ptr<Link> gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
  68.             "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
  69.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Thor", "Norse",
  70.             "Chariot pulled by goats Tanngrisnir and Tanngnjostr", "Hammer called Mjolnir" } })));
  71.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Baldr", "Norse",
  72.             "A giant ship called Hringorni", "None" } })));
  73.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Frejya", "Norse",
  74.             "Chariot pulled by two cats", "Magic called seidr" } })));
  75.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Ares", "Greek",
  76.             "War chariot", "Sword and spear" } })));
  77.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Zeus", "Greek",
  78.             "A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } })));
  79.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Apollo", "Greek",
  80.             "Chariot pulled by the four horses Aethon, Pyrois, Phlegon and Eous", "A bow" } })));
  81.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Hera", "Greek",
  82.             "A chariot drawn by peacocks", "Her intelligence" } })));
  83.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Poseidon", "Greek",
  84.             "A chariot pulled either by a hippocampus or by four horses that can ride on the seas",
  85.             "A three-pronged spear called Trident" } })));
  86.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Athena", "Greek", "",
  87.             "Allowed to use Zeus's Thunderbolt and the Aegis" } })));
  88.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Amaterasu", "Japanese", "",
  89.             "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } })));
  90.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Susanoo", "Japanese", "", "Sword of Totsuka" } })));
  91.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Izanagi", "Japanese", "",
  92.             "Sword of Totsuka (later given to Susanoo)" } })));
  93.         gods = std::make_unique<Link>(gods->add_ordered(std::move(new Link{ new God{ "Bishamonten", "Japanese", "", "A spear" } })));
  94.  
  95.         std::unique_ptr<Link> norse_gods = std::make_unique<Link>(new Link{ new God{ "Odin", "Norse",
  96.             "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } });
  97.         std::unique_ptr<Link> greek_gods = std::make_unique<Link>(new Link{ new God{ "Zeus", "Greek",
  98.             "A chariot pulled by the four major winds shaped as horses", "Thunderbolt and the shield called Aegis" } });
  99.         std::unique_ptr<Link> jap_gods = std::make_unique<Link>(new Link{ new God{ "Amaterasu", "Japanese", "",
  100.             "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
  101.  
  102.         std::unique_ptr<Link> trav = std::make_unique<Link>(std::move(gods->find("Odin")));
  103.         if (trav)
  104.         {
  105.             if (trav == gods)
  106.             {
  107.                 gods = std::make_unique<Link>(std::move(trav->next()));
  108.             }
  109.             trav->erase();
  110.         }
  111.         std::cout << "gods list:\n";
  112.         print_all(gods);
  113.     }
  114.     catch (const std::runtime_error &rte)
  115.     {
  116.         std::cerr << "Runtime error: " << rte.what() << '\n';
  117.         keep_window_open();
  118.         return 1;
  119.     }
  120.     catch (const std::bad_alloc &ba)
  121.     {
  122.         std::cerr << "Bad allocation error: " << ba.what() << '\n';
  123.         keep_window_open();
  124.         return 2;
  125.     }
  126.     catch (const std::overflow_error &ofe)
  127.     {
  128.         std::cerr << "Overflow error: " << ofe.what() << '\n';
  129.         keep_window_open();
  130.         return 3;
  131.     }
  132.     catch (const std::exception &e)
  133.     {
  134.         std::cerr << "Exception: " << e.what() << "\n";
  135.         keep_window_open();
  136.         return 4;
  137.     }
  138.     catch (...)
  139.     {
  140.         std::cerr << "An unknown exception occurred\n";
  141.         keep_window_open();
  142.         return 5;
  143.     }
  144.  
  145.     keep_window_open();
  146. }
  147.  
  148. Link *Link::insert(Link *n)
  149. {
  150.     if (n == nullptr)
  151.     {
  152.         error("Node to add cannot be null");
  153.     }
  154.     n->m_succ = this;
  155.     if (m_prev)
  156.     {
  157.         m_prev->m_succ = n;
  158.     }
  159.     n->m_prev = m_prev;
  160.     m_prev = n;
  161.     return n;
  162. }
  163.  
  164. Link *Link::add(Link *n)
  165. {
  166.     if (n == nullptr)
  167.     {
  168.         error("Node to add cannot be null");
  169.     }
  170.     n->m_prev = this;
  171.     if (m_succ)
  172.     {
  173.         m_succ->m_prev = n;
  174.     }
  175.     n->m_succ = m_succ;
  176.     m_succ = n;
  177.     return n;
  178. }
  179.  
  180. Link *Link::erase()
  181. {
  182.     Link *trav = this;
  183.     if (trav == nullptr)
  184.     {
  185.         return this;
  186.     }
  187.     if (trav->m_succ)
  188.     {
  189.         trav->m_succ->m_prev = trav->m_prev;
  190.     }
  191.     if (trav->m_prev)
  192.     {
  193.         trav->m_prev->m_succ = trav->m_succ;
  194.     }
  195.     return trav->m_succ;
  196. }
  197.  
  198. Link *Link::find(const std::string &name)
  199. {
  200.     Link *trav = this;
  201.     while (trav != nullptr)
  202.     {
  203.         if (trav->m_god->name() == name)
  204.         {
  205.             return trav;
  206.         }
  207.         trav = m_succ;
  208.     }
  209.     return this;
  210. }
  211.  
  212. const Link *Link::find(const std::string &name) const
  213. {
  214.     const Link *c_trav = this;                    // const pointer
  215.     Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
  216.     while (c_trav != nullptr && nc_trav != nullptr)
  217.     {
  218.         if (c_trav->m_god->name() == name)
  219.         {
  220.             return c_trav;
  221.         }
  222.         nc_trav = m_succ;
  223.     }
  224.     return this;
  225. }
  226.  
  227. Link *Link::find_if_myth(const std::string &myth)
  228. {
  229.     Link *trav = this;
  230.     while (trav != nullptr)
  231.     {
  232.         if (trav->m_god->myth() == myth)
  233.         {
  234.             return trav;
  235.         }
  236.         trav = trav->m_succ;
  237.     }
  238.     return this;
  239. }
  240.  
  241. const Link *Link::find_if_myth(const std::string &myth) const
  242. {
  243.     const Link *c_trav = this;                    // const pointer
  244.     Link *nc_trav = const_cast<Link*>(c_trav);    // non-const pointer
  245.     while (c_trav != nullptr && nc_trav != nullptr)
  246.     {
  247.         if (c_trav->m_god->myth() == myth)
  248.         {
  249.             return c_trav;
  250.         }
  251.         nc_trav = nc_trav->m_succ;
  252.     }
  253.     return this;
  254. }
  255.  
  256. Link *Link::advance(int n) const
  257. {
  258.     Link *trav = const_cast<Link *>(this);
  259.     if (trav == nullptr)
  260.     {
  261.         return const_cast<Link*>(this);
  262.     }
  263.     if (n > 0)
  264.     {
  265.         while (n--)
  266.         {
  267.             if (trav->m_succ == nullptr)
  268.             {
  269.                 return const_cast<Link*>(this);
  270.             }
  271.             trav = trav->m_succ;
  272.         }
  273.     }
  274.     else if (n < 0)
  275.     {
  276.         while (n++)
  277.         {
  278.             if (trav->m_prev == nullptr)
  279.             {
  280.                 return const_cast<Link*>(this);
  281.             }
  282.             trav = trav->m_prev;
  283.         }
  284.     }
  285.     return trav;
  286. }
  287.  
  288. Link *Link::add_ordered(Link *n)
  289. {
  290.     if (!n)
  291.     {
  292.         error("Node to insert cannot be null");
  293.     }
  294.    
  295.     Link *trav = this;
  296.     if (!trav)
  297.     {
  298.         return this;
  299.     }
  300.  
  301.     // to make sure to start at head of the list
  302.     while (trav->m_prev != nullptr)
  303.     {
  304.         trav = trav->m_prev;
  305.     }
  306.  
  307.     while (trav->m_god->name() < n->m_god->name() && trav->m_succ)
  308.     {
  309.         trav = trav->m_succ;
  310.     }
  311.  
  312.     if (n->m_god->name() < trav->m_god->name())
  313.     {
  314.         trav = trav->insert(n);
  315.     }
  316.     else
  317.     {
  318.         trav = trav->add(n);
  319.     }
  320.     return trav;
  321. }
  322.  
  323. void print_all(std::unique_ptr<Link> &p)
  324. {
  325.     if (p->previous() != nullptr)
  326.     {
  327.         while (p->previous() != nullptr)
  328.         {
  329.             p = std::make_unique<Link>(std::move(p->previous()));
  330.         }
  331.     }
  332.  
  333.     std::cout << "{\n";
  334.     while (p)
  335.     {
  336.         std::cout << "Name: " << p->god()->name()
  337.             << "; Myth: " << p->god()->myth();
  338.         if (p->god()->vehicle() != "")
  339.         {
  340.             std::cout << "; Vehicle: " << p->god()->vehicle();
  341.         }
  342.         else
  343.         {
  344.             std::cout << "; Vehicle: N/A";
  345.         }
  346.         std::cout << "; Weapon: " << p->god()->weapon();
  347.         if ((p = std::make_unique<Link>(std::move(p->next()))))
  348.         {
  349.             std::cout << "\n";
  350.         }
  351.     }
  352.     std::cout << "\n}\n";
  353. }
Add Comment
Please, Sign In to add comment