First of all, apologies if this is a duplicate question. I'm just learning C++ and probably don't know the correct search terms to find what I'm sure has already been asked.
Anyways, I'm teaching myself C++ by working through the 30 days of code on HackerRank. However, I've hit a roadblock that I can't seem to solve when asked to implement an insert method for a LinkedList. Conceptually, I know what needs to be done, but syntactically I'm running into an issue.
Below is my code, with debugging printouts included. What seems to be happening is that new_node keeps getting put in the same location in memory, regardless of which loop iteration its on. How do I ensure this gets a new place in memory? I seem to get the same behavior regardless of if I declare new_node as static or not.
Here's the code:
#include <iostream>
#include <cstddef>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int d){
data=d;
next=NULL;
}
};
class Solution{
public:
/// ----- MY CODE BEGINS HERE:
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
static Node new_node = Node(data);
curr->next = &new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
static Node new_head = Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head.next << endl;
return &new_head;
}
}
// ------- MY CODE ENDS HERE
void display(Node *head)
{
Node *start=head;
while(start)
{
cout<<start->data<<" ";
start=start->next;
}
}
};
int main()
{
Node* head=NULL;
Solution mylist;
int T,data;
cin>>T;
while(T-->0){
cin>>data;
head=mylist.insert(head,data);
}
mylist.display(head);
}
When I run this with the sample input of (4, 2, 3, 4, 1), I get the following:
----------
2
*** Adding 2 at 0x6022e0 and next points to: 0
----------
3
3,0: 0x6022e0,0,2
*** Adding 3 at 0x7fff3ddc1d80 and next points to: 0
----------
4
4,0: 0x6022e0,0x7fff3ddc1d80,2
4,1: 0x7fff3ddc1d80,0,3
*** Adding 4 at 0x7fff3ddc1d80 and next points to: 0x7fff3ddc1d80
----------
1
1,0: 0x6022e0,0x7fff3ddc1d80,2
1,1: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,2: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,3: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,4: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,5: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
and this continues until a Segmentation Fault ebcause its caught in an infinite loop...
Any ideas why new_node keeps getting placed in the same memory location (with or without the static)? Is this not even the main issue and I'm completely missing the point? Thanks in advance!
-- C++ neophyte.
EDIT: The suggested duplicate doesn't quite address the question here. My trouble was not understanding the difference between pointers and references, but rather the difference between:
Node node_1 = Node(data);
static node_2 = Node(data);
node_3 = new Node(data);
As I was unaware of the new operator at the time of writing the question (obviously!), I did not know to (a) search for this or (b) include this term in the title. The title has been edited for clarity, and this edit has been included for future readers.
When you declare a variable static, there's only one copy of that variable. It gets created the first time you execute the declaration, and future calls to the function reuse the same data. So every time you use new_node, it's the same node.
You need to allocate dynamic data with the new operator. As the operator name implies, this creates a new object every time you use it. When you add a remove() operation to the class, it will use delete to free the memory.
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
Node *new_node = new Node(data);
curr->next = new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
Node *new_head = new Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head->next << endl;
return new_head;
}
}
you use a static variables. These are created only once, and are the same for every function call!
your intend is to create a new Node always, so these variables are not static!
try it out with
Node* new_head = new Node(data);
return new_head;
// as well as
Node* new_node = new Node(data);
curr->next = new_node;
All nodes must be create on the free store (with new), otherwise they get cleaned up when the function ends.
This means you are always referencing to not existing variables, which is a memory corruption. You must as well provide a destructor to delete the new'd nodes.
For more information read about the lifespan of variables.
Further notes:
use nullptr
std::list, or std::linked_list are the containers for lists (i know, you want to learn, but take a look at them)
your class is all public -> you can use a struct, since its the same, but default public for access specifiers.
use unique_ptr for the ownership (this is kinda advanced, but use it early)
Related
I am trying to make a mask delivery, ordering service code.
The function order will add a new order to order list.
The function output will output the list from newest to oldest order.
The function deliver removes the oldest order.
The following is the code:
#include <iostream>
#include <string>
using namespace std;
struct Mask {
string type;
string customer;
Mask *next;
};
void order(Mask *&head, string type, string customer){
cout << "Ordering " << type << " for " << customer << endl;
Mask *oldHead = head;
head = new Mask;
head->type = type;
head->customer = customer;
head->next = oldHead;
}
void output(Mask *head){
cout << "Outputting order list " << endl;
for (Mask *p = head; p != NULL; p = p->next)
cout << " " << p->type << " for " << p->customer << endl;
}
void deliver(Mask *&head){
if (head->next == NULL){
cout << "Delivering " << head->type;
cout << " for " << head->customer << endl;
delete head;
}
else
deliver(head->next);
}
int main()
{
Mask *head = NULL;
order(head, "3M-N95", "Alice");
order(head, "OxyAir", "Burce");
order(head, "3M-N95", "Cindy");
output(head);
deliver(head);
output(head);
}
Everything runs smoothly, but it says segmentation error(core dumped) at the end. I tried adding this:
if (head->next->next == NULL){
deliver(head->next);
head->next == NULL;
}
But the problem still exists. Any help is appreciated.
I changed deliver to this:
void deliver(Mask *&head){
if (head->next->next == NULL){
cout << "Delivering " << head->next->type;
cout << " for " << head->next->customer << endl;
head->next = head->next->next;
delete head->next;
}
else
deliver(head->next);
}
Apparently, just setting the pointer to NULL does not fix the problem, so I just updated it so that the second last pointer pointed directly to the end.
in "deliver" you force the function to meet the condition if(head->next == NULL)
and then trying to reach head->next->next which is like trying to say null->next (resulting with segmentation fault).
I would recommend traversing to the last "Mask" object with a while loop instead of using all those "if" statements which lead to the same result, or at least change the second if to else if in order to avoid meeting this "if" again.
Below I have attached my code.
In the below code I am building a binary tree with 3 nodes. My program is printing different values at same address when passed in different function.
And there are 4 functions in total
main
build
inorder
print
in the inorder function, I am doing the inorder traversal of the tree and saving that in a vector<Node*> so later I can print the inorder traversal in the "print" function.
I am printing the address and the value at each address in all the 4 functions. Getting different values in some functions at the same address. Why is that so?
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int data;
Node *left;
Node *right;
Node(int val)
{
data = val;
left = right = NULL;
}
};
Node *build()
{
Node *root = new Node(50);
root->left = new Node(45);
root->right = new Node(60);
cout << "In Build Function\n";
cout << root << " " << root->data << endl;
cout << root->left << " " << root->left->data << endl;
cout << root->right << " " << root->right->data << endl;
return root;
}
void inorder(Node *root, vector<Node *> &A)
{
if (root == NULL)
return;
inorder((root)->left, A);
free(root->left);
A.push_back(root);
cout << root << " " << root->data << endl;
inorder(root->right, A);
free(root->right);
}
void print(vector<Node *> &A)
{
cout << "\nprint in function\n";
for (int i = 0; i < A.size(); i++)
cout << A[i] << " " << A[i]->data << endl;
cout << endl;
}
int main()
{
Node *root = build();
cout << "\nIn Main Function\n";
cout << root << " " << root->data << endl;
cout << root->left << " " << root->left->data << endl;
cout << root->right << " " << root->right->data << endl;
vector<Node *> A;
cout << "\nIn inorder Function\n";
inorder(root, A);
print(A);
cout << "\nIn Main Function\n";
cout << root << " " << root->data << endl;
cout << root->left << " " << root->left->data << endl;
cout << root->right << " " << root->right->data << endl;
}
output :
In Build Function
0x1d6bc0 50
0x1d6bd8 45
0x1d6bf0 60
In Main Function
0x1d6bc0 50
0x1d6bd8 45
0x1d6bf0 60
In inorder Function
0x1d6bd8 45
0x1d6bc0 50
0x1d6bf0 60
print in function
0x1d6bd8 1928224
0x1d6bc0 50
0x1d6bf0 60
In Main Function
0x1d6bc0 50
0x1d6bd8 1928224
0x1d6bf0 60
Problem 1
Don't use free to deallocate memory that was allocated with new. Use delete.
Problem 2
You are deallocating memory and then using that memory to access the values. This causes undefined behavior. Don't deallocate until you are done usign the objects.
Use of #include <bits/stdc++.h>
Don't do it. See Why should I not #include <bits/stdc++.h>?.
Commenting out the calls to free removed the problems for me. See https://ideone.com/9gs8NL. However, that leaves the code in an unclean state. You should add code to deallocate the Node objects before returning from main.
this happening because in inorder function you are using free keyword in root->left and root->right due to which the memory is de-allocated but the pointer still points to same location and prints the garbage value there.There for in later functions it prints the garbage value.
BY the way there is no need to use free here.
You are using free where you shouldn't. You allocated the nodes with new and you should use delete to free it (as user4581301 already mentioned). The reason you are getting unrelated numbers is you are freeing the data that you are pointing to before you are done with it. If you remove the free lines (which should be delete) then you will see the expected behavior.
I would recommend using a debugger to see when the data you are pointing to has changed.
I have this linked list adt. The only problem i am having is in this remove function. I tried dry running it but can't figure it out correctly. Please someone explain it
void list::remove(int v)
{
node *temp, *pre;
temp = head;
if(temp->data==v)
{
head = temp->next;
delete temp;
cout << endl << v << "has been deleted" <<endl;
return;
}
pre = temp;
while(temp!=0)
{
if(temp->data==v)
{
pre->next = temp->next;
delete temp;
cout << "\nValue deleted" <<endl;
return;
}
pre = temp;
temp = temp->next;
}
cout << endl << v << "not found" <<endl;
}
int main()
{
list l;
l.insert(8);
l.insert(9);
l.insert(10);
l.display();
cout << "After deleting" <<endl;
l.remove(9);
l.display();
}
The code appears to be correct upon first glance. A quick explanation of it would be:You are making two node pointers, one to point to the current element on the list and one to point to the previous one. First case would be that the element you are trying to delete is in the beginning of the list(so it is the head).In this case you move head to the next element(head=temp->next) and delete the node. The other case would be that the element is somewhere in the list. Using the while loop you scan through the list (pre=temp, temp=temp->next are to move you to the next elements) and using the if condition you check if the element is the one you are looking for.
I'm trying to implement a simple linked list. I need an insert function that takes a value and a node to insert after, so I have this:
#include <iostream>
using namespace std;
typedef struct node node;
struct node {
int data;
node * next = NULL;
};
void insert(node *& head, int value, node *& insert_after_me) {
node n; n.data = value;
node * new_node = &n;
if (insert_after_me == NULL) {
insert_after_me = new_node;
cout << "after assign insert: " << insert_after_me->data << endl;
head = new_node;
cout << "after assign head: " << head->data << endl;
}
}
int main () {
node * head = NULL;
node * new_node = NULL;
insert(head, 1, new_node);
cout << head->data << endl;
cout << new_node->data << endl;
cout << head << endl;
cout << new_node << endl;
}
This is obviously an imcomplete implementation, but when I run it I get the following as output:
after assign insert: 1
after assign head: 1
1
1924530936
0x7fff56177928
0x7fff56177928
This tells me in main, head and new_node are pointing to the same thing, yet they have different values stored in data. Why?
Note: Though it seems to me a nonsensical implementation to make insert take a node to insert after and then change that node, that's a requirement of the project. I can't change how insert is called.
This is for a lab I have done, which is to create a simple queue using C++.
#include "Task5.h"
#include <iostream>
using namespace std;
void push(const long &i, node* &n) {
if (n == NULL) {
node *ptr = new node;
ptr -> item = i;
ptr -> next = NULL;
n = ptr;
cout << "Created New Node." << endl;
}
else {
node *ptr = n;
cout << "Created Pointer" << endl;
while (ptr -> next != NULL){
cout << "Finding Next..." << endl;
ptr = ptr -> next;
}
cout << "I'm here." << endl;
node *temp = new node;
temp -> item = i;
ptr -> next = temp;
cout << "Node Created." << endl;
}
}
long pop(node* &n) {
if (n == NULL) cout << "HEY!!! Can't pop an empty queue." << endl;
else {
long val;
node *ptr = n;
n = n -> next;
val = ptr -> item;
delete ptr;
return val;
}
}
int main() {
node *head = NULL;
push(13,head);
push(10,head);
push(18,head);
push(22,head);
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
}
This is giving the following output:
Created New Node.
Created Pointer
I'm Here.
Node Created.
Created Pointer
Finding Next...
I'm here.
Node Created.
Created Pointer
Finding Next...
Finding Next...
I'm here.
Node Created.
13
10
18
22
HEY!!! Can't pop an empty queue.
6296192
HEY!!! Can't pop an empty queue.
6296192
So the end result is that the code works, HOWEVER it outputs 6296192 randomly. I thought maybe I misspell something or cout is converting endl; to hex. My lab instructor also has no idea what's happening. Can someone tell me what is happening? If it helps, I am running this code via Linux-run terminal.
Thanks in advance.
In your function:
long pop(node* &n) {
you don't return anything in case of n == NULL is true. So this is UB, and might also cause such random values in output.
I'd suggest using the debugger with a breakpoint on the first cout << pop(head) << endl; and watch the value returned from pop each time.
Also the compiler is probably giving you a warning about the cause of the issue, always pay attention to the warnings it usually means something unintended will happen.
The cout << pop(head) << endl; uses the value returned by pop() but in the case of an empty queue there is no value returned, resulting in undefined behavior.