Linked list issues

Posted on 2004-11-05
Medium Priority
Last Modified: 2013-12-14
It's probably been 3 years since I've worked with a linked list, and as a result, I'm sure my error is very basic, but I just can't figure it out.  I've been provided with my teacher's code, and I did the best I could, but it still provides a problem.

Basically, I've written an interpreter for a language he's given us.  I'm having problems with the parser, though.  The tokenizer works great.  The input I'm trying to deal with is :

program int X , Y , XY;

It skips over the program fine, no problem.  The next part (int X , Y, XY; ) is an id-list, and that's an issue.  We have to check to first make sure the Id is not already declared before we use the constructor, otherwise, it shouldn't be a part of the list.  The program works great for a bit, as it reads in the X, and sets it to the first node.  Then, the second time through, the parseNode procedure has an error in the list.  I'm thinking it's a result of me building the linked list incorrectly, but I've bolded the line that causes an issue.  Down below that is the debug output I've added.  

void Idlist::parse()
                  cout << "Parsing id-list";
                  int tokNo, tokVal;
                  char idName[10];
                  ParseTree token;
                  token.getToken(tokNo, tokVal, idName);

                  cout << idName;
//outputs X the first time through, Y the second
                  Id2* id2;
                  id = (id2->parseId());
                  token.getToken(tokNo, tokVal, idName);
                  if (tokNo == COMMA)

                        cout << "Choosing second alternative";

So, in this section, basically, the token 'int' is skipped, leading to an id.  The id is in the current token, and getToken reads it in (does not skip it).  Then, the X is parsed correctly, returning back.  It skips over the X, then getToken returns that it is a comma and there are more values, so it recursively calls itself.  The second time through, it starts off by skipping the comma, then the getToken returns the value Y.  In parseID, below, there becomes problems.

#include "Id2.h"
#include "ParseTree.h"

#include <iostream>

class ParseTree;
Id2::Id2(char n1[10], Id2* nid) {
           // private constructor; used by parseId()
           strcpy(name, n1);
           decl = false; init = false; nextId = nid; }

Id2* Id2::parseId() {

      cout << "Parsing ID"; //prints out twice
          char n2[10]; Id2* candId;

              int tokNo, tokVal;

              ParseTree token;

              token.getToken(tokNo, tokVal, n2);

              if (firstId != NULL)
                    candId = Id2::firstId;
                    cout << "Before for"; //This  prints out twice
          for(candId = Id2::firstId; nextId != NULL; candId = nextId)
                    cout << "in loop";
                         //This line never prints, and on the second go round, it should.
               if (strcmp(n2, candId->idName()) == 0) return candId;

          // if not, create a new Id, make that the firstId, and return
          // that.
          candId = new Id2(n2, Id2::firstId);
              Id2::firstId = candId;
              cout << "Id name = " << candId->idName();
          return candId;
int Id2::getIdval() {
      if (!init)
            cout<< "error; uninitialized var";
                        return currVal; }
void Id2::setIdval(int x) { init = true; currVal = x; }
char* Id2::idName() { return name; }

The error is simply an exception error, and when I run it through the Windows debugger, it occurs at the for line in parseId.  The contId does get set to firstId, which is good , but 'this' is set to 0xcccccc.   Therefore, I think it's a problem with next, as it never enters the for loop (and prints out "In for loop") .  I tried earlier using static arrays for the ID names, values, and if they were initialized at all, but it didn't work, as the static variables had problems with references in the member functions.

          for(candId = Id2::firstId; nextId != NULL; candId = nextId)  is the line where it's erroring, then.   Since candId is set to Id2::firstId, that's not the issue.  It's with either one of the nextId statements, leading me to believe (very possibly) that I set it up wrong.

Thanks in advance for your help.  Any insight at all would be helpful.. I've been staring at my code for the last 2 days and I've come to no conclusions.

Question by:savante
  • 2
LVL 19

Accepted Solution

mrwad99 earned 172 total points
ID: 12513313
>> for(candId = Id2::firstId; nextId != NULL; candId = nextId)  is the line where it's erroring, then.  

What on earth is this supposed to do ?!  A for loop has the following form:

for (<initial state>; <test of condition>; <altering state>)
  // action

You have the first two correct, but the third, " candId = nextId" is completely wrong.  This will just run into infinity, since the variable in your testing condition, nextID, which you are testing against NULL, is never altered.  A more suitable implementation would be

for(candId = Id2::firstId; nextId != NULL; nextId++)

which loops through all values of nextID until we hit one that is NULL.

But even this is not fully conventional.  You should be initialising nextID in the first component of the for loop - you are stating

candId = Id2::firstId

candId has no part in the rest of the loop, so why include it ?  

Now I don't know what the overall aim here is, but it should be clear where you are going wrong.  So hopefully you can adjust your for loop accordingly.


LVL 17

Assisted Solution

rstaveley earned 164 total points
ID: 12518924
mrwad99 is right.

Technically, there's nothing to stop you from defining an operator=, which takes an non-const reference parameter, which it alters, like the following:

#include <iostream>

template<typename T> class depletor {
      T t;
public:      depletor(T& t) : t(t--) {}
      depletor<T>& operator=(T& depleted) /* Highly irregular operator= alters the operand!! */
            t = depleted--;
            return *this;
      operator T () const {
            return t;

int main()
      int next = 10;
      for (depletor<int> d = next;next;d = next)
            std::cout << "Depletor is " << static_cast<int>(d) << '\n';

But this is very unconventional and should be avoided for that reason. It is no accident that IOStreams use insertion operators rather than operator=. You shouldn't expect operator= to alter its parameter.

Assisted Solution

esorf earned 164 total points
ID: 12627312
Discussion of the loop aside, there is also a problem with your main().

               Id2* id2;
               id = (id2->parseId());

id2 is uninitialize.

Did you mean to say

    Id2* id2 = new Id2(idName, NULL);

and then delete id2 later on?


- Frank
LVL 19

Expert Comment

ID: 12874417
Three way split between all participants.

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.
Suggested Courses

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question