C++ how to access struct in struct - c++

I got a question about structs.. C++ is not language what I'm learning but I have a need to do exercise..
I have a struct like this:
struct List
{
int data;
List* next;
};
and I got class and methods with which I can add/remove/printout elements of the struct so for example to view elements I got method:
void Kopa::Print()
{
List *tmp = p;
while (tmp != NULL)
{
cout << tmp->data << endl;
tmp = tmp->next;
}
tmp.struktura;
}
The question is, how can I add and access new struct in List struct?
I guess it the struct will look smth like this but I don't understand how to access it with class methods..
struct List
{
int data;
List* next;
struct NewList
{
int data;
NewList* next;
};
};

First you have to declare a member of that structure, just like you declare other member variables:
struct List
{
struct NewList
{
int data;
};
NewList my_new_list; // Declare a member
};
Then you use it like any other member, just nest the member access as needed:
List l;
l.my_new_list.data = ...;
If you mean how to access the NewList structure inside List to declare a local variable, then you have to use the scope operator :::
List::NewList new_list;
new_list.data = ...;

This looks like an implementation assignment for linked list
Your struct looks like a node struct, not a list. So I will be using struct Node instead of List to avoid confusion.
I don't know where your p comes from, but it is essentially how you would create p in your function.
Node *p = new Node();
p->data = 1;
p->next = NULL;
now if you need to add a new one, do the same thing
Node *q = new Node ();
q->data = 2;
q->next = NULL;
//assign q after p
p->next = q;
You can also create a constructor in your struct
Node (Node *previous, int newData)
{
List *q = new Node ();
q->data = newData;
q->next = NULL;
previous->next = q;
}
make sure you call delete to clean up these pointers when you are done with them

Related

C++ Constructor behaving strangely in my Linkedlist program

Today I was taught Linked list in class and I wanted to implement it on my own.
Here's the part of the code that I wrote. Note that traverseLL traverses the Linked list and insertAtEnd inserts a new node at the end of the linked list.
I believe I can implement Linked list logic / methods / functions on my own. But my question is, inside insertAtEnd function when I create a newNode with the parameters - my data to be inserted, and nullptr (because inserting at the end), It inserts garbage values (or memory addresses maybe) in my node, ignoring the data passed to the constructor.
using namespace std;
#define NL '\n'
class Node {
public:
int data;
Node* next;
Node (int data, Node* nextPtr=nullptr) {
data = data;
next = nextPtr;
}
};
void insertAtEnd(Node* &head, int data) {
Node* newNode = new Node(data, nullptr); // <---- Issue in this line
// When I do as above, my linkedlist nodes always store garbage values and not the data being passed.
// However, when I un-comment the below line, I get the correct output.
// newNode->data = data;
if (head == nullptr)
head = newNode;
else {
Node* temp = head;
while (temp->next != nullptr)
temp = temp->next;
temp->next = newNode;
}
}
void traverseLL(Node* head) {
if (head == nullptr)
return;
while (head->next) {
cout << head->data << " -> ";
head = head->next;
}
cout << head->data << NL;
}
int main() {
Node* head = nullptr;
insertAtEnd(head, 10);
insertAtEnd(head, 20);
insertAtEnd(head, 30);
traverseLL(head);
return 0;
}
For example, the output for the above code when keeping newNode->data = data line commented, is :
16259544 -> 16258392 -> 16258392
But when I un-comment that line, my output becomes, which is intended:
10 -> 20 -> 30
Why is this happening? Even though I've defined my constructor, why is it not working?
I think the cause for this is the statement data = data in the constructor.
Reason for this:
Before executing the first statement of constructor, the member variables of the class are allocated memory and contain junk/default values, and when the statement data = data is seen the compiler changes the parameter but not the member variable.
As a result, you are seeing junk/garbage values.
To resolve this we can either explicitly specify the member using this or use member initialization syntax.
You can use any of the following workarounds.
Workarounds:
You can change your class constructor code like any of the below formats:
1.
class Node {
public:
int data;
Node* next;
Node (int data, Node* nextPtr=nullptr) {
this->data = data; // we are explicitly specifying which data to use
next = nextPtr;
}
};
class Node {
public:
int data;
Node* next;
Node (int d, Node* nextPtr=nullptr) {
data = d; // as the member variable and local variable are of different names, no conflict
next = nextPtr;
}
};
class Node {
public:
int data;
Node* next;
// use the member initialization syntax
// Here we are initializing the data while allocating memory itself,
// so answer is perfectly right!
Node (int d, Node* nextPtr=nullptr) : data(data), next(nextPtr) {}
};
More on the member initialization and constructor:
https://en.cppreference.com/w/cpp/language/constructor
How do C++ class members get initialized if I don't do it explicitly?
Hope this helps,
Thanks.

