I am really new to C++ and this code was an example in my book so it should work because I have to implement a few new functions into this. However, I copied the code line for line and I keep getting this error message now my code won't compile until I fix it.
It says that my local pointer 'node' is being used. I don't know what this actually means. Could anyone tell me whats is the error actually telling me? Also could some one help me fix this so I can start my project? I'm only asking for the code because this isn't part of my project, it was already given by the teacher.
Here is my code:
// ListNode.h
#ifndef _LISTNODE_H
#define _LISTNODE_H
#include <cstdlib>
typedef int ItemType;
class ListNode {
friend class LList;
public:
ListNode(ItemType item, ListNode* link = NULL);
private:
ItemType item_;
ListNode *link_;
};
inline ListNode::ListNode(ItemType item, ListNode *link)
{
item_ = item;
link_ = link;
}
#endif // _LISTNODE_H
// LList.h
#ifndef _LLIST_H
#define _LLIST_H
#include "ListNode.h"
class LList {
public:
LList();
LList(const LList& source);
~LList();
LList& operator=(const LList& source);
int size() { return size_; }
void append(ItemType x);
void insert(size_t i, ItemType x);
ItemType pop(int i = -1);
ItemType& operator[](size_t position);
private:
// methods
void copy(const LList &source);
void dealloc();
ListNode* _find(size_t position);
ItemType _delete(size_t position);
// data elements
ListNode *head_;
int size_;
};
#endif // _LLIST_H
// LList.cpp
#include "LList.h"
LList::LList()
{
head_ = NULL;
size_ = 0;
}
ListNode* LList::_find(size_t position)
{
ListNode *node = head_;
size_t i;
for (i = 0; i<position; i++) {
node = node->link_;
}
return node;
}
ItemType LList::_delete(size_t position)
{
ListNode *node, *dnode;
ItemType item;
if (position == 0) {
dnode = head_;
head_ = head_->link_;
item = dnode->item_;
delete dnode;
}
else {
node = _find(position - 1);
if (node != NULL) {
dnode = node->link_;
node->link_ = dnode->link_;
item = dnode->item_;
delete dnode;
}
}
size_ -= 1;
return item;
}
void LList::append(ItemType x)
{
ListNode *node, *newNode = new ListNode(x);
if (head_ != NULL) {
node = _find(size_ - 1);
node->link_ = newNode;
}
else {
head_ = newNode;
}
size_ += 1;
}
void LList::insert(size_t i, ItemType x)
{
ListNode *node;
if (i == 0) {
head_ = new ListNode(x, head_);
}
else {
node = _find(i - 1);
node->link_ = new ListNode(x, node->link_);
}
size_ += 1;
}
ItemType LList::pop(int i)
{
if (i == -1) {
i = size_ - 1;
}
return _delete(i);
}
ItemType& LList::operator[](size_t position)
{
ListNode *node;
node = _find(position);
return node->item_;
}
LList::LList(const LList& source)
{
copy(source);
}
void LList::copy(const LList &source)
{
ListNode *snode, *node;
snode = source.head_;
if (snode) {
node = head_ = new ListNode(snode->item_);
snode = snode->link_;
}
while (snode) {
node->link_ = new ListNode(snode->item_);
node = node->link_;
snode = snode->link_;
}
size_ = source.size_;
}
LList& LList::operator=(const LList& source)
{
if (this != &source) {
dealloc();
copy(source);
}
return *this;
}
LList::~LList()
{
dealloc();
}
void LList::dealloc()
{
ListNode *node, *dnode;
node = head_;
while (node) {
dnode = node;
node = node->link_;
delete dnode;
}
}
I know where the problem is exactly (Line 104 in my code)
node->link_ = new ListNode(snode->item_);
This part of my code is the problem. Could anyone help me fix this problem so I can work on my program? Thanks!
Now that my previous problem was answered I have a new one.
How would I go about testing my code? I have a few lines but it keeps coming out with errors when I try to print out the contents of my LList. This is my test code:
#include "LList.h"
int main()
{
LList b, c;
int x;
b.append(1);
b.append(2);
b.append(3);
c.append(4);
c.append(5);
c = b;
x = b.pop();
}
Could anyone help me write a working test code, this the last thing I will need to start adding my different functions.
This is probably due to warnings being treated as errors in your build. The compiler is complaining that node might not be initialized when node->link is accessed. However, that won't actually be the case because if snode is null, the while block won't be accessed, so you won't access the uninitialized memory. If you want to make the warning go away, putting the while loop inside the if block will probably work:
snode = source.head_;
if (snode) {
node = head_ = new ListNode(snode->item_);
snode = snode->link_;
while (snode) {
node->link_ = new ListNode(snode->item_);
node = node->link_;
snode = snode->link_;
}
}
This is a false warning as the compiler seems to think you are going to use the node without having assigned it (because it might skip the if statement). In this scenario I do not see how this would happen as the while (snode) would never be entered.
You could simply ignore this warning (disable treat warnings as errors in the project settings) or remove this warning from this specific part of code (#pragma warning(disable : 4703)).
To build without treating warnings as errors go to: Project -> Properties -> C/C++ -> Treat warnings as errors. Disable this option or use the pragma directives.
Related
I am trying to make a way to take two Linked List objects (doubly-linked), say LL1 and LL2, and remove the 'overlapping' elements within LL1 which also appear in LL2.
So for example if:
LL1 = {1,2,3};
LL2 = {9,2,8};
I want an output of:
LL1 = {1,3};
I am trying to do this via overloading the '-=' operator to work with two linked list objects. It compiles fine, but I'm getting a 'segmentation fault (core dumped)' error during runtime at the '-=' operator call. Not sure why. Below is my code. Any help would be appreciated, thankyou kindly.
Node.h:
// Node.h
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Header file for Node
#ifndef NODE_H
#define NODE_H
#include <iostream>
#include <cstdlib>
#include "EToll.h"
using namespace std;
class Node {
public:
typedef EToll value_type; //typedef - now value_type is synonym for EToll object
//Constructors:
Node(); //default
Node(value_type&); //constructor with 1 arg - data item
Node(const value_type& i, Node* n, Node* p); //specific constructor with 3 arguments
//Destructor:
~Node();
//mutators (setters):
void set_next(Node*);
void set_prev(Node*);
void set_data(const value_type&);
//accessors (getters):
Node* get_next() const;
Node* get_prev() const;
value_type& get_data();
private:
Node* next; //ptr to next (or NULL)
Node* prev; //ptr to prev (or NULL)
value_type data; //the payload
};
#endif
Node.cpp:
// Node.cpp
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Implementation of Node
#include "Node.h"
#include <cstdlib>
//Constructors:
Node::Node() //default constructor
{
data = value_type(); //creates an empty EToll object, since value_type is a synonym for EToll
next = NULL;
prev = NULL;
}
Node::Node(value_type& item) //constructor with 1 argument - a data item
{
data = item;
next = NULL;
prev = NULL;
}
Node::Node(const value_type& i, Node* n, Node* p) //constructor with 3 arguments
{
data = i;
next = n;
prev = p;
}
//Empty destructor:
Node::~Node(){}
//Mutators (setters):
void Node::set_next(Node* next_ptr) {next = next_ptr;}
void Node::set_prev(Node* prev_ptr) {prev = prev_ptr;}
void Node::set_data(const value_type& new_data) {data = new_data;}
//Accessors (getters):
Node* Node::get_next() const {return next;}
Node* Node::get_prev() const {return prev;}
/* Note that get_data() has Node::value_type& instead of value_type& as it's return type as the
compiler doesn't check if the return type of a function is part of a member function, and thus
it doesn't look in Node for a value_type. A more detailed explanation can be found at: https://stackoverflow.com/questions/68991650/error-value-type-does-not-name-a-type-in-c */
Node::value_type& Node::get_data() {return data;}
LinkedList.h:
// LinkedList.h
/*******************************/
// Last Updated: Tues Aug 31 2021
// Program Description: Header file for LinkedList
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "Node.h"
#include <iostream>
#include <cstdlib>
#include <string>
class LinkedList
{
public:
typedef Node::value_type value_type;
//Constructor:
LinkedList();
//Destructor:
~LinkedList();
//Insert function:
//void insert(value_type& item);
//length function:
int length();
//count function:
int count(string);
//totalIncome function:
double totalIncome();
//addTo functions:
void addToHead(value_type&);
void addToTail(value_type&);
//accessors (getters):
value_type& getHead();
Node* getHeadAdd();
value_type& getTail();
//remove functions:
void removeFromHead();
void removeFromTail();
void remove(string);
void removeByNode(Node* c); //remove a particular node
//search funciton:
//Preconditions: None
//Postconditions: Current points to the first Node storing the target, and true is returned. If not present, current is NULL and false is returned
bool search(const value_type& target);
//concatenation operator (+=) overload:
//Preconditions: LL1 and LL2 are instances of LinkedList
//Postconditions: Each Node of LL2 is traversed. At each individual Node, itis appended to LL1
LinkedList operator += (const LinkedList& LL2);
//remove overlap operator (-=) overload:
//Preconditions: LL1 and LL2 are instances of LinkedList
//Postconditions: Each Node of LL2 is traversed. At each individual Node, it's match is searched for within LL1. If a match is found, the matching Node in LL1 is deleted and the next node in LL2 is traversed
LinkedList operator -= (const LinkedList& LL2);
//NEED A .COUNT FUNCTION!!
private:
Node* head;
Node* tail;
Node* current;
};
//stream insertion operator (<<) overload:
//Preconditions: LinkedList obj "LL" exists and we wish to output it
//Postconditions: LL exists without change
ostream& operator << (ostream& out, LinkedList& LL);
#endif
LinkedList.cpp:
// LinkedList.cpp
/*******************************/
// Last Updated: Wed Aug 31 2021
// Program Description: Implementation of LinkedList
#include "LinkedList.h"
#include <cstdlib>
//Constructors:
LinkedList::LinkedList() //default constructor
{
head = NULL;
tail = NULL;
current = NULL;
}
//Empty destructor:
LinkedList::~LinkedList(){}
//length() function:
//Preconditions: None
//Postconditions: A count of the nodes is returned (ie no of nodes in the LinkedList)
int LinkedList::length()
{
int answer = 0;
for (current = head; current != NULL; current = current->get_next())
{
answer++;
}
return answer;
}
//count function:
int LinkedList::count(string type)
{
int returnCount = 0;
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
//check for match:
if (type == current->get_data().get_type())
{
//increment the counter
returnCount++;
}
}
return returnCount;
}
//totalIncome function:
double LinkedList::totalIncome()
{
double returnTotal = 0;
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
returnTotal = returnTotal + current->get_data().get_charge();
}
return returnTotal;
}
//addToHead function:
//Preconditions: None
//Postconditions: A new node storing the supplied item is created and linked in to be list's new head
void LinkedList::addToHead(Node::value_type& item)
{
Node* newNode = new Node(item);
//Check if the list is empty:
if (length() == 0)
{ //list is empty, so:
head = newNode;
tail = newNode;
} else
{ //list is not empty, so:
head->set_prev(newNode);
newNode->set_next(head);
head = newNode;
}
/*
head = new Node(item, head, NULL);
//In case the list is empty:
if (tail == NULL)
{
tail = head;
}
*/
}
//addToTail function:
//Preconditions: None
//Postconditions: A new node storing the supplied item is created and linked in to be list's new tail
void LinkedList::addToTail(Node::value_type& item)
{
Node* newNode = new Node(item);
//Check if the list is empty:
if (length() == 0)
{ //list is empty, so:
head = newNode;
tail = newNode;
} else
{ //list is not empty, so:
tail->set_next(newNode);
newNode->set_prev(tail);
tail = newNode;
}
}
//getHead function:
Node::value_type& LinkedList::getHead()
{
return head->get_data();
}
//getHeadAdd function:
Node* LinkedList::getHeadAdd()
{
return head->get_next()->get_prev();
}
//getTail function:
Node::value_type& LinkedList::getTail()
{
return tail->get_data();
}
//removeFromHead function:
void LinkedList::removeFromHead()
{
Node* temp;
temp = head->get_next();
if (head != NULL)
{
temp->set_prev(NULL);
head = temp;
} else
{ //list is empty, so update the tail
tail = NULL;
}
}
//removeFromTail function:
void LinkedList::removeFromTail()
{
Node* temp;
temp = tail->get_prev();
if (head != NULL)
{
temp->set_next(NULL);
tail = temp;
} else
{ //list is empty, so update the head
head = NULL;
}
}
//remove function: removes a Node by a string input
void LinkedList::remove(string l)
{
//cycle through LinkedList:
for (current = head; current != NULL; current = current->get_next())
{
//check for match:
if (l == current->get_data().get_licence() && current == head)
{
removeFromHead();
} else if (l == current->get_data().get_licence() && current == tail)
{
removeFromTail();
} else if (l == current->get_data().get_licence())
{
//delete the node
removeByNode(current);
} else
{
//do nothing, move on to next iteration of for loop
}
}
}
//removeByNode function:
//Preconditions: input c points to a node to be removed
//Postconditions: the node pointed to by c before is now gone. current now points to head
void LinkedList::removeByNode(Node* c)
{
current = c;
current->get_prev()->set_next(current->get_next());
current->get_next()->set_prev(current->get_prev());
delete current;
current = head;
}
//search function:
bool LinkedList::search(const Node::value_type& target)
{
for (current = head; current != NULL; current = current->get_next())
{
if (target == current->get_data())
{
return true;
}
}
//else:
return false;
}
// += operator overload (new):
LinkedList LinkedList::operator += (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp = LL2.head;
while (temp != NULL)
{
t->addToTail(temp->get_data());
temp = temp->get_next();
}
return *t;
}
// -= operator overload:
LinkedList LinkedList::operator -= (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp1;
Node* temp2;
//Cycle through LL2:
for (temp2 = LL2.head; temp2 != NULL; temp2 = temp2->get_next())
{
//Cycle through LL1:
for (temp1 = t->head; temp1 != NULL; temp1 = temp1->get_next())
{
//Check if current of LL1 has a match in LL2:
if (temp1->get_data() == temp2->get_data())
{
t->removeByNode(temp1);
}
}
}
return *t;
}
-= operator overload (within LinkedList.cpp, just putting it here under new heading for easy location):
// -= operator overload:
LinkedList LinkedList::operator -= (const LinkedList& LL2)
{
LinkedList* t = this;
Node* temp1;
Node* temp2;
//Cycle through LL2:
for (temp2 = LL2.head; temp2 != NULL; temp2 = temp2->get_next())
{
//Cycle through LL1:
for (temp1 = t->head; temp1 != NULL; temp1 = temp1->get_next())
{
//Check if current of LL1 has a match in LL2:
if (temp1->get_data() == temp2->get_data())
{
t->removeByNode(temp1);
}
}
}
return *t;
}
-= operator call within another 'main()' program:
LinkedList tollBooth1;
LinkedList tollBooth2;
LinkedList dailyReport;
//(add data to tollBooth 1 and 2, merge these 2 objects into dailyReport)
//removing the contents of both booths from daily report:
dailyReport -= tollBooth1;
dailyReport -= tollBooth2;
You've included way too much code. The general ask on this site is to provide a minimal reproducible example.
Problems
I have no idea why you have a member variable named current. It often points to deleted memory.
You need to implement the "rule of three" or the "rule of five" on your LinkedList class. If you copy the LinkedList, and then modify it, you will have dangling pointers.
LinkedList a;
LinkedList b = a;
a.RemoveHead();
// b.head is now pointing to deleted memory.
LinkedList::removeByNode(Node* c) does not update the head and tail member variables if the removed node was the head or tail respectively.
Your operator-= uses temp1 after it has been deleted.
There are likely more issues.
For this problem that I'm currently working on, I'm trying to create a method within this linked list that performs a deep copy from one item to another. Right now the inside of the method is empty because I cannot get anything to work for the life of me. Is there any way I could get some help implementing this deep copy constructor in the area of code below that is commented? Thanks.
#include <string>
#include <iostream>
#include <cstddef>
using std::string;
class Item {
public:
string s;
Item(const char *a_s = "") {
s = a_s;
}
Item(string a_s) {
s = a_s;
}
};
class List {
private:
class ListNode {
public:
Item item;
ListNode * next;
ListNode(Item i) {
item = i;
next = nullptr;
}
};
ListNode * head;
ListNode * tail;
public:
class iterator {
ListNode *node;
public:
iterator(ListNode *n = nullptr) {
node = n;
}
Item& getItem() { return node->item; } //Not sure how this works
void next() { node = node->next; }
bool end() { return node==nullptr; }
};
public:
List() {
head = nullptr;
tail = nullptr; //Sets the head and tail
}
List(const List & copy) { //Trying to create a copy constructor right here.
}
bool empty() { //Tells you if the list is empty
return head==nullptr;
}
void append(Item a) {
ListNode *node = new ListNode(a);
if ( head == nullptr ) {
head = node;
tail = node;
} else {
tail->next = node;
tail = node;
}
}
bool remove (Item ©);
void traverse() {
ListNode *tmp = head;
while(tmp != nullptr) {
tmp = tmp->next;
}
}
iterator begin() const {
return iterator(head);
}
};
bool List::remove(Item ©)
{
if (!empty()) {
copy = head->item;
ListNode *tmp = head->next;
delete head;
head = tmp;
if (head==nullptr)
tail = nullptr;
return true;
}
return false;
}
int main() {
List l;
l.append("eggs");
List l2 = l;
std::cout << "done.\n";
return 0;
}
Assuming that append() is working correctly, you can just call it repeatedly in a loop for each item in copy.
This approach, given how you implemented your linked list with a tail pointer, makes it an ideal solution. You wrote the append function, so it's just a matter of using it in a strategic way.
Be warned however, that if you had implemented your linked list without a tail pointer (where you had to traverse to the end of the list to append), this approach would still work, but would be highly inefficient and not satisfactory.
Here is an example (untested):
List(const List & copy) : head(nullptr), tail(nullptr)
{
ListNode *copyNode = copy.head;
while (copyNode)
{
append(copyNode->item);
copyNode = copyNode->next;
}
}
Note that this was not tested for boundary conditions, so you may need to check for copy being empty before having to go through the loop.
Here is an example that works for a simple case
I am working on an assignment where I create test code to show the implementation of a linked list class in C++. Mostly all the code provided is given from a book other than what I have written for my main function and a few edited lines to add a tail instance. The only error that is showing up right now when I compile is this:
'LList::operator=' : must return a value
I am unsure as to why this error is being produced or how to fix it because it refers to a block of code that was given by the book. That block of code is:
LList& LList::operator=(const LList& source)
{
dealloc();
copy(source);
}
Any help would be greatly appreciated.
Just in case; here is the rest of the code from my source file.
// LList.cpp
#include "LList.h"
#include <iostream>
LList::LList()
{
head_ = NULL;
tail_ = NULL;
size_ = 0;
}
ListNode* LList::_find(size_t position)
{
ListNode *node = head_;
size_t i;
for (i = 0; i<position; i++) {
node = node->link_;
}
return node;
}
ItemType LList::_delete(size_t position)
{
ListNode *node, *dnode;
ItemType item;
if (position == 0) {
dnode = head_;
head_ = head_->link_;
item = dnode->item_;
delete dnode;
}
if (position == size_) {
dnode = tail_;
node = _find(position - 1);
node->link_ = NULL;
tail_ = node;
item = dnode->item_;
delete dnode;
}
else {
node = _find(position - 1);
if (node != NULL) {
dnode = node->link_;
node->link_ = dnode->link_;
item = dnode->item_;
delete dnode;
}
}
size_ -= 1;
return item;
}
void LList::append(ItemType x)
{
ListNode *node, *newNode = new ListNode(x);
if (head_ != NULL) {
node = _find(size_ - 1);
node->link_ = newNode;
tail_ = newNode;
}
else {
head_ = newNode;
tail_ = head_;
}
size_ += 1;
}
void LList::insert(size_t i, ItemType x)
{
ListNode *node;
if (i == 0) {
head_ = new ListNode(x, head_);
tail_ = head_;
}
else if (i == size_) {
tail_ = new ListNode(x, tail_);
}
else {
node = _find(i - 1);
node->link_ = new ListNode(x, node->link_);
}
size_ += 1;
}
void LList::printlist()
{
ListNode *temp = head_;
while (temp) {
std::cout << temp->item_ << std::endl;
temp = temp->link_;
}
}
ItemType LList::pop(int i)
{
if (i == -1) {
i = size_ - 1;
}
return _delete(i);
}
ItemType& LList::operator[](size_t position)
{
ListNode *node;
node = _find(position);
return node->item_;
}
LList::LList(const LList& source)
{
copy(source);
}
void LList::copy(const LList &source)
{
ListNode *snode, *node;
snode = source.head_;
if (snode) {
node = head_ = new ListNode(snode->item_);
snode = snode->link_;
while (snode) {
node->link_ = new ListNode(snode->item_);
node = node->link_;
snode = snode->link_;
}
}
size_ = source.size_;
}
LList& LList::operator=(const LList& source)
{
dealloc();
copy(source);
}
LList::~LList()
{
dealloc();
}
void LList::dealloc()
{
ListNode *node, *dnode;
node = head_;
while (node) {
dnode = node;
node = node->link_;
delete dnode;
}
}
int main()
{
LList mylist;
mylist.append(6);
mylist.append(3);
mylist.append(1);
mylist.printlist();
mylist.insert(2, 4);
mylist.printlist();
mylist.pop(1);
mylist.printlist();
mylist.size();
}
Where you have this code:
LList& LList::operator=(const LList& source)
{
dealloc();
copy(source);
}
Change it to this:
LList& LList::operator=(const LList& source)
{
dealloc();
copy(source);
return *this; // Note the addition of this return statement.
}
Explanation:
Here, you're overriding the = operator on LList, and in C++, operator overrides must return a value. At least in the case of operator=, you will most often want to just return the object itself.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to test out the code my professor gave us. We have to change the implementation of the code but that is not what I am stuck on. I am stuck on making a working test code. He gave me the test code to run but when I try to run it I keep getting errors which shouldn't be the case. Could anyone tell me what the problem is in my test code so I can start changing and adding different functions into my code? Thanks
Here is my code:
// ListNode.h
#ifndef _LISTNODE_H
#define _LISTNODE_H
#include <cstdlib>
typedef int ItemType;
class ListNode {
friend class LList;
public:
ListNode(ItemType item, ListNode* link = NULL);
private:
ItemType item_;
ListNode *link_;
};
inline ListNode::ListNode(ItemType item, ListNode *link)
{
item_ = item;
link_ = link;
}
#endif // _LISTNODE_H
// LList.h
#ifndef _LLIST_H
#define _LLIST_H
#include "ListNode.h"
class LList {
public:
LList();
LList(const LList& source);
~LList();
LList& operator=(const LList& source);
int size() { return size_; }
void append(ItemType x);
void insert(size_t i, ItemType x);
ItemType pop(int i = -1);
ItemType& operator[](size_t position);
private:
// methods
void copy(const LList &source);
void dealloc();
ListNode* _find(size_t position);
ItemType _delete(size_t position);
// data elements
ListNode *head_;
int size_;
};
#endif // _LLIST_H
// LList.cpp
#include "LList.h"
LList::LList()
{
head_ = NULL;
size_ = 0;
}
ListNode* LList::_find(size_t position)
{
ListNode *node = head_;
size_t i;
for (i = 0; i<position; i++) {
node = node->link_;
}
return node;
}
ItemType LList::_delete(size_t position)
{
ListNode *node, *dnode;
ItemType item;
if (position == 0) {
dnode = head_;
head_ = head_->link_;
item = dnode->item_;
delete dnode;
}
else {
node = _find(position - 1);
if (node != NULL) {
dnode = node->link_;
node->link_ = dnode->link_;
item = dnode->item_;
delete dnode;
}
}
size_ -= 1;
return item;
}
void LList::append(ItemType x)
{
ListNode *node, *newNode = new ListNode(x);
if (head_ != NULL) {
node = _find(size_ - 1);
node->link_ = newNode;
}
else {
head_ = newNode;
}
size_ += 1;
}
void LList::insert(size_t i, ItemType x)
{
ListNode *node;
if (i == 0) {
head_ = new ListNode(x, head_);
}
else {
node = _find(i - 1);
node->link_ = new ListNode(x, node->link_);
}
size_ += 1;
}
ItemType LList::pop(int i)
{
if (i == -1) {
i = size_ - 1;
}
return _delete(i);
}
ItemType& LList::operator[](size_t position)
{
ListNode *node;
node = _find(position);
return node->item_;
}
LList::LList(const LList& source)
{
copy(source);
}
void LList::copy(const LList &source)
{
ListNode *snode, *node;
snode = source.head_;
if (snode) {
node = head_ = new ListNode(snode->item_);
snode = snode->link_;
while (snode) {
node->link_ = new ListNode(snode->item_);
node = node->link_;
snode = snode->link_;
}
size_ = source.size_;
}
LList& LList::operator=(const LList& source)
{
if (this != &source) {
dealloc();
copy(source);
}
return *this;
}
LList::~LList()
{
dealloc();
}
void LList::dealloc()
{
ListNode *node, *dnode;
node = head_;
while (node) {
dnode = node;
node = node->link_;
delete dnode;
}
}
#include "LList.h"
#include <iostream>
using namespace std;
int main()
{
LList b, c;
int x;
b.append(1);
b.append(2);
b.append(3);
c.append(4);
c.append(5);
c = b;
x = b.pop();
cout << c;
}
Could anyone help me write a working test code, this the last thing I will need to start adding my different functions.
I keep getting this error:
Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'LList' (or there is no acceptable conversion) c:\users\koopt_000\documents\visual studio 2013\projects\lab10\lab10\testlist.cpp 18 1 Lab10
Any help?
In your code:
cout << c;
is the problem. You cannot print your linked list that way (Edit: Unless you have an overload for the operator << which does not appear in your code).
For printing the elements, you can iterate through the list starting from the first node to the last. Something like that would work:
void LList::printList()
{
ListNode *tmp = head_;
while(tmp) {
std::cout<<tmp->item_;
tmp=tmp->link_;
}
}
PS: don`t forget the put the method prototype into the class definition. And of course in your main method can call to the function as follows:
...
c.printList();
....
Hope that helps!
You are attempting to output your LList, but it's not quite that straight forward. You need to overload the output operator:
friend std::ostream& operator<< (std::ostream& stream, const LList& list) {
// Write code here to iterate through the list
// and output each item...
// Return the stream so we can chain outputs..
return stream;
}
For academic purposes, I'm trying to develop a little "textual adventure game". I have to implement all data structures by my own. Now, I have some problems with the implementation of a generic (template) LinkedList.
In the specific, this data structure works with everything (primitive data types and custom objects) BUT strings! (standard library strings).
When I try to add strings to a list, the application crashes with the following error (in console):
"terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_constructor null not valid"
The list is implemented as a "double linked list" using the head-node as first-last node
Here the code ("Abstract" List interface):
#ifndef LIST_H_
#define LIST_H_
template <class T>
class List
{
public:
virtual ~List() {}
virtual T get(int position) = 0;
virtual List* add(T item) = 0;
virtual List* insert(T item, int position) = 0;
virtual List* remove(int position) = 0;
virtual int size() const = 0;
virtual bool isEmpty() const = 0;
protected:
private:
};
#endif /* LIST_H_ */
This is the LinkedList implementation (the "node" class):
#include "List.h"
#include <stdlib.h>
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
template <class T>
class ListNode
{
public:
ListNode(T item)
{
mItem = item;
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item;
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem;
}
T getItem()
{
return mItem;
}
ListNode<T>* getNext()
{
return mNext;
}
ListNode<T>* getPrev()
{
return mPrev;
}
void setItem(T item)
{
mItem = item;
}
void setNext(ListNode<T>* next)
{
mNext = next;
}
void setPrev(ListNode<T>* prev)
{
mPrev = prev;
}
protected:
private:
T mItem;
ListNode<T> *mNext, *mPrev;
};
The LinkedList class:
template <class K>
class LinkedList : public List<K>
{
public:
LinkedList()
{
mSize = 0;
mFirstNode = NULL;
}
~LinkedList()
{
// implementazione distruttore tramite ciclo sui nodi
}
K get(int position)
{
K item = NULL;
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL) item = targetNode->getItem();
return item;
}
List<K>* add(K item)
{
if (mFirstNode == NULL)
{
mFirstNode = new ListNode<K>(item);
mFirstNode->setNext(mFirstNode);
mFirstNode->setPrev(mFirstNode);
}
else
{
ListNode<K>* newNode = new ListNode<K>(item, mFirstNode, mFirstNode->getPrev());
mFirstNode->getPrev()->setNext(newNode);
mFirstNode->setPrev(newNode);
}
mSize++;
return this;
}
List<K>* insert(K item, int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
ListNode<K>* newNode = new ListNode<K>(targetNode->getItem(), targetNode->getNext(), targetNode);
targetNode->setItem(item);
targetNode->setNext(newNode);
mSize++;
}
return this;
}
List<K>* remove(int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
targetNode->setItem(targetNode->getNext()->getItem());
targetNode->setNext(targetNode->getNext()->getNext());
//delete targetNode->getNext();
mSize--;
}
return this;
}
int size() const
{
return mSize;
}
bool isEmpty() const
{
return (mFirstNode == NULL) ? true : false;
}
protected:
ListNode<K>* getNodeAtPosition(int position)
{
ListNode<K>* current = NULL;
if (mFirstNode != NULL && position < mSize)
{
current = mFirstNode;
for (int i = 0; i < position; i++)
{
current = current->getNext();
}
}
return current;
}
private:
int mSize;
ListNode<K>* mFirstNode;
};
#endif /* LINKEDLIST_H_ */
Suggestions?
Part of your problem is here:
ListNode(T item)
{
mItem = item; // for a std::string, this will be a class member, non-pointer
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item; // same here
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem; // you are attempting to delete an item you never created
}
You should either change your constructors to create a T* object on the heap (which will then be deleted in your destructor), or remove the delete line from your destructor.
This problem will be evident with far more than just std::string, by the way.
Somewhere in your program you are doing this:
std::string s(nullptr);
Calling std::string's constructor with a null pointer is causing it to throw a std::logic_error exception.
From the standard:
ยง 21.4.2
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
Requires: s shall not be a null pointer and n < npos.
It seems it's not possible to pass std::string as template argument...
Strings as Template Arguments
Now I use an "old" - char const* - to achieve the expected result, even if I have to implement my personal "utils" methods to work with those pointers now...