c++ store items into an array - c++

I have this code that in my mind, it recieved an item called Vehicle and it has to store it in an array called Node. This is the code related to this part of the program:
void Table::process(Vehicle v, int cont) {
char a='A'+cont;
putVehicle(a,v);
Node.a_v[cont]=v;
if(cont==0) a_surt=v.rowVehicle();
}
This is how I have the array on the private part of Table.h:
struct Node{
Vehicle a_v;
};
The error I get is:
error: expected primary-expression before '.' token
I have the includes I need, but everytime I type this: Node.a_v It gives me that error.
Any advice?

If you want to use a struct, you need to declare a Node before using it. Also, the struct needs to contain an array (or better, look into vectors for more flexibility).
struct Node {
Vehicle[10] a_v; // 10 is max number of Vehicles in array
};
Node myNode;
myNode.a_v[cont] = v;
Remember that if you want to keep this Node around and put more things in it, it needs to be declared in the right scope. For example, to have your process function add a Vehicle to a Node that exists outside of the function process, you could something like this:
void Table::process(Node n, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) {
n.a_v[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
It kind of looks like you're just trying to use an array. In that case you're looking for something like this:
// This would go somewhere in your program. Again, 10 is just an example.
Vehicle vehicleArray[10];
// Send this array to this function
void Table::process(Vehicle[] vArray, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) { // In a real program, don't hard-code array limits.
vArray[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}

You should use Node object to get access to the a_v variable. This line
Node.a_v[cont]=v;
Is incorrect. You should do something like that:
Node n;
n.a_v[cont]=v;

everytime I type this: Node.a_v It gives me that error.
Node is a type; types define the structure of a objects, but they do not have fields of their own (except the static fields, which belong to all instances at once; they are accessed differently anyway).
In order to use a . or -> operator, you need an instance of a Node, like this:
Node x;
x.a_v = ...
It is not clear in your case from where the Node instances should be coming, though. In order to access them, you would need to either pass them in as parameters, or make them available statically/globally (not recommended).

Okay, so Node is NOT the name of your array. It's the name of a user-defined type that is supposed to contain an array. Your Node, however, does not contain an array. It contains one Vehicle, named a_v. I assume a_v is supposed to represent an Array of Vehicles. Therefore, you need to allocate the array. Something like this:
struct Node {
Vehicle a_v[AMOUNT];
};
If you don't know at compile-time how large you want your arrays to be, then they must be dynamically allocated, like this:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
};
If it's dynamically allocated, then it must also be deallocated:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
};
AND if it's dynamically allocated, you need to add provisions for copying or disable copying:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
// Disable copies (with C++11 support):
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// Disable copies (without C++11 support) by making them private and not defining them.
private:
Node(const Node&);
Node& operator=(const Node&);
};
Then to access one of the Vehicles, you'd need to do so like this:
Node n; // Declare a node, which contains an array of Vehicles
n.a_v[cont] = v; // Copy a Vehicle into the array of Vehicles
Note, however, that if you declare the Node instance in this function, then it is local and it will go out of scope as soon as your function ends. You need to declare the Node instance as a member of your Table if you want it to persist past the function call.
class Table
{
private:
Node n;
};
Lastly, as others have suggested, I'd highly recommend that you read a C++ book to learn C++. My personal recommendation is this book (5th edition, don't buy 6th or 7th - the author of those editions is terrible).

Related

How to avoid using new operator in C++?

