Saturday 28 January 2017

Unable to retrieve values from object in Linked List in C++




update: added LinkedList.h and SymbolTable.h



So I'm having difficulty with a programming assignment from school. This is my first C++ course, the previous ones were taught in Java.



I created a linked list of SymbolTable objects and I need to retrieve the id (std::string) and value (int) from each when traversing the list, but any values I try to get just return null.



I think I'm missing something fundamental here, but not sure what.



this is the output I get, notice the blank line is from calling
cout << temp->data->getID() << endl;




I'm really at a loss of how to fix/get around this.



output:



C:\Users\spud\Documents\Visual Studio 2010\Projects\EECS1580_assign_01\Debug>EEC
S1580_assign_01.exe
Reading file...
Parsing...id_1 = 40
id_1

40

Parsing...var_2 = 50
var_2
50

Parsing...id_1 += 30
Parsing...var_2-=20
Parsing...id_1*=5
Parsing...k_27=80

k_27
80

Parsing...k_27 /= 20
done reading..
done


Here's the code




LinkedList.cpp



#include "StdAfx.h"
#include "LinkedList.h"
#include
#include
#include "SymbolTable.h"

using namespace std;



// define node for LinkedList
typedef struct node
{
public:
SymbolTable *data; // data in node
node *next; // link to next node
node()
{
next = NULL;

data = new SymbolTable();
}
};


node *head = NULL; // empty linkedList
node *tail = NULL;
node *curr = NULL;



LinkedList::LinkedList()
{
head = new node();
}

LinkedList::~LinkedList()
{
node *q;
if( head == NULL )
return;


while( head != NULL )
{
q = head->next;
delete head;
head = q;
}
}



// insert node at front of LinkedList
void LinkedList::insert(string id, int value)

{
SymbolTable *s = new SymbolTable(id, value);

node *temp; //create a temporary node
temp = new node; //allocate space for node

temp->data = s; // store data(first field)

temp->next = head; // store the address of the pointer head(second field)
head = temp; // transfer the address of 'temp' to 'head'
cout << temp->data->getID() << endl;
}

void LinkedList::display()
{
node *q;
cout << endl;


for(q = head; q != NULL; q = q->next)
cout << q->data->toString() << endl;
}


void LinkedList::traverse()
{

node *curr;
curr = head;

SymbolTable *temp;

if(head == NULL)
cout << "End of list.\n";
else
{
while(curr != NULL) {
//cout << temp->data.toString() << " ";
temp->setID(curr->data->getID());
temp->setValue(curr->data->getValue());

cout << temp->getID() << endl;
curr = curr->next;
}
}
}

/*void find(string tofind, char op, int value)
{
node *temp1; // create tmp node
temp1 = head; // transfer address of p to temp1

//string t = "";
while(temp1 != NULL)
{
// t = temp1->data.getID();
// if(tofind.compare(t) == 0)
{
cout << "match!" << endl;
// temp1->data.performOp(op, value); // perform op
}
// temp1 = temp1->next; // transfer address of temp->next to temp

}
cout << "no match!" << endl;
}*/

void LinkedList::sort()
{
node *temp, *temp1, *temp2;
//temp = new node;
//temp1 = new node;
//temp2 = new node;


for(temp1 = head; temp1 != NULL; temp1 = temp1->next)
for(temp2 = head; temp2 != NULL; temp2 = temp2->next)
{
if(temp1->data->toString() < temp2->data->toString())
{
temp->data = temp2->data;
temp2->data = temp1->data;
temp1->data = temp->data;
}

}
}


SymbolTable.cpp



#include "StdAfx.h"
#include "SymbolTable.h"
#include
#include

#include
#include
#include

using namespace std;

string id;
int value;
int final;



void SymbolTable::setID(string s)
{
id = s;
}

void SymbolTable::setValue(int a)
{
value = a;
}


// Will perform the requested operation on the node
int SymbolTable::performOp(char op, int val)
{
// final value to return
int final = 0;
// determine which op to use, then exec it
switch (op) {
case '+':
value += val; break;

case '-':
value -= val; break;
case '*':
value *= val; break;
case '/':
value /= val; break;
case '%':
value %= val; break;
default:
// no operation performed

cout << "noOp" << endl;
break;
}

cout << id << " New Value: " << value << endl;

// return the new value
return value;
}


// returns a string with info about the node
string SymbolTable::toString(void)
{
// create new string to return
string mString;
// append id and = to the string
mString.append(id).append("=");
// append in to string
ostringstream oss;
oss << value;

mString += oss.str();
cout << mString << endl;
// return the final string
return mString;
}

// return Id
const string SymbolTable::getID(void)
{
return id;

}
const int SymbolTable::getValue(void)
{
return value;
}

// return the link that this obj points to
//SymbolTable* SymbolTable::getLink()
//{
// return link;

//}

// set link
//void SymbolTable::setLink(SymbolTable *s)
//{
// link = s;
//}

// Constructor
SymbolTable::SymbolTable(string a, int v)

