How to access user-chosen struct variable C++ - c++

I am using a function to print out data from a linked list, the list Nodes have 2 variables which could be accessed, data or index. I want to add a parameter to the print() function that allows the user to call the variables name within the Node that they want to be outputted, I've heard of passing by reference and I'm pretty sure this is what I want to do but haven't found any resources that actually work for my code.
(simply I want to pass a variable name to a function).
here is my code:
struct Node {
int data;
int index;
Node *next;
}
Node *_current;
Node *_next;
Node *_head;
Node *_temp;
Node *_tail;
Node *_last;
// all this is handled correctly
void print(*variable name*) {
Node *n = _head;
while (n->next != nullptr) {
std::cout << n-> *variable name* << std::endl;
n = n->next;
}
}
p.s: variable name is not necessarily a pointer but just (literally) referring to the variable name parameter I want to add.
this code works if I swap out variable name to 'std::cout << n->data <<...' and runs without any other issues. (btw Whole code isn't provided just the parts needed to explain what I want to change)
any helpful information is greatly appreciated, Thank you in advance. :)

p.s: variable name is not necessarily a pointer
But it is a pointer. A member pointer, specifically:
void print(int Node::*member) {
Node *n = _head;
while (n->next != nullptr) {
std::cout << n->*member << std::endl;
n = n->next;
}
}
It would get invoked as either
print(&Node::data);
or
print(&Node::index);

You can pass in a string.
void print(const string& str) {
Node *n = _head;
if(str.compare("index")==0){
while (n->next != nullptr) {
std::cout << n->index << std::endl;
n = n->next;
}
}
else if(str.compare("data")==0){
while (n->next != nullptr) {
std::cout << n->data << std::endl;
n = n->next;
}
}
}

Related

Last node is not printed in Linked List

I was trying to learn the Linked list and perform insertion operations from beginning of the list. while printing the nodes, the first node is not printed. Here is the core functions which I have written. Can someone help me?
struct Node //basic structure for a node
{
ll data; //data which we want to store
Node* link; //address of the next node;
};
Node* head=NULL;
void Insert(ll x) //insertion at beginning
{
Node* temp=new Node();
temp->data=x;
temp->link=head; //we are linking new node with previously connected node
head=temp;
}
void Print()
{
Node* temp=head;
while(temp->link!=NULL) //traversing the list until last element(last element.link = NULL)
{
cout<<temp->data<<" ";
temp=temp->link;
}
cout<<endl;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
f(i,0,5)
{
ll x;cin>>x;
Insert(x);
}
Print();
return 0;
}
Your Print function requires that the last node is linked or it won't be printed. Since the last node is never linked, it will never be printed.
void Print()
{
Node* temp = head;
while(temp) // <- corrected condition
{
std::cout << temp->data << ' ';
temp = temp->link;
}
std::cout << '\n';
}
It's because of your check in the while. The node will have link set as NULL, and therefore it will exit the while without printing it. My recommendation is changing the while check to (temp != NULL), but you can also fix it by putting a cout << temp->data; after the loop
In general the function Print can invoke undefined behavior when it is called for an empty list due to the expression temp->link that uses a null pointer to access memory.
Another side effect is that the last node will be skipped due to the condition in the while loop (if the list has only one node then its value will not be outputted)
while(temp->link!=NULL)
The function can be declared and defined the following way
std::ostream & Print( std::ostream &os = std::cout )
{
for ( const Node *current = head; current != nullptr; current = current->next )
{
os << current->data << " -> ";
}
return os << "null";
}
And in main the function can be called like
Print() << '\n';
The function is flexible. You can use it to write data in a file providing a corresponding file stream.
The function Insert can be simplified the following way
void Insert( ll x ) //insertion at beginning
{
head = new Node { x, head };
}
Pay attention to that it is a bad idea to declare the pointer head in the global namespace. In this case all functions depend on the global variable and you can not for example to use two lists in your program.
So you should declare the pointer in main.
int main()
{
Node *head = nullptr;
//...
In this case for example the function Insert can look the following way
void Insert( Node * &head, ll x ) //insertion at beginning
{
head = new Node { x, head };
}
and called in main like
Insert( head, x );

I have written a code for creating a linked list. While printing the list items I am getting SIGSEV error. How do we fix it?

I know I have done a silly mistake and to not make it again in the future I want to know why this error is showing up in the following code. I have already read on the internet that it is caused when our program is trying to access memory block which is not yet created but I cannot find where it is occurring in my program.
Thank You, Guys.
struct node
{
int value;
struct node *next;
};
typedef struct node Node;
Node *createNewNode(int value)
{
Node *result = new Node;
result->value = value;
result->next = NULL;
return result;
}
Node *insertHeadNode(Node **head, Node *nodeToInsert)
{
nodeToInsert->next = *head;
*head = nodeToInsert;
return nodeToInsert;
}
void print_list(Node *head)
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->value << "->";
temp = temp->next;
}
cout << endl;
}
int main()
{
int value, i;
Node *head;
Node *tmp;
while (i < 5)
{
cout << "Enter the value of the linked list: ";
cin >> value;
tmp = createNewNode(value);
insertHeadNode(&head, tmp);
i++;
}
print_list(head);
return 0;
}
One more thing. I have dynamically created a struct in the createNewNode function. So we do delete it at the end of our program, right?
You have multiple parts in your code that result in undefined behavior.
You never initialize i so doing i < 5 isn't valid.
You never initialize Node *head so that one also holds an indeterminate value, that value is assigned to nodeToInsert->next in insertHeadNode.
So also cout << temp->value << "->"; would be invalid, at the point when temp = temp->next has reaced the node for which you assinged that indeterminate to next.

