C++ Access violation reading location, class this pointer is NULL - c++

I would like to get some help with my current project as I struggle to understand what exactly went wrong in my program. I believe the problem is with my constructor. When I call member function it behaves as I haven't initialized my class members.
Here is my class:
class BankList {
public:
// constructor
BankList();
BankList(int size);
bool isEmpty() const;
int size() const;
void insertBankEntry(std::string account, std::string level, std::string lName, std::string fName, float value); // add a single entry to the list
void insertBankData(std::string fileName); // populate list data from the file
void deleteBankEntry(std::string key); // delete a single entry
void findBankEntry(std::string key) const; // Find and display one element using key
void checkBankEntry(std::string account);
void printHashBankData() const; // List data in hash table sequence
void printHashKeyBankData() const; // List data in key sequence (sorted)
void printTreeBankData() const; // Print indented tree
void writeBankData(); // Write data to a file
void outputHashStatistic() const; // print hash stats
private:
HashList* hashlist;
Tree* tree;
int count; // number of records
int hashSize;
};
Here are my constructors:
BankList::BankList()
{
HashList* hashlist = new HashList();
Tree* tree = new Tree();
count = 0;
hashSize = 0;
}
BankList::BankList(int size)
{
HashList* hashlist = new HashList(size);
Tree* tree = new Tree();
count = 0;
hashSize = size;
}
The function I am trying to call:
void BankList::insertBankEntry(string account, string level, string lName, string fName, float value) // add a single entry to the list
{
BankCustomer* customer = new BankCustomer(account, level, lName, fName, value);
hashlist->insert(customer);
tree->Insert(customer);
count++;
}
However, it does work if I place this code in my function.
if (!tree || !hashlist)
{
tree = new Tree();
hashlist = new HashList();
}
main:
int size = getSize();
BankList* list = new BankList(size);
list->insertBankEntry("123412341234", "Gold", "Jonhson", "Steve", 1234.45);
Thanks in advance!

In the constructors you are hiding the member variables (by declaring variables with the same name as the members) hence your member variables remain un-initialized
HashList* hashlist = new HashList(); // hiding the member variable this->hashlist
Tree* tree = new Tree(); // hiding the member variable this->tree
Just use
hashlist = new HashList();
tree = new Tree();
inside the constructors.

Related

Issue regarding dynamically created object in c++

I was asked to make a project on the phonebook using BST in c++. So I have made class "BstDetails" which has all the relevant information needed and made another class "PhoneBook" where I implement the insert, deletion, etc functions. "Phonebook" is actually also the friend class of "BstDetails". So in class "PhoneBook", I call the function "create" to make a new entry in the phonebook. I dynamically create object but I am confused about how will I actually assign input data to entries of the object. Can someone guide me?
#include<iostream>
#include<string>
using namespace std;
class BstDetails{
private:
string name;
long number;
BstDetails* left;
BstDetails* right;
friend class PhoneBook;
public:
BstDetails(){
left=NULL;
right=NULL;
}
};
class PhoneBook{
private:
BstDetails* root;
public:
PhoneBook(){
root=NULL;
}
void create(BstDetails name , BstDetails number){
if(root==NULL){
BstDetails* data=new BstDetails();
}
}
};
BstDetails constructor should be passed name and number
public:
BstDetails(const std::string& n, long num) :
left(nullptr),
right(nullptr)
name(n),
number(num)
{
}
Your create method on phonebook takes similar parameters and returns a BstDetails
BstDetails* create(const std::string& name, long number){
return new BstDetails(name, number);
}
So create is just a thin wrapper around new, so you may consider not needing that helper function.
But you could build up a create method such as this the following that creates a node and inserts into the tree
void create(const std::string& name, long number) {
BstDetails* node = new BstDetails(name, number);
BstDetails** ppParent = &root;
BstDetails* parent = *ppParent;
while (parent) {
ppParent = (node->name < parent->name) ? &(parent->left) : &(parent->right);
parent = *ppParent;
}
*ppParent = node;
}

Searching for a node in a tree structure

