I'm trying to create a program that reads from a text file and stores the words into a singly linked list. I'm supposed to create my own linked list as opposed to using the STL. I've tried looking up a fair number of tutorials, but I keep getting an error on the variable "head." It says "a value type of Node cannot be used to initialize an entity of type Node"
This is List.cpp:
#include "List.h"
#include "Node.h"
#include <iostream>
using namespace std;
void List::add(string s){
Node* newNode = new Node();
newNode->addString(s);
newNode->setNext(NULL);
Node *temp = head;
if(temp != NULL)
{
while(temp->Next() != NULL)
{
temp = temp->Next();
}
temp->setNext(newNode);
}
else
{
head = newNode;
}
}
void List::print(){
Node *temp = head;
if(temp == NULL)
{
cout<<"EMPTY"<< endl;
return;
}
if(temp->Next() == NULL)
{
cout<<temp->Word();
cout<< "-->";
cout<< "NULL" << endl;
}
else
{ do{
cout<<temp->Word();
cout<<"-->";
temp = temp->Next();
}
while( temp != NULL);
cout << "NULL" << endl;
}
}
void List::read(ifstream& fin){
while(!fin.eof())
{
fin>>sTemp;
add(sTemp);
}
}
This is Node.h
using namespace std;
#include <string>
class Node
{ string val;
Node* next;
public:
Node(void){}
Node(string s)
{
val = s;
next = nullptr;
}
void addString(string aString){ val = aString;};
void setNext(Node* aNext){next = aNext;};
string Word(){return val;};
Node* Next(){return next;};
string sTemp;
};
This is List.h
#include <string>
#include <fstream>
#include "Node.h"
using namespace std;
class List{
Node* head;
public:
List()
{
head = NULL;
}
void print();
void add(string s);
void find(string key);
void read(ifstream& fin);
string sTemp;
}
Under the actual List.cpp, it gives me an error when I say Node *temp = head; with the aforementioned error. Any reason why and how can I fix this?
Part of the problem here is that in List.cpp you've included Node.h twice.
directly includes List.h which itself includes Node.h
directly includes Node.h
I'm surprised that the compiler didn't warn you about this. It seems instead that it chose to redefine Node hence you end up with two Node values which aren't compatible. You need to add include guards to your header files to prevent double includes
List.h
#if !LIST_H
#define LIST_H
...
#endif
Node.h
#if !NODE_H
#define NODE_H
...
#endif
Also note that it's generally speaking considered bad practice to have using statements in header files. Instead use namespace qualified names in headers and put the using statements into the .cpp files.
Related
I'm writing a binary tree in object-oriented format. I've had experience with binary trees before, but it's been a while since I've touched on this. My problem is that I'm unable to assign a node to my root. Every time I check in debugging mode, the root remains NULL. While this is happening, the cur node contains all the information it's assigned.
I've tried making my root private and changing this->root = NULL; to root-> = NULL;. I've also tried making all of my functions public, but it didn't make a difference. I tried declaring root's children to NULL values and name to an empty string as well.
main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include "Friends.h"
using namespace std;
int main() {
string line;
ifstream file;
file.open("friends.txt");
Friends f;
while (getline(file, line)) {
f.insert(f.root, line);
}
f.print(f.root);
system("pause");
return 0;
}
Friends.cpp
#include "Friends.h"
#include <iostream>
#include <string>
using namespace std;
Friends::Friends() {
this->root = NULL;
}
Friends::node* Friends::createNode(string& val) {
node* newNode = new node();
newNode->left = NULL;
newNode->right = NULL;
newNode->name = val;
return newNode;
}
Friends::node* Friends::insert(node* cur, string& val) {
if (!cur) {
cur = createNode(val);
}
else if (val < cur->name) {
insert(cur->left, val);
return cur;
}
else if (val > cur->name) {
insert(cur->right, val);
return cur;
}
return NULL;
}
void Friends::print(node* cur) {
if (!cur) {
return;
}
print(cur->left);
cout << cur->name << endl;
print(cur->right);
}
Friends.h
#ifndef FRIENDS_H
#define FRIENDS_H
#include <string>
using namespace std;
class Friends {
private:
struct node {
string name;
node* left;
node* right;
};
public:
node* root;
node* insert(node* cur, string&);
void print(node* cur);
Friends();
node* createNode(string&);
};
#endif
The root node should have a node, but has keeps showing up as a NULL value. It doesn't run with any errors either. It just remains as NULL.
change from:
node* insert(node* cur, string&);
to :
node* insert(node* &cur, string&);
should fix
Of course the implementation header should also be changed
So far I have created a simple linked list project that I will build on in the future. All files compile correctly but when I try to build my project it comes up with a link error. I used an empty project to start. The main.cpp is used to demo that my linked list actually works. I'm really stuck and don't know how to solve this issue.
Main.cpp
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include "LinkedList.cpp"
#include "LinkedList.h"
using namespace SDI;
template <class T>
int LinkedList<T>::main()
{
LinkedList<T> menu;
menu.insert(1);
menu.insert(4);
menu.insert(7);
menu.insert(2);
menu.insert(8);
menu.display();
Std::cout << "-----" << endl;
menu.remove(2);
menu.remove(1);
menu.remove(10);
menu.display();
return 0;
};
header file LinkedList.h
#ifndef SDI_LL
#define SDI_LL
namespace SDI
{
template < class T >
class LinkedList
{
class Node
{
int number;
Node* next;
};
private:
T head;
T current;
T temp;
public:
LinkedList();
~LinkedList();
int main();
void insert(int add);
void remove(int remove);
void display();
};
}
#endif
LinkedList.cpp
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include "LinkedList.h"
using namespace SDI;
template <class T>
LinkedList<T>::LinkedList()
{
head = NULL;
current = NULL;
temp = NULL;
};
template <class T>
void LinkedList<T>::insert(int add)
{
newnode = new Node;
newnode->next = NULL;
newnode->number = add;
if (head != NULL)
{
current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
else
{
head = newnode;
}
};
template <class T>
void LinkedList<T>::remove(int remove)
{
remove1 = NULL;
temp = head;
current = head;
while (current != NULL && current->add != remove)
{
temp = current;
current = current->next;
}
if (current == NULL)
{
std::cout << "N/A\n";
delete remove1;
}
else
{
remove1 = current;
current = current->next;
temp->next = current;
if (remove1 == head)
{
head = head->next;
temp = NULL;
}
delete remove1;
}
};
template <class T>
void LinkedList<T>::display()
{
current = head;
while (current != NULL)
{
std::cout << current->number;
current = current->next;
}
};
You need a global main() function in your program, not the static version from LinkedList. The main function is called the entry point, and a quick lookup of the error message tells you this.
http://en.cppreference.com/w/cpp/language/main_function
Something along the lines of this might work:
int main()
{
LinkedList<int> menu;
menu.insert(1);
menu.insert(4);
menu.insert(7);
menu.insert(2);
menu.insert(8);
menu.display();
Std::cout << "-----" << endl;
menu.remove(2);
menu.remove(1);
menu.remove(10);
menu.display();
return 0;
};
Currently, you define a completely unrelated "main" function inside your class. This is just a plain normal function of your class and in no way related to the previously mentioned int main() entry point function.
I want to read in student names from a file and insert them into my linked-list, but I am having this problem with an error box. The error reads "Expression: Invalid Null Pointer."
I've googled with no such luck. I think I have an idea where I've went wrong, but I don't know how to fix it.
If you could help, that would be great!
Here is my code:
P.S I'm not nearly done so my code might be incomplete, I'm just trying to weed out all my errors now so I don't have triple my errors at the end.
LList.h
#include <iostream>
#include <iomanip>
#include <string>
#ifndef LLIST_H
#define LLIST_H
typedef int ElementType;
class LList
{
public:
LList();
~LList();
void insert(std::string new_data);
void display();
void remove(std::string delete_data);
private:
class Node
{
public:
std::string data;
Node *next;
Node(std::string data_value = NULL);
};
Node *head;
int mySize;
};
#endif LLIST_H
LList.cpp
#include <iomanip>
#include <iostream>
#include <string>
#include "LList.h"
using namespace std;
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
LList::~LList()
{
delete this -> head;
}
void LList::insert(string new_data)
{
Node *tempHolder;
tempHolder = this->head;
while (tempHolder->next != NULL)
tempHolder = tempHolder -> next;
Node *newNode = new Node(new_data);
tempHolder ->next = newNode;
this->mySize++;
}
void LList::display()
{
Node *temp;
temp = head->next;
while(temp -> next != NULL)
{
cout << temp -> data << endl;
temp = temp -> next ;
}
}
void LList::remove(string delete_data)
{
Node *tempHolder;
tempHolder = head;
while (tempHolder->next != NULL )
{
if (tempHolder->next->data == delete_data)
{
Node *delete_ptr = tempHolder->next;
tempHolder->next = tempHolder->next->next;
delete delete_ptr;
mySize-- ;
break;
} else
tempHolder = tempHolder->next;
}
}
Main.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include "LList.h"
#include <fstream>
using namespace std;
int main()
{
LList student;
ifstream infile;
char readLine[500];
infile.open ("names.txt");
if(infile.is_open())
{
while (!infile.eof())
{
infile.getline(readLine,sizeof(readLine)); // read a line from file
student.insert(readLine);
}
}
else
{
cout << "Can't open file!" << endl;
}
}
I found my problem.
In:
LList::LList()
{
this -> head = new Node(0);
mySize = 0;
string data = "";
}
Node(0);
is calling my
LList::Node::Node (string data_value)
{
this -> data = data_value;
this -> next = NULL;
}
which is initialized as a string.
I changed
Node(0);
to
Node("");
and it worked flawlessly.
I wonder could you give the reference where you read that you may to write?
Node(std::string data_value = NULL);
Class std::string has no constructor that converts NULL to an object of type std::string.
it would be much better to declare the constructor without a default argument
Node( std::string data_value );
There is no any sense to create a node without data.
In fact there is no any need to declare a constructor of Node. It could be used as an aggregate.
Also change the constructor of LList as
LList::LList() : head( 0 ), mySize( 0 ){}
Also the destructor is invalied
LList::~LList()
{
delete this -> head;
}
You have to delete not only head but all nodes in the LList.
Also nodes in a single linked list are inserted in the beginning of the list that is before the head.
I would write method insert the following way provided that the constructor of Node is removed bacause it is not needed.
void LList::insert( const std::string &new_data )
{
head = new Node { new_data, head };
}
If your compiler does not support the initializer list then you indeed need to define constructor in class Node.
Node( const std::string &data_value, next_node = NULL );
In this case method insert will look as
void LList::insert( const std::string &new_data )
{
head = new Node( new_data, head );
}
I'm trying to implement a linked list in C++, but every time I compile, I get an error that says 'Node* Node::nextPtr' is private. If I change nextPtr to have public protection, then I don't get the error and my list is fine. Can someone tell me why this is and how to fix it? My list and node classes are as follows:
//list.h
#include <string>
#include "node.h"
using namespace std;
class List
{
public:
List();
bool isEmpty();
void insertAtFront(string Word);
void displayList();
private:
Node * firstPtr;
Node * lastPtr;
};
//node.h
#ifndef NODE_H
#define NODE_H
#include <string>
using namespace std;
class Node
{
public:
Node(string arg);
string getData();
private:
string data;
Node * nextPtr;
};
//node.cpp
#include <iostream>
#include <string>
#include "node.h"
using namespace std;
Node::Node(string arg)
:nextPtr(0)
{
cout << "Node constructor is called" << endl;
data = arg;
}
string Node::getData()
{
return data;
}
//list.cpp
#include <iostream>
#include "list.h"
#include "node.h"
using namespace std;
List::List()
:firstPtr(0), lastPtr(0)
{
}
bool List::isEmpty()
{
if(firstPtr == lastPtr)
return true;
else
return false;
}
void List::displayList()
{
Node * currPtr = firstPtr;
do
{
if(currPtr->nextPtr == lastPtr) // Error here
cout << endl << currPtr->getData() << endl;
cout << endl << currPtr->getData() << endl;
currPtr = currPtr->nextPtr; //Error here
}
while(currPtr != lastPtr);
}
void List::insertAtFront(string Word)
{
Node * newPtr = new Node(Word);
if(this->isEmpty() == true)
{
firstPtr = newPtr;
cout << "Adding first element...." << endl;
}
else if(this->isEmpty() == false)
{
newPtr->nextPtr = firstPtr; //Error here
firstPtr = newPtr;
cout << "Adding another element...." << endl;
}
}
You didn't show the definitions of your member functions inside the List class, but I bet it is due to those member functions try to access nextPtr from the Node class. You can,
make nextPtr public from Node
add public accessor functions to Node to access it
declare List as a friend from Node, friend class List;
Because somewhere in your code, you access Node * nextPtr by non member functions of class Node. You can create a getter for nextPrt to avoid that.
So for my assignment, I am supposed to implement a Node class that just contains data and pointers to its two siblings and a BinaryTree that reads in these Nodes and creates a binary tree out of them. My problem is pointing to the root of the Tree does not seem to work. Any help you can provide would be appreciated!
Note: The error is found a few lines into the addNode method in the BinaryTree.cpp file which can be found at the end of the question. Also, I am not able to access the value of size either, so I believe this is some sort of weird scope issues I cannot resolve. I also cannot use the "this" keyword in the addNode function.
I am also not allowed to use structs, per my homeworks' instruction.
Node.H
#include <iomanip>
using namespace std;
class Node
{
public:
int data;
Node* leftChild;
Node* rightChild;
Node(int data, Node* leftChild, Node* rightChild);
};
Node.cpp
#include <iomanip>
#include <iostream>
#include "Node.h"
using namespace std;
Node::Node(int data, Node* leftChild, Node* rightChild)
{
this->data = data;
this->leftChild = leftChild;
this->rightChild = rightChild;
}
BinaryTree.H
#include <iomanip>
#include "Node.h"
using namespace std;
class Tree
{
public:
Tree(int data);
void addNode(int data);
void inOrder(Node* N);
protected:
Node* root;
int size;
int data;
private:
int printNode(Node* N);
};
BinaryTree.cpp
#include <iostream>
#include <iomanip>
#include "BinaryTree.h"
using namespace std;
//Tree constructor. Sets the values of data, size, and root.
Tree::Tree(int data)
{
this->data = data;
this->size = 0;
this->root = new Node(data, NULL, NULL);
}
//Adds a node to the current Tree.
void addNode(int data)
{
Node* tempNode = new Node(data, NULL, NULL);
Node* current = root; //THIS IS THE ERROR LINE.
while(current!=NULL)
{
//If the data we are trying to add is already in the Tree
if(current->data == tempNode->data)
{
cout << "Data already in the Tree.";
}
//If the data for the new node is larger than the old
else if(current->data < tempNode->data)
{
//See if the right child is null. If so, add the tree node there.
if(current->rightChild == NULL)
{
current->rightChild = tempNode;
return;
}
//Otherwise, traverse down the right tree.
else
{
current = current->rightChild;
}
}
//The data is smaller than the current node
else
{
//See if the left child is null. If so, add the tree node there.
if(current->leftChild == NULL)
{
current->leftChild = tempNode;
return;
}
//Otherwise, traverse down the left tree
else
{
current = current->leftChild;
}
}//End of leftChild Else
}//End of while
}//End of addNode
void addNode(int data)
should be:
void Tree::addNode(int data)
as it is a member function of class Tree
//Adds a node to the current Tree.
void addNode(int data)
Should be:
//Adds a node to the this Tree
void Tree::addNode(int data)