Using pointers with recursion

I want to have a node that will be able to point to another node through the function insert. However, I've messed up somehow so that the pointer p does not point to the next Node. I'm unsure of how to use my function in a way such that it will point to the recurred variable a.
This issue is occurring on a AVL tree assignment I've been working on. I've recreated the error in a simpler fashion in the below code.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next = NULL;
};
Node* insert(Node *a) {
cout << "inserter" << endl;
if (a != NULL) {
a->next = insert(a->next);
}
else {
cout << "inserting" << endl;
Node *a = new Node;
a->data = 10;
a->next = NULL;
}
return a;
}
int main() {
Node *p = new Node;
p->data = 5;
insert(p);
cout << "please" << endl;
cout << p->data << endl;
cout << p->next << endl;
cout << p->next->data << endl;
cout << "done" << endl;
return 0;
}
The output is:
inserter
inserter
inserting
please
5
000000
And then it crashes, as p->next is not pointing to anything. I don't know how I can get it to point to the recurrsed pointer a.
My main objective is to have a->next be changed without using a returning function, instead a void function that can change a->next using an & in the pass by reference. But I'm unsure how to incorporate the & into a pointer. This hasn't been working (Node *&a).
Your main reason for p->next being null is that the pointer you want to return is out of scope when you return it.
Outside of else {}, the new pointer you created is no longer valid.
else {
cout << "inserting" << endl;
a = new Node;
a->data = 10;
a->next = NULL;
}
Because of the Node* before a in your code, you are declaring a new Node pointer, instead of using the one that was passed to the function.
In your code, it doesn't seem like you are implementing a tree. It seems more like you are implementing a linked list.
Whatever. In the way you are doing, you can never track the starting node. You have to save it for traversing the tree/linked list.
struct node
{
int data;
node *next;
};
node *head, *tail;
void createnode(int value)
{
node *temp=new node;
temp->data=value;
temp->next=NULL;
if(head==NULL)
{
head=temp;
tail=temp;
temp=NULL;
}
else
{
tail->next=temp;
tail=temp;
}
}

Inserting a single element in a linked list gives a segmentation fault - C++

