I am getting the error "invalid null pointer" - c++

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

Related

Undefined reference to 'Inventory::insertEnd(Node*, int)'

I’m getting an “undefined reference to” error when trying to build/compile my program:
obj\Debug\main.o||In function main':|
C:\Users\user1\Desktop\Project5Example\main.cpp|13|undefined reference toInventory::insertEnd(Node*, int)'|
...
||error: ld returned 1 exit status|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
I’m quite new to c++. What am I doing wrong? and how can I fix it?
I feel is has to do with my head node? But can’t really figure out how what it is.
The error happens on main.cpp line head = inventory1.insertEnd(head, 8);
Here is my code:
Inventory.h
#ifndef INVENTORY_H
#define INVENTORY_H
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
struct Node
{
int data;
Node* next;
};
class Inventory
{
public:
// Default Constructor
Inventory();
// MODIFICATION MEMBER FUNCTIONS
Node *newNode(int data);
Node* insertEnd(Node* head, int data);
private:
// Data members
Node *head;
Node *trailer;
};
#endif // INVENTORY_H
Inventory.cpp
#include "Inventory.h"
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
Inventory::Inventory()
{
// Set the header and trailer to NULL
head = NULL;
trailer = NULL;
}
// Allocates a new node with given data
Node *newNode(int data)
{
Node *new_node = new Node;
new_node->data = data;
new_node->next = NULL;
return new_node;
}
// Function to insert a new node at the
// end of linked list using recursion.
Node* insertEnd(Node* head, int data)
{
// If linked list is empty, create a
// new node (Assuming newNode() allocates
// a new node with given data)
if (head == NULL)
return newNode(data);
// If we have not reached end, keep traversing
// recursively.
else
head->next = insertEnd(head->next, data);
return head;
}
main.cpp
#include <iostream>
#include "Inventory.h"
using namespace std;
int main()
{
// Create an inventory list
Inventory inventory1;
Node* head = NULL;
head = inventory1.insertEnd(head, 8);
head = inventory1.insertEnd(head, 11);
head = inventory1.insertEnd(head, 20);
return 0;
}
For starters the structure Node should be a private member of the class Inventory. Correspondingly the class Inventory should not contain public member functions that have the return type Node *. So for example this member function
Node *newNode(int data);
should be removed. In turn this public member function
Node* insertEnd(Node* head, int data);
should be declared like
void insertEnd( int data );
If it is required (but it is not required) the function could call a private static member function declared like
static Node* insertEnd(Node* head, int data);
As you declared a two-sided singly-linked list then it does not make sense to define the function insertEnd as a recursive function because there is no recursion. A new node ia appended to the node that you named like trailer though it would be better to name it like tail.
Moreover in the definitions of the functions newNode and insertEnd you forgot to specify name of the class Inventory like
Node * Inventory::newNode(int data)
{
//...
}
Node * Inventory::insertEnd(Node* head, int data)
{
//...
}
And this part in main
Inventory inventory1;
Node* head = NULL;
head = inventory1.insertEnd(head, 8);
head = inventory1.insertEnd(head, 11);
head = inventory1.insertEnd(head, 20);
does not make sense. The object inventory1 already contains the data member head (and trailer) that should be updated for the object.
The class can be defined for example the following way as it is shown in the demonstrative program below.
#include <iostream>
class Inventory
{
public:
Inventory() = default;
Inventory( const Inventory & ) = delete;
Inventory & operator =( const Inventory & ) = delete;
~Inventory();
void insertEnd( int data );
void clear();
friend std::ostream & operator <<( std::ostream &, const Inventory & );
private:
struct Node
{
int data;
Node *next;
} *head = nullptr, *tail = nullptr;
};
Inventory::~Inventory()
{
clear();
}
void Inventory::insertEnd( int data )
{
Node *node = new Node { data, nullptr };
if ( tail == nullptr )
{
head = tail = node;
}
else
{
tail = tail->next = node;
}
}
void Inventory::clear()
{
while ( head != nullptr )
{
Node *node = head;
head = head->next;
delete node;
}
tail = head;
}
std::ostream & operator <<( std::ostream &os, const Inventory &inventory )
{
for ( Inventory::Node *node = inventory.head; node != nullptr; node = node->next )
{
os << node->data << " -> ";
}
return os << "null";
}
int main()
{
Inventory inventory;
for ( const auto &data : { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } )
{
inventory.insertEnd( data );
}
std::cout << inventory << '\n';
return 0;
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

Root node should have an assigned node, but remains NULL. Why can't I assign a node to my root?

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

Read from text file and make a dictionary text file

I want to read a text file and store new words in linked list. From this linked list I want to write a dictionary file with new words. I don't know why my code don't run. Can anyone help me?
p/s: when i run debug it found this when store vector element to new_node->word
Error
This is my code
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstring>
using namespace std;
typedef struct dictionary
{ string word;
int line;
int page;
struct dictionary* next;
} node;
int main()
{
node* Head = NULL;
ifstream file("filetest.txt");
if(file.fail())
cout << "Loi mo file! "<<endl;
string temp;
int cpage = 1,cline = 1;
while(getline(file,temp))
{
stringstream spliter;
spliter << temp;
vector<string> result;
while(!spliter.eof())
{
string str;
spliter >> str;
result.push_back(str);
}
for(size_t i = 0;i != result.size();i++)
{
if(Find(Head,result[i])==0)
{
Append(&Head,result[i],cline,cpage);
}
}
cline++;
if(cline == 25)
cpage++;
}
file.close();
;
ofstream outfile("test.txt");
node* p = Head;
while(p != NULL)
{
outfile << p->word <<","<<p->page<<"-"<<p->line<<endl;
p=p->next;
}
}
Append( add member to linked list)
void Append(node** First,string &newstr,int newl,int newp)
{
node* new_node = (node*)malloc(sizeof(node));
node* last = *First;
new_node->word=newstr;
new_node->line=newl;
new_node->page=newp;
new_node->next = 0;
if(*First == 0)
{
*First = new_node;
return;
}
while(last->next != 0)
{
last = last->next;
}
last->next = new_node;
return;
}
Find( check if a word is new or not)
int Find(node* head,string &tumoi)
{
node* current = head;
while(current != 0)
{
if(current->word == tumoi)
return 1;
current = current->next;
}
return 0;
}
You should not use malloc with C++ types. It does not properly initialize them.
Your node struct contains a std::string which needs to have its constructor called to be properly initialized.
When you do this
node* new_node = (node*)malloc(sizeof(node));
new_node->word=newstr;
The new_node->word is not initialized and can contain pointers to nowhere.
You should do
node* new_node = new node();
new_node->word=newstr;
instead.

Singly Linked List assign issue (nullptr)

what's wrong with this simple Linked List ?
// linked_lst1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class Node
{
int data;
Node* next;
friend class LinkedList;
};
class LinkedList
{
private:
Node* s;
public:
LinkedList() : s(NULL)
{};
void add(int x)
{
Node* s1 = new Node();
s1 = s;
if (!s1)
{
s->data = x;
return;
}
while (s1->next)
s1 = s1->next;
Node* temp = new Node;
temp->data = x;
s1->next = temp;
temp->next = NULL;
}
void showList()
{
Node* s1 = new Node;
s1 = s;
while (s1)
{
cout << s1->data << " ";
s1 = s1->next;
}
}
};
Here is main section :
int main()
{
LinkedList list;
list.add(3);
list.showList();
return 0;
}
I think there is an assign issue in s->data = x;, but I don't know how to solve it...
Notice that this is just an educational simple code and I don't want to use templates etc.
I think, I got what was wrong.
You make a new node and then immediately overwrite s1 to point to whatever s was pointing to -- you lose all access to the newly created node.

No errors, but output is not right. Pointer issue possibly

Im reading strings from a file and inserting them into a LinkedList in alphabetical order (C++). I have made the node and list classes but something is wrong with them. I have done this in Java and it works 100% without any problems. This leads me to believe that I must have messed up with pointers somewhere. This is also only the second time I use the '->' symbol. So I may have used it erroneously somewhere. Some helpful tips are appreciated. Thanks in advance.
//NODE CLASS
#include <string>
#include <iostream>
using namespace std;
class Node {
string word;
int count;
Node* next;
public:
Node (string aWord) {
word = aWord;
count = 1;
}
Node (string aWord, Node* theNext) {
word = aWord;
next = theNext;
}
void increaseCount() {
count++;
}
string getWord() {
return word;
}
int getCount() {
return count;
}
Node* getNext() {
return next;
}
void setNext(Node* theNext) {
next = theNext;
}
};
//LIST CLASS
#include<iostream>
using namespace std;
class LinkedList {
Node* head;
public:
LinkedList() {
head = new Node(" ");
}
void insert(string word) {
Node* temp = head;
Node* previous = head;
while (temp != NULL && temp->getWord() < word) {
previous = temp;
temp = temp->getNext();
}
if (temp == NULL) {
Node* node= new Node(word);
previous-> setNext(node);
} else {
if (temp-> getWord() == word) {
temp->increaseCount();
} else if (temp->getWord() > word) {
Node* node = new Node(word, temp);
previous->setNext(node);
}
}
}
void print() {
Node* temp = head->getNext();
while (temp != NULL) {
cout<< temp;
temp=temp->getNext();
}
}
};
//MAIN
#include <iostream>
#include <iostream>
#include <fstream>
#include "Node.h"
#include "LinkedList.h"
using namespace std;
int main(int argc, const char * argv[]) {
ifstream inFile("WordsStatisticData1.txt");
if (!inFile.is_open())
cout<< "Could not open the file"<< endl;
else {
string readData;
LinkedList list = *new LinkedList(); //Probably a problem here
while (inFile >> readData) {
list.insert(readData);
inFile.close();
list.print();
}
}
}
I may be declaring things totally wrong within the main as well.
My output looks like an address '0x' with random characters.
You're printing out temp where temp is a Node*. A pointer is just the address of an object, hence why you're getting an address in your output.
Seems like you want to get the string that the Node contains. If so, you want:
cout << temp->getWord();
Another problem you have is that you close your file and print the list inside the loop, which means it'll happen right after the first word has been read. You probably mean to do this after the loop, so all of the words in the file can be read.
You also have problem with the line you marked as such. Using the new keyword will dynamically allocate an object. These objects need to be later deleted with delete. However, you dereference the dynamically allocated object (with *) and copy it, losing any reference to the dynamically allocated object - this is a classic memory leak. The dynamic allocation here is completely unnecessary. Just do:
LinkedList list;