So I wrote a Linked List based implementation of the Stack ADT recently. However, I'm not quite sure why there is a bit of a discrepancy between how the nodes of the Stack are being declared. The compiler gets very angry and won't compile until I write them a certain way for certain functions. I'm extremely curious as to why this is the case.
Here are two different methods which the compiler wants two different formats.
Here is my destructor where the compiler wants StackNode *temp.
template <typename DataType>
StackLinked<DataType>::~StackLinked() {
StackNode *temp;
while (top != 0) {
temp = top;
top = top->next;
delete temp;
}
}
Here is my assignment operator overload where the compiler wants StackNode<DataType> *temp.
template <typename DataType>
StackLinked<DataType>& StackLinked<DataType>::operator=(const StackLinked& other) {
if (this != &other) {
StackNode<DataType> *newNode, *current, *last;
if (top != 0) {
StackNode<DataType> *temp;
while (top != 0) {
temp = top;
top -> top->next;
delete temp;
}
}
if (other.top == 0) {
top = 0;
}
else {
current = other.top;
top = new StackNode<DataType>;
top->dataItem = current->dataItem;
top->next = 0;
last = top;
current = current->next;
while (current != 0) {
newNode = new StackNode<DataType>;
newNode->dataItem = current->dataItem;
newNode->next = 0;
last-> next = newNode;
last = newNode;
current = current->next;
}
}
}
return *this;
}
I don't know why this is, but the unknown is bothering me.
Note: My StackNode class is an inner class of the StackLinked class.
EDIT: Class declaration:
#ifndef STACKARRAY_H
#define STACKARRAY_H
#include <stdexcept>
#include <iostream>
using namespace std;
#include "Stack.h"
template <typename DataType>
class StackLinked : public Stack<DataType> {
public:
StackLinked(int maxNumber = Stack<DataType>::MAX_STACK_SIZE);
StackLinked(const StackLinked& other);
StackLinked& operator=(const StackLinked& other);
~StackLinked();
void push(const DataType& newDataItem) throw (logic_error);
DataType pop() throw (logic_error);
void clear();
bool isEmpty() const;
bool isFull() const;
void showStructure() const;
private:
class StackNode {
public:
StackNode(const DataType& nodeData, StackNode* nextPtr);
DataType dataItem;
StackNode* next;
};
StackNode* top;
};
#endif
If any other details are needed. Just ask! Thank you for your time!
From the code you showed, StackNode<DataType> is not correct, because StackNode is not a class template.
This makes me think you have a template also named StackNode that the compiler is finding. Go check whether any of your files contain another version of StackNode.
Related
I have just finished a project for Post Fix Notation(RPN) using stack. I am not having much luck with some of the compiler errors so I come to you guys while I work on debugging on my side also.
This file given to us. We are suppose to derive a stack class from it.
#ifndef ABSTRACTSTACK_H
#define ABSTRACTSTACK_H
#include <string>
using namespace std;
/* --------------- Class 'Oops' ---------------
Class
Thrown when an error is encountered.
Member 'm_msg' stores an error message.
*/
class Oops
{
string m_errormsg;
public:
Oops(string msg) : m_errormsg(msg) {}
const string& getMsg() const
{
return m_errormsg;
}
};
/* --------------- Abstract Class AbstractStack --------------- */
template < typename T >
class AbstractStack
{
public:
// Purpose: Checks if a stack is empty
// Returns: 'true' if the stack is empty
// 'false' otherwise
virtual bool isEmpty() const = 0;
// Purpose: looks at the top of the stack
// Returns: a const reference to the element currently on top of the stack
// Exception: if the stack is empty, THROW a 'Oops' object with an error message!!!
virtual const T& top() const throw ( Oops ) = 0;
// Purpose: push an element into the stack
// Parameters: x is the value to push into the stack
// Postconditions: x is now the element at the top of the stack,
virtual void push(const T& x) = 0;
// Purpose: pop the stack
// Postconditions: the element formerly at the top of the stack has
// been removed
// Note: Poping an empty stack results in an empty stack.
virtual void pop() = 0;
// Purpose: clears the stack
// Postconditions: the stack is now empty
virtual void clear() = 0;
};
#endif
Here is my derived class and it's implementation.
#ifndef STACK_H
#define STACK_H
#include<string>
#include<iostream>
#include<cstdlib>
#include "abstractstack.h"
using namespace std;
template<typename T>
struct Node
{
T Data;
Node<T>* next;
};
template<typename T>
class Stack : public AbstactStack<T>
{
private:
Node<T>* Top;
public:
//Purpose: Destructor
//Postconditions: The stack is now empty
~Stack() {};
//Purpose: Default Constructor
//Postconditions: Top is initialized to 'NULL'
Stack(); Top(NULL){};
//Overloaded = Operator
//Postconditions: *this is now equal to rhs
const Stack<T>& operator = (const Stack<T>& rhs);
//Purpose: Check if a stack is empty
//Returns: 'true' if the stakc is empty, 'false' otherwise
bool isEmpty() const;
//Purpose: Looks at the top of the stack
//Returns: a const reference to the element currently on top of the stack
//Exception: if the stack is empty, THROW a 'Oops' object with an error message!!!"
const T& top() const throw(Oops);
//Purpose: push an element into the stack
//Parameters: x is the value to push into the stack
//Postconditions: x is now the element at the top of the stack
void push(const T& x);
//Purpose: pop the stack
//Postconditions: the element formerly at the top of the stack has been removed
//Popping an empty stack results in an empty stack
void pop();
//Purpose: clears the stack
//Postconditions: the stack is now empty
void clear();
//Reverses the stack
//Postconditions: stack is now in reverse order
void reverse();
};
#include "stack.hpp"
#endif
Implementation (.hpp)
#include <string>
#include <iostream>
using namespace std;
template<typename T>
const Stack<T>& Stack<T>::operator = (const Stack<T>& rhs)
{
if (this != &rhs)
{
if (Top != NULL)
clear();
Node<T>* rhsPtr = rhs.Top;
Node<T>* copyPtr = Top = new Node<T>;
copyPtr->Data = rhsPtr->Data;
while (rhsPtr->next != NULL)
{
rhsPtr = rhsPtr->next;
copyPtr->next = new Node<T>;
copyPtr = copyPtr->next;
copyPtr->Data = rhsPtr->Data;
}
copyPtr->next = NULL;
}
return(*this)
}
template<typename T>
Stack<T>::Stack(const Stack<T>& rhs)
{
Top = NULL;
*this = rhs;
}
template<typename T>
bool Stack<T>::isEmpty()
{
return(Top == NULL);
}
template<typename T>
const T& top() const throw(Oops)
{
if (Top != NULL)
return(Top->Data);
else
throw Oops(Stack is Empty!);
}
template<typename T>
void Stack<T>::push(const T& x)
{
Node<T>* newNode = new Node;
newNode->Data = x;
if (isEmpty())
{
Top = newNode;
return;
}
newNode->next = Top;
Top->next = newNode;
}
template<typename T>
void Stack<T>::pop()
{
Node<T>* temp;
if (Top != NULL)
{
temp = Top;
Top = Top->next;
delete temp;
}
}
template<typename T>
void Stack<T>::clear()
{
Node<T>* temp;
while (Top != NULL)
{
temp = Top;
Top = Top->next;
delete temp;
}
}
template<typename T>
void Stack<T>::reverse()
{
Node<T>* current;
Node<T>* previous;
Node<T>* next;
previous = NULL;
current = Top;
while (current != NULL)
{
next = current->next;
current->next = previous;
previous = current;
current = next;
}
Top = previous;
}
The compiler is unhappy with my Stack class. "stack.h:25:34: error: expected template-name before ‘<’ token
class Stack : public AbstactStack
I've been told that I cannot inherit from Abstract because it is not a class but my professor tells me that it is fine and that I should add a forward declaration in my .cpp of Stack but I'm not sure how this goes. I know I am far from done but I would like to be able to solve at least this error so I can see if my program works correctly or not.
I posted my main program into Pastebin with its headers and implementation here in case it is needed. http://pastebin.com/1t2YGa2c
Seems to me that the problem that you are having is just a typo in the following line :
class Stack : public AbstactStack<T>
Change AbstactStack<T> to AbstractStack<T> and this should work.
The error you are getting explains that the class name before the character < should be a template, but since you made a typo in the name of the class, it does not recognize.
Make sure you read and understand the error messages! They are often very helpful when solving problems like these.
Little side note : If you take a look at your error messages, you'll see the filename where the error is, followed by the line number and the column number (stack.h:25:34). Very useful information when debugging.
I am attempting to make a queue in c++ using a double linked list. I Have not fully tested everything since i am stuck at the step where you dequeue. I attempted to create a temp node, and move around stuff so when I call delete on the head node in the queue (called queue), and then set the head to a temp node which is the next element, (you can see in the code) but when I call delete, is where it crashes, according to MS Visual studios 2013. Also to add how weird this is, following the stack called, after delete is called, setPrev is called and set the prev node and crashes there. Now I never call this function during any of my destructors deletes so any help will do. I will try my best to understand any answers but I am still new to c++ terminology. Below is my code. Oh one last thing, in main, all I did was call enqueue once, then dequeue once, then delete
Node Class
...
#ifndef TSDNODE_H
#define TSDNODE_H
template <class T>
class DNode
{
private:
DNode<T>* next;
DNode<T>* prev;
T data;
public:
DNode(T);
void setNext(DNode<T>* next);
void setPrev(DNode<T>* prev);
DNode<T>* getNext() const;
DNode<T>* getPrev() const;
T getData() const;
void setData(T data);
~DNode();
};
template <class T>
DNode<T>::DNode(T data)
{
this->next = nullptr;
this->data = data;
this->prev = nullptr;
}
template <class T>
void DNode<T>::setNext(DNode<T>* next)
{
this->next = next;
}
template <class T>
void DNode<T>::setPrev(DNode<T>* prev)
{
this->prev = prev;
}
template <class T>
DNode<T>* DNode<T>::getNext() const
{
return this->next;
}
template <class T>
DNode<T>* DNode<T>::getPrev() const
{
return this->prev;
}
template <class T>
T DNode<T>::getData() const
{
return this->data;
}
template <class T>
void DNode<T>::setData(T data)
{
this->data = data;
}
template <class T>
DNode<T>::~DNode()
{
delete this->next;
delete this->prev;
this->next = nullptr;
this->prev = nullptr;
}
#endif /* TSDNODE_H */
....
Queue Class
....
#ifndef TSQUEUE_H
#define TSQUEUE_H
#include "TSDNode.h"
#include <string>
template <class T>
class Queue
{
private:
DNode<T>* queue;
DNode<T>* tail;
int size;
public:
Queue();
void enqueue(T data);
T dequeue();
~Queue();
};
template <class T>
Queue<T>::Queue()
{
this->queue = nullptr;
this->tail = this->queue;
size = 0;
}
template <class T>
void Queue<T>::enqueue(T data)
{
if (this->tail != NULL)
{
this->tail->setNext(new DNode<T>(data));
this->tail->getNext()->setPrev(this->tail);
this->tail = this->tail->getNext();
}
else
{
this->queue = new DNode<T>(data);
this->tail = this->queue;
}
size++;
}
template <class T>
T Queue<T>::dequeue()
{
T data;
if (this->queue == nullptr)
{
delete this->tail;
delete this->queue;
this->tail = nullptr;
std::string ex = "Exception: Empty Queue\n";
throw ex;
}
else if (this->queue != nullptr)
{
data = this->queue->getData();
DNode<T>* node = this->queue->getNext();
this->queue->setNext(nullptr);
this->queue->setPrev(nullptr);
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
delete this->queue;
this->queue = node;
}
size--;
return data;
}
template <class T>
Queue<T>::~Queue()
{
delete this->queue;
this->queue = nullptr;
this->tail = nullptr;
}
#endif /* TSQUEUE_H */
In your DNode destructor, you don't want to delete the next and prev nodes. You only want to delete this node, not everything it links to.
Remove these lines
delete this->next;
delete this->prev;
Edit: Actually this isn't your problem, because you are clearing out the next and prev values before you delete the node. I still think it is better to not automatically delete the whole chain, but as long as you are consistent with how you handle node deletion it should still work.
You actually problem is that when you dequeue the last node, you still try to set the next pointer of the next node in this line:
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
At this point node is nullptr, so trying to access node->next causes a crash. A simple if test is all you need
if (node != nullptr)
node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here
Edit 2:
Also note that in the case where the next node in the queue is nullptr, you also want to set the tail to nullptr.
I have three files and I want to compile and run them, but I keep getting some errors and warnings. Redefinition of struct Node< T >. I don't know much about templates, but this looks right to me. And, I spent a lot of time trying to figure out whats wrong. Thanks.
//mystack.h
#ifndef MYSTACK_H
#define MYSTACK_H
template <class T>
struct Node
{
T info;
T *next;
};
template <class T>
class MyStack
{
private:
struct Node<T> *top;
public:
void Push(T item);
void Pop();
int Top();
void Print();
};
#endif
//mystack.cpp
#include <iostream>
#include "mystack.h"
template <class T>
struct Node
{
T info;
T* next;
};
template <class T>
class MyStack
{
private:
struct Node<T>* top;
public:
void Push(T item)
{
if(top == NULL)
{
top = new( struct Node<T> );
top->info = item;
top->next = NULL;
} else
{
Node<T>* temp;
temp = top;
top = new( struct Node<T> );
top->info = item;
top->next = temp;
}
}
void Pop()
{
if( top == NULL )
{
} else
{
Node<T>* temp;
temp = top->next;
delete top;
top = temp;
}
}
int Top()
{
return top;
}
void Print()
{
if(top != NULL)
{
Node<T>* temp;
temp = top;
while(temp != NULL)
{
std::cout << temp << std::endl;
temp = temp->next;
}
}
}
};
One mistake you did in the listings is that you redefine this structure as it says.
Thats the definition:
template <class T>
struct Node
{
T info;
T* next;
};
This definition is done in both listings.
Edit: The second thing is that your class method implementation does not look right. You will have the most success if you try not to split cpp and header files while using templates.
If you were designing a class instead of a template, what you're doing would be wrong because you're redefining types.
But since you're writing templates, you're wrong earlier than that: you can't separately compile templates.
Brief pointer on the C++ compilation model:
// Definition of Node
template<typename T>
struct Node {
T info;
T* next; // shouldn't that be a Node*?
};
// Definition of MyStack
template <typename T>
class MyStack
{
private:
Node<T> *top;
public:
// Declarations, but not definitions, of the Mystack function members.
void Push(T item);
void Pop();
int Top();
void Print();
};
// Example definition of MyStack::Push
template<typename T>
void
MyStack<T>::Push(T item)
{
// as before
}
The type definitions usually appear in headers (if they are to be reused in different TUs) with include guards as you are doing. The guards are here because the definitions must appear at most once per TU. Do not manually repeat a type definition (e.g. in a source file as you did). This is wrong as it should be: nobody wants copy-n-paste errors.
The function members definitions usually appear in source files, unless they are the members of a template. In the latter case it's simpler to put them in headers (they don't have to be inline either).
You can learn the details of the compilation model elsewhere on SO, or in books, or on the Internet. Searching for 'template definition' or 'one definition rule' (or ODR) can help.
First, In header, remove 'struct' from the line 'struct Node *top;'. In C++ structs are almost identical to classes, the only difference being that struct members are public by default and class members are private by default. You do not need to preface struct types with the struct keyword like in straight C.
Second, Your CPP is all wrong. Templates are instantiated by the compiler when needed, so they do not live in CPP files to be compiled into objects like normal (apart from template specializations). You can put your template definitions in the HPP itself or a better general solution is to use an IPP file, i.e
// mystack.ipp
#ifndef MYSTACK_IPP
#define MYSTACK_IPP
#include "mystack.h"
#include <iostream>
template <class T>
void MyStack<T>::Push(T item)
{
if(top == NULL)
{
top = new( struct Node<T> );
top->info = item;
top->next = NULL;
} else
{
Node<T>* temp;
temp = top;
top = new( struct Node<T> );
top->info = item;
top->next = temp;
}
}
template <class T>
void MyStack<T>::Pop()
{
if( top == NULL )
{
} else
{
Node<T>* temp;
temp = top->next;
delete top;
top = temp;
}
}
template <class T>
int MyStack<T>::Top()
{
return top;
}
template <class T>
void MyStack<T>::Print()
{
if(top != NULL)
{
Node<T>* temp;
temp = top;
while(temp != NULL)
{
std::cout << temp << std::endl;
temp = temp->next;
}
}
}
#endif
Then '#include "mystack.ipp"' in any file which makes use of the implementation of MyStack
I need some help making this program for class. We are working with g++ (linux? its through putty on a server) I am having a lot of issue with this linked list. The current error that it is giving me is
queue.cpp:2: error: expected unqualified-id before âusingâ
Wondering if anyone could help me figure it out. A little bit of searching shows that the problem seems to be in the #define somewhere? The error shows that it is in the .cpp file but i think it is in the .h file. Also if you could give me any programing advise about anything that seems off, wrong or if there a better way of doing it.
the queue.h file below
#ifndef QUEUE_H
#define QUEUE_H
template <class Object>
class Queue
{
public:
Queue();
Queue(const Queue& a_queue);
Queue& operator =(const Queue& rhs);
bool enqueue(const Object& d);
bool dequeue(const Object& d);
bool isEmpty() const;
~Queue();
private:
struct ListNode
{
Object obj;
ListNode *next;
};
ListNode *head;
}
#endif //Queue_H
#include "queue.cpp" //include queue.cpp with file
the queue.cpp file here.
#include <iostream>
using namespace std;
template <class Object>
Queue<Object>::Queue()
{
head = NULL;
}
template <class Object>
Queue<Object>::Queue(const Queue<Object>& a_queue)
{
head=NULL;
*this=a_queue;
}
template <class Object>
Queue<Object>& Queue<Object>::operator =(const Queue<Object> &rhs)
{
ListNode *nodePtr;
nodePtr = rhs.head;
if(this != rhs){
this.head = NULL;
while(nodePtr != NULL){
this.enqueue(nodePtr->obj);
nodePtr = nodePtr->next;
}
}
}
template <class Object>
bool Queue<Object>::enqueue (const Object& d) //Enqueue
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode;
previousNode = NULL;
nodePtr = NULL;
newNode = new ListNode;
newNode->obj = d;
newNode->next = NULL;
if(isEmpty){
head = newNode;
return true;
}
else{
nodePtr = head;
previousNode = NULL;
while(nodePtr != NULL){
previousNode = nodePtr;
nodePtr=nodePtr->next;
}
if(previousNode->next == NULL){
previousNode->next = newNode;
return true;
}
else
return false;
}
}
template <class Object>
bool Queue<Object>::dequeue (const Object& d) //Dequeue
{
ListNode *nodePtr;
if(!head)
return false;
else{
if(head->next != NULL){
nodePtr = head;
d=nodePtr->obj;
head = head->next;
delete nodePtr;
}else
delete head;
return true;
}
}
template <class Object>
bool Queue<Object>::isEmpty() const //Check if Empty
{
if(!head)
return true;
else
return false;
}
template <class Object>
Queue<Object>::~Queue() //Destructor
{
Object temp;
while (head != NULL)
dequeue (temp);
}
Don't include your implementation file from the header. Include the header from the implementation file.
I don't see you say "using namespace std" in the header in your code, but you say in your comment that you do that. Don't. Never say using namespace in a header file.
Place all template definitions in the header.
You're missing a semicolon in your class definition in the header.
Your assignment operator is not exception-safe. Make sure your copy-constructor is correct and then use the copy & swap idiom.
Your copy-constructor is incorrect. If you want to support lazy copy (copy on write) then that's fine, but you're missing the actual deep copy operation. Be extra-careful with the copy constructor, because it extremely important you get it right.
You need a semicolon after your class declaration in the header.
class Queue
{
public:
Queue();
Queue(const Queue& a_queue);
Queue& operator =(const Queue& rhs);
bool enqueue(const Object& d);
bool dequeue(const Object& d);
bool isEmpty() const;
~Queue();
private:
struct ListNode
{
Object obj;
ListNode *next;
};
ListNode *head;
};
EDIT -- Answered below, missed the angled braces. Thanks all.
I have been attempting to write a rudimentary singly linked list, which I can use in other programs. I wish it to be able to work with built-in and user defined types, meaning it must be templated.
Due to this my node must also be templated, as I do not know the information it is going to store. I have written a node class as follows -
template <class T> class Node
{
T data; //the object information
Node* next; //pointer to the next node element
public:
//Methods omitted for brevity
};
My linked list class is implemented in a seperate class, and needs to instantiate a node when adding new nodes to the end of the list. I have implemented this as follows -
#include <iostream>
#include "Node.h"
using namespace std;
template <class T> class CustomLinkedList
{
Node<T> *head, *tail;
public:
CustomLinkedList()
{
head = NULL;
tail = NULL;
}
~CustomLinkedList()
{
}
//Method adds info to the end of the list
void add(T info)
{
if(head == NULL) //if our list is currently empty
{
head = new Node<T>; //Create new node of type T
head->setData(info);
tail = head;
}
else //if not empty add to the end and move the tail
{
Node* temp = new Node<T>;
temp->setData(info);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
}
//print method omitted
};
I have set up a driver/test class as follows -
#include "CustomLinkedList.h"
using namespace std;
int main()
{
CustomLinkedList<int> firstList;
firstList.add(32);
firstList.printlist();
//Pause the program until input is received
int i;
cin >> i;
return 0;
}
I get an error upon compilation however - error C2955: 'Node' : use of class template requires template argument list - which points me to the following line of code in my add method -
Node* temp = new Node<T>;
I do not understand why this has no information about the type, since it was passed to linked list when created in my driver class. What should I be doing to pass the type information to Node?
Should I create a private node struct instead of a seperate class, and combine the methods of both classes in one file? I'm not certain this would overcome the problem, but I think it might. I would rather have seperate classes if possible though.
Thanks, Andrew.
While the answers have already been provided, I think I'll add my grain of salt.
When designing templates class, it is a good idea not to repeat the template arguments just about everywhere, just in case you wish to (one day) change a particular detail. In general, this is done by using typedefs.
template <class T>
class Node
{
public:
// bunch of types
typedef T value_type;
typedef T& reference_type;
typedef T const& const_reference_type;
typedef T* pointer_type;
typedef T const* const_pointer_type;
// From now on, T should never appear
private:
value_type m_value;
Node* m_next;
};
template <class T>
class List
{
// private, no need to expose implementation
typedef Node<T> node_type;
// From now on, T should never appear
typedef node_type* node_pointer;
public:
typedef typename node_type::value_type value_type;
typedef typename node_type::reference_type reference_type;
typedef typename node_type::const_reference_type const_reference_type;
// ...
void add(value_type info);
private:
node_pointer m_head, m_tail;
};
It is also better to define the methods outside of the class declaration, makes it is easier to read the interface.
template <class T>
void List<T>::add(value_type info)
{
if(head == NULL) //if our list is currently empty
{
head = new node_type;
head->setData(info);
tail = head;
}
else //if not empty add to the end and move the tail
{
Node* temp = new node_type;
temp->setData(info);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
}
Now, a couple of remarks:
it would be more user friendly if List<T>::add was returning an iterator to the newly added objects, like insert methods do in the STL (and you could rename it insert too)
in the implementation of List<T>::add you assign memory to temp then perform a bunch of operations, if any throws, you have leaked memory
the setNextNull call should not be necessary: the constructor of Node should initialize all the data member to meaningfull values, included m_next
So here is a revised version:
template <class T>
Node<T>::Node(value_type info): m_value(info), m_next(NULL) {}
template <class T>
typename List<T>::iterator insert(value_type info)
{
if (m_head == NULL)
{
m_head = new node_type(info);
m_tail = m_head;
return iterator(m_tail);
}
else
{
m_tail.setNext(new node_type(info));
node_pointer temp = m_tail;
m_tail = temp.getNext();
return iterator(temp);
}
}
Note how the simple fact of using a proper constructor improves our exception safety: if ever anything throw during the constructor, new is required not to allocate any memory, thus nothing is leaked and we have not performed any operation yet. Our List<T>::insert method is now resilient.
Final question:
Usual insert methods of single linked lists insert at the beginning, because it's easier:
template <class T>
typename List<T>::iterator insert(value_type info)
{
m_head = new node_type(info, m_head); // if this throws, m_head is left unmodified
return iterator(m_head);
}
Are you sure you want to go with an insert at the end ? or did you do it this way because of the push_back method on traditional vectors and lists ?
Might wanna try
Node<T>* temp = new Node<T>;
Also, to get hints on how to design the list, you can of course look at std::list, although it can be a bit daunting at times.
You need:
Node<T> *temp = new Node<T>;
Might be worth a typedef NodeType = Node<T> in the CustomLinkedList class to prevent this problem from cropping up again.
That line should read
Node<T>* temp = new Node<T>;
Same for the next pointer in the Node class.
As said, the solution is
Node<T>* temp = new Node<T>;
... because Node itself is not a type, Node<T> is.
And you will need to specify the template parameter for the Node *temp in printlist also.
// file: main.cc
#include "linkedlist.h"
int main(int argc, char *argv[]) {
LinkedList<int> list;
for(int i = 1; i < 10; i++) list.add(i);
list.print();
}
// file: node.h
#ifndef _NODE_H
#define _NODE_H
template<typename T> class LinkedList;
template<typename T>class Node {
friend class LinkedList<T>;
public:
Node(T data = 0, Node<T> *next = 0)
: data(data), next(next)
{ /* vacio */ }
private:
T data;
Node<T> *next;
};
#endif//_NODE_H
// file: linkedlist.h
#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H
#include <iostream>
using namespace std;
#include "node.h"
template<typename T> class LinkedList {
public:
LinkedList();
~LinkedList();
void add(T);
void print();
private:
Node<T> *head;
Node<T> *tail;
};
#endif//_LINKEDLIST_H
template<typename T>LinkedList<T>::LinkedList()
: head(0), tail(0)
{ /* empty */ }
template<typename T>LinkedList<T>::~LinkedList() {
if(head) {
Node<T> *p = head;
Node<T> *q = 0;
while(p) {
q = p;
p = p->next;
delete q;
}
cout << endl;
}
}
template<typename T>LinkedList<T>::void add(T info) {
if(head) {
tail->next = new Node<T>(info);
tail = tail->next;
} else {
head = tail = new Node<T>(info);
}
}
template<typename T>LinkedList<T>::void print() {
if(head) {
Node<T> *p = head;
while(p) {
cout << p->data << "-> ";
p = p->next;
}
cout << endl;
}
}
You Should add new node in this way
Node<T>* temp=new node<T>;
Hope you Solved :)
#include<iostream>
using namespace std;
template < class data > class node {
private :
data t;
node<data > *ptr;
public:
node() {
ptr = NULL;
}
data get_data() {
return t;
}
void set_data(data d) {
t = d;
}
void set_ptr(node<data > *p) {
ptr = p;
}
node * get_ptr() {
return ptr;
}
};
template <class data > node < data > * add_at_last(data d , node<data > *start) {
node< data > *temp , *p = start;
temp = new node<data>();
temp->set_data(d);
temp->set_ptr(NULL);
if(!start) {
start = temp;
return temp;
}
else {
while(p->get_ptr()) {
p = p->get_ptr();
}
p->set_ptr(temp);
}
}
template < class data > void display(node< data > *start) {
node< data > *temp;
temp = start;
while(temp != NULL) {
cout<<temp->get_data()<<" ";
temp = temp->get_ptr();
}
cout<<endl;
}
template <class data > node < data > * reverse_list(node<data > * start) {
node< data > *p = start , *q = NULL , *r = NULL;
while(p->get_ptr()) {
q = p;
p = p->get_ptr();
q->set_ptr(r);
r = q;
}
p->set_ptr(r);
return p;
}
int main() {
node < int > *start;
for(int i =0 ; i < 10 ; i ++) {
if(!i) {
start = add_at_last(i , start);
}
else {
add_at_last(i , start);
}
}
display(start);
start = reverse_list(start);
cout<<endl<<"reverse list is"<<endl<<endl;
display(start);
}