How to fix Access Violation Reading location error? [closed] - c++

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 6 years ago.
Improve this question
I am currently working on a program that uses a Hash table. I have worked on my own Hash table class and the program works but then crashes after it has already done the work involving the hash table. The error I get is a Access Violation reading location error. I have spent hours going through my code and still cannot find what I'm doing wrong or why the program is crashing. Here are my problem classes below:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
#include <iostream>
using namespace std;
class hashTable
{
public:
hashTable();
virtual ~hashTable();
void insertNode(string nodeData);
bool removeNode(string nodeKey);
Node * checkForDuplicate( string nodeData );
private:
LinkedList * tableArray;
int length;
int hash(string stateKey);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
hashTable::hashTable()
{
length = 181667;
tableArray = new LinkedList[length];
}
int hashTable::hash(string stateKey) {
int multiplier = 1;
int total = 0;
int l = stateKey.length();
for(int i = l - 1; i > -1; --i) {
int temp;
temp = (stateKey[i] - '0') * multiplier;
total += temp;
multiplier = multiplier * 10;
}
return(total) % length;
}
void hashTable::insertNode(string stateData) {
Node * newNode;
newNode = new Node;
newNode->data = stateData;
int index = hash(newNode -> data);
tableArray[index].insertNode(newNode);
delete newNode;
}
bool hashTable::removeNode(string nodeKey) {
int index = hash(nodeKey);
return tableArray[index].removeNode(nodeKey);
}
Node * hashTable::checkForDuplicate( string nodeData )
{
int index = hash( nodeData );
return tableArray[ index ].getNode(nodeData);
}
hashTable::~hashTable()
{
delete [] tableArray;
//dtor
}
LinkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<string>
#include<iostream>
using namespace std;
struct Node {
string data;
Node *next;
};
class LinkedList
{
public:
LinkedList();
void insertNode(Node * newNode);
bool removeNode(string stateData);
Node * getNode(string stateData);
int getLength();
virtual ~LinkedList();
private:
Node * top;
int length;
};
#endif // LINKEDLIST_H
LinkedList.cpp:
#include "LinkedList.h"
LinkedList::LinkedList()
{
top = new Node;
top->next = NULL;
length = 0;
}
void LinkedList :: insertNode(Node * newNode) {
Node * a = top;
Node * b = top;
while(b) {
a = b;
b = a -> next;
if (a== NULL) { break; }
}
a -> next = newNode;
newNode -> next = NULL;
length++;
}
bool LinkedList :: removeNode(string stateData) {
if(!top -> next){
return false;
}
Node * a = top;
Node * b = top;
while(b) {
if(b->data == stateData) {
a->next = b->next;
delete b;
length--;
return true;
}
a = b;
b = a ->next;
}
return false;
}
Node * LinkedList :: getNode(string stateData) {
if(top == NULL) { return NULL ;}
Node * current = top;
while (current->next != NULL) {
if((current->data == stateData)) {
return current;
}
current = current -> next;
}
return NULL;
}
int LinkedList :: getLength() {
return length;
}
LinkedList::~LinkedList()
{
Node * a = top;
Node * b = top;
while (b) {
a = b;
b = a->next;
if(b) delete a;
}
}

Your hashTable::insertNode() method is allocating a new Node object, then passing it to LinkedList::insertNode() to take ownership of the object, but then delete's it afterwards, thus leaving the LinkedList with a dangling pointer to invalid memory. Any access to that node will cause undefined behavior. DO NOT delete the new node after LinkedList takes ownership of it.
It would be better if LinkedList::insertNode() took a string as input instead of a Node* pointer. Let LinkedList allocate the new node internally.
Also, there are some other minor issues with your LinkedList() implementation in general (like not following the Rule of Three, and not using a double-linked list for more efficient inserts and removals).
Try something more like this instead:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
class hashTable
{
public:
hashTable();
hashTable(const hashTable &src);
~hashTable();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
bool checkForDuplicate(const std::string &nodeData);
hashTable& operator=(const hashTable &rhs);
private:
std::vector<LinkedList> tableArray;
int length;
int hash(const std::string &nodeData);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
hashTable::hashTable()
: length(181667), tableArray(new LinkedList[length])
{
}
hashTable::hashTable(const hashTable &src)
: length(src.length), tableArray(new LinkedList[length])
{
for (int i = 0; i < length; ++i)
tableArray[i] = src.tableArray[i];
}
hashTable::~hashTable()
{
delete[] tableArray;
}
hashTable& hashTable::operator=(const hashTable &rhs)
{
hashTable tmp(rhs);
std::swap(tableArray, tmp.tableArray);
std::swap(length, tmp.length);
return *this;
}
int hashTable::hash(const std::string &nodeData)
{
int multiplier = 1;
int total = 0;
int l = nodeData.length();
for(int i = l - 1; i > -1; --i)
{
int temp = (nodeData[i] - '0') * multiplier;
total += temp;
multiplier *= 10;
}
return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
int index = hash(nodeData);
tableArray[index].insertNode(nodeData);
}
bool hashTable::removeNode(const std::string &nodeData)
{
int index = hash(nodeData);
return tableArray[index].removeNode(nodeData);
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
int index = hash(nodeData);
return (tableArray[index].getNode(nodeData) != NULL);
}
LinkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <string>
struct Node
{
std::string data;
Node *previous;
Node *next;
};
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList &src);
~LinkedList();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
Node* getNode(const std::string &nodeData);
int getLength();
LinkedList& operator=(const LinkedList &rhs);
private:
Node *head;
Node *tail;
int length;
};
#endif // LINKEDLIST_H
LinkedList.cpp:
#include "LinkedList.h"
#inclue <algorithm>
LinkedList::LinkedList()
: head(NULL), tail(NULL), length(0)
{
}
LinkedList::LinkedList(const LinkedList &src)
: head(NULL), tail(NULL), length(0)
{
Node *current = src.top;
while (current != NULL)
{
insertNode(current->data);
current = current->next;
}
}
LinkedList::~LinkedList()
{
Node *current = top;
while (current != NULL)
{
Node *next = current->next;
delete current;
current = next;
}
}
LinkedList& LinkedList::operator=(const LinkedList &rhs)
{
LinkedList tmp;
Node *current = rhs.top;
while (current != NULL)
{
tmp.insertNode(current->data);
current = current->next;
}
std::swap(top, tmp.top);
std::swap(bottom, tmp.bottom);
std::swap(length, tmp.length);
return *this;
}
void LinkedList::insertNode(const string &nodeData)
{
Node *newNode = new Node;
newNode->data = nodeData;
newNode->previous = NULL;
newNode->next = NULL;
if (top == NULL) top = newNode;
if (bottom != NULL)
{
newNode->previous = bottom;
bottom->next = newNode;
}
bottom = newNode;
length++;
}
bool LinkedList::removeNode(const string &nodeData)
{
Node* node = getNode(nodeData);
if (node != NULL)
{
if (node->next != NULL)
node->next->previous = node->previous;
if (node->previous != NULL)
node->previous->next = node->next;
if (top == node)
top = node->next;
if (bottom == node)
bottom = node->previous;
delete node;
length--;
return true;
}
return false;
}
Node* LinkedList::getNode(const string &nodeData)
{
Node *current = top;
while (current != NULL)
{
if (current->data == nodeData)
return current;
current = current->next;
}
return NULL;
}
int LinkedList::getLength()
{
return length;
}
With that said, you can then get rid of LinkedList altogether by using std::list instead, and simplify hashTable's memory management by using std::vector:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include <list>
#include <vector>
class hashTable
{
public:
hashTable();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
bool checkForDuplicate(const std::string &nodeData);
private:
std::vector< std::list<std::string> > tableArray;
int hash(const std::string &stateKey);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
#include <algorithm>
hashTable::hashTable()
: tableArray(181667)
{
}
int hashTable::hash(const std::string &nodeData)
{
int multiplier = 1;
int total = 0;
int l = nodeData.length();
for(int i = l - 1; i > -1; --i)
{
int temp = (nodeData[i] - '0') * multiplier;
total += temp;
multiplier *= 10;
}
return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
int index = hash(nodeData);
tableArray[index].push_back(nodeData);
}
bool hashTable::removeNode(const string &nodeData)
{
int index = hash(nodeData);
std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
if (iter != tableArray[index].end())
{
tableArray[index].erase(iter);
return true;
}
return false;
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
int index = hash(nodeData);
std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
return (iter != tableArray[index].end());
}

Related

double free detected in tcache 2 when initializing a list, crashes upon entry insertion

Reading from a file, each line is stored in a list as an individual row. Each row contains two standard values and a variable amount stored in a list. Therefore each node has two values and a list. Initialization through operator>> works, but as soon as I try to run the loadfile function it crashes with the error: free(): double free detected in tcache 2 Aborted (core dumped)
Here is the code
#include <iostream>
#include "Resource.h"
#include "list.h"
#include "node.h"
using std::cout;
using rows = List<Resource>;
using row = Node<Resource>;
void loadFile(string idata, rows &res)
{
ifstream ifs(idata, ifstream::in);
while (ifs.good())
{
Resource s;
ifs >> s;
row *temp = new Node<Resource>(s);
res.insert(temp);
}
ifs.close();
}
int main()
{
rows resList;
loadFile("data.txt", resList);
cout << resList.getHead()->getValue();
}
this is the source for the class that stores the values, that will be wrapped in a Node template class.
#ifndef RESOURCE_H
#define RESOURCE_H
#include <iostream>
#include <fstream>
#include <string>
#include "list.h"
#include "node.h"
#include <stdio.h>
#include <algorithm>
using std::cout;
using std::istream;
using std::string;
class Resource
{
private:
string Name;
int amt;
List<string> clientList;
public:
Resource(string n, int a) : Name(n), amt(a) {}
Resource(string n) : Resource(n, 0) {}
Resource() : Resource("", 0) {}
string getName()
{
return this->Name;
}
int getAmt()
{
return this->amt;
}
void setName(string n)
{
this->Name = n;
}
void setAmt(int a)
{
this->amt = a;
}
friend ostream &operator<<(ostream &out, const Resource &r)
{
out << r.Name << ";" << r.amt;
List<string> temp = r.clientList;
for (Node<string> *app = temp.getHead(); app != NULL; app = app->getNext())
{
out << ';';
out << app->getValue();
}
return out;
}
friend istream &operator>>(istream &in, Resource &r)
{
string Name;
string amt;
string params;
string tempVar;
getline(in, Name, ';');
getline(in, amt, ';');
getline(in, params, '\n');
const int paramsOriginalLength = count(params.begin(), params.end(), ';');
for (int i = 0; i < paramsOriginalLength; i++)
{
r.clientList.insert(params.substr(0, params.find(';')));
params.erase(0, params.find(';') + 1);
}
r.setName(Name);
r.setAmt(stoi(amt));
return in;
}
};
#endif
EDIT: Since the problem might be caused by the data structure's defintion I will include the source of list.h and node.h
List:
#ifndef LIST_H
#define LIST_H
// Standard Template Linked List - List - by Eduardo Meli - 2020
#include "node.h"
#include <iostream>
using namespace std;
template <class T>
class List
{
private:
int length;
Node<T> *head;
public:
List(int length, Node<T> *head) : length(length), head(head) {}
List() : List(0, NULL) {}
Node<T> *getHead()
{
return this->head;
}
int getLength()
{
return this->length;
}
void insert(T value)
{
Node<T> *app = new Node<T>(value);
this->insert(app);
}
void insert(Node<T> *n)
{
if (head == NULL)
{
head = n;
length++;
return;
}
Node<T> *curr = head;
while (curr->getNext() != NULL)
{
curr = curr->getNext();
}
curr->setNext(n);
length++;
}
void deleteNode(Node<T> *n)
{
if (n == this->getHead())
{
this->head = head->getNext();
this->length = length - 1;
delete n;
return;
}
Node<T> *prev = head;
Node<T> *curr = head->getNext();
while (curr != NULL)
{
if (curr == n)
{
prev->setNext(curr->getNext());
length--;
return;
}
prev = curr;
curr = curr->getNext();
}
}
Node<T> *deleteNode(T value)
{
if (this->seekNode(value))
{
if (head->getValue() == value)
{
Node<T> *temp = head;
head = head->getNext();
length--;
return temp;
}
Node<T> *prev = head;
Node<T> *curr = head->getNext();
while (curr != NULL)
{
if (curr->getValue() == value)
{
prev->setNext(curr->getNext());
length--;
return curr;
}
prev = curr;
curr = curr->getNext();
}
}
return NULL;
}
void print()
{
Node<T> *nk = this->getHead();
while (nk != NULL)
{
cout << nk->getValue() << endl;
nk = nk->getNext();
}
}
~List()
{
Node<T> *ptr;
for (ptr = head; head; ptr = head)
{
head = head->getNext();
delete ptr;
}
}
};
#endif
And node:
#ifndef NODE_H
#define NODE_H
// Standard Template Linked List - Node - by Eduardo Meli - 2020
#include <fstream>
#include <iostream>
using namespace std;
template <class T>
class Node
{
private:
T value;
Node<T> *next;
public:
Node(T value, Node<T> *next) : value(value), next(next) {}
Node(T value) : Node(value, NULL) {}
Node() : Node(0, NULL) {}
T getValue()
{
return this->value;
}
Node<T> *getNext()
{
return this->next;
}
void setValue(T val)
{
this->value = val;
}
void setNext(Node<T> *n)
{
this->next = n;
}
friend ostream &operator<<(ostream &out, const Node &n)
{
out << n.value;
return out;
}
};
#endif

strdup for converting const char* to char*

I have designed for Huffman tree convert binary code with shorter bin code. In main if you call a Binary tree.init(q), then the tree would come out with key: frequency and value: bin code. The problem is converting const char* with char*. I've looked at some codes, and here I converted it by using strdup. Sometimes works fine but sometimes doesn't work. so I checked out the parameter for the function. Is there wrong in calling strdup or maybe others?
#pragma once
#include <stdio.h>
#include <queue>
#include <iostream>
#include "pch.h"
#include <string.h>
#include <string>
#define _CRT_SECURE_NO_WARNINGS
//this is a header file
using namespace std;
class Node
{
public:
//key : frequency, value : code
int f;
char* code;
Node* left;
Node* right;
int getFrequency()
{
return f;
}
char* getCode()
{
return code;
}
void init(int frequency, char* codestring)
{
f = frequency;
code = codestring;
}
Node* getLeft() {
return left;
}
Node* getRight()
{
return right;
}
void setLeft(Node* L)
{
left = L;
}
void setRight(Node* R)
{
right = R;
}
void setFrequency(int frequency)
{
f = frequency;
}
void setCode(char* string)
{
code = string;
}
};
class BinaryTree
{
public:
typedef priority_queue<int, vector<int>, greater<int>> pq;
pq q;
Node* proot;
int sizeofqueue;
void init(pq PriorityQueue)
{
q = PriorityQueue;
sizeofqueue = q.size();
N = 0;
int comparetimes = q.size() - 1;
for (int i = 0; i < comparetimes; i++)
{
if (i == 0)
{
put_first_two_nodes();
}
else
{
if (proot->getFrequency() <= q.top())
{
put_right_node();
}
else if (proot->getFrequency() > q.top())
{
put_left_node();
}
q.pop();
}
}
}
void put_first_two_nodes()
{
Node* pleft = new Node();
(*pleft).setFrequency(q.top());
(*pleft).setCode("0");
q.pop();
Node* pright = new Node();
(*pright).setFrequency(q.top());
(*pright).setCode("1");
put(pleft, pright);
q.pop();
}
void put_right_node()
{
Node* pright = new Node();
pright->setFrequency(q.top());
pright->setCode("1");
put(proot, pright);
appendcode(0);
}
void appendcode(int prefix)
{
string pre;
if (prefix == 1) pre = "1";
else pre = "0";
Node* targetNode = proot->getRight();
char* rcode = targetNode->getRight()->getCode();
char* lcode = targetNode->getLeft()->getCode();
string lefts = pre;
string rights = pre;
lefts.append(lcode);
rights.append(rcode);
char* leftstring = strdup(lefts.c_str());
char* rightstring = strdup(rights.c_str());
targetNode->getLeft()->setCode(leftstring);
targetNode->getRight()->setCode(rightstring);
free(leftstring);
free(rightstring);
}
void put_left_node()
{
Node* pleft = new Node();
pleft->setFrequency(q.top());
pleft->setCode("0");
put(pleft, proot);
appendcode(1);
}
char* get(int k)
{
return getItem(*proot, k);
}
char* getItem(Node root, int k)
{
//if there's no node
if (&root == nullptr) return "";
//if f or root > k, search left sibling
if (root.getFrequency() > k) return getItem(*(root.getLeft()), k);
//else, search right sibling
else if (root.getFrequency() < k) return getItem(*(root.getRight()), k);
//get it
else return root.getCode();
}
void put(Node* left, Node* right)
{
put_item(left,right);
}
void put_item(Node* left, Node* right)
{
//make new node that has sibling with left and right
Node* newnode = new Node();
newnode->setLeft(left);
newnode->setRight(right);
//exchange the new node and root without losing data
Node* temp;
temp = proot;
proot = newnode;
newnode = temp;
//proot's frequency : left f + right f
(*proot).setFrequency((*left).getFrequency() + (*right).getFrequency());
}
void printpost()
{
postorder(proot);
}
void postorder(Node* root)
{
if (root != nullptr)
{
if (root->getLeft() != nullptr) postorder(root->getLeft());
if (root->getRight() != nullptr) postorder(root->getRight());
printf("%d : %s ",root->getFrequency(), root->getCode());
}
}
private:
int N;
Node root;
};
You shouldn't use const char* and char* at all in c++ (unless when sometimes dealing with legacy or foreign interfaces).
Switch up your code to use eg. std::string or std::string_view (c++17) instead (string_view requires a bit more understanding to handle correctly and is const so to speak - so I would stick to string off the bat). Pass std::string by reference or by const reference where neccesary. The overhead of std::string is for most programs negliable.

templateClassName <className> t; Cannot assign class to template class argument

C++ noob here. I trying to create a student information program by implementing
a Linked-List class as its data structure.
LinkedList.h
#pragma once
#include <stdexcept>
template <typename T>
class LinkedList
{
private:
struct Node
{
T elem;
Node *prev;
Node *next;
};
Node *header;
Node *trailer;
int size;
public:
LinkedList()
{
header = new Node;
trailer = new Node;
header->next = trailer;
trailer->prev = header;
}
~LinkedList()
{
while (!isEmpty())
removeFirst();
delete header;
delete trailer;
}
const int& n_elem() const
{
return size;
}
const bool isEmpty() const
{
return size == 0;
}
const T& getFirst() const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return header->next->elem;
}
const T& getLast() const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return trailer->prev->elem;
}
void addFirst(const T& item)
{
addBetween(item, header, header->next);
}
void addLast(const T& item)
{
addBetween(item, trailer->prev, trailer);
}
void addAt(int index, const T& item)
{
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
addBetween(item, node, node->next);
}
const T removeFirst()
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return remove(header->next);
}
const T removeLast()
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return remove(trailer->prev);
}
const T removeAt(int index)
{
if (isEmpty())
throw std::out_of_range("List is empty.");
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
return remove(node->next);
}
const T& itemAt(int index) const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
return node->next->elem;
}
protected:
void addBetween(const T& item, Node *predecessor, Node *successor)
{
Node *newest = new Node;
newest->prev = predecessor;
newest->next = successor;
predecessor->next = newest;
successor->prev = newest;
size++;
}
const T remove(Node *node)
{
Node *predecessor = node->prev;
Node *successor = node->next;
predecessor->next = successor;
successor->prev = predecessor;
T oldItem = node->elem;
size--;
delete node;
return oldItem;
}
};
Student class is defined below.
Program.cpp
#include "stdafx.h"
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
class Student
{
public:
string name;
string id;
int score;
static const int total = 100;
double grade;
Student(string n, string i, int s)
{
name = n;
id = i;
score = s;
grade = getGrade(score);
}
private:
double getGrade(int score)
{
return (23.0 / 3.0 - ((20.0 * score) / (3.0 * total)));
}
};
LinkedList<Student> l;
int main()
{
//Some code here
return 0;
}
I don't know the reason why
LinkedList<Student> l;
produces an error:
LinkedList<Student>::Node::Node(void)': attempting to reference a deleted function
But when I use:
LinkedList<Student*> l;
there's no error.
Please help.
I'm using Visual Studio 2015.
And sorry for bad English.
In LinkedList<Student>, the inner struct Node looks like this:
struct Node
{
Student elem;
Node *prev;
Node *next;
};
so every Node contains a Student.
However, you'll note that Student has a constructor that takes arguments:
Student(string n, string i, int s)
and it does not have a constructor that does not take arguments.
So if you were to write new Node, the computer would create a Node, and as part of that it would create a Student, but it can't do that because it doesn't have any arguments to give to Student's constructor.
That's (approximately) what "deleted function" means here - normally the compiler would make a Node constructor for you, but in this case it can't.
And so new Node doesn't work, because Node doesn't have a constructor.
Probably the easiest fix here is just to give Student a no-argument constructor as well - something like:
Student()
{
name = "";
id = "";
score = 0;
grade = getGrade(score);
}