deep copy in struct pointers

in this code, I think it must do deep copy because I'm passing pointers, but it doesn't.
I think it must print 3, but print 0. what should I do to solve this? i want to have a deep copy instead of a shallow copy.
struct node{
int number = 0;
struct node* right_child = NULL;
struct node* left_child = NULL;
};
void test(struct node* node1 , struct node* node2){
node1 = node2;
}
int main(){
struct node* a1 = new struct node;
struct node* a2 = new struct node;
a2->number = 3;
test(a1 , a2);
cout << a1->number;
}
The simple C-ish way: We ad a function that recursively clones the nodes
#include <iostream>
struct node{
int number = 0;
node* right_child = nullptr; // nullptr safer than NULL
node* left_child = nullptr;
};
node * clone(const node * src){
if (src) { // there is a node. Copy it.
return new node{src->number,
clone(src->right_child), // clone right
clone(src->left_child)}; // clone left
}
else { // no node. Nothing to do and end the branch
return nullptr;
}
}
void test(node*& node1, // reference to pointer
node* node2){
delete node1; // Free storage currently used by node1
// But what of the nodes that could be in its tree?
// Think on this. Ask another question if necessary.
// this is where the simple way starts to fall down
node1 = clone(node2);
}
int main(){
struct node* a1 = new node; // wasted memory. We're about to replace it.
// need a more complicated tree to prove deep copy works
struct node* a2 = new node{3,
new node{4, nullptr, nullptr}, // a right node
nullptr}; // no left node
// a2->number = 3; done above now
test(a1 , a2);
std::cout << a1->number << ' '
<< a1->right_child->number;
delete a1; // clean up
delete a2;
}
More complicated canonical C++ way using The Rule Of Three and The Copy and Swap Idiom
#include <iostream>
#include <algorithm> // for std::swap
struct node{
int number = 0;
node* right_child = nullptr; // nullptr safer than NULL
node* left_child = nullptr;
static node * clone(node * src)
{
if (src)
{
return new node(*src);
}
return nullptr;
}
// generic constructor
node(int number = 0,
node* right_child = nullptr,
node* left_child = nullptr):
number(number),
right_child(right_child),
left_child(left_child)
{
}
//copy constructor
node (const node & src):
number(src.number),
right_child(clone(src.right_child)),
left_child(clone(src.left_child))
{
}
// assignment operator via copy and swap.
node & operator=(node src)
{
std::swap(number, src.number);
std::swap(right_child, src.right_child);
std::swap(left_child, src.left_child);
return *this;
}
// destructor
~node()
{
delete right_child;
delete left_child;
}
};
void test(node* node1,
node* node2){
*node1 = *node2; // now, thanks to all of the infrastructure above, we can
// assign nodes with the dumb old = operator. All we have to do
// is dereference the pointers.
}
int main(){
struct node* a1 = new node; // wasted memory. We're about to replace it.
// need a more complicated tree to prove deep copy works
struct node* a2 = new node{3,
new node{4, nullptr, nullptr}, // a right node
nullptr}; // no left node
// a2->number = 3; done above now
test(a1 , a2);
std::cout << a1->number << ' '
<< a1->right_child->number;
delete a1; // clean up
delete a2;
}
All of the nodes are now self-managing.
But, my opinion, the nodes should be kept as dumb as they are in the simple example. They shouldn't need to know about the tree at all. Knowledge of the tree should be in a Tree class that uses the nodes as simple containers. The Tree class should do all of the management of the nodes--creating, copying, cloning, deleting--because only it knows everything necessary to represent the tree. The users of the tree shouldn't even know nodes exist. They put data into the tree, take data out of the tree, and observe the tree without caring how the tree works and being able to so something stupid like
delete a_node;
and blow the crap out of data the tree isn't done with yet.
The Tree class preferably works iteratively rather than recursively so that the trees can be arbitrarily sized. Unless you're really careful recursing through a large tree to clone it, delete it, display it, or pretty much anything else you do with a tree runs the risk of exhausting automatic storage and causing what's typically called a Stack Overflow.
just use
void test(struct node *node1, struct node *node2) { *node1 = *node2; }
instead of
void test(struct node *node1, struct node *node2) { node1 = node2; }
and it will print 3.
This is because...
when you do node1 = node2; int the test1, you assign the pointer itself, not the structure pointed to by the pointer.When the function ends, the parameters node1 and node2 will be destroyed, so you have done nothing...