I have a C++ program that creates Huffman codes for all characters in file. It works good, but I want to create nodes without using new operator because I know that you shouldn't use it. I tried using a vector global variable for saving nodes but that doesn't work.
std::vector<Node> nodes;
Node* create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
Node temp;
temp.m_value = value;
temp.m_counter = counter;
temp.m_left = left;
temp.m_right = right;
nodes.push_back(temp);
return &nodes[nodes.size() - 1];
}
Edit: I added more code, I did't really explained what doesn't work. Problem is in generate_code(), it never reaches nullptr. I also tried using Node and not Node* but the same thing happened.
void generate_code(Node* current, std::string code, std::map<unsigned char, std::string>& char_codes) {
if (current == nullptr) {
return;
}
if (!current->m_left && !current->m_right) {
char_codes[current->m_value] = code;
}
generate_code(current->m_left, code + "0", char_codes);
generate_code(current->m_right, code + "1", char_codes);
}
void huffman(std::ifstream& file) {
std::unordered_map<unsigned char, ull> char_frequency;
load_data(file, char_frequency);
std::priority_queue<Node*, std::vector<Node*>, Comparator> queue;
for (auto& node : char_frequency) {
queue.push(create_node(node.first, node.second, nullptr, nullptr));
}
while (queue.size() != 1) {
Node* left = queue.top();
queue.pop();
Node* right = queue.top();
queue.pop();
auto counter = left->m_counter + right->m_counter;
queue.push(create_node('\0', counter, left, right));
}
std::map<unsigned char, std::string> char_codes;
Node* root = queue.top();
generate_code(root, "", char_codes);
for (auto& i : char_codes) {
std::cout << +i.first << ": " << i.second << "\n";
}
}
The general answer is of course to use smart pointers, like std::shared_ptr<Node>.
That said, using regular pointers is not that bad, especially if you hide all pointers from the outside. I wouldn't agree with "you shouldn't use new", more like "you should realize that you have to make sure not to create a memory leak if you do".
In any case, for something like you do, especially with your vector, you don't need actual pointers at all. Simply store an index for your vector and replace every occurence of Node* by int, somewhat like:
class Node
{
public:
// constructors and accessors
private:
ValueType value;
int index_left;
int index_right;
}
I used a signed integer as index here in order to allow storing -1 for a non-existent reference, similar to a null pointer.
Note that this only works if nothing gets erased from the vector, at least not before everything is destroyed. If flexibility is the key, you need pointers of some sort.
Also note that you should not have a vector as a global variable. Instead, have a wrapping class, of which Node is an inner class, somewhat like this:
class Tree
{
public:
class Node
{
...
};
// some methods here
private:
vector<Node> nodes;
}
With such an approach, you can encapsulate your Node class better. Tree should most likely be a friend. Each Node would store a reference to the Tree it belongs to.
Another possibility would be to make the vector a static member for Node, but I would advise against that. If the vector is a static member of Node or a global object, in both cases, you have all trees you create being in one big container, which means you can't free your memory from one of them when you don't need it anymore.
While this would technically not be a memory leak, in practice, it could easily work as one.
On the other hand, if it is stored as a member of a Tree object, the memory is automatically freed as soon as that object is removed.
but I want to create nodes without using new operator because I know that you shouldn't use it.
The reason it is discouraged to use new directly is that the semantics of ownership (i.e. who is responsible for the corresponding delete) isn't clear.
The c++ standard library provides the Dynamic memory management utilities for this, the smart pointers in particular.
So I think your create function should look like follows:
std::unique_ptr<Node> create_node(unsigned char value, unsigned long long counter, Node* left, Node* right) {
std::unique_ptr<Node> temp = std::make_unique<Node>();
temp->m_value = value;
temp->m_counter = counter;
temp->m_left = left;
temp->m_right = right;
return temp;
}
This way it's clear that the caller takes ownership of the newly created Node instance.

How to initialize an array instance of the class within it self?

I want to be able to create an array of Nodes, within a constructor of Node. However i am getting some kind of heap error.
I wrote a Node class with a constructor trying to instantiate Node array with new.
class Node
{
private:
Node* nodes;
int max_size;
int current_size;
public:
Node()
{
max_size = 10;
current_size = 0;
nodes = new Node[max_size]; // Error is here*
}
};
I am hoping to create an object that creates 10 instances of that object within a constructor. As I am writing this i realized that this will create an infinite loop. Those 10 will create another 10 each, and so on. How should i go about solving this? Should i make a double pointer?
If you try to instantiate new Node objects in the Node constructor you will keep making recursive calls to the constructor and run out of memory. You are trying to create a node, which creates 10 nodes, and each of those create 10 nodes, and so on.
If you want to just allocate space for max_size nodes, you will need to use a double pointer if you don't want to use std::vector.
class Node {
private:
Node** nodes;
...
public:
// Constructor
Node() {
...
nodes = new Node*[max_size];
}
};
Outside the constructor you can populate that array with new Node objects through a separate function.

Copy constructor for a vector of pointers

I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};

Linked List using Void* pointers