Singly-Linked List Add Function - Read Access Violation

I'm trying to create a basic singly-linked list using a separate Node class and LinkedList class. I barely know what I'm doing as I've just started learning C++, so any help would be greatly appreciated.
The LinkedList part of the code runs on its own, but I'm sure there are some corrections to be made there too. My main problem is that, when trying to add to the linked list, I'm getting (at line 64 of LinkedList.h):
Exception thrown: read access violation. this->head was nullptr.
I'm using Microsoft Visual Studio 2015. Here's the code:
LinkedList.h (it's inline):
#pragma once
#include <iostream>
using namespace std;
class Node
{
private:
Node *next = NULL;
int data;
public:
Node(int newData) {
data = newData;
next = NULL;
}
Node() {
}
~Node() {
if(next)
delete(next);
}
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
void setNext(Node newNext) {
*next = newNext;
}
Node getNext() {
return *next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
{
head = NULL;
size = 0;
}
~LinkedList()
{
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, *head);
++size;
}
int remove()
{
if (size == 0) {
return 0;
}
else {
*head = (*head).getNext();
--size;
return 1;
}
}
int remove(int numberToRemove)
{
if (size == 0)
return 0;
Node *currentNode = head;
for (int i = 0; i < size; i++) {
if ((*currentNode).getData() == numberToRemove) {
*currentNode = (*currentNode).getNext();
return 1;
}
}
}
void print()
{
if (size == 0) {
return;
}
else {
Node currentNode = *head;
for (int i = 0; i < size; i++) {
cout << currentNode.getData();
currentNode = currentNode.getNext();
}
cout << endl;
}
}
};
List Tester.cpp
// List Tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main()
{
LinkedList myList;
myList.add(4);
system("pause");
}
You are making copies where you should not:
This:
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
should be:
Node(int newData, Node* newNext) {
data = newData;
next = newNext;
}
Because now this:
head = new Node(numberToAdd, *head);
becomes this:
head = new Node(numberToAdd, head);
and will work even if head is a null pointer. You may need to adjust your other code accordingly.
Your whole implementation is full of errors. It should look more like this instead:
#pragma once
#include <iostream>
class Node
{
private:
int data;
Node *next;
public:
Node(int newData, Node *newNext = NULL)
: data(newData), next(newNext)
{}
void setNext(Node *newNext) {
next = newNext;
}
Node* getNext() {
return next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
: head(NULL), size(0)
{
}
~LinkedList()
{
Node *currentNode = head;
while (currentNode)
{
Node *nextNode = currentNode->getNext();
delete currentNode;
currentNode = nextNode;
}
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, head);
++size;
}
bool remove()
{
Node *currentNode = head;
if (!currentNode)
return false;
head = currentNode->getNext();
delete currentNode;
--size;
return true;
}
bool remove(int numberToRemove)
{
Node *currentNode = head;
Node *previousNode = NULL;
while (currentNode)
{
if (currentNode->getData() == numberToRemove)
{
if (head == currentNode)
head = currentNode->getNext();
if (previousNode)
previousNode->setNext(currentNode->getNext());
delete currentNode;
return true;
}
previousNode = currentNode;
currentNode = currentNode->getNext();
}
return false;
}
void print()
{
Node *currentNode = head;
if (!currentNode) return;
do
{
std::cout << currentNode->getData();
currentNode = currentNode->getNext();
}
while (currentNode);
std::cout << std::endl;
}
};
Which can then be simplified using the std::forward_list class (if you are using C++11 or later):
#pragma once
#include <iostream>
#include <forward_list>
#include <algorithm>
class LinkedList
{
private:
std::forward_list<int> list;
public:
void add(int numberToAdd)
{
list.push_front(numberToAdd);
}
bool remove()
{
if (!list.empty())
{
list.pop_front();
return true;
}
return false;
}
bool remove(int numberToRemove)
{
std::forward_list<int>::iterator iter = list.begin();
std::forward_list<int>::iterator previous = list.before_begin();
while (iter != list.end())
{
if (*iter == numberToRemove)
{
list.erase_after(previous);
return true;
}
++previous;
++iter;
}
return false;
}
void print()
{
if (list.empty()) return;
std::for_each(list.cbegin(), list.cend(), [](int data){ std::cout << data });
std::cout << std::endl;
}
};

Testing a C++ Linked Implementation Error [closed]

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;
}