How do I access a specific pointer, within an array of structures?

I have a structure with two pointers that I am storing inside of an array of the same type. I am unsure of how to access the pointers in each specific index of the array.
class List
{
public:
List();
private:
struct L_Node
{
L_Node *next;
L_Node *prev;
int iValue; // not actually doing anything in this example
}
L_Node head[4];
L_Node tail[4];
}
In the constructor, I am wanting head[0] next to be pointing to tail[0] next, head[1] next to tail[1] next and so on, with *prev to be pointing from tail to head to form a doubly linked list. For head, prev = NULL, and in tail next=NULL. In between the head and tail arrays, I am trying to have some dynamic instances of L_Node.
As of now, in my constructor, I have
head->next = new L_Node;
head->prev = NULL;
tail->next = NULL;
tail->prev = new L_Node;
head->next->next = tail;
tail->prev->prev = head;
It compiles, however I am unsure of how it is behaving. Is head[0] pointing through the dynamic struct to tail[0] and so on?
Thanks in advance for any help or tips.
EDIT:
would a typedef for a pointer such as
typedef L_Node *L_Ptr;
be of help?
From your description, this is what you need in the constructor of List:
List::List()
{
for (int i = 0; i != 4; ++i )
{
head[i].next = tail[i];
tail[i].prev = head[i];
}
}
I would add a constructor in L_Node to have sane initial values for its member data.
L_Node() : next(NULL), prev(NULL), iValue(0) {}

Appending node to LinkedList