{

// initialize the id
id = a;
cout << getID() << endl;
// initialize the value
value = v;
cout << getValue() << endl;
final = 0;
}

SymbolTable::SymbolTable()
{
id = "";
value = 0;
}

// deConstructor
SymbolTable::~SymbolTable(void)
{
// clear the string

id.clear();
// set value to 0
value=0;
}


Main



#include "stdafx.h"
#include

#include
#include
#include
#include
#include
#include "SymbolTable.h"
#include "LinkedList.h"

using namespace std;


//SymbolTable *root = NULL;

LinkedList mylist;

void parse(string line)
{
int value;
string svalue;
string id;
char op;


cout << "Parsing..." << line << endl;

// remove all spaces
for(int i=0; i if(line[i] == ' ')
line.erase(i,1);

int eqSpot = line.find('='); // find the =
svalue = line.substr(eqSpot+1, line.length()-1); // set value

switch(line.at(eqSpot-1)){ // set op
case '+': op = '+'; eqSpot--; break;
case '-': op = '-'; eqSpot--; break;
case '*': op = '*'; eqSpot--; break;
case '/': op = '/'; eqSpot--; break;
default: op = '='; break;
};

id = line.substr(0, eqSpot); // set id


stringstream ss(svalue); // convert std::string svalue to int value
ss >> value;

if(op == '=') // if decleration..
{
// create new node in the LinkedList
mylist.insert(id, value); // insert s into LL
}
else // else is operation
{

// myList.find(id, op, value);
}
}

/*// sorts the nodes in the LL
void sort()
{
SymbolTable *temp1;
SymbolTable *temp2;
SymbolTable *temp;


cout << "Sorting Nodes..." << endl;
for( temp1 = root ; temp1!=NULL ; temp1 = temp1->getLink() )
{
for( temp2 = temp1->getLink() ; temp2!=NULL ; temp2 = temp2->getLink() )
{
if( temp1->getID() > temp2->getID() )
{
temp = temp1->getLink();
temp1->setLink(temp2->getLink());

temp2->setLink(temp);
}
}
}
}
// should print out the toString for each node
void printNodes()
{
SymbolTable *node = root;


do
{
cout << node->toString() << endl;
}while((node = node->getLink()) != NULL);
}
// Will traverse the string, comparing IDs and will return a pointer to that node or null if not found
SymbolTable* traverse(string id)
{
SymbolTable *temp1; // create tmp node
temp1 = root;


while(temp1 != NULL)
{
cout << temp1->toString() << endl;
if(id.compare(temp1->getID()) == 0)
{
// Found!
cout << "MATCH" << endl;
return temp1;
};

cout << root->getLink() << endl;
if(temp1 == temp1->getLink())
temp1 = NULL;
else
temp1 = temp1->getLink(); // transfer address of temp->next to temp
};

cout << "NO MATCH FOUND" << endl;
return NULL;


}
*/

// some test values
int _tmain(int argc, _TCHAR* argv[])
{
// Read input
mylist = LinkedList();
string line;
ifstream myfile ("input.txt"); // input file

if (myfile.is_open())
{
cout << "Reading file..." << endl;
while ( myfile.good() ) // read file line by line
{
getline(myfile,line);
if(line.compare("") == 0) // end of file
break;
else
parse(line); // parse the line

}
myfile.close();
cout << "done reading.." << endl;
}
else cout << "Unable to open file";

//myList.sort();

//myList.traverse();


cout << "done";
//return 0;

return EXIT_SUCCESS;
}


LinkedList.h



#pragma once

#include "SymbolTable.h"
#include

class LinkedList
{
private:

public:
LinkedList(void);
~LinkedList(void);

void insert(std::string id, int value);
void display();
void traverse();
void sort();
//void find(std::string, char, int);
};


SymbolTable.h




#pragma once
#include
#include
#include
#include
#include

class SymbolTable
{
public:

int performOp(char, int);
std::string toString(void);
const std::string getID(void);
void setValue(int);
void setID(std::string);
const int getValue();
SymbolTable(std::string, int);
SymbolTable();
~SymbolTable(void);
};


Answer



One problem is removing spaces in parse function



 // remove all spaces                                             
for(int i=0; i if(line[i] == ' ')
line.erase(i,1);



When space is removed index should not be incremented, so that you can remove the possible next space.



But you main problem is having global variables that should have been members of SymbolTable:



string id;
int value;
int final;


Instead of this above you should have the following (in SymbolTable.h):




class SymbolTable
{
string id;
int value;
int final;

// declaration of all the member functions
...
};



Also, in this code you don't need destructor (the one you call deConstructor). All members will be automatically deleted when the object is deleted itself. You only have to worry about deleting objects of which you only have a pointer.



Global variables that pertain to LinkedList should also be members of that class, instead of being global:



class LinkedList
{
node *head;
node *tail;

node *curr;

// declaration of all the member functions
...
};


And their initialization should be done in constructor:



LinkedList::LinkedList()

{
head = NULL; // empty linkedList
tail = NULL;
curr = NULL;
}

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...