I am a bit new to using multi-files. I have this very simple code for a linked list, but when I debug, it "stops working".
This problem has occured with me several times before. I want to know is there something wrong with my "linked list" code? Or is something wrong with the multi-files organization?
Any help would be highly appreciated.
======================================
//linkedListMAIN.cpp
#include "linkedlist.cpp"
void main()
{
linkList<int> l;
l.append(5);
l.traverse();
}
======================================
//linkedList.h
#include<iostream>
using namespace std;
template <class T>
class linkList
{
private:
struct node
{
T data;
node *next;
};
node *head;
node *tail;
int noOfEl;
public:
linkList()
{
noOfEl = 0;
head=tail=NULL;
}
void traverse();
int length();
void insertAt(T, int);
T delAt(int);
void append(T);
void clear();
};
======================================
//linkedList.cpp
#include "linkedlist.h"
template <class T>
void linkList<T>:: traverse()
{
node<T> *current=head;
if(head == NULL)
{
cout<<"List empty."<<endl;
}
while(current != NULL)
{
cout<<current->data;
current = current->next;
}
}
template <class T>
void linkList<T>::append(T data)
{
node< *newNode= new node;
newNode->next = NULL;
tail->next = newNode;
tail = newNode;
noOfEl++;
}
You should not include the .cpp in inkedListMAIN.cpp but the header (.h). Also unless you are using c++11 you will have to put the class definition of templated classes in the header.
Related
So far, I have implemented a basic LinkedList. This works, but only for integers, and I would like it to work for any type.
I'm trying to get it to work for first any same type (i.e a LinkedList of just strings, or then just ints). After, I would like it to find a way of making it a LinkedList of anything (containing strings, then ints, then longs, all in one list).
#include <iostream>
struct Node{
Node(int value);
Node *next;
int data;
};
Node::Node(int value){
this->data = value;
this->next = nullptr;
}
struct LinkedList{
Node *head;
LinkedList();
void push_back(int value);
void print();
};
LinkedList::LinkedList(){
this->head = nullptr;
}
void LinkedList::push_back(int value){
Node *n = new Node(value);
if(this->head == nullptr){
this->head = n;
} else {
Node *cursor = this->head;
while (cursor->next != nullptr){
cursor = cursor->next;
}
cursor->next = n;
}
}
void LinkedList::print(){
Node *cursor = this->head;
while(cursor != nullptr){
std::cout << cursor->data << '\n';
cursor = cursor->next;
}
}
int main(){
LinkedList l = LinkedList();
l.push_back(1);
l.push_back(2);
l.print();
}
The above works, however, only for ints.
I'm knew, but I think the way is to use templates, however, doing so, I seem to be doing overkill? and it doesn't compile? Is there a cleaner was to do this?
#include <iostream>
template <typename T>
struct Node {
Node(T value);
int data;
Node<T> *next;
};
template <typename T>
Node<T>::Node(T value){
this->next = nullptr;
this->data = value;
}
template <typename T>
class LinkedList{
public:
LinkedList();
Node<T> *head;
void push_back(T data);
void print();
};
template <typename T>
LinkedList<T>::LinkedList(){
this->head = nullptr;
}
template <typename T>
void LinkedList<T>::push_back(T data){
Node *n = new Node(data);
if(this->head == nullptr){
this->head = n;
} else {
Node *cursor = this->head;
while(cursor->next != nullptr){
cursor = cursor->next;
}
cursor->next = n;
}
}
template <typename T>
void LinkedList<T>::print(){
Node *cursor = this->head;
while(cursor != nullptr){
std::cout << cursor->data << '\n';
cursor = cursor->next;
}
}
int main(){
LinkedList<T> *list = new LinkedList<T>();
list->push_back(1);
list->push_back(2);
list->push_back(3);
}
When declaring template classes, you use the "T" as a 'type placeholder' in the declaration and implementation (as you have done). However, when you want to actually use an object of the templated class, you replace the "T" with the actual type you want.
So, in your main (assuming you want an int type), you would have code like this:
int main(){
LinkedList<int> *list = new LinkedList<int>(); // THIS object uses "int" wherever "T" occurs in the declaration/implementation
list->push_back(1);
list->push_back(2);
list->push_back(3);
}
I also noticed a 'possible/probable error' in your struct declaration, where you specified that the data member is of (fixed) type int; maybe (almost certainly, actually, as you later assign a "T"-type value to it) you want this to vary according to the actual type requested? If so, make the following change:
template <typename T>
struct Node {
Node(T value);
// int data;
T data; // Data will be whatever "T" is when an object is created.
Node<T> *next;
};
Feel free to ask for further clarification and/or explanation.
I realize the title isn't too descriptive so here are the details. I'm implementing my own Binary Tree class in C++. I have written a template Node class and template Binary Tree class already, for the most part, and am stuck on something. I created an empty binary tree (root node is null) and when I try to set that node it fails miserably. here is the code and more explanation:
template<class T> class Node
{
T _key;
Node<T> *_leftChild;
Node<T> *_rightChild;
public:
Node();
Node(T key);
Node(T key, Node<T> *leftChild, Node<T> *rightChild);
~Node();
bool hasLeftChild();
bool hasRightChild();
void setKey(T key);
void setLeftChild(Node<T> *node);
void setRightChild(Node<T> *node);
T getKey();
Node<T>* getLeftChild();
Node<T>* getRightChild();
bool compare(Node<T> *compareNode); // return true if this.Node < compareNode
};
Node implementation not really necessary.. ( I dont think ) it's quite long.
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T> class BinaryTree
{
Node<T> *_root;
public:
BinaryTree();
BinaryTree(Node<T> *root);
~BinaryTree();
Node<T>* getRoot();
void insert(Node<T> **root, Node<T> *node);
};
template<class T>
BinaryTree<T>::BinaryTree()
{
this->_root = NULL;
}
template<class T>
BinaryTree<T>::BinaryTree(Node<T> *root)
{
this->_root = root;
}
template<class T>
BinaryTree<T>::~BinaryTree()
{
// delete stuff
}
template<class T>
Node<T>* BinaryTree<T>::getRoot()
{
return this->_root;
}
template<class T>
void BinaryTree<T>::insert(Node<T> **root, Node<T> *node)
{
if(!*root)
{
*root = node;
}
}
Main:
BinaryTree<int> *tree = new BinaryTree<int>();
Node<int> *root = tree->getRoot();
Node<int> **root1 = &root;
cout << tree->getRoot() << endl;
Node<int> *noChildrenNode = new Node<int>(2);
tree->insert(&root1, noChildrenNode);
cout << tree->getRoot() << endl;
Inserts current functionality is just supposed to replace the NULL root pointer to the node pointer passed in as a parameter. The failing miserably part is since the pointer is a copy it isn't actually setting the root node.. but I can't seem to figure out how to set up a pointer to a pointer to the root node so it can be altered.. I've got to be close and any help will be MUCH appreciated.
Thanks
First, you've got to include the exact text of any error messages. "fails miserably" is not adequate.
I think you want
root = node;
Not
*root = node;
Because if root is null, using *root is a null pointer exception.
I am trying to create a custom List template in C++ but haven't gotten very far! I have the skeleton of the coding done and am now trying to fill it in. Basically, I would like it to be possible to create a new list where the two nodes (first, last) will be NULL until values are added into the list.
However, there is a huge error message which seems to be a i/o one. It is too long to paste here. I'm sure I am doing something silly that will be spotted by those more experienced then me.
#include <iostream>
using namespace std;
template <class T>
class node {
T value;
node<T> *next;
node<T> *previous;
};
template <class T>
class my_list {
public:
node<T> first;
node<T> last;
my_list(){
first = NULL;
last = NULL;
}
~my_list(){
}
void push_back(T val);
};
template <class T>
void my_list<T>::push_back(T val){
if (this->first == NULL) {
cout << "Hello";
}
}
int main() {
my_list<int> newlist;
newlist.push_back(5);
}
You need to fix your declaration of first and last:
node<T> *first;
node<T> *last;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get “unresolved external symbol” errors when using templates?
LinkedList.h
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<iostream>
template<class T> class LinkedList;
//------Node------
template<class T>
class Node {
private:
T data;
Node<T>* next;
public:
Node(){data = 0; next=0;}
Node(T data);
friend class LinkedList<T>;
};
//------Iterator------
template<class T>
class Iterator {
private:
Node<T> *current;
public:
friend class LinkedList<T>;
Iterator operator*();
};
//------LinkedList------
template<class T>
class LinkedList {
private:
Node<T> *head;
public:
LinkedList(){head=0;}
void push_front(T data);
void push_back(const T& data);
Iterator<T> begin();
Iterator<T> end();
};
#endif /* LINKEDLIST_H */
LinkedList.cpp
#include "LinkedList.h"
#include<iostream>
using namespace std;
//------Node------
template<class T>
Node<T>::Node(T data){
this.data = data;
}
//------LinkedList------
template<class T>
void LinkedList<T>::push_front(T data){
Node<T> *newNode = new Node<T>(data);
if(head==0){
head = newNode;
}
else{
newNode->next = head;
head = newNode;
}
}
template<class T>
void LinkedList<T>::push_back(const T& data){
Node<T> *newNode = new Node<T>(data);
if(head==0)
head = newNode;
else{
head->next = newNode;
}
}
//------Iterator------
template<class T>
Iterator<T> LinkedList<T>::begin(){
return head;
}
template<class T>
Iterator<T> Iterator<T>::operator*(){
}
main.cpp
#include "LinkedList.h"
using namespace std;
int main() {
LinkedList<int> list;
int input = 10;
list.push_front(input);
}
Hi, I am fairly new at c++ and I am trying to write my own LinkedList using templates.
I followed my book pretty closely and this is what I got. I am getting this error though.
/main.cpp:18: undefined reference to `LinkedList::push_front(int)'
I have no clue why, any ideas?
You are using templates in your Program. When you use templates, you have to write the code and the headers in the same file because the compiler needs to generate the code where it is used in the program.
You can do either this or include #inlcude "LinkedList.cpp" in main.cpp
This question might help you.
Why can templates only be implemented in the header file?
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