I am trying to create a function that adds a node to the end of a LinkedList. I know how to do it using loops, but my professor wants it done a certain way and I don't understand why it's not working. He practically gave us all the code for it..
This is the pseudo-code he gave us:
process append(data)
if (not the end)
next->append(data);
else
next=new Node();
next->data=data;
next->data = nullptr;
And this is what I came up with:
struct Node {
int data;
Node* next;
};
struct LinkedList {
Node* head;
LinkedList() {head = nullptr;}
void prepend(int data) {
if (head == nullptr) {
Node* tmp = new Node();
tmp->data=data;
tmp->next=nullptr;
}
else {
Node* tmp = new Node();
tmp->data=data;
tmp->next=head;
head=tmp;
}
}
void append(int data) {
Node* tmp = head;
if (tmp->next != nullptr) {
tmp=tmp->next->append(data);
}
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
};
int main()
{
LinkedList LL = LinkedList();
LL.prepend(7);
LL.append(6);
std::cout << LL.head->data << std::endl;
}
My prepend (to add to the beginning of the LinkedList) works fine, but when I try this code, I get
main.cpp:48:20: error: 'struct Node' has no member named 'append'
tmp->next->append(data);
So I'm pretty sure that there's something wrong with saying next->append(data), which from what I understood, is supposed to be recursively calling back the append function until it reaches a nullpointer. I'm thinking maybe there's some sort of way to write it, but people in my class are telling me that the next->append(data) thing SHOULD work, so I guess I'm not exactly sure why this isn't doing anything. I tried instead writing the append function in the Node struct, but then it says that head wasn't declared in the scope and I really just don't know how to work with this. I'm also sort of new to classes/structs in C++ so I'm assuming it's something about that that I'm not understanding.
The class Node has not any method named append so you get that error message:
tmp->next->append(data);
^^^^^^^^^^^^^
struct Node {
int data;
Node* next;
};
To append a node to a linked-list, you don't need an append method within Node. Remove that. Correct the append process in LinkedList::append:
void append(int data) {
Node* tmp = head;
while (tmp->next)
tmp = tmp->next;
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
I did't test, but you need something like above code. At first, it tries to access to the end of list. Then it appends a node.
Recursive implementation:
void append(int data) {
append(data, head);
}
void append(int data, Node *node) {
if (node->next)
append(data, node->next);
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
Your append method isn't defined on the Struct Node. Instead it's defined on the LinkedList class so you need to invoke it accordingly. You can redefine the append method to take a node as a parameter or add an append method to the Struct Node itself. Also there's no need to assign the result of append to tmp =
Your append method is void.
tmp->next is a Node, so to call append function, you must declare it in Node struct
Like this
struct Node
{
void append(int data)
{
if (next)
next->append(data);
else
{
next = new Node();
next->data = data;
next->next= nullptr;
}
}
int data;
Node* next;
};
it's clear from the pseudo code next->append(data); that append is meant to be a member of Node.
Here's how you might use Node::append from LinkedList::append
class LinkedList {
void append(int data) {
if (head == nullptr) {
head = new Node();
head->data=data;
head->next=nullptr;
}
else {
head->append(data);
}
}
}
The node structure does not contain any append method.
Moreover, you are splitting work that can be done in one methos to two methods, writing more code.
See my answer to another question here with working code I wrote
https://stackoverflow.com/a/37358192/6341507
As you can see, I solve all in method
AddItem(int i)
I start seeing that creating linked list i kindof har for many people here, so I will further edit my answer there to provide additional information.
Good luck!

Mixing abstract classes and templates, a recipe for disaster?

I'm having problems with the following situation. I have three classes that are involved in this mixup. List, ListNode, City. I have a List<City *>, where the list will be made up of a set of ListNode<City *> (standard wrapper around the list nodes).
City is an abstract class, so there are several classes that inherit from it that could be placed in this list and accessed polymorphically. The List class has a getHead() method which returns a pointer to a ListNode that is the head.
Any city has a population, so to access the populations, I'd expect the following to work. It's not, thus my question. I broke it down into pieces to make it simpler along the way:
ListNode<City *> *head= country->city_list->getHead();
City *headnode = *head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
getPopulation() returns an integer. country is defined as List<City*> *city; Any help on how I could figure out my problem would be greatly appreciated.
edit adding more code for better idea of what I'm working with. First, ListNode:
template <class T>
class ListNode
{
public:
ListNode() {next = 0;node = 0;};
ListNode(T *t) {node = t; next = 0;};
ListNode(const ListNode &l)
{
//long copy constructor. snip.
};
T *getNode() const { return node; }
ListNode *getNext() const { return next; };
private:
T *node;
ListNode *next;
};
Now, here is what might relevant in the List class..
template <class T>
class List
{
public:
List()
{
head = 0;
size = 0;
};
List(ListNode<T> *t)
{
head = t;
size = 1;
};
List(T *t)
{
head = new ListNode<T>(t);
size = 1;
};
List(const List<T> &t)
{
// long copy constructor. snip.
};
//bunch of irrelevent methods.
ListNode<T> *getHead() const {return head;};
List &operator+=(T &t)
{
this->insert(&t);
size++;
return (*this);
};
private:
List &insert(T *t)
{
ListNode<T> *current = head;
if (current == 0)
{
head = new ListNode<T>(t);
}
else
{
while (current->getNext() != 0)
{
current = current->getNext();
}
current->setNext(new ListNode<T>(t));
}
return (*this);
};
ListNode<T> *head;
int size;
};
I have a hunch that the process of inserting might be the problem. I insert with the List class's += operator, shown in the List implementation above. It calls the private insert method shown above, as well. It looks like this:
City *somecity = new City(x,y,z); //some parameters. integers.
*city_list += somecity; // where city_list is a List.
I think you've got a variable scoping problem.
Your ListNode class contains a pointer to the node value. Your ListNode constructor takes in a pointer to the node value and saves it.
The problem is if that pointer is to a local variable that then goes out of scope. Your ListNode's node pointer is now pointing to an object that doesn't exist. e.g. in this example
addToList(List<int>& myList)
{
int x = 3;
myList += x; // pointer to x is in the list
}
// Out of scope; x no longer exists, but myList has a pointer to it.
// Accessing this node will result in an error.
There are a couple possible remedies:
Have your ListNode contain values rather than pointers. The drawback here is that you will be making copies of the values
Implement ListNode using a reference counted smart pointer which will manager the lifetime of the object.
Well, what you could do is:
ListNode<City *>* head = new ListNode<City*>(country->city_list->getHead());
City* headnode = head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
It will take the existing City (on the memory) and put it at the head of the List node, and so on.
and if you want to copy them, maybe you could just make this:
ListNode<City *>* head = new ListNode<City*>*(new City(country->city_list->getHead()));
City* headnode = new City(head->getNode());
cout << "Test: " << headnode->getPopulation() << endl;
Hope it will help you.