Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Exception for doubly circular linked list

  1. May 24, 2008 #1

    Defennder

    User Avatar
    Homework Helper

    I'm studying for an introductory C++ programming course and I'm trying to write the code for a doubly-circular linked list. To keep it simple, I had written my list to be tailored to that of a wedding dinner guest invitation list. Hence I didn't use templates at all. I've attempted to compile this code, but for some reason I just couldn't get it to compile because of some error due to exception handling.

    This is the error I get(among a lot of other errors, so I figured I'll fix this one at a time, so for now just focus on the red text):
    Code (Text):
    In file included from weddinglist.h:2,
                     from weddinglistimp.cpp:2:
    [COLOR="Blue"]exception.h:4: error: redefinition of `class exception'
    exception.h:4: error: previous definition of `class exception'[/COLOR]
    In file included from weddinglistimp.cpp:2:
    [COLOR="Red"]weddinglist.h:20: error: `exception' has not been declared
    weddinglist.h:22: error: `exception' has not been declared
    weddinglist.h:24: error: `exception' has not been declared[/COLOR]
    weddinglistimp.cpp:40: error: `exception' has not been declared
    weddinglistimp.cpp: In member function `void weddinglist::insert(int, const relation&, const std::string&)':
    weddinglistimp.cpp:44: error: `exception' undeclared (first use this function)
    weddinglistimp.cpp:44: error: (Each undeclared identifier is reported only once for each function it appears in.)
    weddinglistimp.cpp: At global scope:
    weddinglistimp.cpp:82: error: `exception' has not been declared
    weddinglistimp.cpp: In member function `void weddinglist::remove(int)':
    weddinglistimp.cpp:86: error: `exception' undeclared (first use this function)
    weddinglistimp.cpp: At global scope:
    weddinglistimp.cpp:110: error: `exception' has not been declared
    weddinglistimp.cpp: In member function `void weddinglist::retrieve(int, relation&, std::string&)':
    weddinglistimp.cpp:113: error: `exception' undeclared (first use this function)
    weddinglistimp.cpp: At global scope:
    weddinglistimp.cpp:121: error: `exception' has not been declared
    weddinglistimp.cpp:121: error: ISO C++ forbids declaration of `exception' with no type
    weddinglistimp.cpp: In function `int exception(std::string)':
    weddinglistimp.cpp:121: error: `int exception(std::string)' used prior to declaration
    weddinglistimp.cpp:122: error: `_message' undeclared (first use this function)
    weddinglistimp.cpp: At global scope:
    weddinglistimp.cpp:124: error: `exception' has not been declared
    weddinglistimp.cpp:124: error: ISO C++ forbids declaration of `exception' with no type
    weddinglistimp.cpp: In function `int exception()':
    weddinglistimp.cpp:125: error: `_message' undeclared (first use this function)
    weddinglistimp.cpp: At global scope:
    weddinglistimp.cpp:127: error: `exception' has not been declared
    weddinglistimp.cpp:127: error: non-member function `std::string getmessage()' cannot have `const' method qualifier
    weddinglistimp.cpp: In function `std::string getmessage()':
    weddinglistimp.cpp:128: error: `_message' undeclared (first use this function)
     
    As you can see, most of the errors are related to the 'exception' class I've defined and included in the header file. So I figured if I fix that error, most of the other errors would disappear as well.

    This is the contensts of 'weddinglist.h':
    Note: The red text indicates the lines for which the compiler error message is displayed for.
    Code (Text):
    #include <string>
    #include "exception.h"
    using namespace std;

    enum relation { pal, coworker, relative };

    class weddinglist{

        public:
            //Constructor, destructor
            weddinglist();
            ~weddinglist();

            //Small functions
            bool isempty() const;
            int getlength() const;

            //Big functions
            void insert(int index, const relation& type, const string &name)
           [COLOR="Red"] throw (exception);[/COLOR]
            void remove(int index)
            [COLOR="red"]throw (exception);[/COLOR]
            void retrieve(int index, relation& type, string& name)
            [COLOR="red"]throw (exception);[/COLOR]

        private:
            struct node{
                string _name;
                relation _type;
                node *next, *prev;};

                int size;
                node *head;
                node* find(int index) const;
    };
    Contents of "exception.h":

    Code (Text):
    #include <string>
    using namespace std;

    class exception{
        public:
        exception(string errmessage);
        exception();
        string getmessage() const;

        private:
        string _message;
    };
     
    Contents of 'weddinglistimp.cpp'. This is the implementation file for the above-mentioned member functions of the doubly-circular linked list:

    Code (Text):
    #include "exception.h"
    #include "weddinglist.h"
    #include <string>
    #include <iostream>
    using namespace std;

    weddinglist::weddinglist()
        :size(0), head(NULL){}

    weddinglist::~weddinglist()
    {
        while (!isempty())
            remove(1);
    } // end destructor

    bool weddinglist::isempty() const
    {
        return size == 0;
    } // end isempty

    int weddinglist::getlength() const
    {
        return size;
    } // end getLength

    weddinglist::node *weddinglist::find(int index) const
    {
        if ( (index < 1) || (index > getlength()) )
            return NULL;
        else // count from the beginning of the list.
        {
            node *cur = head;
            for (int skip = 1; skip < index; ++skip)
                cur = cur->next;
            return cur;
        } // end if
    } // end find

    void weddinglist::insert(int index, const relation& type, const string& name)
    throw (exception)
    {

        if( (index<1)||(index>(getlength()+1)))
            throw exception("Bad index specified");

        else{
            cout<<"Line 42"<<endl;
            node *ptr = new node;
            size++;
            cout<<"Line 45"<<endl;
            cout<<size<<endl;
            ptr->_name = name;
            ptr->_type = type;
            cout<<"Line 48"<<endl;

            if((index==1) || (index==size))
            {  
                node *last = find(size-1);
                cout<<"Line 53"<<endl;
                ptr->next = head;
                ptr->prev = last;
                cout<<"Line 56"<<endl;
               
                if(size!=1){
                head->prev = ptr;
                cout<<"Line 58"<<endl;
                last->next = ptr;
                cout<<"Line 59"<<endl;}

                head = ptr;}

            else{
                node *cur = find(index);
                ptr->next = cur->next;
                ptr->prev = cur;
                node *nextnode = cur->next;
                nextnode->prev = ptr;}
        }
    }

    void weddinglist::remove(int index)
    throw (exception)
    {

        if ( (index<1)||(index>getlength()))
            throw exception("Bad index specified");
        else
        {
            size--;
            if (index==1){
                node *last = find(index);
                node *cur = head->next;
                cur->prev = last;
                last->next = cur;
                delete head;
                head = cur;}

            else{
                node *cur = find(index);
                node *nodeptr = cur->prev;
                nodeptr->next = cur->next;
                nodeptr = cur->next;
                nodeptr->prev = cur->prev;
                delete cur;
                cur = NULL;}
        }
    }

    void weddinglist::retrieve(int index, relation& type, string& name)
    throw (exception)
    {
            if ( (index<1) || (index>getlength()) )
                throw exception("Bad index specified");

            else{
                node *cur = find(index);
                type = cur->_type;
                name = cur->_name;}
        }

    exception::exception(string errmessage){
        _message = errmessage;}

    exception::exception(){
        _message = "Out of index error default";}

    string exception::getmessage() const{
        return _message;}
    Now the question I have here is this: Why does the compiler say that 'exception' is undefined when I have so defined it in a user-defined header file and included it? Furthermore, why does it say (highlighted as blue text in the first CODE block) that a class redefinition has been attempted? I've only defined the class 'exception' once.
     
  2. jcsd
  3. May 24, 2008 #2

    Borek

    User Avatar

    Staff: Mentor

    Aren't you including excteption.h twice? Both in weddinglistimp.cpp and in weddinglistimp.h?
     
  4. May 24, 2008 #3

    Defennder

    User Avatar
    Homework Helper

    Commenting out either one of those #include statements makes the error highlighted in blue disappear. Thanks. But what of the error in red?
     
  5. May 24, 2008 #4
    Try putting the exception member function definitions in their own cpp file. Also, use header include guards, e.g.:
    Code (Text):

    #ifndef SOME_UNIQUE_STRING
    #define SOME_UNIQUE_STRING

    #endif
     
    That should help you avoid redefinition errors.
     
  6. May 24, 2008 #5
    I made a post here but then checked and found it was inaccurate. One minute.
     
    Last edited: May 24, 2008
  7. May 24, 2008 #6
    Which #include did you comment out? If you commented out the one in weddinglist.h then that is your problem, because weddinglist.h must have exception.h included (otherwise "exception" is not defined at the time weddinglist.h is interpreted). If you comment out the one in weddinglist.cpp then it appears both red and blue errors go away.

    You should do the define-guard thing JaWiB suggests either way just as a matter of cleanliness.
     
  8. May 24, 2008 #7

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You could of course cure a lot of problems by getting rid of the throw(exception) in the prototype definitions. That is what most professional programmers have learned to do. (Read the paper cited in your other thread on exceptions for an explanation why.) The language isn't quite as good at exceptions as are other languages. The declaration is more or less eye candy in C++.

    That said, you should always put in a #define guard in each and every header file you write. You will see such a guard mechanism in every single header file in the standard library include files. Look at them as a guide.

    BEWARE: The standard include files use something like
    #ifndef _CPP_CMATH
    #define _CPP_CMATH
    ...
    #endif

    What you need to beware of: Never, ever, ever use a label that starts with underscore. If you do, you might collide with a guard label in some standard include file. A leading underscore is reserved for use by the compiler vendor. This is unenforced (and unenforceable) rule in the C and C++ standards. Don't even use a leading underscore for a variable (or element, or function, or ...) name. *All* uses of leading underscores are reserved for use by the compiler vendor. BTW, you broke that unenforced rule several times in your code. Even though the rule is unenforced you should nonetheless always obey it.
     
    Last edited: May 24, 2008
  9. May 24, 2008 #8

    rcgldr

    User Avatar
    Homework Helper

    There is one exception, a struct prototype (at least in Windows environments):

    Code (Text):

    struct _WEDDINGLIST{
        struct _WEDDINGLIST *next;
        struct _WEDDINGLIST *prev;
        // ...
    }WEDDINGLIST, *PWEDDINGLIST;
     
    Note, some older compilers may not support self references in structures.
     
  10. May 24, 2008 #9

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    That is a violation of the standard, pure and simple. There are no exceptions to this rule in the standard, not even for Microsoft or for Jeff Reid. The resulting code is non-compliant. It will compile, of course, because this rule is not enforced.

    This rule is completely unenforceable because the C/C++ preprocessor is distinct from the language proper. (The C/C++ preprocessor language is in fact a completely different language than C or C++ proper. The X11 developers used this to their advantage in the form of the now-defunct imake.) The C/C++ preprocessor knows the difference between compiler-provided and end developer content but it does not parse that content other than to the extent needed to expand macros. By the time the preprocessor is finished, the C/C++ compiler proper does not necessarily know whether a name with a leading underscore came from a file provided by the compiler vendor or written by the end developer.
     
  11. May 24, 2008 #10

    Defennder

    User Avatar
    Homework Helper

    Thanks for all your replies, guys. Unfortunately the problem still persists and I really don't know how to get rid of that error.

    I kind of agree with you. From my own limited programming practice, I've had a lot less errors when I remove the throw(exception) from the prototype definitions. But unfortunately, the course I'm taking seems to encourage it, and much of the code written in the notes actually incorporates such a practice. Believe it or not, the course I'm taking actually says doing so constitutes good programming practice. See here:

    [​IMG]

    I'm rather new to C++ and to programming in general. How do I access the standard C++ library header files?


    For some reason, my notes actually encourage the opposite. See:
    [​IMG]

    I tried out your suggestion and the problem still persists. You mean you tried it out and it works? I als tried separating the class implementation for exception.h and weddinglist.h, but still it persists.
     
  12. May 25, 2008 #11

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    When the identifier begins with a single underscore followed by a lowercase letter, it's only reserved at file scope; e.g. it's fair game for class members and local variables. That said...

    Allow me to suggest a slightly different condition: put the underscore at the end of your identifiers; that way you'll have no worries. (Just don't use a pair of underscores -- that is also reserved)
     
  13. May 25, 2008 #12

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    I would like to point out that there exists a class std::exception, which might be causing you some problems.
     
  14. May 25, 2008 #13

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    I say it's still off limits. It's certainly one of my rules, and since I write the rules for a bunch of other people, its their rule as well. Suppose you don't put your classes, methods, functions etc in a namespace. Your _local variable can then hide a global _local variable or _local function declared in some old C language header file. That header file might well use that _local variable or function in a macro, and that old C language header might well be #included by a C++ header file that your file #includes, directly or indirectly. Kaboom!
     
  15. May 25, 2008 #14

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Yikes! More on this later.

    I can understand the thing with exceptions. The C++ language design community swung and missed with the exception declaration thing. Professional programmers know this from experience, but book authors and college professors often lack that experience. It makes sense to learn about exceptions, and then throw some of that knowledge away (the declaration part).

    Now for the yikes. Never do this:
    Code (Text):
    if ( b == 0 )
        throw string ("b is zero!!");
    Always use braces. I have helped far to many people chase a bug down that turns out to have resulted from missing braces. The C/C++ community swung and missed on that as well. To see this in a book (or lecture material) is just bad. Adding braces doesn't cost anything other than a tiny bit of typing and saves a whole lot of agony.

    BTW, Sorry for the exceptionally bad baseball puns. I couldn't resist throwing them out.
     
    Last edited: May 25, 2008
  16. May 25, 2008 #15

    Defennder

    User Avatar
    Homework Helper

    It appears you are right, Hurkyl. I renamed that class to listexception and all the compiler errors related to undeclared 'exception' disappeared. It is now able to compile successfully. Thanks!

    On the other hand, while it could compile successfully, it gives only a semi-correct output before terminating at "Segmentation Fault". Well, at least I'm past that irritating exception handling error, so I guess what's left is for me to debug the doubly circular linked list implementation code. I added a lot of cout<<"Line XX"<<endl; to the implementation file so I could debug it.
     
  17. May 25, 2008 #16

    Hurkyl

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    But you are not the worldwide C/C++ czar of style; you have no business imposing your rule upon those outside of your authority. Nor do your rules affect what identifiers are reserved in what contexts in the standard.

    I'm somewhat confused by your rant, though, since I also advised the OP not to use leading underscores.


    That's the problem with nonconforming implementations -- their behavior doesn't conform to the standard.

    (I don't see the point about talking about namespaces; whether or not the function/class is in the global namespace is irrelevant to the results when a macro references a shadowed identifier)
     
    Last edited: May 25, 2008
  18. May 25, 2008 #17

    rcgldr

    User Avatar
    Homework Helper

    I just go with the flow. If it's good enough for Microsoft ... Here's a typical example of this usage by Microsoft in mapiwin.h:

    Code (Text):

    typedef struct _WIN32_FIND_DATA {
        DWORD dwFileAttributes;
        FILETIME ftCreationTime;
        FILETIME ftLastAccessTime;
        FILETIME ftLastWriteTime;
        DWORD nFileSizeHigh;
        DWORD nFileSizeLow;
        DWORD dwReserved0;
        DWORD dwReserved1;
        TCHAR cFileName[MAX_PATH];
        TCHAR cAlternateFileName[14];
    } WIN32_FIND_DATA, *PWIN32_FIND_DATA;
     
    I've seen a quite a few windows app programmers use this same convention. I have looked into this and it seems that leading underscores are discouraged (when did this happen?), so I'll switch to using trailing underscores for my stuff. However I'm still stuck with all those Microsoft include files.
     
    Last edited: May 25, 2008
  19. May 25, 2008 #18

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: Exception for doubly circular linked list
  1. Linked List (Replies: 9)

  2. Linked list (Replies: 12)

Loading...