I am using templates in c++ to create a linked list. I have coded a few functions , but the deletion of node ( either from head/tail ) isnt working properly. It displays an error and terminates. When debugging , the 'this' shown in watch windows contains a head which is null, which i have no idea why. Here is my code:
SLlistSc.h
#ifndef SLlistSc_H
#define SLlistSc_H
#include<iostream>
using namespace std;
template<class T> class SLlist;
template <class T> class snode{
friend class SLlist<T>;
private:
T info;
snode<T> *next;
public:
inline T getter() const { return info; }
inline void setter(T setValue){ info = setValue; }
snode(){ info = 0; next = 0; }
snode(T inf , snode *nex = 0){ info = inf; next = nex; }
~snode(){ delete next; }
};
template <class T> class SLlist{
private:
snode<T> *head, *tail;
static int total;
public:
SLlist(){ head = tail = 0; }
~SLlist(){
snode<T> *p = head;
while (head != 0){
head = head->next;
delete p;
p = head;
}
}
inline void incrcnt(){ total++; }
inline void decrcnt(){ total--; }
void displayList();
void addToHead(T inf);
void addToTail(T inf);
T deleteFromHead();
T deleteFromTail();
int returnIndex();
void deleteInfo();
void deleteAll();
};
template <class T> void SLlist<T>::displayList(){
snode<T> *p = head;
while (p != 0){
cout << "\n->" << p->info;
p = p->next;
}
return;
}
template <class T> void SLlist<T>::addToHead(T inf){
snode<T> *temp = new snode<T>(inf, 0);
if (head == 0){ head = tail = temp; temp = 0; delete temp; incrcnt(); return; }
else { temp->next = head; head = temp; temp = 0; delete temp; incrcnt(); return; }
}
template <class T> void SLlist<T>::addToTail(T inf){
snode<T> *temp = new snode<T>(inf, 0);
if (head == 0){ head = tail = temp; temp = 0; delete temp; incrcnt(); return; }
else{ tail->next = temp; tail = temp; temp = 0; delete temp; return; }
}
template <class T> T SLlist<T>::deleteFromHead(){
if (head == 0){ cout << "\nList is already empty"; return (T)0; }
if (head == tail){ delete head; head = tail = 0; T info = head->info; return info; }
else {
T info = head->info;
snode<T> *temp = head;
head = head->next;
temp = 0;
delete temp;
return info;
}
}
template <class T> T SLlist<T>::deleteFromTail(){
if (head == 0){ cout << "\nList is already empty"; return (T)0; }
if (head == tail){ delete head; head = tail = 0; T info = head->info; return info; }
else {
T info = tail->info;
snode<T> *temp = head;
while (temp != 0)
{
temp = tail;
}
delete tail;
tail = temp;
temp = 0; delete temp;
return (T)info;
}
}
#endif
and the cpp file : SLlistSc.cpp
// SLlistSc.cpp : Defines the entry point for the console application.
//
#include"SLlistSc.h"
#include<iostream>
using namespace std;
template <class T> int SLlist<T>::total = 0;
void main()
{
cout << "\t\t\t Singly Linked List Super Class Implementation";
SLlist<int> List1;
int userchoice=0, inf=0;
do{
cout << "\n\n\t\t Menu"
<< "\n\t1. Display List"
<< "\n\t2. Add to Head"
<< "\n\t3. Add to tail"
<< "\n\t4. Delete from Head"
<< "\n\t5. Delete from Tail"
<< "\n\t6. Exit";
cin >> userchoice;
switch (userchoice){
case 1: List1.displayList(); break;
case 2: cout << "\nEnter info to be added:";
cin >> inf;
List1.addToHead(inf); break;
case 3: cout << "\nEnter info to be added:";
cin >> inf;
List1.addToTail(inf); break;
case 4: inf = List1.deleteFromHead();
cout << "\n Value" << inf << "deleted from list"; break;
case 5: inf = List1.deleteFromTail();
cout << "\n Value" << inf << "deleted from list"; break;
case 6: cout << "\n\t\t\t\tExiting";
exit(0);
default: continue;
}
} while (userchoice < 4);
}
Another thing i would like to ask is , when we use templates on a class (eg. class A) , we are required to replace the A with A everywhere. Is it because compiler generates a new class ie.
A<T> isnt = A.
And while using friend class SLlist inside snode class , why do i have to declare as follows :
template<class T> class SLlist;
before the snode class? why cant i declare it directly in the snode class as :
friend class SLlist<T>;
Also if there is a chance of improvemet in my code , please go hard on me. Thanks.
You are attempting to use a pointer that is invalid because the block containing that pointer has been freed.
The Microsoft C++ debug runtime library overwrites freed memory with the pattern 0xFEEEFEEE which makes this problem easier to identify.
Related
I'm trying to implement a stack using a doubly linked list. I know that the functions for my stack class (push, pop) should contain calls to member functions of my doubly linked list class, but I'm having trouble actually implementing that.
dlist.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include "dlist.hpp"
using namespace std;
void dlist::appendNodeFront(int shares, float pps){
Node *n = new Node(shares, pps);
if(front == NULL){
front = n;
back = n;
}
else {
front->prev = n;
n->next = front;
front = n;
}
}
void dlist::appendNodeBack(int shares, float pps){
Node *n = new Node(shares, pps);
if(back == NULL){
front = n;
back = n;
}
else {
back->next = n;
n->prev = back;
back = n;
}
}
void dlist::display(){
Node *temp = front;
cout << "List contents: ";
while(temp != NULL){
cout << temp->value << " ";
temp = temp->next;
}
cout << endl;
}
void dlist::display_reverse(){
Node *temp = back;
cout << "List contents in reverse: ";
while(temp != NULL){
cout << temp->value << " ";
temp = temp->prev;
}
cout << endl;
}
void dlist::destroyList(){
Node *T = back;
while(T != NULL){
Node *T2 = T;
T = T->prev;
delete T2;
}
front = NULL;
back = NULL;
}
stack.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include "stack.hpp"
using namespace std;
stack::stack(){
int i;
for(i = 0; i < 1500; i++){
shares[i] = 0;
pps[i] = 0;
}
first = 0;
}
void stack::push(int num, float price){
if(first ==(1500-1)){
cout << "Stack is full" << endl;
return;
}
first++;
shares[first] = num;
pps[first] = price;
return;
}
void stack::pop(int *num, float *price){
if(first == -1){
cout << "Stack is empty" << endl;
return;
}
num = &shares[first];
price = &pps[first];
cout << shares[first] << endl;
cout << pps[first] << endl;
shares[first] = 0;
pps[first] = 0;
first--;
return;
}
Should the push function in stack basically be a call to appendNodeFront() or appendNodeback()? Any help or advice is greatly appreciated!
You can create a stack class, then use linked list class as its container. In a linked list class there is virtually no limit to the number of items, so you add artificial limit to make it work like a stack. In a linked list, items can be added/removed anywhere in the list, you can limit add/remove the tail node only to make it work like stack. The example below demonstrate the usage.
Node that this is purely a programming exercise. Stack is relatively primitive compared to Doubly-linked list. Encapsulating a linked-list inside stack has no advantage. Also note, I declared all members as public for the sake of simplifying the problem, you may want to change some members to protected/private
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
class Node
{
public:
Node *prev;
Node *next;
int shares;
float pps;
Node(int vshares, float vpps)
{
shares = vshares;
pps = vpps;
prev = next = nullptr;
}
};
class dlist
{
public:
Node *head;
Node *tail;
dlist()
{
head = tail = nullptr;
}
~dlist()
{
destroy();
}
void push_back(int shares, float pps)
{
Node *node = new Node(shares, pps);
if (head == NULL)
{
head = tail = node;
}
else
{
tail->next = node;
node->prev = tail;
tail = node;
}
}
void destroy()
{
Node *walk = head;
while (walk)
{
Node *node = walk;
walk = walk->next;
delete node;
}
head = tail = nullptr;
}
};
class stack
{
public:
int maxsize;
int count;
dlist list;
stack(int size)
{
count = 0;
maxsize = size;
}
void push(int num, float price)
{
if (count < maxsize)
{
list.push_back(num, price);
count++;
}
}
void pop()
{
Node *tail = list.tail;
if (!tail)
{
//already empty
return;
}
if (tail == list.head)
{
//only one element in the list
delete tail;
list.head = list.tail = nullptr;
count--;
}
else
{
Node *temp = list.tail->prev;
delete list.tail;
list.tail = temp;
list.tail->next = nullptr;
count--;
}
}
void display()
{
Node *walk = list.head;
while (walk)
{
cout << "(" << walk->shares << "," << walk->pps << ") ";
walk = walk->next;
}
cout << "\n";
}
};
int main()
{
stack s(3);
s.push(101, 0.25f);
s.push(102, 0.25f);
s.push(103, 0.25f);
s.push(104, 0.25f);
s.display();
s.pop();
s.display();
return 0;
}
I'm new with data structures in C++, and i'm trying to do a doubly linked list with templates. All the examples that i have seen are only for 1 element of the template node, so i'm trying to put 2 elements in the template node in the list, but i don't know how to do it, anyway, i tried to make the list.
Here's the code:
#include<iostream>
#include<cstring>
using namespace std;
template<class T>
// node class
class node
{
public:
node();
node(T);
~node();
node *next;
T data[2];
void borra_todo();
void print();
};
// by defect
template<typename T>
node<T>::node()
{
data[0] = NULL;
data[1] = NULL;
next = NULL;
}
// by parameter
template<typename T>
node<T>::node(T data_)
{
data[0] = data_[0];
data[1] = data_[1];
next = NULL;
}
// delete nodes
template<typename T>
void node<T>::borra_todo()
{
if (next)
next->borra_todo();
delete this;
}
// node printing
template<typename T>
void node<T>::print()
{
cout << data[0] << " " << data[1] << "->";
}
template<typename T>
node<T>::~node() {}
// list
template <class T>
class list
{
private:
node<T> *m_head;
int m_num_nodes;
public:
list();
~list();
void add_head(T);
void add_end(T);
void add_sort(T);
void fill(char r[30], char n[30]);
void search(T);
void del_by_data(T);
void print();
};
template<typename T>
list<T>::list()
{
m_num_nodes = 0;
m_head = NULL;
}
//add in the beginning
template<typename T>
void list<T>::add_head(T data_)
{
node<T> *new_node = new node<T>(data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
new_node->next = m_head;
m_head = new_node;
while (temp)
{
temp = temp->next;
}
}
m_num_nodes++;
}
// add to the last
template<typename T>
void list<T>::add_end(T data_)
{
node<T> *new_node = new node<T> (data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new_node;
}
m_num_nodes++;
}
// it is supposed that sorts items in the list ...
template<typename T>
void list<T>::add_sort(T data_)
{
node<T> *new_node = new node<T> (data_);
node<T> *temp = m_head;
if (!m_head)
{
m_head = new_node;
}
else
{
for (int i =0; i <= 1; i++)
{
if (m_head->data[0] > data_[i])
{
new_node->next = m_head;
m_head = new_node;
}
else
{
while ((temp->next != NULL) && (temp->next->data[0] < data_[i]))
{
temp = temp->next;
}
new_node->next = temp->next;
temp->next = new_node;
}
}
m_num_nodes++;
}
}
// sort adding ...
template<typename T>
void list<T>::fill(char rfc[30])
{
char temprfc[30];
char tempnombre[30];
temprfc = "DUDE010101R0";
tempnombre = "Dude";
add_sort(temprfc, tempnombre);
temprfc = "AUDE010101R1";
tempnombre = "Commander";
add_sort(temprfc, tempnombre);
}
// print list
template<typename T>
void list<T>::print()
{
node<T> *temp = m_head;
if (!m_head)
{
cout << "List is empty" << endl;
}
else
{
while (temp)
{
temp->print();
if (!temp->next)
cout << "NULL\n";
temp = temp->next;
}
}
cout << endl;
}
// search the list
template<typename T>
void list<T>::search(T data_)
{
node<T> *temp=m_head;
int cont=1;
int cont2=0;
while(temp)
{
if(strcmp(temp->data,data_[0]))
{
cout<<"Element found " << temp->data;
cout << " in position: " << cont << endl;
cont2++;
}
temp=temp->next;
cont++;
}
if(cont2==0)
{
cout << "Element not found"<<endl;
}
}
// ... delete by data
template<typename T>
void list<T>::del_by_data(T data_)
{
node<T> *temp = m_head;
node<T> *temp1 = m_head->next;
int cont =0;
if (m_head->data == data_)
{
m_head = temp->next;
}
else
{
while (temp1)
{
if (temp1->data == data_)
{
node<T> *aux_node = temp1;
temp->next = temp1->next;
delete aux_node;
cont++;
m_num_nodes--;
}
temp = temp->next;
temp1 = temp1->next;
}
}
if (cont == 0)
{
cout << "No data" << endl;
}
}
// destroy the constructor
template<typename T>
list<T>::~list() {}
int main()
{
list<char> list1;
char element1[30];
char element2[30];
int dim, choice, pos;
do{
cout << "Select a choice.\n";
cout << "1. Print list\n";
cout << "2. Delete an element of the list\n";
cout << "3. Search an element of the list\n";
cout << "4. Exit\n";
cin >> choice;
switch(choice)
{
case 1:
{
cout << "Printing list:\n";
list1.fill("1","2");
list1.print();
break;
}
case 2:
{
cout << "Element to delete: ";
cin >> element1;
list1.search(element1);
element1 = "";
break;
}
case 3:
{
cout << "Element to search: ";
cin >> element1;
list1.search(element1);
element1 = "";
break;
}
}
}while(choice != 4);
return 0;
}
The code doesn't compile, it marks errors like:
" error: prototype for ‘void list::fill(char*)’ does not match any in class ‘list’
void list::fill(char rfc[30])
^
t3b.cpp:79:8: error: candidate is: void list::fill(char*, char*)
void fill(char r[30], char n[30]);"
Any ideas on how to fix it? Or any ideas on how to put 2 elements in a node using templates?
Thanks in advance.
Dude, you should really try to isolate the error a little bit before posting it. This is 500 lines of code, I had to copy and paste it all into an editor before I could even look at it.
When you declared fill, it had two arguments, when you defined it, it had one. Also, I would avoid arrays of characters for numerous reasons, instead use std::string.
If you can follow my main below, I run the program, I am able to enter an integer, it finds the next prime number, then asks for data. Once I enter data once, the program hangs. Seems to be in an infinite loop, or something. It doesn't crash. When I pause it, it brings up read.c file with an arrow on line 256. Not sure what this means whatsoever. Any help would be much appreciated.
I have the following class and member function declarations in hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#define TRUE 1
#define FALSE 0
#define VERBOSE 0x01
#define NON_VERBOSE 0x02
#include "linkedlist.h"
class hashTable{
public:
int keys;
int tableSize;
linkedList<int> **table;
hashTable(const int n);
//~hashTable();
void hash(int value);
int search(int value);
int divisionMethod(int value, int sizeOfTable);
int midSquareMethod(int value, int sizeOfTable);
int total();
void printHashTable();
int next_prime(int value, char flag);
};
// constructor
hashTable::hashTable(const int n){
linkedList<int> newList;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>*[tableSize];
for (int i = 0; i < tableSize; i++)
table[i] = { new linkedList<int> };
}
// Compute the Hash Function and "Hash" element into table
void hashTable::hash(int value){
table[value % tableSize]->addToHead(value);
keys++;
//divisionMethod(midSquareMethod(value, tableSize), tableSize)
}
// Simple Search Function
// Returns the element searched for if found, 0 otherwise
int hashTable::search(int value){
return(table[value % tableSize]->search(value));
}
// Divsion Method for producing a semi-unique key
int hashTable::divisionMethod(int value, int sizeOfTable){
int key;
key = value % sizeOfTable;
return(key);
}
// Middle Square Method for producing a semi-unique key
int hashTable::midSquareMethod(int value, int sizeOfTable){
int key;
key = ((value * value) & 0x0ff0) >> 4; // pick the middle 8 bits
return(key);
}
// Returns the total number of keys in the table
int hashTable::total(){
return(keys);
}
// Print the hash table (for demonstration purposes
void hashTable::printHashTable(){
int i = 0, valueToPrint;
while (i < tableSize){
cout << i << ": ";
valueToPrint = table[i]->removeFromHead();
while (valueToPrint != 0){
cout << valueToPrint << " -> ";
valueToPrint = table[i]->removeFromHead();
}
cout << "|" << endl;
i++;
}
}
int hashTable::next_prime(int value, char flag){
int FOUND = FALSE;
int n;
while (!FOUND) {
for (n = 2; (n * n) <= value && (value % n) != 0; ++n);
if ((n * n) <= value) {
if (flag == VERBOSE)
cout << value << " is divisible by " << n << "\n";
value++;
}
else {
if (flag == VERBOSE)
cout << "The next largest prime is " << value << "\n";
FOUND = TRUE;
}
}
return(value);
}
#endif
Here is my linkedlist.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
using namespace std;
template <class TYPE>
class Node{
public:
TYPE data;
Node* next;
// constructor
Node(TYPE const& x){
data = x;
next = NULL;
}
};
template <class TYPE>
class linkedList{
//struct Node{
// TYPE data;
// Node *next;
//};
public:
Node<TYPE> *head;
Node<TYPE> *tail;
int size;
// constructor
linkedList(){
head = NULL;
tail = NULL;
size = 0;
}
~linkedList();
void addToHead(TYPE value);
void addToTail(TYPE value);
TYPE removeFromHead();
TYPE removeFromTail();
TYPE search(TYPE searchData);
TYPE isEmpty();
};
//destructor
template <class TYPE>
linkedList<TYPE>::~linkedList(void){
while (head){
Node<TYPE> *temp = head;
head = head->next;
delete temp;
}
}
// Insert an element at the head (start) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToHead(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
if (isEmpty())
head = newNode;
else{
newNode->next = head;
head = newNode;
}
}
// Add an element to the tail (end) of the linked list
template <class TYPE>
void linkedList<TYPE>::addToTail(TYPE value){
Node<TYPE> *newNode = new Node<TYPE>(value);
Node *tempPtr;
if(isEmpty()){
head = newNode;
tail = newNode;
}
else{
tail->next = newNode;
tail = tail->next;
}
}
// Remove an element from start of Linked List
template <class TYPE>
TYPE linkedList<TYPE>::removeFromHead(){
TYPE tempValue;
Node<TYPE> *temp;
if (head){
tempValue = head->data;
temp = head;
if (head == tail)
head = tail = 0;
else
head = head->next;
delete temp;
return tempValue;
}
else
return 0;
}
// Remove an element from the end of the linked list
template <class TYPE>
TYPE linkedList<TYPE>::removeFromTail(){
TYPE tempValue;
Node *temp;
if (tail){
tempValue = tail->data;
if (head == tail){
delete head;
head = tail = 0;
}
else{
for (temp = head; temp->next != tail; temp = temp->next);
delete tail;
tail = temp;
tail->next = 0;
}
return tempValue;
}
else
return 0;
}
// Search for an element in the linked list
// Will return the element if found, otherwise it returns 0
template <class TYPE>
TYPE linkedList<TYPE>::search(TYPE searchData){
Node<TYPE> *temp;
temp = head;
while (temp->next != tail){
if (tail->data == searchData)
return searchData;
if (temp->data == searchData)
return searchData;
else
temp = temp->next;
}
return 0;
}
// isEmpty() function checks if head == NULL
template <class TYPE>
TYPE linkedList<TYPE>::isEmpty(){
return(head == NULL);
}
#endif
Here is my main:
#include "hashtable.h"
int main(){
int n, input;
cout << "Enter an integer: ";
cin >> n;
cout << "\n\n";
hashTable myHashTable(n);
cout << "Enter some values into the table:" << endl;
cin >> input;
while (input != 0){
myHashTable.hash(input);
cin >> input;
}
myHashTable.printHashTable();
}
Something must be wrong, you have in attribute of your hashTable class ... a hashTable pointer. It must be a linkedlist pointer, nop ?
I did find out what was causing all this. It was the way that I was implementing the linked lists in my array of pointers. Pretty much just programmer error from long nights. Of course there is a lot wrong with my code that I posted here, which I fixed it all, e.g. search function in my hash class, etc.,
Here is what I changed that pretty much fixed a good portion of my problem posted here:
hashTable::hashTable(const int n, char hFunction){
keys = 0;
hashFunction = hFunction;
tableSize = next_prime(n, VERBOSE);
cout << "Table size is: " << tableSize << "\n\n"; // for debugging
system("pause"); // for debugging
table = new linkedList<int>[tableSize];
I also changed my linkedList<int> **table to linkedList<int> *table. If anyone else needs any pointers on the rest of this NOW working hash function, just get a hold of me.
Trying to learn C++. Was wondering if someone could point me in the right direction on this error (pun intended).
The class is a LinkedList (reproduced in its entirety below). The error occurs on this line:
LinkedList<T>::ListNode LinkedList::find(int pos) const {
and says:
expected constructor, destructor, or type conversion before
'LinkedList'
Any tips would be greatly appreciated.
#ifndef LINKEDLIST_HPP
#define LINKEDLIST_HPP
#include <iostream>
using namespace std;
template <class T>
class LinkedList {
private:
// a ListNode consists of the item and a pointer to the next ListNode
struct ListNode {
T data;
ListNode *next;
};
int size; //Size of the list
ListNode *head; //the beginning of the list
public:
LinkedList(); // default oonstructor
~LinkedList(); // destructor
virtual bool isEmpty ();
virtual int getLength ();
virtual void insert (int pos, T item);
virtual T remove (int pos);
virtual T retrieve (int pos);
//helper methods
LinkedList(LinkedList ©List); //copy constructor
ListNode *find (int pos) const; // internal find function
};
//default constructor
template <class T>
LinkedList<T>::LinkedList() {
size = 0;
head = NULL;
}
//destructor
template <class T>
LinkedList<T>::~LinkedList() {
//loop through each node, and delete it
ListNode* current = head;
while (current != NULL) {
ListNode* next = current->next;
delete current;
current = next;
}
head = NULL; // set head node to back to null
}
//copy constructor
template <class T>
LinkedList<T>::LinkedList(LinkedList& copyList) {
size = copyList.size;
// if copyList is empty
if (copyList.head == NULL)
head = NULL;
else {
//create a new head
head = new ListNode;
head->data = copyList.head->data;
//create a new list
ListNode *newPtr = head; // start at the head
// iterate through rest of list to be copied
for (ListNode *copyPtr = copyList.head->next; copyPtr != NULL; copyPtr = copyPtr->next) {
newPtr->next = new ListNode;
newPtr->data = copyPtr->data;
}
//make last ListNode's next point to NULL
newPtr->next = NULL;
}
}
template <class T>
bool LinkedList<T>::isEmpty() {
if (size == 0)
return true;
return false;
}
template <class T>
int LinkedList<T>::getLength() {
return size;
}
// used in other methods to find a given index
template <class T>
LinkedList<T>::ListNode LinkedList::find(int pos) const {
// check that pos is in bound of LinkedList
if ((pos < 1) || pos > getLength()) {
cout << "Find position of out bounds" << endl;
return NULL;
} else { //search through ListNodes
ListNode *temp = head; // start at the head
for (int i = 1; i < pos; ++i)
temp = temp->next;
return temp;
}
}
template <class T>
T LinkedList<T>::retrieve(int pos) {
T tempData; // to hold retrieved data
try {
if ((pos < 1) || (pos > getLength())) {
cout << "Retrieve request outside LinkedList's bounds" << endl;
return NULL;
}
else { //traverse list
ListNode *temp = find(pos);
tempData = temp->data;
return tempData;
}
} catch (int e) {
cout << "Could not retrieve position " << pos << endl;
}
}
template <class T>
void LinkedList<T>::insert(int pos, T item) {
//check bounds
if ((pos < 1) || (pos > getLength() +1))
cout << "Must insert at a position between 1 and getLength() + 1" << endl;
else {
try {
//create new ListNode
ListNode *temp = new ListNode;
temp->data = item;
//if the new item is at the first position
if (pos == 1) {
temp->next = head;
head = temp;
}
else {
ListNode *prev = find(pos - 1);
temp->next = prev->next;
prev->next = temp;
}
//increment size
++size;
} catch (int e) {
cout << "Error inserting " << item << " at position " << pos << endl;
}
}
}
template <class T>
T LinkedList<T>::remove(int pos) {
//check bounds
if ((pos < 1) || (pos > getLength()))
cout << "Must remove a position between 1 and getLength()" << endl;
else {
try {
ListNode *temp; //to hold shifted node
//if node to be deleted is first node
if (pos == 1) {
temp = head;
head = head->next;
}
//for anything but the head
//write over the node before the pos'th index
else {
ListNode *prev = find(pos - 1);
temp = prev->next;
prev->next = temp->next;
}
//destroy temp, to free up memory
temp->next = NULL;
delete temp;
//decrement size
--size;
} catch (int e) {
cout << "Error removing item from position " << pos << endl;
}
}
}
#endif /* LINKEDLIST_HPP */
ListNode is a dependant type, so it needs to be qualified with typename. Also, your find function was declared to return a pointer-to-ListNode, but the definition returns a ListNode by value. This seems like a simple typo:
template <class T>
typename LinkedList<T>::ListNode* LinkedList<T>::find(int pos) const {
Qualify the dependant type with typename and add <T> (I'm not sure if this is necessary, might as well do it though):
typename LinkedList<T>::ListNode* LinkedList<T>::find(int pos) const {
See: Where and why do I have to put the "template" and "typename" keywords?
Also, your definition doesn't match. In-class it returns a pointer, but outside it returns a value.
Should be
LinkedList<T>::ListNode LinkedList<T>::find(int pos) const {
Hi I am trying to make a doubly linked list to store individual numbers as nodes of a doubly linked list and then add them together and print them out for a homework assignment. I am having a lot of trouble getting this to work and have traced my problem to my add node functions as they don't update the pointers correctly. For example on the AddToFront() function I can't understand how I can get the prev pointer to work and point to the node behind it.
I can't use the STL and have to implement the LL myself in case anyone is wondering. Thanks!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
/////// PART A
template <class T>
class List {
private:
struct Node {
T data;
Node *next;
Node *prev;
};
Node *front, *current, *rear;
public:
List();
~List();
void AddtoFront (T newthing);
void AddtoRear (T newthing);
bool FirstItem (T & item);
bool LastItem (T & item);
bool NextItem (T & item);
bool PrevItem (T & item);
};
template <class T>
List<T>::List() {
front = NULL; current = NULL; rear = NULL;
}
template <class T>
List<T>::~List() {
}
template <class T>
void List<T>::AddtoFront (T newthing) {
if (front == NULL) {
Node *temp;
temp = new Node;
temp->data = newthing;
temp->next = front;
temp->prev = NULL;
front = temp;
} else {
Node *temp;
temp = new Node;
front->prev = temp;
temp->data = newthing;
temp->next = front;
temp->prev = NULL;
front = temp;
}
}
template <class T>
void List<T>::AddtoRear (T newthing) {
if (rear == NULL) {
Node *temp;
temp = new Node;
temp->data = newthing;
temp->prev = rear;
temp->next = NULL;
rear = temp;
} else {
Node *temp;
temp = new Node;
rear->next = temp;
temp->data = newthing;
temp->prev = rear;
temp->next = NULL;
rear = temp;
}
}
template <class T>
bool List<T>::FirstItem (T & item) {
if (front == NULL) { return false; }
current = front;
item = front->data;
return true;
}
template <class T>
bool List<T>::LastItem (T & item) {
if (rear == NULL) { return false; }
current = rear;
item = rear->data;
return true;
}
template <class T>
bool List<T>::NextItem (T & item) {
if (current != NULL) current = current->next;
if (current == NULL) { return false; }
item = current->data;
return true;
}
template <class T>
bool List<T>::PrevItem (T & item) {
if (current == NULL) { return false; }
if (current->prev != NULL) current = current->prev;
item = current->data;
return true;
}
/////// PART B
class BigNumber {
private:
//complete here...
//include here a List of integers, or shorts etc
List<int>L;
public:
//complete here...
//what methods do you need?
//e.g., ReadFromString, PrintBigNumber, AddBigNumbers
BigNumber();
~BigNumber();
void ReadFromString(char * decstring);
void PrintBigNumber();
void AddBigNumbers(BigNumber B1, BigNumber B2);
};
BigNumber::BigNumber(){
// anything here?
}
BigNumber::~BigNumber(){
//you can keep that empty
}
void BigNumber::ReadFromString (char * decstring ) {
//read a string, adding a new node per digit of the decimal string
// To translate 'digits' to integers: myinteger=decstring[index]-48
//You need to use the AddtoFront()
int temp;
for (unsigned i=0; i < strlen(decstring); ++i) {
//cin >> decstring[i];
temp = decstring[i]-48;
//L.AddtoFront(temp);
L.AddtoRear(temp);
//cout <<"Number added!" <<endl;
}
}
void BigNumber::PrintBigNumber () {
//complete here, print the list (i.e., use FirstItem() and NextItem() )
int val;
if (L.FirstItem(val)) {
cout << val;
} else {
cout << "print failed";
}
//if (L.FirstItem(val)) { cout << "true-first";} else { cout <<"false-first";};
//if (L.LastItem(val)) { cout << "true";} else { cout <<"false";};
//L.FirstItem(val);
//cout << val;
/*while (L.PrevItem(val)){
cout << val;
//cout <<"Print error!Value not here.";
}*/
}
void BigNumber::AddBigNumbers(BigNumber B1,BigNumber B2){
//complete here.
//use FirstItem(), NextItem() and AddNode()
//to add two big numbers, what do you have to do? Be careful about the carry
//Remember to add the last carry, the resulting number can have one more digit than B1 or B2
}
/////// PART C
BigNumber B1, B2, RES;
int main (int argc, char ** argv) {
//use command line arguments
if(argc!=3){printf("usage: executable number1 number2\n");exit(0);}
B1.ReadFromString(argv[1]);
B2.ReadFromString(argv[2]);
//print
cout << endl<< "Add the following numbers " << endl;
B1.PrintBigNumber();
cout << " + ";
B2.PrintBigNumber();
cout << " = " << endl;
//compute the addition
RES.AddBigNumbers(B1,B2);
//print the result
RES.PrintBigNumber();
cout << endl;
return 0;
}
EDIT: I added in a line each in AddToFront() and AddToRear(). Is this on the right track?
AddtoFront needs to also update the prev pointer for front. That is, you're currently doing
temp -> front <-> rest_of_list
where it needs to be
temp <-> front <-> rest_of_list.
Also, you might notice that the two branches of your if statement in AddtoFront are identical... :)