Hashmap initializing dynamic array of nodes with nullptr c++ - c++

I'm having trouble correctly initializing a dynamic array of nodes with nullptr.
HashMap::HashMap(int size)
{
this->sizeOfArray = size;
this->hashArray = new Node*[this->sizeOfArray];
for (int i = 0; i < this->sizeOfArray; i++)
{
hashArray[i] = nullptr;
}
}
this is what my 'hashArray' looks like in the header.
Node **hashArray;
the forloop completes all 500 loops but when I am looking at the data in the array, I can only see the first element before I get 'Unable to read memory'.
Here is an image of what I mean
https://ibb.co/d0GLw9
Here is what Node looks like
Node()
{
value = 0;
}
Node(std::string input)
{
key = input;
value = 1;
next = nullptr;
}
Node(std::string input, int count)
{
key = input;
this->value = count;
next = nullptr;
}
Node(std::string input, int count, Node *next)
{
key = input;
this->value = count;
this->next = next;
}
Node *next;
std::string key;
unsigned int value;
I suspect this problem is contributing to me not being able to add any new nodes to the hashArray later on.

All of your 500 Node pointers are NULL, however the type of the hashArray is Node **, that's why the debugger shows you only one element as if it's a pointer to one Node pointer. In other words, since your array is dynamic, the debugger doesn't know how many elements to show.
The error you're getting is in regard to viewing the contents of the first Node whose pointer is NULL, which is naturally can't be read.

Related

Why am I getting this runtime error: member access within null pointer of type 'Solution::node' (solution.cpp)

I was solving a question on leetcode 1409. Queries on a Permutation With Key, but I am getting this runtime error I don't know why. I am unable to debug this error.
Problem Statement:Given the array queries of positive integers between 1 and m, you have to process all queries[i] (from i=0 to i=queries.length-1) according to the following rules:
In the beginning, you have the permutation P=[1,2,3,...,m].
For the current i, find the position of queries[i] in the permutation P (indexing from 0) and then move this at the beginning of the permutation P. Notice that the position of queries[i] in P is the result for queries[i].
Return an array containing the result for the given queries.
My approach: I created a linkedlist to store the integers form 1 to m.
Then according to each query, I pass it to a function getpos() which returns the position of that query in the list and then updates it as per the directions given in problem statement.
This return value is then added to a result vector which is supposed to be the final answer after all queries are processed.
I have added comments to better understand my code
class Solution {
public:
struct node {
int data;
node* next = NULL;
};
node* addnode(node* head, int data) {
if(head == NULL) {
head = new node;
head->data = data;
}
else {
node* temp = head;
while(temp->next != NULL) { temp = temp->next; }
temp->data = data;
}
return head;
}
int getpos(node** head, int data) { //To get position of given query
int count = 0;
node* temp = *head;
node* prev;
while(temp->data != data) { //runtime error:member access within null pointer of type 'Solution::node' (solution.cpp); SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:32:21
prev = temp;
temp = temp->next;
count++;
}
prev->next = temp->next; //searched node deleted
temp->next = *head; //add the searched node to beginning of the list
*head = temp; //udapate head
return count; //we have position stored in count;
}
vector<int> processQueries(vector<int>& queries, int m) {
node* head = NULL;
for(int i=0;i<m;i++) { head = addnode(head,i+1); }
int n = queries.size();
vector<int> result;
for(int i=0;i<n;i++) { result.push_back(getpos(&head,queries[i])); }
return result;
}
};
Please debug and explain the cause of the error. I face many runtime errors which I fail to debug.
Your add_node function is bugged. Just take a deep breath and look at the code. add_node should allocate a node using new every time it is called. Ask yourself how many times and under what circumstances your version allocates a new node?
I'm sure you can see that your code only allocates a new node when head equals NULL, therefore it must be bugged.
Incidentally if you wanted a linked list why didn't you use std::list? You would have avoided the mistake you made.

Problem with insertion at a certain point in linked list with inherited functions in C++

I am trying to insert a number at a certain position in a linked list. However I cannot access the next pointer normally because it is a private member, and have to use a getNext function. I am unsure of how to assign next pointers with this function as it gives me errors.
#pragma once
class IntListNode {
public:
IntListNode(int e, IntListNode *nextptr):
elem(e), next(nextptr) { }
int &getElement() {return elem;}
IntListNode *getNext() {return next;}
private:
int elem; // linked list element value
IntListNode *next; // next item in the list
};
This is the code I have attempted but I keep receiving errors.
void IntegerList::AddAtPosition(int num, int placement)
{
IntListNode* temp1 = head;
IntListNode* temp2 = head;
temp1->getElement() = num;
if (placement == 0)
{
head = temp1;
}
else
{
for (int i = 0; i < placement - 2; i++)
{
temp2 = temp2->getNext();
}
temp1->getNext() = temp2->getNext();
temp2->getNext() = temp1;
//THe Lines getting errors
}
}
Error message:
E0137 "expression must be a modifiable lvalue"
Change your getNext() method to this: IntListNode*& getNext() {return next;}.
The IntListNode *getNext() version will return the value of next member but not it's address so this line is not modifiable: tempX->getNext() = tempY;
Edit
Based on the restrictions/conditions mentioned by the OP, I can think of only way to this is:
*temp1 = IntListNode(temp1->getElement(), temp2->getNext());
*temp2 = IntListNode(temp2->getElement(), temp1);

