0

I am trying to catch exceptions on the double linkedlist. But I do not know how execute it so it gives errors like "not enough memory, deleting an element from an empty list, and any other exceptions that can be found". When I run it just outputs the double linked list without the exceptions. Thanks!

#include <cstdlib>
#include <iostream>
using namespace std;
struct Node
{
    int data;
    Node* next;
    Node* prev;
};
void printFront(Node*head)
{
    Node* firstToLast = head;
    while (firstToLast != nullptr)
    {
        cout << firstToLast->data << endl;
        firstToLast = firstToLast->next;
    }
}
void printBack(Node* tail)
{
    Node* firstToLast = tail;
    while (firstToLast != nullptr)
    {
        cout << firstToLast->data << endl;
        firstToLast = firstToLast->prev;
    }
}
void main()
{
    
        Node* head;
        Node* tail;
        //1st node
        Node* node = new Node();
        node->data = 4;
        node->next = nullptr;
        node->prev = nullptr;
        head = node;
        tail = node;
        //2nd node
        node = new Node();
        node->data = 5;
        node->next = nullptr;
        node->prev = tail;
        tail->next = node;
        tail = node;
        //3rd node
        node = new Node();
        node->data = 6;
        node->next = nullptr;
        node->prev = tail;
        tail->next = node;
        tail = node;
        printFront(head);
        try
        {
            if (tail != head)
            {
                throw 2;
            }
        }
        catch (exception x)
        {
            cout << "The error is ...  " << x.what();
        }
}
  • 1
    `2` is an `int`, not an `std::exception`, so obviously you can't catch it like that. – Yksisarvinen Jul 25 '22 at 11:41
  • 1
    You need to throw an exception class like this `throw std::runtime_error{};` and always catch by const&, so `catch(const std::exception& x)` you will need to include . Note I explicitly use the `std::` namespace. Do not use `using namespace std` : [Why using namespace std is consider bad practice](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Pepijn Kramer Jul 25 '22 at 11:44
  • How would I write it though instead of the 2. I tried putting the word exception instead of the int and it still shows me the same thing without any exceptions. – Larrythelobster Jul 25 '22 at 11:45
  • You don't have any functions that *should* throw. Currently you repeat a bunch of operations in `main`, the only of which could go wrong are the `new Node()`s – Caleth Jul 25 '22 at 11:45
  • @Caleth I think OP is experimenting still, the throw's should ofcourse still move to functions. – Pepijn Kramer Jul 25 '22 at 11:46
  • exceptions should be caught by reference – 463035818_is_not_an_ai Jul 25 '22 at 11:46
  • 1
    @463035818_is_not_a_number const reference – Pepijn Kramer Jul 25 '22 at 11:46
  • 1
    Has your instructor taught you about classes, member functions, `public` and `private`, testing your code by deliberately doing "incorrect" things? – Caleth Jul 25 '22 at 11:51
  • Hopefully you learn about constructors really soon because a lot of this just vanishes if you do that. – tadman Jul 25 '22 at 12:02
  • @Caleth You mean "define an abstract base class first" (interface), then write unit tests (e.g. using google_test) and do stuff with dependency injection? ;) They might as well first teach the USE the tested version of std::list before having a go at implementing a list themselves. And after that they will never look back and always use std::list – Pepijn Kramer Jul 25 '22 at 12:04
  • @PepijnKramer not even that. Getting to the point where `int main() { List list; list.remove(1); }` even compiles involves a fair amount of teaching. You don't need gtest to do that. – Caleth Jul 25 '22 at 12:07
  • @Caleth I forgot to put "cynic" mode on ;) But yes you are right it does take a few steps to get there. Shouldn't be a problem to make that first program use std::list though (first teach use of a correct list then implement one yourself). – Pepijn Kramer Jul 25 '22 at 12:12

2 Answers2

1

Your try/catch makes little sense.

If you want to catch deleting an element from an empty list, you should

  1. Write a function that deletes an element from a list.
  2. Make it throw an exception when the input list is empty.
  3. Finally, catch that exception when you try calling said function. Not inside the function itself. That's not what exceptions are for.

You can throw exceptions of almost any data type, but that's bad practice. Create an exception class and throw objects of that class.

 class MyListException
 {
   // add an explicit constructor with a string argument, 
   // and a virtual destructor
   public:
     std::string what() { return m_what; }
   private:
     std::string m_what;
 };

 // somewhere
 if (...) {
    throw MyListException("deleting from an empty list");
 }

 // somewhere else
 try {
    // something 
 }
 catch (const MyListException& e) {
    // std::cout << ... << ... << e.what(); 
 }

If you want to catch a "not enough memory" condition, you need to look up which standard exception is thrown when new fails to allocate memory. Write a function that allocates an awful lot of nodes, and try calling that function, catching that exception. Note that on some modern operating systems you are not likely to get such an exception (look up "OOM killer" if you want to know more).

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • It would be nice `class MyListException : public std::runtime_error {` to make the application more general. – Ivan Jul 25 '22 at 12:07
1

You could catch any type (as an integer) but is considered a bad practice (it's funny there's an example throwing 42 in cpp reference) and you can have unexpected results.

However, the "right" way is throwing a std::runtime_error and then catching it.

You can simply add error text as

std::runtime_error("my error");

Or you could do something more elaborate by creating a class that inherits from std::runtime_error and adding more information to it.

Finally in your catch, you can get the error description as:

catch (const std::exception& e)
{
    std::cout << "Failed  with: " << e.what();
}

This is a great lecture about exceptions that may help you a lot :)

Ivan
  • 1,352
  • 2
  • 13
  • 31
  • Upvoted in part for the linked lecture. Very readable practical advice that doesn't get philosophical or preachy. – Persixty Jul 25 '22 at 12:36