Assigning a struct pointer value from struct vector - c++

#include <iostream>
#include <vector>
using namespace std;
struct Sn {
int SnId;
double spentEnergy;
};
class Node {
//other stuff
private:
vector<Sn> SnRecord;
public:
int getBestSn(Sn* bestSn);
void someFunction();
};
int main()
{
Node nd;
nd.someFunction();
return 0;
}
void Node::someFunction() {
//adding some records in vector just for testing purpose
Sn temp;
temp.SnId = 1; temp.spentEnergy = 5;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
cout << "Size of SnReocord is " << SnRecord.size() << endl;
//choosing best sn
Sn *bestSn;
int returnCode = -1;
returnCode = getBestSn(bestSn);
if (returnCode == 0){ //means there is a best SN
cout<< "Found best SN with id = "<< bestSn->SnId << endl;
}
else {
cout <<"NO SN "<< endl;
}
}
int Node::getBestSn(Sn* bestSn) {
int tblSize = (int)SnRecord.size();
if (tblSize == 0)
return -1;
//here i have to assign *bestSn a selected value from vector
//suppose SnRecord[2] is best Sn
cout << "Best sn id is " << SnRecord[2].SnId<< endl; //works OK,
bestSn = &SnRecord[2]; ///// giving me core dump ERROR in my own program but in this simplified version it only gives wrong value
return 0;
}
The output now is:
Size of SnReocord is 3
Best sn id is 2
Found best SN with id = 520004336
In my own program it gives me Core dump error, if I comment this line (and make proper other comments according to function call), the error is gone and simulation executes normally.
I saw examples with arrays, the work if a pointer is assigned a value in this way:
int numbers[5];
int * p;
p = &numbers[2]; //works OK.
but for vectors its not working. Or may be its problem of vector of structures, I'm unable to figure out. Any suggestions?

Ok actually the problem is solved by using suggestion of Sn* & bestSn. But I don't understand this solution. Why can't I pass a pointer variable and it saves a pointer value in it which latter could be accessed?

Related

Strange C++ output with boolean pointer

I have the following code:
#include <iostream>
using namespace std;
int main() {
int n = 2;
string s = "AB";
bool* xd = nullptr;
for (int i = 0; i < n; i += 100) {
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
cout << "wtf: " << " " << (*xd) << " " << endl;
}
}
When I run this on my own mac with g++ -std=c++17, I get a random integer every time (which is odd since *xd should be a bool). Weirdly enough, this doesn't happen on online IDEs like csacademy and onlinegdb.
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
tmp is an automatic variable. It is destroyed automatically at the end of the scope where the variable is declared. In this case, the lifetime of the object ends when the if-statement ends. At that point, the pointer xd which pointed to the variable becomes invalid.
(*xd)
Here, you indirect through an invalid pointer. That's something that a program must never do. The behaviour of the program is undefined. The program is broken. Don't do this.

C++ access an element of struct array in a struct

