Printing out a doubly linked list using a reference variable? - c++

I was given this function to define and I'm a little confuse do how to do that. It's supposed to print out a linked list either forwards or backward.
void printList(List& source, bool direction)
{
}
So I understand that I will use the direction variable in an if statement but I don't know what do with the source variable. Here is my guess:
void printList(List& source, bool direction)
{
ListNode *p = source;
if(direction)
{
while(p)
{
cout << p->value<< " ";
p->next
}
}
else
{
while(p)
{
cout << p->value<< " ";
p->next
}
}
}
Also just so there is not confusion for you guys I am using another class callded ListNode class that has three values: next , previous , value.

ListNode *p = source;
is actually invalid syntax, since source isn't a pointer type. You want to assign the address:
ListNode *p = &source;
// ^
Supposed you have a double linked list, the statements to proceed in a particular direction will be
p = p->next;
or
p = p->previous;
depending on the implied semantics of the direction value.
Also note, that it's sufficient to provide a const reference for the parameter, if you're not intend to have changes seen outside of the function:
void printList(const List& source, bool direction)
// ^^^^^

Related

38:10: error: member reference base type 'Node *' is not a structure or union *prev->next = temp;

Code is to insert element at the end position of link list. I am passing pointer to the Node pointer to insert method while doing so I am getting the error member reference base type 'Node *' is not a structure or union on line number 38, which is *prev->next = temp;. Please explain the issue and if you provide the solution on the same logic, it will be better.
#include "iostream"
using namespace std;
struct Node {
int data;
Node* next;
};
void insertElement(Node**, Node**, int);
void printLinkList(Node** head);
int main(int argc, char const *argv[]) {
Node *head = NULL, *prev = NULL;
int num, pos;
char controller;
cout << "To add element to link list press y, to quit press any other key: ";
cin >> controller;
while(controller == 'y') {
cout << "Enter element: ";
cin >> num;
insertElement(&head, &prev, num);
cout << "To add next element to link list press y, to quit press any other key: ";
cin >> controller;
}
printLinkList(&head);
return 0;
}
void insertElement(Node **head, Node **prev, int num) {
Node *temp = new Node();
temp->data = num;
temp->next = NULL;
if(*head == NULL) {
*head = temp;
}
if(*prev != NULL) {
*prev->next = temp;
}
*prev = temp;
}
void printLinkList(Node** head) {
Node* temp = *head;
while(temp != NULL) {
cout << temp->data << ", ";
temp = temp->next;
}
cout << endl;
}
The error message would be self-explanatory if your expression was less complex. Still, it is reasonably straight-forward when taken out of context.
member reference base type 'Node *' is not a structure or union
This says that at some point you tried to access the member of a pointer to Node, which is not allowed because only structures and unions have members. (The compiler is using "structure" to cover both struct and class.) In particular, pointers do not have members.
Hopefully this rings true. If temp is a Node*, then the expression temp.data does not make sense; you need first to de-reference the pointer, as in (*temp).data or the equivalent temp->data. So what is going on in your code?
At the problematic point in your code, you have a pointer-to-pointer, which is often not the best approach. The pointer-to-pointer, prev, appears in the sub-expression prev->next, which is equivalent to (*prev).next. Consider that last expression. Since prev is Node**, a single de-reference gives Node* which is the situation from above: trying to access the next field does not make sense unless you first de-reference the pointer, as in (**prev).next. This is close to what you wrote, but not quite.
The correct expression, (**prev).next is equivalent to (*prev)->next. Your expression, *prev->next, is equivalent to *(prev->next) or *((*prev).next). There is a difference in the order of evaluation. This difference is one reason pointers-to-pointer are challenging to manage correctly. (The language is not designed to succinctly accommodate pointers-to-pointer-to-structure. Instead, it assumes the more likely scenario for two levels of indirection is pointer-to-structure-with-pointer-member.)
Since you are coding in C++ instead of C, there is a nifty language feature that helps avoid this problem. Have insertElement accept Node pointers by reference instead of by address. This reduces the complexity of your expressions, removing your current problem, and addresses the future problem where you never checked if the function's parameters are null. (You have a check for *head being null, but that check blows up if head itself is null.)
void insertElement(Node *&head, Node *&prev, int num);
With this change, occurrences inside the function body of head* become head, of prev* become prev, and the call to the function becomes insertElement(head, prev, num); (no address-of operator). You get simpler syntax so you can focus on the logic of inserting an element.
See also Meaning of *& and **& in C++.