I need help finding and returning a "node" in a general tree structure. Each node can have more than 2 children so it's not a binary tree. I've been given the following code, this Element object has a list to contain its children, I create one element node pointer in main and using that I have to add and search for children. This is for a school project but I'm not looking for answers (an answer wouldn't hurt). Any advice on how to go about this problem would be much appreciated, thanks!
#pragma once
#include <iostream>
#include <list>
#include <sstream>
using namespace std;
class Element
{
private:
list<Element*> children;
char* _tag;
int _value;
// private methods
public:
// default constructor
Element();
// non-default constructors
Element( char* name); // value is set to -99 if not given
Element(char* name, char* value);
// destructor, must recursively destruct its children
// and release the memory allocated for _tag
~Element();
// ostream operator ( pre-order traversal)
friend ostream& operator << (ostream& out, const Element& E);
void display_xml(); // print out the tree in xml-- format
void addChild( Element* child); // add a child
// Find the first element such that _tag == tag
// returns “this” pointer of this element
Element* findTag( char* tag);
char* getName();
int getValue();
void setName(char* name);
void setValue( int value);
int height(); //b return the height
int size(); // return the size
// other methods
};
this is my best attempt at a solution, it has obvious problems but I'm new to all of this and some explanation on a proper solution, or some sample code would be very helpful!
Element* Element::findTag(char* tag)
{
list<Element*> temp = children;
int s = temp.size();
if(getName() == tag)
{
return this;
}
else
{
for(int i = 0; i < s; i++)
{
findTag((*temp.front()).getName());
temp.pop_front();
}
}
}
I will give you a pseudo-code for searching for a node that has a value val in a tree rooted at root:
find(Node root, val)
if(root.value == val) return root //-- if the recursion found the node we are searching for
else
for every child x of root //-- re-cursing on the children of root
if(find(x, val) != null) return x //-- if one of the calls found the node we are searching for
return null //-- if we did not find the node we want in the sub-tree rooted at root

Issues loading data from a struct into a vector of that struct

