I've been searching for quite a time for an answer, although there were similar problems I still couldn't improve my code so it would work.
I have a simple lifo structure to which I am trying to add one element and print the structure. It prints nothing and when I am debbuging I have this <bad ptr> in char * nameOfVariable.
I would appreciate any help! Here is my source code:
#include<stdio.h>
struct Variable
{
double value;
char *name;
struct Variable *next;
} *variables[80000];
void pop(Variable * head);
void push(Variable * head, char *name, double value);
void show(Variable * head);
int main(){
for(int i = 0; i <80000; i++){
variables[i] = nullptr;
}
char *nameOfVariable = "aaab";
double value = 5;
push(variables[0], nameOfVariable, value );
show(variables[0]);
system("pause");
return 0;
}
void push(Variable * head, char *name, double value)
{
Variable * p ;
p = head;
head = new Variable;
head -> name = name;
head -> value = value;
head -> next = p;
}
void pop(Variable * head)
{
Variable *p;
if (head != NULL)
{
p = head;
head = head -> next;
free(p);
}
}
void show(Variable * head)
{
Variable *p;
p = head;
while (p!=NULL){
printf("%c %f ", p->name, p->value);
p=p->next;
}
printf("\n");
}
PS - I cant use STL so string is not an option :)
You are storing a pointer into a parameter location:
void push(Variable * head, char *name, double value)
{
Variable * p ;
p = head;
head = new Variable;
But the parameter location is local to the function and discarded upon return.
Why do you allocate an array of 80000 elements?
In order to change a location by a function you must either pass the address of that location (a Variable** head in your case) or use a reference.
Much better would be the definition of a class for your stack...
And another one: storing a variable's name as a char* will almost certainly cause trouble later on. Prepare for memory allocation of a char[] and copy the name string.
You do not save the variable you created in push so they all get lost
void push(Variable * head, char *name, double value) {
Variable * p ;
p = head;
head = new Variable;
head -> name = name;
head -> value = value;
head -> next = p;
}
When the function enters head points to null.
in head = new Variable; head now points to a newly created variable on the heap
when the function exits no one keeps track of the newly created variable on the heap. The memory is leaked and there is no way to access that element.
NOTE: You should be aware that Changes you write to head in the function push do not affect variables[0] you passed to the function. variables[0] is pointer to a Variable somewhere. Initially it is nullptr meaning it does not point at anything. head is a copy of variables[0] that means a different pointer that happens to point at the same place in memory (in your case nullptr). That means though that if you change head it points at something else and is no longer pointing to the same object as variables[0]
Suggested Changes:
Make push a function that returns a Variable* to the caller. Which is the new head.
Make push a function that accepts a Variable*& as an in/out parameter and returns the new head in that
(My preference) create a deque struct that holds a Variable* head memeber. pass a deque* to all these functions (push/pop) and in these functions manage the memory
Related
I know that pointers hold the address of a variable. And references point to the same address in the symbol table (that is, the same address of the variable, that they are assigned to).
My question is, how do reference to pointers exactly work. And when do we need them, as opposed to using pointer alone (and not using reference to pointer). It will be helpful if you could explain me the use of reference to pointer, with respect to a singly linked list.
I have the following code that deletes the head pointer of a linked list using a function:
struct Node
{
int data;
Node* next;
};
struct Node* newNode(int data)
{
Node* temp = new Node;
temp->data = data;
temp->next = nullptr;
return temp;
}
Node* deleteHead(Node* &head)
{
if (head)
{
Node* temp = head;
head = head->next;
delete temp;
}
return head;
}
int main()
{
Node* head = newNode(1);
head->next = newNode(6);
head->next->next = newNode(4);
head->next->next->next = newNode(8);
head = deleteHead(head);
Node* temp = head;
while (temp != nullptr)
{
cout << temp->data << " " << endl;
temp = temp->next;
}
return 0;
}
In the deleteHead(Node* &head) function, the function takes the argument, Node* &head. But, the code works fine, even when the argument is Node* head. for what cases do we need to pass Node* & instead of Node* in a linked list?
Following is the deleteHead(Node* &head) function above, which works the same, if we only use Node* head as the argument, instead of Node* &head -
You pass a pointer by reference for the same reason you pass a non-pointer by reference: To let the function modify its value.
Let me use a simpler example
#include <iostream>
void foo(int*& x) {
*x = 42; // change the value of the int x points to
x = nullptr; // change the value of x
}
The first line modifies the value x points to (but it does not modify x). The second line modifies x itself.
int main() {
int y = 42;
int* y_ptr = &y;
foo(y_ptr);
if (y_ptr == &y) std::cout << "cannot happen";
}
Because we set x = nullptr, y_ptr will not point to y anymore after the call.
Now if we modify foo to not take a reference we get:
#include <iostream>
void foo(int* x) {
*x = 42; // change the value of the int x points to
x = nullptr; // change the value of x
}
Again the first line modifies the int pointed to by x. However, now the second line only has an effect on x local to the function.
int main() {
int y = 42;
int* y_ptr = &y;
foo(y_ptr);
if (y_ptr == nullptr) std::cout << "cannot happen";
}
The value of y_ptr cannot change by passing it to foo, because it is passed by value.
In your code you have
Node* deleteHead(Node* &head)
{
if (head)
{
Node* temp = head;
head = head->next;
delete temp;
}
return head;
}
And when you write head = deleteNode(head) two things are happening:
the function modifies head (because it is passed by reference) to point to head->next.
the function also returns this "new" head (pointing to head->next) and that is assigned to head.
So you basically asign to headtwice. Because head is passed by reference deleteNode would do the right thing without using the return value:
deleteNode(head); // this already does modify head
...or put the other way around: If you return the "new" head (head->next) from the fucntion and assign it to head, then it does not matter if you pass the pointer by reference, because the assignment done inside the function has the same effect.
Your code is similar to
int* bar(int*& x) {
x = nullptr;
return x;
}
and then call it via
int y = 42;
int* y_ptr = &y;
y_ptr = bar(y_ptr);
where the same effect could be achieved by not using the returned value bar(y_ptr). Or the same without pointers (because pointers really make no difference here):
int moo(int& x) {
x = 0;
return x;
}
int x = 42;
x = moo(x); // same as `moo(x)`
PS: You dont need both (return the pointer and assign it already in the function), so better make the function return void.
So,
both, reference and pointer contain an address of variable/memory.
reference has semantic of variable (if you set the value, you write data into referenced memory),
pointer has semantic of pointer (if you set the value, pointered memory isn't changed) and you can set the pointer which addresses an other memory.
about deleteHead(Node* &head) - you use the reference of real variable that contains pointer of Node. The function returns new value of head in the same variable and as return value too.
References are "safe pointers" that are used with value semantics (which is really helpful in an operator overloading context), so the usage of references is very similar to the usage of pointers in C, except these points:
References hold a single value and not an array
References are non-null (which is not always desirable)
It means that you can (or, should) pass a reference whenever you want to change the original passed variable (and not a copy of it).
Saying that, the C (rought) equivalent to your function is Node* deleteHead(Node** head).
Note that since you passed a reference, the original head variable was modified and thus your function becomes a bit weird, since it both modifies head and returns its value.
You can use one of the following options:
(1) deletes head (if the list size is non-empty) and returns a pointer to the next element, this is not advisable since it will leave head as a dangling pointer. This is your original function but it does not receive a reference.
Node* deleteHead(Node* head)
{
if (head)
{
Node* temp = head; // You might want to use auto
head = head->next;
delete head;
}
return head;
}
(2) The same as your function, but returns no value (because you already modified head). This one will not work without passing a reference.
void deleteHead(Node* &head)
{
if (head)
{
Node* temp = head->next;
delete head; // deletes the content of head
head = temp;
}
}
With the reference to pointer deleteHead function, you may use head = deleteHead(head) or deleteHead(head) since head is just a reference of head in the main function, any change on head in the deleteHead function is actually applied on head variable in the main function. With the pointer version, you must use head = deleteHead(head).
I am trying to create one singly linked list and swap two int element in sub-
function.
in function swap(int *a,int *b) , the type of parameter is int *,and it can work successfully.
in function build_sll(node *head), the singly linked list won't be created successfully.
Once I set the type of parameter to be build_sll(node *&head),and it will be created singly linked list successfully.
Confused with:
function swap(int *a,int *b) passed the address of a b, I could modify the value of a b .
function build_sll(node *head) passed only the value of pointer head. I could not modify the value of head.
why here does not pass the address of head. The only difference between them is their data type.
while set build_sll(node *head), after GDB my code, and I found that all the node object have been created successfully. In main if I visited the allocated address, it does record the node information. how to delete memory in such case.
See my code to make clear my question.
#include<iostream>
#include<cstdlib>
#include<memory.h>
using namespace std;
typedef struct node{
int num;
struct node * next;
node(int num,struct node * next)
{
this->num = num;
this->next = next;
}
}node;
void build_sll(node *&head);
void del_memory(node *&head);
void travel_sll(node *head);
void swap(int *,int *);
int main()
{
int a =10 ,b = 5;
node *head = NULL;
build_sll(head);
travel_sll(head);
del_memory(head);
swap(&a,&b);
cout << a <<" "<< b <<"\n";
exit(0);
}
void build_sll(node *&head)
{
head = new node(0,NULL);
node * tail = head;
for(int index = 1 ; index < 8;index++)
{
node * temp = new node(index,NULL);
tail -> next = temp;
tail = temp;
}
}
void travel_sll(node *head)
{
if(head)
{
head = head -> next;
while(head)
{
cout << head->num <<"\n";
head = head -> next ;
}
}
}
void del_memory(node *&head)
{
delete [] head;
}
void swap(int *a,int *b)
{
int t;
t = *a;
*a = *b;
*b = t;
}
function swap(int *a,int *b) passed the address of a b, I could modify the value of a b . function build_sll(node *head) passed only the value of pointer head. I could not modify the value of head. why here does not pass the address of head. The only difference between them is their data type.
In function swap, you want to modify/access the value of int so passing int * or int & would work. Passing arguments of type int is good for reading the value of arguments, but if you change it, only local copy is updated and not the values with which you called the function.
In function build_sll you want to change the argument of type node *. So you should pass argument of type node ** or node *& to ensure you can change the value with with it was called. Passing node * would only change the local copy (in called function) and original value in the callee function would remain unchanged.
Your options are:
Preferable node * build_sll(node *);
OK node * build_sll(node *&);
Avoid this: node * build_sll(node **); etc
If I understood the first question correctly, you're confused why you can modify the values of a and b through pointers, and can't modify the value of head through the same syntax.
If this is the case, this happens because the type of a and b is int, and int *a points to the address of the variable in memory, thus enabling you to modify in the function through dereference. You could implement the swap function like this:
void swap(int &a,int &b)
{
int t;
t = a;
a = b;
b = t;
}
and swap(a,b) would work.
As you correctly noticed, the datatype of head is different, it's node *. To modify it's value you need a pointer to the memory address, where pointer itself is stored. Thus, you need to pass a reference to the node *head to modify it. build_sll function could be implemented with dereferences too
void build_sll(node **head)
{
*head = new node(0,NULL);
node * tail = head;
for(int index = 1 ; index < 8;index++)
{
node * temp = new node(index,NULL);
tail -> next = temp;
tail = temp;
}
}
However, the syntax with double pointers is not preferred, as it leads to using dereferences constantly, so it's better to use a & syntax
function swap(int *a,int *b) passed the address of a b, I could modify the value of a b . function build_sll(node *head) passed only the value of pointer head. I could not modify the value of head. why here does not pass the address of head. The only difference between them is their data type.
Well:
swap(&a,&b);
Here you're passing the address of a, and of b - that is, you're constructing pointers which point at the values that a and b refer to, and passing those pointers as arguments to the swap function.
build_sll(head);
Here you're passing the value of head (which happens to be a pointer variable). The value passed points at something (or is null), but it doesn't point at the value that head itself refers to..
If you look inside build_s11, assuming it was declared to receive a node * parameter:
void build_sll(node *head)
{
head = new node(0,NULL);
Then you'll not that the parameter is also called head - but this is coincidental. What it does mean is that assignment is just changing the value of the parameter variable, not of the original variable. That is, head inside build_s11 is a different variable to head in the calling expression; there are two variables, and you are modifying the one inside the function, but not the one in the caller.
So why doesn't it behave the same way in swap? Well, the fundamental difference is that in build_s11 you are assigning to the parameter variable itself, whereas in swap you are assigning to the pointer target:
*a = *b;
If you wanted to see consistent behaviour, you should use consistent syntax. build_s11 could be declared as:
void build_sll(node **head);
and you would call it as:
build_sll(&head);
... and then you could change the value of of a passed-by-pointer node * value by assinging to *head:
void build_sll(node **head)
{
*head = new node(0,NULL);
node * tail = *head;
... etc. Note that it is now consistent: just as in swap you used *a and *b (rather than plain a and b), you are now using *head in build_s11 (rather than head).
Of course you can also use a reference, as you have done in your full code posting.
I am learning list in C++ independently, and i have searched many websites about it. However, almost every approach to create a list is the same.
They usually create a struct as the node of a class. I want to create a class without using struct. So I created a class name ListNode which contains an int data and a pointer.
The main member functions of my class are AddNode and show.
Although, this program compiles successfully, it still does not work as I wish.
Here is the header file:
#ifndef LISTNODE_H_
#define LISTNODE_H_
#pragma once
class ListNode
{
private:
int data;
ListNode * next;
public:
ListNode();
ListNode(int value);
~ListNode();
void AddNode(ListNode* node,ListNode* headNode);
void show(ListNode* headNode);
};
#endif
Here is the implementation:
#include "ListNode.h"
#include<iostream>
ListNode::ListNode()
{
data = 0;
next = NULL;
}
ListNode::ListNode(int value)
{
data = value;
next = NULL;
}
ListNode::~ListNode()
{
}
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
node->next = headNode;
headNode =node;
}
void ListNode::show(ListNode* headNode) {
ListNode * traversNode;
traversNode = headNode;
while (traversNode != NULL) {
std::cout << traversNode->data << std::endl;
traversNode = traversNode->next;
}
}
Main function:
#include"ListNode.h"
#include<iostream>
int main()
{
using std::cout;
using std::endl;
ListNode* head = new ListNode();
for (int i = 0;i < 3;i++) {
ListNode* Node = new ListNode(i);
head->AddNode(Node, head);
}
head->show(head);
return 0;
}
As far as I am concerned, the output should be
2
1
0
However, the output is a single zero. There must be something wrong in the AddNode and show function.
Could you please tell me what is wrong with these two functions?
When you call head->AddNode(node, head) you´re passing the memory directions which the pointers point, when the function arguments receive those directions, they are now pointing to the same directions, but those are another pointers, no the ones you declared in main. You could see it like this:
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
/*when the arguments get their value it could be seen as something like:
node = Node(the one from main)
headNode = head(the one from main)*/
node->next = headNode;
/*Here you are modifying the new inserted node, no problem*/
headNode = node;
/*The problem is here, you´re modifying the memory direction
headNode points to, but the headNode argument of the function, no the one declared in main*/
}
So the pointer head in main() always points to the same first node you also declared in main().
In order to fix this you should change your code this way:
void ListNode::AddNode(ListNode* node,ListNode** headNode) {
/* second paramater now receives a pointer to apointer to a node */
node->next = *headNode;//the same as before but due to pointer syntaxis changes a bit
*headNode = node;//now you change the real head
}
And when you call it:
head->AddNode(Node, &head);//you use '&' before head
Now the real head, no the one in the function, will point to the last node you inserted.
I was trying to implement BST using C++ , so i tried this:
#include <iostream>
#include <stdlib.h>
struct node
{
int value;
node* left;
node* right;
};
void insert(node *cur , int val)
{
if(!cur)
{
cur = new node;
cur->value = val;
cur->left = NULL;
cur->right = NULL;
return;
}
if(val <= cur->value)
insert(cur->left , val);
else
insert(cur->right , val);
}
using namespace std;
int main()
{
node *root = NULL;
insert(root , 20);
insert(root , 21);
cout<<(*root).value;
return 0;
}
but I have a problem, my insert() function works good, but the change in cur does not seem to reflect into the root pointer, as root remains NULL after the `insert() function calls. What is wrong here?
EDIT: Thanks for all your answers, making a pointer to a pointer seems to be to be ugly and tedious, is there any other way around, acheiving this with some other design?
Here, the root itself has been passed to insert() using pass-by-value. so, from insert(), the value of root cannot be changed. In other words, the cur is local to insert() function. Any changes made to cur itself won't impact the actual argument passed.
If you want to change the value of root from insert(), you need to pass a pointer to root from main().
To elabotare, you can change the value at the address pointed by cur from insert(). So, following the same analogy, if you change
insert(&root , 20);
void insert(node **cur , int val)
all the occurrences of cur to *cur
you should be all good to go.
If you want the function to operate on the outside pointer rather than a local copy you need to pass by reference:
void insert(node*& cur, int val)
{
// ...
}
Otherwise the function works on a copy of the pointer and the outside variable remains unchanged.
The wrong is that you pas a pointer by value, change that value but the caller does not know about it. Change it to
void insert(node **cur , int val)
{
if(!*cur)
{
*cur = new node;
(*cur)->value = val;
(*cur)->left = NULL;
(*cur)->right = NULL;
return;
}
if(val <= (*cur)->value)
insert((*cur)->left , val);
else
insert((*cur)->right , val);
}
And change function call accordingly (...exercise!)
C++ makes function calls as Call by Value. So it makes a copy of the pointer and passes that to the function. If you pass that pointer, you have access to the data the pointer is pointing to, but NOT to the pointer outside the function itself, as only the adress the pointer is pointing to is copied.
You need to pass a pointer to the pointer if you want to modify the pointer itself (that would be the C attempt) or pass by reference, of which c++ is capable of.
If you want to use the C attempt:
void insert(node ** cur , int val)
if(!(*cur))
{
(*cur) = new node;
(*cur)->value = val;
(*cur)->left = NULL;
(*cur)->right = NULL;
return;
}
or the C++ attempt (here you only have to modify the type of cur, everthing else will remain as it is):
void insert(node *& cur , int val)
If you reassign cur to a new node in insert, that does not mean that root is assigned that value (especially that root is not an address at all, but NULL).
Either pass a pointer to an empty node to insert on initialization (and update it with relevant data) or return a new node (and assign it to root in main).
I have a class Node:
class Node {
public:
int item;
Node * nextLink;
};
Outside a function I declare a Node pointer:
Node * newNode;
Then, I pass this pointer to a function foo:
void foo(Node * node) {
node = new Node();
node->item = 1;
Node * anotherNode = new Node();
anotherNode->item = 2;
node->nextLink = anotherNode;
}
Actual call:
foo(newNode);
At the end of foo (but before existing) I can see that node->item and node->nextLink point to the correct places. However, when returned from foo, I check newNode, and the item is correct, but the nextLink is not there.
Any suggestions?
Thanks
You need to pass a reference. You are modifying a copy of the pointer
try
void foo(Node*& node)
Within foo() you're modifying a local copy of the pointer being passed to the function. Change foo to the following:
void foo(Node ** node) {
*node = new Node();
(*node)->item = 1;
Node * anotherNode = new Node();
anotherNode->item = 2;
(*node)->nextLink = anotherNode;
}
Then the call becomes:
foo( &newNode );
What you say is happening doesn't quite make sense to me. Since you are passing the pointer variable by value, its value in the calling function should not be changed at all, as far as I can see, so you actually shouldn't see any of the results of your function.
Although I can't explain the details of what's happening in your current code, I highly recommend you try it this way:
Node * foo(void) {
Node * node = new Node();
node->item = 1;
Node * anotherNode = new Node();
anotherNode->item = 2;
node->nextLink = anotherNode;
return node;
}
and call like:
Node *newNode = foo();
Since your function doesn't actually do anything with the pointer value that is passed in, it makes more sense for it to create everything using local variables and return pointer to the newly allocated node.
(You can also pass a reference to the pointer as other have suggested, but I don't see that as good programming style in this case. It is clearer to simply return the pointer from the function and assign it to the appropriate variable in the calling code.)
You have three choices. You can pass a Node** as input, a Node*& as input, or you can return a Node* from the foo method. All three options work.
If you want the function foo to change the pointer, you have to call it with the adress of the pointer, like this:
Node * newNode;
void foo(Node ** nodepointer) {
(*nodepointer) = new Node();
(*nodepointer)->item = 1;
Node * anotherNode = new Node();
anotherNode->item = 2;
anotherNode->nextLink = NULL;
(*nodepointer)->nextLink = anotherNode;
}
foo(&newNode);
As shown above you should also set anotherNode->nextLink to NULL to mark the end of the list.