Cannot access member of an object via pointer

This problem seems like a trivial one but I am unable to get my head around it.
I am trying to add a node by passing in a root element to a function insert. The function first checks if the current root is empty, if it is, it simply creates a new node and set it as a root. My first attempt was something like this
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node(int x) {
data = x;
}
};
void insert(Node *node, int x) {
cout << &node << "\n";
if(node == NULL) {
node = new Node(x);
}
}
int main () {
Node *aNode;
aNode = NULL;
insert(aNode, 8);
cout << aNode << "\n";
return 0;
}
This of course didn't work since I was passing pointers by value which was causing aNode to be still NULL and with some googling I came to know I need to pass pointers by reference, my second attempt was something like this
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node(int x) {
data = x;
}
};
void insert(Node **node, int x) {
if(*node == NULL) {
*node = new Node(x);
cout << *node->data << "\n"; //gives error but program runs fine without it
}
}
int main () {
Node *aNode;
aNode = NULL;
insert(&aNode, 8);
cout << aNode->data << "\n";
return 0;
}
Now that worked without the cout in insert function since the cout in main printed 8 which is what I wanted but compiler gave error request for member 'data' in '* node', which is of pointer type 'Node*' (maybe you meant to use '->' ?) while at cout of insert. I changed the insert as follows to run some tests and results were confusing
void insert(Node **node, int x) {
if(*node == NULL) {
Node *bNode = new Node(x);
cout << bNode << "\n"; // prints address of bNode
cout << *node << "\n"; // prints NULL which is correct
*node = bNode;
cout << *node << "\n"; // prints the same address as of bNode
cout << bNode->data << "\n"; // prints 8
cout << *node->data << "\n"; // gives error WTF!!!
}
}
Can somebody please explain?
#RemyLebeau comment was spot on and pointed out the exact problem. So here is the solution.
Problem Background
So I had a pointer to an object of type Node aNode and had a function insert(Node *node, int x). I wanted the function insert to check if given pointer to node doesn't point to anything then create a new node and set the reference in provided node. The expectation was that after setting the reference aNode will point to the newly created node as well. However it was a false expectation because I was passing the pointer by value instead of reference which meant node in the function insert was a different one than aNode
Buggy Solution
So the solution was to pass reference of aNode to function insert. So I changed my function call to insert, to this
insert(&aNode, 8);
And change the function definition of insert to this
void insert(Node **node, int x)
That fixed the problem, since **node was now dereferened to the address of aNode and I was able to get its value by simply dereferencing node by *node. The problem occured when I tried to access members of Node by *node->data. The reason was that * and -> are actually operators and -> has higher precedence than *. So while evaluating *node->data it was actually executing in this way *(node->data) which means compiler was actually trying to dereference node->data instead of node. The quick solution was just to access data like this (*node)->data.
Right Solution
Although through parenthesis I was able to achieve the desired behavior but the syntax was ugly. The right solution as #pm100 pointed to use reference in function definition instead of dereferencing it twice which means declare function like this
void insert(Node *&node, int x)
instead of like this
void insert(Node **node, int x)
That enabled to access node members simply like node->data instead of (*node)->data
If you are new to pointers like me do watch https://www.youtube.com/watch?v=Rxvv9krECNw

Local variable pointer overwritten on each method call