I want to create a generic linked list in C/C++ (without using templates of C++).
I have written following simple program and it works fine as of now -
typedef struct node
{
void *data;
node *next;
}node;
int main()
{
node *head = new node();
int *intdata = new int();
double *doubledata = new double();
char *str = "a";
*doubledata = 44.55;
*intdata = 10;
head->data = intdata;
node *node2 = new node();
node2->data = doubledata;
head->next = node2;
node *node3 = new node();
node3->data = str;
node3->next = NULL;
node2->next = node3;
node *temp = head;
if(temp != NULL)
{
cout<<*(int *)(temp->data)<<"\t";
temp = temp->next;
}
if(temp != NULL)
{
cout<<*(double *)(temp->data)<<"\t";
temp = temp->next;
}
if(temp != NULL)
{
cout<<*(char *)(temp->data)<<"\t";
temp = temp->next;
}
return 0;
}
My question is -
I need to know the data type of the data I am printing in the code above.
For example - first node is int so i wrote -
*(int *)(temp->data)
second is double and so on...
Instead, is there any generic way of simply displaying the data without worrying about the data type?
I know you can achieve this with templates, but what if I have to do this in C only ?
Thanks,
Kedar
The whole point of a generic list is that you can store anything in it. But you have to be realistic... You still need to know what you are putting in it. So if you are going to put mixed types in the list, then you should look at using a Variant pattern. That is, a type that provides multiple types. Here's a simple variant:
typedef struct Variant
{
enum VariantType
{
t_string,
t_int,
t_double
} type;
union VariantData
{
char* strVal;
int intVal;
double doubleVal;
} data;
} Variant;
You can then tell yourself "I'm storing pointers to Variants in my void* list. This is how you would do it in C. I assume when you say "C/C++" you mean that you're trying to write C code but are using a C++ compiler. Don't forget that C and C++ are two different languages that have some overlap. Try not to put them together in one word as if they're one language.
In C, the only way to achieve generics is using a void*, as you are already doing. Unfortunately, this means that there is no easy way to retrieve the type of an element of your linked list. You simply need to know them.
The way of interpreting data in memory is completely different for different data type.
Say a 32 bit memory block has some data. It will show different values when you typecast it as int or float as both are stored with different protocols. When saving some data in memory pointed by variable of type void*, it does not know how to interpret the data in its memory block. So you need to typecast it to specify the type in which you want to read the data.
This is a little bit like sticking all the cutlery in a drawer, but instead of putting knifes in one slot, forks in another slot, and spoons in a third slot, and teaspoons in the little slot in the middle, we just stick them all in wherever they happen to land when chucking them in, and then wondering why when you just stick your hand in and pick something up, you can't know what you are going to get.
The WHOLE POINT of C++ is that it allows you to declare templates and classes that "do things with arbitrary content". Since the above code uses new, it won't compile as C. So there's no point in making it hold an non-descriptive pointer (or even storing the data as a pointer in the first place).
template<typename T> struct node
{
T data;
node<T> *next;
node() : next(0) {};
};
Unfortunately, it still gets messier if you want to store a set of data that is different types within the same list. If you want to do that, you will need something in the node itself that indicates what it is you have stored.
I have done that in lists a few times since I started working (and probably a couple of times before I got a job) with computers in 1985. Many more times, I've done some sort of "I'll store arbitrary data" in a something like a std::map, where a name is connected to some "content". Every time I've used this sort of feature, it's because I'm writing something similar to a programming language (e.g. a configuration script, Basic interpreter, LisP interpreter, etc), using it to store "variables" that can have different types (int, double, string) or similar. I have seen similar things in other places, such as OpenGL has some places where the data returned is different types depending on what you ask for, and the internal storage has to "know" what the type is.
But 99% of all linked lists, binary trees, hash-tables, etc, that I have worked on contain one thing and one thing only. Storing "arbitrary" things in a single list is usually not that useful.
The answer below is targeting at C++ and not C. C++ allows for what you want, just not in the way that you want to do it. The way I would implement your problem would be using the built-in functionality of the virtual keyword.
Here's a stand-alone code sample that prints out different values no matter the actual derived type:
#include <iostream>
#include <list>
class Base
{
public:
virtual void Print() = 0;
};
class Derived1 : public Base
{
public:
virtual void Print()
{
std::cout << 1 << std::endl; // Integer
}
};
class Derived2 : public Base
{
public:
virtual void Print()
{
std::cout << 2.345 << std::endl; // Double
}
};
class Derived3 : public Base
{
public:
virtual void Print()
{
std::cout << "String" << std::endl; // String
}
};
int main(void)
{
// Make a "generic list" by storing pointers to a base interface
std::list<Base*> GenericList;
GenericList.push_back(new Derived1());
GenericList.push_back(new Derived2());
GenericList.push_back(new Derived3());
std::list<Base*>::iterator Iter = GenericList.begin();
while(Iter != GenericList.end())
{
(*Iter)->Print();
++Iter;
}
// Don't forget to delete the pointers allocated with new above. Omitted in example
return 0;
}
Also notice that this way you don't need to implement your own linked list. The standard list works just fine here. However, if you still want to use your own list, instead of storing a void *data;, store a Base *data;. Of course, this could be templated, but then you'd just end up with the standard again.
Read up on polymorphism to learn more.

