I am getting a segmentation fault in my Separate Chaining Hash Table object.
bool hashTable::addNode(int id, string information){
bool inserted = false;
int position = hash(id);
cout << &hashtable[position]<<endl;
if(hashtable[position]==NULL){
hashtable[position]->data.id = id;
hashtable[position]->data.information = information;
hashtable[position]->next = NULL;
inserted = true;
} else {
Node* current = new Node;
current = hashtable[position];
while(current!=NULL){
if(id < hashtable[position]->data.id){
current->data.id = id;
current->data.information = information;
current->next = hashtable[position];
hashtable[position] = current;
inserted = true;
} else if(id < current->data.id){
current->data.id = id;
current->data.information = information;
current->next = hashtable[position]->next;
hashtable[position]->next = current;
inserted = true;
} else if(current->next==NULL){
Node *temp;
temp->next = NULL;
temp->data.id = id;
temp->data.information = information;
current->next = temp;
inserted = true;
}
current = current->next;
}
}
return inserted;
}
Essentially, I have an array of head pointers to handle the separate chaining, but the segmentation fault in addNode is messing me up. To be clear, I am calling a public AddEntry first which calls the AddNode for each individual LinkedList in the array.
#ifndef HASH_H
#define HASH_H
#include <iostream>
#include <string>
#include "data.h"
using std::string;
using std::cout;
using std::endl;
#define SIZE 15
class hashTable{
public:
hashTable();
~hashTable();
bool addEntry(int id, string information);
string getEntry(int id);
bool removeEntry(int id);
int getCount();
void displayTable();
private:
bool removeNode(int id, int position);
bool addNode(int id, string information);
int count = 0;
Node* hashtable = new Node[SIZE]; //array of head pointers
int hash(int id);
};
#endif
Sorry if I didn't word this the best this is my first time on Stack Overflow.
There are a few spots in your code where it looks like you're using the address-of operator & incorrectly. Let's start with this one:
if (&hashtable[position] == NULL) {
...
}
I completely see what you're trying to do here - you're trying to say "if the slot at index position holds a null pointer." However, that's not what this code actually does. This says "if the location in memory where hashtable[position] exists is itself a null pointer." That's not possible - hashtable[position] refers to a slot in an array - so this if statement never fires.
It might be helpful to draw pictures here to get a better sense of what's going on. For example, suppose you have an empty hash table, as shown here:
+-------+ +------+------+------+------+ +------+
| |------>| null | null | null | null | ... | null |
+-------+ +------+------+------+------+ +------+
hashtable
Here, hashtable[position] refers to the pointer at index position in the array pointed at by hashtable. With an empty hash table, hashtable[position] will evaluate to NULL because that's the contents of the pointer at that slot. On the other hand, &hashtable[position] refers to something like this:
&hashtable[position]
+-------+
| |
+-------+
|
v
+-------+ +------+------+------+------+ +------+
| |------>| null | null | null | null | ... | null |
+-------+ +------+------+------+------+ +------+
hashtable
Here, &hashtable[position] points to one of the pointers in the array. And while the pointer &hashtable[position] is pointing at something that is a null pointer, it itself is not a null pointer, since it's pointing to a valid object in memory.
Changing the code to read
if (hashtable[position] == NULL) {
...
}
correctly expresses the idea of "if the entry at index position within the hashtable array isn't a null pointer."
There are similar errors in your code at a few other points. Read over what you have with an eye toward the following question: do I want the pointer stored in the array at some index, or do I want the location in memory where that pointer happens to live?
Related
The problem with the code is that I cant assign new nodes without affecting previously assigned nodes while using switch. It keeps reassigning with the latest given node inputs
linked list structure node the structure for linked list is assigned as follows
typedef struct stringData {
char *s;
struct stringData *next;
} Node;
create insert and print linked list Below is the code for creating and printing linked list
Node *createNode(char *s) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->s = s;
newNode->next = NULL;
return newNode;
}
void insert(Node **link, Node *newNode) {
newNode->next = *link;
*link = newNode;
}
void printList(Node *head) {
while (head != NULL) {
printf("%s\n", head->s);
head = head->next;
}
}
main when am compiling I cant assign linked list in run time ,that is when I have to assign the more than one node while in switch .How can I remove this mistake?
Node *head = NULL;
Node *tail = NULL;
Node *n;
char message_arr[10] = {};
int choice =0;
int len;
char str[20];
n = createNode("Hi");
insert(&head, n);
tail = n;
n = createNode("Hello");
insert(&tail->next, n);
tail = n;
n = createNode("How are you");
insert(&tail->next, n);
tail = n;
int index,ind;
while(choice!=6)
{
printf("\nChoose one option from the list\n");
printf("\n 1. New Message 2. Display all messages 3.Delete all messages\n");
printf("\nEnter your choice?\n");
scanf("\n%d",&choice);
switch(choice)
{
case 1:
printf("\nEnter new message\n");
scanf("%s",message_arr);
n = createNode(message_arr);
insert(&tail->next, n);
tail = n;
break;
case 2:
printf("\nMessages so far:\n\n");
printList(head);
break;
case 3:
printf("\nDeleting all messages.....\n");
free_list(head);
printf("\nMessages deleted.....\n");
break;
case 6:
exit(0);
break;
default:
printf("Please enter valid choice.");
}
}
return(0);
Output
Choose one option from the list 1. New Message 2. Read a Message 3.
Display all messages 4. Delete a message 5.Delete all messages
Enter your choice?
1
Enter new message
morning
Choose one option from the list 1. New Message 2. Read a Message 3.
Display all messages 4. Delete a message 5.Delete all messages
Enter your choice?
1
Enter new message
giya
Choose one option from the list
1. New Message 2. Read a Message 3. Display all messages 4. Delete a
message 5.Delete all messages
Enter your choice?
3
Messages so far:
Hi
Hello
How are you
giya
giya
when I'am calling the switch's first case to enter "new message " twice, then the first message already assigned is also replaced by the second one and is displayed twice as giya giya
> when I'am calling the switch's first case to enter "new message " twice, then the first message already assigned is also replaced by the second one and is displayed twice as giya giya
The reason is that all your newly created nodes s member pointer is pointing to same buffer message_arr. That's why, when displaying them, all of them print the current content of message_arr buffer, which is the last value you have entered.
To understand it better:
First you have entered value morning for newly created node in list:
---------
--->| | |-->NULL
---------
|
| message_arr
| ---------------------
|_________________>|m|o|r|n|i|n|g| | | |
---------------------
then you have entered value giya for newly created node in list:
--------- ---------
--->| | |-->| | |--->NULL
--------- ---------
| |
| | message_arr
| |----> ---------------------
|----------------->|g|i|y|a| | | | | | |
---------------------
To solve this problem, after creating new node, you should allocate memory to s pointer member of Node structure and copy the content of message_arr buffer to the allocated memory. Alternatively, you can use strdup() to resolve this issue:
Node *createNode(char *s) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->s = strdup(s); // <----------
The strdup() function returns a pointer to a new string which is a duplicate of the string passed to it. strdup() allocates memory for the new string and returns its pointer. Make sure to free it using free() once you are done with it. Note that strdup() is not part of the C Standard.
Since, you have added both the C and C++ tag to your question, an important point for this way of initialisation:
char message_arr[10] = {};
Empty initialisers is as per C++ standard but are non-conforming in C, though some C compilers accept it.
In C, you should do:
char message_arr[10] = {0};
which is acceptable in C++ as well.
Follow good programming practice, make sure to check return value of malloc(), scanf() etc. Also, make sure to check whether the user input for choice is valid or not. You should check, what happens when user give input as some character instead of number for choice prompt!
I was going through a tutorial on Linked Lists in C++. I found the following code for the implementation for inserting an element in the Linked List:
/* Given a reference (pointer to pointer) to the head
of a list and an int, appends a new node at the end */
void append(Node** head_ref, int new_data)
{
/* 1. allocate node */
Node* new_node = new Node();
Node *last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be
the last node, so make next of
it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty,
then make the new node as head */
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
return;
}
In step 1, we are declaring a pointer with name new_node and it is pointing to a dynamically created block.
What I couldn't understand is that, if the function is called 4 times then how can a new pointer variable with the same name be created on each call? Since we are using dynamic memory allocation, therefore it won't be dumped when we return from function.
So, how is this piece of code working?
Variable names don't exist at runtime, only at compile-time.
The new_node variable represents a chunk of memory that is local to the append() function. Each time append() is called, a new memory chunk is created when it enters scope, and that chunk is released when it goes out of scope.
Each call to new allocates a new block of dynamic memory. In this case, the memory address of that block is being stored inside that local memory chunk that new_node represents.
append()
+----------------+
| new_node |
| +------------+ | +-------------+
| | 0xABCDABCD |-|------| Node object |
| +------------+ | +-------------+
+----------------+
I was learning about how to use classes and wrote the following code:
#include<iostream>
using namespace std;
class DQNode
{
public:
int data;
DQNode *next, *last;
DQNode(int num, DQNode *n, DQNode *l)
{
data = num;
next = n;
last = l;
}
};
class Deque
{
private:
DQNode *top, *bottom;
int size;
public:
Deque()
{
top = NULL;
bottom = NULL;
size = 0;
}
void addFirst(int inp)
{
DQNode nn(inp, NULL, top);
if(top != NULL)
{
(*top).next = &nn;
}
top = &nn;
if(bottom == NULL)
{
bottom = &nn;
}
}
void PrintAll()
{
cout<<top->data<<endl;
}
};
int main()
{
Deque n;
n.addFirst(5);
cout<<"yo"<<endl;
n.PrintAll();
}
The above code prints "yo" followed by a random integer, interesting part is that on removing cout<<"yo"<<endl;the output is exactly as expected i.e 5.
So, if someone understands what is going wrong please help me.
You have undefined behavior.
This is what happens when you break the rules. When you're lucky, you program crashes with a segmentation fault. Other times, you're unlucky and your program misbehave.
How did you break the rules? Well, you access a dead object.
The source of the problem is happening in your addFirst function. You store a DQNode in your Deque but that node dies.
You see, all local variable with automatic storage have well defined rules for when they live and die. Their lifetime is scope based. It look like this:
// Lifetimes
void addFirst(int inp) // inp
{ // |
DQNode nn(inp, NULL, top); // | nn
if(top != NULL) // | |
{ // | |
(*top).next = &nn; // | +--- <- top->next
} // | |
top = &nn; // | +--- <- top
if(bottom == NULL) // | |
{ // | |
bottom = &nn; // | +--- <- bottom
} // | |
} // | X -- nn dies
// X -- inp dies
Variable with automatic lifetimes are first to live, last to die. There is no exceptions. At the } character at the end of the function, where its scope ends, all local variable are destroyed. nn first, then inp.
At that point, top, bottom or top->next is still pointing to nn, which has been destroyed!
Then, in your PrintAll function is reading through the pointers=, which point to a destroyed variable. At that point, you read whatever is on the stack in that point of the program. A simple call to cout can allocate variables in the places where nn was, and assign whatever needed values. You pointer will still point there, and print garbage.
What can you do about it?
Well, you don't want automatic storage. It doesn't do what you want. You want to take control over the lifetime of the variables and deallocate them when you decide when you don't need them anymore. This is called the free store. You create objects there using dynamic allocation:
void addFirst(int inp)
{
// new will dynamically allocate the object on the free store.
DQNode* nn = new DQNode(inp, NULL, top);
if(top != NULL)
{
(*top).next = nn;
}
top = nn;
if(bottom == NULL)
{
bottom = nn;
}
} // the `nn` pointer dies, but not the object it refers to!
However, your program will never deallocate the variable on its own, you must do it manually or you'll get a memory leak.
~Deque() {
// traverse the tree
// delete all node in the tree
}
Luckily, there is also a tool called a std::unique_ptr which will take care of deleting the allocated object when it dies.
The name unique_ptr comes from unique owner. The ownership of memory can be transferred, but there is always one and only one owner. When the owner dies, it deallocate the object from the free store:
// create a int equal to 1 on the free store using dynamic allocation
std::unique_ptr<int> int_a = std::make_unique<int>(1);
std::unique_ptr<int> int_b = nullptr;
// transfer ownership from int_a to int_b
int_b = std::move(int_a);
// int_a is null
// int_b point to a int equal to 1
// This is disallowed, you cannot have two owner, so no copy
// int_a = int_b;
// can have an observing raw pointer:
int* int_c = int_b.get();
// transfer ownership back
int_a = std::move(int_b);
// at that point int_a is equal to int_c
// int_a is the owner, int_c simply point to the same int.
// int_b is null
// Set the last owner to null:
int_a = nullptr;
// the int has been destroyed because there is no owner left.
// int_a is null, int_b is null
// int_c is a dangling pointer, point to the dead object.
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
struct node {
int data;
node* next;
node* prev;
};
node *sentinel;
int numItem;
void pushBack(int new_data){
sentinel = new node();
while( (sentinel->next)!= NULL)
{
sentinel = sentinel->next;
}
node *toAdd = new node();
toAdd->data = new_data;
sentinel->next = toAdd;
toAdd->next = NULL;
numItem++;
}
void print(){
}
int main(){
pushBack(1);
pushBack(2);
pushBack(3);
pushBack(4);
pushBack(5);
print();
return 0;
}
I am implementing a pushBack() method which is to add items to the end of the linkedlist.
How to implement print() method in order to print out elements in linkedList?
My problem is I don't know how to start at the first index of linkedList.
Your problem is actually a lot deeper than just your print() function: your push_back() doesn't work the way you want it to work as far as I can tell! I strongly recommend you take a piece of paper and draw your list structure with the individual elements. Initially, you'd have an empty list:
=========
| head -+-->nil
=========
When inserting one element, you need to arrive at this structure, instead:
========= ===========
| head -+------>| data=1 |
========= | next --+-->nil
nil<-+- prev |
===========
Doing so only requires to create a new node and modify the head. Adding more nodes is a bit more interesting as you either need to also remember the last node or you need to walk the list to add something to its end. The picture after adding three nodes with data 1, 2, and 3 in this order should look something like this:
========= =========== =========== ===========
| head -+------>| data=1 |<-\/-->| data=2 |<-\/-->| data=3 |
========= | next --+--/\ | next --+--/\ | next --+->nil
nil<-+- prev | \--+- prev | \--+- prev |
=========== =========== ===========
Coding this up is, obviously, done in push_back() but your current push_back() wouldn't yield this structure. Once you have this structure, you'd just start your print() with the head and print the respective data fields.
Trying to implement a function in my linkedlist class that will return total amount of data stored within the list. i.e. linkedlist of 5, 10, 20 total would return 35.
My node class contains the getNextPtr and getData methods.
I implement a new Node and call it currentPtr and make it point to headPtr.
On compile i get: "36-request for member getNextPtr in currentPtr which is of non class type"
It's the same for 38 and 40, with 38 being the getData in currentPtr.
Not quite sure what I'm missing...
int LinkedList::getTotal()
{
int total = 0;
Node *currentPtr = headPtr;
(36) while(currentPtr.getNextPtr() != NULL)
{
(38) total += currentPtr.getData();
(40) currentPtr = currentPtr.getNextPtr();
}
return total;
}
The idea is to travel through the linked list until it reaches tailptr which will point to null, adding whatever data it encounter in to total.
Hope that makes some sense, thanks in advance :)
If you want to dereference a pointer you need to use ->, not .
e.g. your code becomes:
while(currentPtr != NULL)
{
total += currentPtr->getData();
currentPtr = currentPtr->getNextPtr();
}
I also find it more natural to write while(currentPtr) (i.e. 'while I have a valid pointer') instead of explicitly testing for NULL.
First of all, you should use -> instead of .
Second, your code has a minor bug. If you reach the last node, it's next is NULL, but that node still has data which you are ignoring. (Because you don't go in the while if ptr->next == NULL. That said, you should change the condition to ptr != NULL)
I suggest one of these codes:
If you have a dummy node in the beginning of the list (dummy node is a node with no data, just in the beginning of the list)
int LinkedList::getTotal()
{
int total = 0;
Node *currentPtr = headPtr->getNextPrt();
while (currentPtr != NULL) // or simply while (currentPtr)
{
total += currentPtr->getData();
currentPtr = currentPtr->getNextPtr();
}
return total;
}
And if you don't have a dummy node, it's just a little different:
int LinkedList::getTotal()
{
int total = 0;
Node *currentPtr = headPtr;
while (currentPtr != NULL) // or simply while (currentPtr)
{
total += currentPtr->getData();
currentPtr = currentPtr->getNextPtr();
}
return total;
}
currentPtr is a pointer, not a class type (object). Use the -> to access it's members, not ..
while (currentPrt->getNextPtr()) { ...
The code Node *currentPtr... declares a pointer to Node.
When accessing member variables or functions of objects through a pointer -
as is the case here - you need to dereference the pointer.
In your case, this means replacing the . member accessor with a ->
So your code should look like:
while(currentPtr->getNextPtr() != NULL)
{
total += currentPtr->getData();
currentPtr = currentPtr->getNextPtr();
}