I am currently reading a book on data structures and learning c++ on the side. I am trying to implement a simple linked list. Below is some code for a list that can take a maximum of two elements (in order to isolate my problem).
What is going wrong is the pointer declaration to the next node in the list. When I create a new Node instance and create a pointer to it, the pointer stays the same on each method call, so all elements in the list point to the same node. However, if I create a pointer directly, everything works as expected.
What I am guessing is that I have some fundamental misunderstanding of pointers, references and the new keyword.
Feel free to run the code below. The working code is commented out.
#include <iostream>
using namespace std;
template <typename T> class Node {
public:
Node(T nvalue) {
this->value = nvalue;
this->next = NULL;
}
T value;
Node *next;
};
template <typename T> class LinkedList {
public:
Node<T> *head;
LinkedList() {
this->head = NULL;
}
void append(T newVal) {
// Correct
// Node<T>* newNode_ptr = new Node<T>(newVal); // newNode_ptr is different on each call
// Incorrect!?
Node<T> newNode = Node<T>(newVal);
Node<T> * newNode_ptr = &newNode; // newNode_ptr is the same on each call
cout << "New Node Address: " << newNode_ptr << endl;
if (!(this->head)) {
this->head = newNode_ptr;
cout << "Value 0: " << this->head->value << endl;
} else {
this->head->next = newNode_ptr;
cout << "Value 0: " << this->head->value << endl;
cout << "Value 1: " << this->head->next->value << endl;
}
}
};
int main() {
LinkedList<int> list = LinkedList<int>();
list.append(21);
cout << "..." << endl;
list.append(42);
}
Note that this code is not exactly well designed (some stuff should be private, using namespace std should be avoided). I am familiar with python so this pointer stuff is a little overwhelming. Thanks for your help in advance!
Node<T>* newNode_ptr = new Node<T>(newVal);
This is the more correct way of the two. It is normal that the address of newNde_ptr is different, it's what you want. Each node is a different node, two different objects cannot have the same address! The version without new gives the same address because you are creating the objects on the stack. This will not work, every node is destroyed at the end of the append function. You will see unusual results (if it doesn't crash) if you move the printing portion of append to another function. Since all your pointers point to the same address (in your case) and at the point where you print out the values that address just so happens to be a valid Node, you do not see a crash. However, this is undefined behavior and can change for any number of reasons.
The difference between free-store (heap for malloc/free) and the stack is a fundamental concept of c++. You should read about it here.
The reason I saw more correct way of the two is that you still have to remember to delete your nodes. A better way would be to use std::unique_ptr instead of raw pointers to avoid that (and may other) mistakes that using raw pointers encourages.
// Node * next; becomes
std::unique_ptr<Node> next;
// Node<T> newNode = Node<T>(newVal); becomes
newNode = std::make_unique<T>(newVal);

Getting wrong output with custom linked list implementation

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.

How to change LinkedList head pointer globally and not locally