Delete entry from a list in ISO C89

I have to develop a library function for a phonebook which uses lists.
This function has to delete the nth entry from the list.
It is a linked list,and the entries are structs which contain the strings name,srnm,nmbr,addr,the int number and the next pointer.
Every time I call the function,however,VS gives me lot of exceptions and triggered breakpoints,and says I've corrupted the heap.
I have no idea of where I could have made this mistake that corrupts the heap.Please Help.
Here's what I've done so far :
typedef struct list {
char name[20];
char srnm[20];
char nmbr[20];
char addr[20];
unsigned int number;/*Contact index*/
struct list *next;
} entry;
static unsigned int count = 0;
static entry *hol = NULL;/*pointer to the head of the list*/
int delete_contact(unsigned int n) {
int i=0,k=0;
if(n>count) return -1;
hol[n-1].next = hol[n-1].next->next;
for(i=n;i<count;i++) {
hol[i]=hol[i+1];
}
for(i=n;i<count;i++)
hol[i].number = hol[i].number-1; /*Updates the contact index*/
count--; /*Updates the global variable that gives the number of contacts */
return 0;
}
Suggested solution
hol is a pointer, so, hol[n-1] etc. might not refer to a entry struct in memory, consider when n = 0. Either way, this is not how you should access different entries in your list structure.
For a singly-linked list you have to consider 3 cases,
If n = 0 (i.e. the first entry) is being deleted
If the entry to be deleted is somewhere inside the list
If the entry is the last entry in the list.
It is my understanding that number is the index of the list entry and that you've used dynamic memory allocation for the list entries. Furthermore, since you appear to be using the C89 standard (which does not allow loop variable initialization) I have adapted the code below as best as I could to C89, but I do not use that standard myself:
int delete_contact(unsigned int n) {
int i = 0;
int k = 0;
// Check if the index refers to an element not included in the list
if (n > count) { return -1; }
entry* tmp = hol;
if (n == count - 1) {
// Iterate to the last entry
while (tmp->next) {
tmp = tmp->next;
}
free(tmp); // Free the list entry
// Decrement the global counter keeping track of the
// amount of list elements
count--;
// No need to edit the contact indexes
return;
}
entry* remaining_list = hol;
if (n == 0) {
// Free the head of the list
hol = hol->next;
remaining_list = hol;
free(tmp); // tmp points to the head of the list already
} else {
// The list entry is somewhere inside the list
int idx = 0;
// Iterate until tmp points to the n-1:th entry
while (idx < n - 1) {
tmp = tmp->next;
idx++;
}
entry *to_be_freed = tmp->next; // n:th entry
tmp->next = tmp->next->next;
remaining_list = tmp->next;
free(to_be_freed);
}
// Decrement the contact index on all the remaining entries
while (remaining_list) {
remaining_list->number--;
remaining_list = remaining_list->next;
}
// Decrement the global counter keeping track of the
// amount of list elements
count--;
return 0;
}
Tips
You'd be better served by creating a more expressive list interface, possibly one that isn't bound to the values stored inside it. That way you could create a
list_size()
function and remove the global counter.
Here is a little something to get you started:
typedef struct node {
void* value;
struct node* next;
} node;
typedef struct list {
node* head;
node* tail;
size_t len;
} list;
Reference material
Linked list basics
Linked list exercises

How to print the Data part of Linkedlist