This thing has been driving me crazy for a while now.
I need to create and traverse (post order) a general tree where each node (a structure) is added by the user via console.
I am NOT allowed to use STL.
The user specifies how many nodes will be added, and how many 'child' nodes it can hold (number) and the name of the node (string).
Example input:
5
1 A
2 B
1 C
1 D
3 E
The above means that 5 nodes will be added. The first one (A) can accept one 'child' node, (B) can accept 2 such nodes and (C) can accept 1 etc.
The newly added nodes have to always be added to the 'highest' possible node from the top (if it still can accept a new 'child' node, if not possible you go to the next one).
The idea is to create an array (I know how many nodes will be added in total) and put those nodes specified by the user there and 'link' them accordingly using array of pointers inside of a structure.
The output of given example should be: E C D B A
I have written the whole thing as follows but I am unable to traverse the tree:
structure:
struct node {
string name = "";
int noChildrenAdded = 0;
int possibleNoChildren = 0;
int childrenFreeSlots = 0;
node* children = nullptr;
node* father = nullptr;
};
traverse function that's not working
void traverse(node* father)
{
cout << father->name << endl;
if (father == nullptr) {
return;
}
for (int i = 0; i < father->possibleNoChildren; i++) {
if (&father->children[i] == nullptr) {
continue;
}
traverse(&father->children[i]);
}
cout << father->name << "\n";
}
main
int main() {
int n = 0;
short g = 0;
string name;
cin >> n;
node* tree = new node[n];
node* tmp = nullptr;
//adding children to tree array
for (int i = 0; i < n; i++) {
cin >> g >> name;
tree[i].possibleNoChildren = tree[i].childrenFreeSlots = g;
tree[i].name = name;
tree[i].noChildrenAdded = 0;
tree[i].children = new node[1];
}
// making connections between nodes
for (int son = 1; son < n; son++) {
for (int father = 0; father < son; father++) {
if (tree[father].childrenFreeSlots > 0) {
//resizing array
if (tree[father].noChildrenAdded == 0) {
tree[father].children[0] = tree[son];
}
else {
int added = tree[father].noChildrenAdded;
tmp = new node[added + 1];
for (int i = 0; i < added; i++) {
tmp[i] = tree[father].children[i];
}
delete[] tree[father].children;
tree[father].children = nullptr;
tree[father].children = tmp;
tree[father].children[added] = tree[son];
tmp = nullptr;
}
tree[father].noChildrenAdded++;
tree[father].childrenFreeSlots -= 1;
break;
}
}
}
//this is how it should be
cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
//tree[0].children[0] is holding pointer to drzewo[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
//traverse(&tree[0]);
delete[] tree;
}
THE PROBLEMS
I am unable to access details of a structure (for example noChildrenAdded) - I am getting zero, despite the fact that noChildrenAdded is populated. When I access it via tree array I am getting the correct number but when I do it via pointer inside of a struct I am getting 0.
Example:
This is correct: cout << "Father: " << tree[1].name << "\tchildren added: " << tree[1].noChildrenAdded << endl;
But this is not (despite both should be giving the same number/answer):
//tree[0].children[0] is holding pointer to tree[1] so the below should give me the same answer as above.
//this is giving me wrong answer
node* ptr = &tree[0].children[0];
cout << "Father: " << ptr->name << "\tchildren added: " << ptr->noChildrenAdded << endl;
I expect I have messed up assigning children to the *children array inside of a struct. The name seems to be accessible fine but not the noChildren.
Both should be giving the same answer but they are not:
enter image description here
Any help would be greatly appreciated!
PS: when I use this code with static array of children everything is ok, traversal works fine but when I get a dynamic array it's broken. Static array alas won't do as it taking too much memory and takes way too long so my program fails the requirements.
Just as #igor-tandetnik suggested, using an array of node* pointers solved the problem. In my case solution was to use node** children not node *children.

list requires class type

So I'm trying to make a bubble sort algorithm in class and I'm having this problem where it keeps giving me an error when I'm trying to find the length of the list where it says "expression must have a class type" and for the life of me I cannot figure out what to do. the tutorial I'm using isn't an help and I cannot find any other people with the same problem.
if anyone gets what it is asking I would appreciate the help, and any explanation would also be appreciated as I'm still new and would like to understand so I can try to learn
this was all done on VS 2017 (the free version)
#include "pch.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
bool found = true;
int target{ 0 };
int temp{};
bool ordered{ false };
int list[10] = { 4,6,5,1,3,2,10,8,9,7 };
cout << list.length() << endl;
bool swapped{ false };
while (ordered = false)
{
target = 0;
while (target != list.length)
{
if (list[target] > list[target + 1])
{
swapped == true;
list[target] = temp;
list[target] = list[target + 1];
list[target + 1] = temp;
target = target + 1;
}
else
{
target = target + 1;
}
}
if (swapped == false)
{
ordered = true;
}
}
cout << list << endl;
getchar();
return 0;
}
link to the photo of the error message
The error you have mentioned ("expression must have a class type") is caused by the below statement and other similar statements :
cout << list.length() << endl;
list is an integer array of size 10 as per this statement int list[10];
So you cannot use a . on it. You can use the . operator on a structure or class or union only. And even if list were a class/structure, length() method should be defined in it for the above to work.
Instead you should use sizeof operator. You can store it in a variable and use it later on.
size_t length = sizeof list/sizeof list[0];
cout << length << endl;

Class method returns last made of class, C++