I have TWO implementations of this.
Why does this particular implementation NOT work? I have a pointer to a pointer and im changing the inside point but it doesn't retain the change in the main function
#include <iostream>
using namespace std;
struct Node {
int value = 4;
Node* next;
};
void insertFront(Node*, Node**);
int main(){
Node head;
head.value = 32;
head.next = nullptr;
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
system("pause");
return 0;
}
void insertFront(Node* newHead, Node** head2){
cout << "Inside before swap " << (*head2)->value << endl;
newHead->next = *head2;
*head2 = newHead;
cout << "Inside after swap " << (*head2)->value << endl;
}
Why does this one work? Can someone please explain IN DETAIL the pointer magic going on? I have a vague idea but im still a little bit confused. I understand that using a pointer to the head pointer allows you to change the head address globally but it's still a little bit cloudy. Can someone please clarify, what is going on with these pointers in both implementation?
#include <iostream>
using namespace std;
struct Node {
int value = 4;
Node* next;
};
void insertFront(Node*, Node**);
int main(){
Node** head = new Node*;
(*head) = new Node;
(*head)->value = 32;
(*head)->next = nullptr;
cout << (*head)->value << endl;
insertFront(new Node, head);
cout << (*head)->value << endl;
system("pause");
return 0;
}
void insertFront(Node* newHead, Node** head2){
cout << "Inside before swap " << (*head2)->value << endl;
newHead->next = *head2;
*head2 = newHead;
cout << "Inside after swap " << (*head2)->value << endl;
}
Both implementations are using double-indirection wrong, and both leak memory. You're question seems more about double-indirection than just about what works and what doesn't (whether you realize it or not). Its a C question, and though also applicable in C++, it is less so with that language because reference parameters make this somewhat easier (arguably).
I could simply say "use references to pointers" (which you could do), but that would be like you saying "why doesn't my car work?" and me answering "because this car over here will work". So I will provide a C answer (much to the dismay of my own common sense, as I can feel the furnaces firing up from the flamethrowers about to be sent my way). If I have time, I will include the C++ answer (using references), but no guarantees on that.
Pointers to pointers are no different than any other pointer type. All pointer types are types who's variables are defined to "point" to something of that type (I know, its repetitive and trivial, but bear with me here). The trivial example:
void foo(int x)
{
x = 5;
}
obviously doesn't change x on the caller side, and you seem keenly aware of that. If you want to change an in/out parameter using pointers, you need to declare the formal parameter to be a pointer-to type, dereference said-pointer parameter within the function body, and pass the address from the caller. Ie.
void foo(int *p)
{
*p = 5;
}
int main()
{
int x = 0;
foo(&x);
}
The truth is parameters are all pass-by-value in C, even pointer parameters. Yeah, read that again. You say what? Seriously. Its true. It just so happens the "value" you're passing is an address rather than the value within some variable, and in so being as such, the receiver must be something that is prepared to take, and manipulate, data via that address: a pointer.
Now. Pointers to pointers are no different. Pointers to pointers hold addresses of (wait for it...) pointers. Just like our first example, this:
struct Node
{
int data;
struct Node *next;
}
vod foo(Node* ptr)
{
Node *p = new Node();
p->data = 0;
p->next = ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(root);
}
won't work. You can fix this several ways. One way is using a pointer-to-pointer (the C way). Another uses a reference to pointer (the C++ way).
First the C way, which demonstrates the whole mantra of passing something by address means declaring the parameter to be a pointer-to type (in this case a pointer to pointer type), and passing the address of the thing to modify:
void foo(Node** ptr)
{
Node *p = new Node();
p->data = 0;
p->next = *ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(&root); // LOOK: passing address of our root pointer
}
Do you see how, just like in our trivial example using int and int*, we have to pass the address of the thing we're modifying to a function that takes a pointer-to-type? In this case the "type" is, itself, a pointer type.
Now, arguable, the C++ way using a reference is trivial by comparison, but IMHO it isn't as clear what is going on, only because there is literally a single character difference between the version that doesn't work and the version that does. Look at this:
vod foo(Node*& ptr) // LOOK added &
{
Node *p = new Node();
p->data = 0;
p->next = ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(root);
}
Notice how everything else in this is identical to the version that does not work. Everyone has their preferences, and knowing what to look for allows me to use either method, but I can see why some have such difficulty writing and debugging what is essentially double-indirection code hidden in a reference type. Some engineers prefer to send all their out-params as pointer-to types, and I'm generally one of them.
Peeling Back Your Code
After all of that, lets peel back your code and see where things go to hell. I'll dissect the one that does not work, and hopefully you can see why neither version is honestly very good:
First your type:
struct Node
{
int value = 4;
Node* next;
};
Nothing horridly questionable here. The default value assignment in the structure definition. This will puke on non-current-day C++, so likely throw that out for now. If you want a default value, make a constructor (which you should have anyway to ensure all members are properly initialized to something):
struct Node
{
int value;
Node* next;
Node(int val = 4)
: value(val)
, next()
{}
};
Ok. Next up..
void insertFront(Node*, Node**);
You seem to want to use a pure node interface. Most people writing a linked list would do this:
void insertFront(Node** ppRoot, int value);
but we'll go with your version for now. The actual implementation of this:
void insertFront(Node* newHead, Node** head2)
{
newHead->next = *head2;
*head2 = newHead;
}
is correct. Yes it could orphan anything previously being pointed to by newHead->next, but that doesn't seem to be a concern of yours, so we go with it for now.
Finally the torrent: main().
int main()
{
Node head;
head.value = 32;
head.next = nullptr;
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
system("pause");
return 0;
}
This has multiple issues. First, your mixing dynamic nodes with non-dynamic nodes.
Node head;
head.value = 32;
head.next = nullptr;
Bad idea. This is no reasonable way calling code (in particular cleanup code that deletes each node from the list), has any clue whether something being pointed to is dynamic or not. Don't do that.. Using the constructor version of Node from above, this should simply be:
Node* head = new Node(32);
Next you're dynamically allocating a pointer; (not a Node; a pointer)
Node** headptr = new Node*;
Bad idea. there is no need to do that at all. You already have a pointer variable to your list head (its called, not-coincidentally, head). This appears all to be a setup for invoking the insertion function. To do that, everything from Node** headptr = new Node*; on down can simply be replaced with this:
insertFront(new Node(10), &head); // LOOK: passing address of head pointer
cout << head->value << endl;
The way you are using your pointers is so, so wrong.
Let's look at this code:
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
Let's first clean up this code a bit. There is no reason to allocate a Node * on the free store (using new), and then reference it through a Node **. It can and should simply be a local variable and referenced directly. To do that, we replace Node** headptr = new Node*; with simply Node *phead, and replace all instances of (*headptr) with merely phead:
Node* phead;
phead= new Node; // #2
*phead= head; // #3
phead->value = 32;//redundant, I know
phead->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, &phead); // here we are passing the address of phead so that insertFront() can modify it
cout << head.value << endl;
Now look at this code carefully. You allocated space for a new Node on line 2, and made phead point to it. You copied the contents of head into this new Node on line 3. Then your insertFront() call modified a newly allocated node and set phead to point to that new node instead. At no point did any pointer ever point to head, and its value is never touched; when you check head.value, of course they remain the same.