The structure is only in one function of my class. I have been debugging and trying everything I can think of. This is for a graph and the function is for a Dijkstra formula. The main issue I get is that my data never gets into my vector (vector open).
Not sure if all the code is need since all the problems happen in this function. Code not currently used (trying to get data into the vector first) has been commented out.
void Graph::Dijkstra(string start, string end, vector<string> &path)
{
struct node
{
string name;
vector<string> connection;
int costSoFar;
node() {name = " "; costSoFar = 0;}
node(node& other)
{
name = other.name;
connection = other.connection;
costSoFar = other.costSoFar;
}
};
vector<string> adjacent;
node startNode;
node current;
node endNode;
vector<node> open;
node closed[MAX_VERTICES];
int small, temp;
bool found = false;
bool inClosed = false;
bool inOpen = false;
string tempVertex;
// starting node is added open list
// startNode = node();
startNode.name = start;
startNode.costSoFar = 0;
//adjacent.push_back(startNode.name);
open.push_back(startNode);
temp = 0; // used a place holder for debugging
//open[0].name = startNode.name;
//open[0].costSoFar = startNode.costSoFar;
}
Any help would be greatly appreciated. I have looked at similar post and attempted their suggestions not sure why my vector will not take input even if I try to directly apply it (see commented code above).
I believe std containers require a copy constructor of the form:
node(const node& other);
That's the form of the default copy constructor if you don't provide one. If do provide a copy constructor then this default one will not be provided for you, so you must define one of that form.
OK I found my own solution. It appears if the structure is created inside the function it cannot access variables the way it needs to. All I did was move the node struct to the outside of the function.
struct node
{
string name;
vector<string> connection;
int costSoFar;
node() {name = " "; costSoFar = 0;}
node(const node& other)
{
name = other.name;
connection = other.connection;
costSoFar = other.costSoFar;
}
};
void Graph::Dijkstra(string start, string end, vector<string> &path)
{ // the other code needed }

Why doesn't a member function change my objects data members?

So I was working on a Project for a computer science class in which we need to create a binary search tree and a corresponding index. We needed to use recursion for this project.
Here is my class implementation:
class Leaf;
struct indexEntries;
class BinarySearchTree{
public:
BinarySearchTree();
~BinarySearchTree();
//Helper Functions for recursive calls
std::string search(std::string);
void BuildTree(std::string);
void inOrderPrint();
private:
//Recursive Functions
void BuildTreeR(int start, int end, Leaf * r);
void inOrderPrint(Leaf * start);
Leaf * search(std::string inquiry, Leaf * start);
void DeallocateTree(Leaf * start);
//Data members
Leaf * root;
std::vector<indexEntries> BSTindex;
};
class Leaf{
public:
Leaf(){
indexID = "";
AccNum = "";
left = NULL;
right = NULL;
};
void set_index(std::string input) {indexID = input;};
void set_AccNum(std::string input) {AccNum = input;};
void set_left(Leaf* newLeft) {left = newLeft;};
void set_right(Leaf* newRight) {right = newRight;};
std::string get_index() {return indexID;};
std::string get_AccNum() {return AccNum;};
Leaf * get_left() {return left;};
Leaf * get_right() {return right;};
private:
std::string indexID;
std::string AccNum;
Leaf * left;
Leaf * right;
};
And when I try to pass Leaf * BinarySearchTree::root to the function void BinarySearchTree::BuildTreeR(int, int, Leaf*) the Leaf that the root is pointing to goes unchanged.
Here is my BuildTreeR() function:
void BinarySearchTree::BuildTreeR(int start, int end, Leaf * parent){
int mid = (start+end)/2;
if(parent == NULL){
parent = new Leaf;
parent->set_index((BSTindex[mid]).indexID);
std::string fullEntry = BSTindex[mid].dataBaseEntry;
parent->set_AccNum(fullEntry.substr(4, 3));
}
if((mid-1)>start){
BuildTreeR(start, mid-1, parent->get_left());
}
if((mid+1)<end){
BuildTreeR(mid+1, end, parent->get_right());
}
}
Using the debugger, I found that the leaf pointed to by Leaf * parent gets changed, but these changes are not carried over to Leaf * BinarySearchTree::root, which stops my program from working.
The debugger says that the value of the data I'm trying to change is
CXX0030: Error: expression cannot be evaluated
Has anyone had this happen before/ know how to fix it?
Your analysis of the problem is exactly right: the pointer is passed by value, so any changes that the function makes to the value of parent are not visible to the caller.
One way to fix the problem is by passing the parent pointer by reference:
void BinarySearchTree::BuildTreeR(int start, int end, Leaf *& parent){
(note the added &).
This way any changes made to parent inside the function will automatically be visible to the caller.

Accessing another classes member

I have the following
class book
{
friend class linkedList;
private:
class student
{
friend class book;
string name;
string number;
string gpa;
student *left;
student *right;
student(string name1, string number1, string gpa1,
student *left1 = NULL, student *right1 = NULL)
{
name = name1;
number = number1;
gpa = gpa1;
left = left1;
right = right1;
}
};
int count;
student *root;
ofstream recordBook;
void _add(student *&, string, string, string);
void _display_book(student *);
bool _search_for_name(string, string&, string&);
bool _edit_entry(string &name, string &edited_number);
void _del_person(student *&, string);
void _save(student *root);
void _del_Tree(student *);
public:
student *currentRoot;
book(void); //Constructor
~book(void);//Destructor
void add(string entry_name, string telephone_number, string gpa);
void display_book();
bool search_for_name(string find_name);
bool edit_entry(string entered_name, string edited_number);
void del_person(string entry_name);
void save();
void load_data();
};
class linkedList
{
friend class book;
int someInt;
struct node
{
public:
string key;
node *link;
node *link2;
} *pointer;
public:
student book::*currentRoot = &book::currentRoot;
linkedList();
~linkedList();
void append(string &str);
void del(string &str);
void display();
};
And I need to make a pointer to "student *currentRoot" from my linkedList classes function.
void linkedList::append(string &str)
{
node *q, *t;
if(pointer == NULL)
{
pointer = new node;
pointer->key = str;
pointer->link = NULL;
pointer->link2 = currentRoot;
someInt += 1;
}
else
{
q = pointer;
while(q->link != NULL)
{
q = q->link;
}
t = new node;
t->key = str;
t->link = NULL;
q->link = t;
someInt += 1;
}
}
In linkedList::append I need to make link2 point to where currentRoot is pointing to. How can I do this? (currentRoot is already set to point at a node in a binary tree. Just gotta get my hash table to also point there.) Thanks for any help.
In comments you said:
In the simplest terms I can think of... I am trying to get a pointer in one class to point to another pointer in a different class.
To answer that question: an inner class has no special relationship to the outer class. For example, a student instance within the book class has no direct way to access its “containing” class.
To do this you would have to pass a pointer to the containing book class into student’s constructor and store it in an instance variable within student.
However, this has a big caveat: when the student instance holds a pointer to the containing book class, that pointer could become invalid. For example, if you are storing book instances in a container like a std::vector, the vector may reallocate memory, invalidating any pointers to books held within the vector.
If you can guarantee that the book will not be stored in an STL container (or anywhere else where it can get moved) then this approach can work.
I would still reconsider the overall approach as having instances store pointers in this way seems fragile. There could be a composition-based approach that would work.
The use of friend is suspect.
Typical object-oriented programming dictates that a linked list container class should only deal with pointers to class objects, and should not know about or deal with anything within the class objects themselves.
If the contained class does need to expose information about itself (i.e., any of its members), it should provide public accessor functions for doing so.
I agree with what others commented about code, so I won't repeat it and just point to invalid syntax in your code:
public:
student book::*currentRoot = &book::currentRoot;
1) the pointer to member is not what you wanted, it should have been:
public:
book::student* book::*currentRoot;
2) you cannot assign to non-static member in class definition. It's only allowed for static members of integral type. But you can assign to it somewhere where you have an object:
void foo()
{
linkedList l;
l.currentRoot = &book::currentRoot;
}