So for school I have to make a Node class that holds a time and a number (it's used for an insertion sort later). I'm still new to C++ so I'm probably doing something wrong here, but whenever I call my GetNumber() method, it will return only the number of the last Node that was made. My code is below:
Node.cpp
#include "Node.h"
int n, t;
Node::Node(int number, int time)
{
n = number;
t = time;
}
Node::~Node(void)
{
}
int Node::GetTime(void)
{
return t;
}
int Node::GetNumber(void)
{
return n;
}
And in main:
Node f(123, GetTickCount());
for (int i = 0; i < 1000; i++){}
Node g(124, GetTickCount());
for (int i = 0; i < 1000; i++){}
Node d(111, GetTickCount());
cout << f.GetNumber() << " " << f.GetTime()<<endl;
cout << g.GetNumber() << " " << g.GetTime()<<endl;
cout << d.GetNumber() << " " << d.GetTime()<<endl;
And the output:
111 168921894
111 168921894
111 168921894
int n, t;
You are declaring n and t as global variables - they don't belong to any particular object. All Nodes will see the same n and t objects.
You should be declaring these as members of Node:
class Node {
// ...
int n, t;
// ...
};
The problem here is you are using file level variables as the storage for all Node values. Instead you need to store them as instance fields in the type
class Node {
...
private:
int n;
int t;
};
Once those fields are defined delete the declaration at the top of the file for n and t
You didn't define "n" and "t" in the class and so they are global and only the last one to change is the one that is relevant.

converting int to pointer

I want to save int value to a pointer variable. But I get an error:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = (int*)no_of_records; // <<< Doesn't give value of NumRecPrinted
cout << "NumRecPrinted!" << NumRecPrinted;
return 0;
}
I tried doing this but I get 0 as return:
int main()
{
int demo(int *NumRecPrinted);
int num = 2;
demo(&num);
cout << "NumRecPrinted=" << num; <<<< Prints 0
return 0;
}
int demo (int *NumRecPrinted)
{
int no_of_records = 11;
NumRecPrinted = &no_of_records;
}
NumRecPrinted returns as 0
It's sometimes useful to "encode" a non-pointer value into a pointer, for instance when you need to pass data into a pthreads thread argument (void*).
In C++ you can do this by hackery; C-style casts are an example of this hackery, and in fact your program works as desired:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = (int*)no_of_records;
cout << "NumRecPrinted!" << NumRecPrinted; // Output: 0xa (same as 10)
return 0;
}
You just need to realise that 0xa is a hexadecimal representation of the decimal 10.
However, this is a hack; you're not supposed to be able to convert ints to pointers because in general it makes no sense. In fact, even in the pthreads case it's far more logical to pass a pointer to some structure that encapsulates the data you want to pass over.
So, basically... "don't".
You want to be doing this:
NumRecPrinted = &no_of_records;
i.e. you're taking the address of no_of_records and assigning it to NumRecPrinted.
And then to print it:
cout << "NumRecPrinted!" << *NumRecPrinted;
i.e. you're dereferencing NumRecPrinted which will get the int stored at the memory address pointed to by NumRecPrinted.
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL; // assign pointer NumRecPrinted to be valued as NULL
int *NumRecPrinted2 = NULL;
int no_of_records = 10; // initialize the value of the identificator no_of_records
NumRecPrinted = (int*)no_of_records; // sets a pointer to the address no_of_records
NumRecPrinted2 = &no_of_records; // gives a pointer to the value of no_of_records
cout << "NumRecPrinted!" << NumRecPrinted; // address of no_of_records 0000000A
cout << "NumRecPrinted!" << *NumRecPrinted2; // value of no_of_records 10
system("pause"); // ninja
return 0;
}
Here is the corrected version:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = &no_of_records; // take the address of no_of_records
cout << "NumRecPrinted!" << *NumRecPrinted; // dereference the pointer
return 0;
}
Note the added ampersand and the asterisk.
(int *)no_of_records gives you a pointer to the address no_of_records. To get a pointer to the value of no_of_records, you need to write &no_of_records.
I really like using union for this sort of stuff:
#include <iostream>
using namespace std;
int main()
{
static_assert(sizeof(int) == sizeof(int*));
union { int i; int* p; } u { 10 };
cout << "NumRecPrinted! " << u.p;
return 0;
}