Basically I want to print the data part of the Linked list which is basically an Integer pointer and I am assigning it an array at the time of creation, I want to print all the values of it how to do so ???
Thank you.
Here is my code
using namespace std;
struct Node{
Node *next;
int *data;
};
class DataLine{
private:
Node *first;
public:
DataLine(){
first=NULL;
}
void create_list(){
Node *temp=new Node;
int i=2;
int dat[5]={12,13,14,13,16};
temp->data=dat;
temp->next=NULL;
if(first==NULL){
//cout<<"hello 1"<<endl;
first=temp;
}
else{
Node *curr=first; //We are now doing trevercing so we are assigning the first to the node because we donot want to move the first bacuse link break if we move the first
while(curr->next!=NULL) //searching end of list
{
curr=curr->next; //Moving to the next node
}
curr->next=temp; //insert node
temp=NULL; //Making the temp enpty to use it for the new purpose
//delete temp;
}
}
void print_list()
{
Node *prnt=first; //We are now again want trevercing so we agin run the node by the new node
while(prnt!=NULL) //Checking the loop will run till it get the null in the node means its address part and data part both are nUll
{
for(int i=0;i<5;i++)
cout<<" ***** The "<<" node is "<<*(prnt->data+i)<<endl; //Printing the data
prnt=prnt->next; //Moving to the next node
}
}
};
int main(){
DataLine dl;
dl.create_list();
dl.print_list();
_getch();
return 0;
}
The idea of your void print_list(void) is correct but you can make it much cleaner, note however I changed your output to print a single node per line (change that back if you want). The structure of a for loop seems, to me, perfect for linked lists and keeps the linked list code our of the body of the loop.
void print_list(void) const
{
for (Node* p = first; p != NULL; p = p->next)
{
for (int i = 0; i < Node::unLength; ++i) std::cout << p->data[i] << ", ";
std::cout << std::endl;
}
}
However, as pointed out in some of the comments, there are other problems in your create list code. The way I would suggest to fix these (for this program) would be to redefine your structure to always hold a fixed number of integers.
struct Node
{
enum { unLength = 5 };
Node* next;
int data[unLength];
};
I have also added here a constant for the length of the array, since its bad practice to have magic numbers floating around your code, what happens if you mistype one of them?
Now in your void create_list() you can go:
void create_list()
{
Node* temp = new Node;
// Set the next node of temp
temp->next = NULL;
// Add some data to temp (we can't just assign the data pointer in C/C++)
int data[Node::unLength] = {0, 1, 2, 3, 4};
for (int i = 0; i < Node::unLength; ++i) temp->data[i] = data[i];
Node *p = first;
while (p != NULL) p = p->next;
p->next = temp;
}
There is no point setting temp to NULL since temp is deleted straight after the function returns. In your previous code you set the pointer in Node to data (temp->data=dat;, this doesn't work either since dat was deleted as soon as the function returned, you need to instead allocate memory and copy the values from dat which is what the for loop in the above code does.
For you class constructor (and destructor) I would suggest:
class DataLine
{
private:
Node* first;
public:
DataLine(void) : first(NULL) {}
~DataLine(void)
{
while (first != NULL)
{
Node *temp = first->next;
delete first;
first = temp;
}
}
You had the right idea, but there are a few subtle things about C/C++ that aren't obvious in higher level languages, such as copying arrays and the scope of variables.
If you are using C++ however, I would really suggest not worrying about linked lists, just create a std::vector, in C++ 11 something like the following might work (untested):
#include <vector>
#include <array>
int main(int argc, char** argv)
{
std::vector< std::array<int, 5> > myData;
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
myData.push_back({0, 1, 2, 3, 4});
for (const auto& i : myData)
{
for (int j : i) std::cout << j << ", ";
std::cout << std::endl;
}
return 0;
}

C++ Access Violation With Hash Tables and Linked Lists

So I've been trying to create a class that handles 1000 linked lists, and initially declares pointers to them.
This is the code that deals directly with my issues:
struct node
{
char name[40];
char numb[12];
node * next;
};
class hashTable
{
public:
//Creates a table of 1000 pointers to linked-list nodes
node * table[1000];
//Functions
void addNode(char name[40], char numb[12])
{
node * temp; //Initializes temp node as pointer
temp = new node; //Points temp node to a new node
int hash = h(g(name)); //The hash of the key (name) used to check nodes
temp = table[hash]; //sets the temporary node to the first node of the list
while (temp->next != 0)
{
//...
Right at the while loop is where I get the error "Access violation reading location 0xcccccd00"
I'm not sure why it can't access the table member, unless perhaps it is because these values have not been initialized or anything?
You're likely not doing two things. First make sure your hash table is properly initialized to contain all-NULL-pointers. Secondly, make sure any pointer retrieved from the hash table is valid prior to dereferencing it:
For the first issue:
hashTable::hashTable() : table()
{
}
Also, you want to make sure this thing cleans up properly
hashTable::~hashTable()
{
for (size_t i=0;i<sizeof(table)/sizeof(table[0]); ++i)
{
node *temp = table[i];
while (temp)
{
node *victim = temp;
temp = temp->next;
delete victim;
}
}
}
For the second issue:
void addNode(const char *name, const char *numb)
{
int hash = h(g(name)); //The hash of the key (name) used to check nodes
node *temp = table[hash]; //sets the temporary node to the first node of the list
if (temp)
{
// preexisting entry. walk that list looking for matching key.
node **pp = &temp->next;
while (temp)
{
if (0 == strcmp(temp->name, name))
break;
pp = &temp->next;
temp = temp->next;
}
// link to last node if not found in list
if (!temp)
*pp = new node(name, numb);
}
else
{ // no prior entry. create a new one and store it at table[hash].
table[hash] = new node(name, numb);
}
}
Note: the above code assumes the node class is implemented as
struct node
{
char name[40];
char numb[12];
node * next;
node(const char* name_, const char *numb_)
: next()
{
strncpy(name, name_, sizeof(name)/sizeof(name[0])-1);
name[ sizeof(name)/sizeof(name[0])-1 ] = 0;
strncpy(numb, numb_, sizeof(numb)/sizeof(numb[0])-1);
numb[ sizeof(numb)/sizeof(numb[0])-1 ] = 0;
}
};
Personally, I'd use std::string
If the value of hash is greater than (or equal to) 1000, temp will point to an invalid area.
And you are leaking the memory allocated by new node since you are overwriting the temp variable.