C++ Losing Template Data

I don't consider myself all that knowledgeable in C++ but I'm having a hard time with this concept. So I have a class the holds some template datatype and a double. I want the m_data variable to be generic, but right now I'm only testing with an unsigned int. When I call the function SetData() with say a pointer to an unsigned int I lose the info the pointer is pointing to. This happens when I go out of scope, so I felt I need to do a deep copy of it...
I tried many different constructors and assignment operators but I still lose the info... I feel I'm missing something obvious about templates here.If anyone could point me in the right direction as to why the data is being lost I would be very grateful.
Small bit of code:
template<typename T>
class PointNode {
public:
PointNode(double p){ m_point = p;}
~PointNode();
void SetData(T * data);
T * GetData() const;
private:
double m_point;
T *m_data;
};
template<typename T>
void PointNode::SetData(T * data)
{
m_data = data;
}
template<typename T>
T * PointNode::GetData()
{
return m_Data;
}
OK some more info. This class is being stored in a map that is a member of another class. Heres a bit of it.
template<typename T>
class AuMathPointTreeT
{
public:
//Member Variables
double m_dTolerance;
unsigned int m_cPoint;
map<VectorKey, PointNode<T> > m_tree; /*map posing as a tree */
typename map<VectorKey, PointNode<T> >::iterator iter; /* iterator */
pair< typename map<VectorKey, PointNode<T> >::iterator, bool > return_val;
/* Tree methods */
//constructor
AuMathPointTreeT(double tol);
...
};
In another program I'm using this class, creating node and setting the template data like so
if (node = pnttree.AddPoint(point) )
{
unsigned int * data = new unsigned int();
*data = pntCount;
node->SetData(data);
++pntCount;
}
UPDATE: Ok discovered the culprit of what's wrong, and would like suggestions on how to approach it. When I insert a node into the map class a few functions are called in the process and im losing the original pointer to the newly allocated node class object. Here is what I'm doing.
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
AddPoint(double point)
{
PointNode<T> * prNode = MakeNode(point);
m_cPoint++;
return prNode;
}
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
MakeNode(double point)
{
PointNode<T> * prNode = new PointNode<T>;
//set the contents for the node just performs a few calcs on the values
prNode->SetNode(point, m_dTolerance);
//Create the key class using the
VectorKey key(point, m_dTolerance);
//Store the key,node as a pair for easy access
return_val = m_tree.insert( pair<VectorKey, PointNode<T> >(key, *prNode) );
if (return_val.second == false)
prNode = NULL;
unsigned int * test = new unsigned int;
*test = 55;
prNode->SetData(test); //if call this here its no longer the right pointer
return prNode;
}
So after looking at this... I really still want to return a pointer and use it. But maybe the iterator being held by return_val? Im open on suggestions for all aspects too.. Sorry this question has been a mess :\
I don't think this has anything to do with the use of templates. Once a local variable goes out of scope, its location on the stack could be over-written by other data.
If you expect the template class instance to out-live the local variable whose address is passed to SetData, you should consider allocating the data on the heap not the stack. Either way, I'd suggest replacing the raw m_data pointer with an appropriate smart pointer. For example, the use of shared_ptr<> in the template class and its client code should reduce the amount of data copying while at the same time ensuring the data remains valid regardless of whether or not the original data variable is in scope.
If you want a deep copy, you must use T and not T*, or you must do dynamic memory allocation with T* (but it's overkill) and will bring a similar result.
If you really want Nodes of pointers, it will be when you use your Node.
Exemple:
int number = 5;
Node<int*> oneNode(&number); // number will die at end of scope
Node<int> anotherNode(number); //anotherNode can be used without risk
your code will not compile because of your constructor
PointNode(double p){ m_point = p;}
m_point is const, you have to write it to the initializer list:
PointNode(double p) : m_point(p) {}