The below code intends to perform insertion of a single element in a linked list and then print it. Although, I am getting a segmentation fault while printing the value in main function. Could you please help me identify what is wrong with it ?
I have tried to print the value of data in the insert function and it works fine which means the creation of new node and assignment of the value to it is working fine.
#include<iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
//insert a new node
Node* insertNode(int data,Node* head)
{
Node* cNode = head;
if (!head)
{
head = new Node;
head->data = data;
head->next = NULL;
}
else
{
while(cNode->next)
{
cNode = cNode->next;
}
cNode->next = new Node;
cNode->next->data = data;
cNode->next->next = NULL;
}
return head;
}
// print a list
void print(Node* head)
{
/*while(head->next)
{
cout << head->data << " ";
head = head->next;
}*/
cout << "printing data" << endl;
cout << "data : " << head->data;
}
int main()
{
cout << "inside main" << endl;
Node* aNode = NULL;
insertNode(2,aNode);
print(aNode);
return 0;
}
I expect the print function to print the value of data for the single node that I created .
Your head parameter in insertNode function should be a reference (or a pointer to pointer to Node). Beacause in the current form, it is an input parameter, but you need to be in-out parameter. It means that in the current code, your aNode variable is NULL and is always stays NULL.
I recommend this:
void insertNode(int data, Node &head)
Then you create an object in main this way: Node aNode;
It will allow you to update the existing variable directly and you don't need a return value. Also, this way it will be a little bit more C++like, your original code is more like a plain C code.
Or if you want to write it in plain C:
void insertNode(int data, Node **head)
Then you change the call from main: insertNode(2, &aNode);

c++ linked list not working

I am trying to make a linked list but am running into problems because I am deleting my nodes twice. The problem only arises when a node is passed into a function (if it is passed by reference everything is fine) which leads me to believe that the object being passed into the function is being copied in such a way that the pointers are pointing to nodes from the original list not the new list. I tried to get around this by overloading the = operator but this didn't work either. An explanation of what I'm doing wrong would be great.
Thanks for the help
#include <iostream>
struct node{
node(int n){
if (n == 1){
data = 1;
next = NULL;
}
if (n == 2){
data = 2;
next = new node(1);
next -> next = NULL;
}
}
~node(){
std::cout << data << std::endl;
if (next != NULL) delete next;
}
void operator=(node a){
next = NULL;
}
int data;
node* next;
};
void func2(node v){
}
int main(){
node v(2);
if (v.next -> next == NULL) std::cout << "true\n";
func2(v);
return 0;
}
Your suspicions are correct, but therein lies the problem; when you pass the node into func2, you're only copying the first node, not the entire list. The copy constructor will copy the first node, and the pointer in the first node (which points to the original second node), so when v goes out of scope in func2 it gets deleted once, then gets deleted again when it goes out of scope of main. You'll need to write the copy constructor to do a "deep copy," traversing the entire list and copying every node into a new address.
Remember also that the copy constructor should return *this in most cases, this is in the C++ FAQ and in the book "Effective C++" by Scott Meyers. Thus the signature should be:
node& operator=(const node& node);
If you're going to overload the assignment operator, you should probably also define a copy constructor. Good job explaining the problem, by the way.
Edit: The code would look like this. I apologize that I haven't tested this; I'm on my tablet and editing this is painful...
#include <iostream>
struct node{
node(const node& toCopy) : data(toCopy.data)
{
if(toCopy.next != null) {
next = new node(toCopy);
}
}
node(int n){
if (n == 1){
data = 1;
next = NULL;
}
if (n == 2){
data = 2;
next = new node(1);
next -> next = NULL;
}
}
node& operator=(const node& toCopy) {
if(&toCopy != this) {
data = toCopy.data;
if(next != NULL) {
next = new node(toCopy);
}
}
return *this;
}
~node(){
std::cout << data << std::endl;
if (next != NULL) delete next;
}
int data;
node* next;
};
void func2(node v){
}
int main(){
node v(2);
if (v.next -> next == NULL) std::cout << "true\n";
func2(v);
return 0;
}