I have a list that hold an array of lists.
I have 2 object types "Flight" and "People" The other one is "Management". I created a list that holds a list of people for each Flight object made. I'm trying to make a list of lists that holds lists of people assigned to each Flight.
But I can only add 1 list to the list of list at location 0. Anything beyond that is a segmentation fault.
This is my Flight Class;
class Flight {
public:
int maxPeople;
int currentPos = -1;
int flightNo;
People list[50]; // list of people
public:
Passenger *list;
Flight();
Flight(int maxPassenger, int flightNo);
void addPeople(Passenger passenger);
};
class Management {
public:
const int maxFlights=20;
public:
Management();
addFlight(Flight flight);
};
This is my implementation of the prototypes:
//Global Variables
int currentPos1=-1; //
Flight *list2[20]; //list of list
//Constructor
Flight::Flight(int maxPeople2, int flightNo2) {
maxPeople = maxPeople2;
list = new People[maxPassenger]; //List means List of Passengers
flightNo = flightNo2;
Management::Management() {};
//Addflight
void Management::addFlight(Flight flight) {
currentPos1++;
*list2[currentPos1] = flight;
}
//Main
int main(void) {
Flight f1 (25, 333);
Flight f2 (25, 444);
a.addFlight(f1); // works
a.addFlight(f2); //Segfault
}
I am incrementing the currentPos1 everytime I add. And the list of lists (*list[20]) has 20 spots assigned. I can't figure out why it'll try to access a location out of that 20 that doesn't exist and causing segmentation fault.
Any Help would be very appreciated.
You don't initialize or allocate storage for any of the pointers in list2 anywhere. It's random that the first call to addFlight() doesn't segfault. This code
*list2[currentPos1]
ends up dereferencing a random memory location. If you change it to this:
list2[currentPos1] = &flight;
Well that's about as bad, because flight is a function parameter that's going to go away as soon as addFlight() returns.
Why are you using pointers and native arrays? Don't do that. Use std::vector.
Change list2 to
std::vector< Flight > list2;
and in addFlight()
list2[currentPos1] = flight;
i changed function addFlight() in Management as follows and it worked(atleast in my complier which didnt have complete code)
list2[currentPos1]=& flight;
which origiinally was
*list2[currentPos1]=flight;
Related
I'm trying to create a linked list that has 2 data types and a function that inserts nodes. But in order to insert nodes, I have to create at least 1 empty node first.
linked list struct
struct receipt{
string name;
double price;
receipt* link;
};
function that inserts a node at the end of the list
void insert(receipt** head_name_ref, string new_name, double new_price)
{
receipt* new_name_node = new receipt();
receipt *last = *head_name_ref;
new_name_node->name = new_name;
new_name_node->price = new_price;
new_name_node->link = NULL;
if (*head_name_ref == NULL)
{
*head_name_ref = new_name_node;
return;
}
while (last->link != NULL)
{
last = last->link;
}
last->link = new_name_node;
return;
}
function that print the list
void printList(receipt* n){
while(n!=NULL){
cout<<"Name: "<<n->name<<'\t'<<" ";
cout<<"Price: "<<n->price<<'\t'<<" ";
cout<<endl;
n=n->link;
}
}
main function
int main(){
receipt* head = NULL;
head = new receipt;
insert(&head, "item", 23);
printList(head);
return 0;
}
here is a picture of the output https://i.stack.imgur.com/6Ss02.png
Consider that in a more complex program you would have much more than simply a main function. When creating a data structure you have to store a pointer or reference to an object in some way that other functions can receive or access the pointer. For something this simple a global variable or instance of a struct containing the attributes of the list would suffice. Simply initialize the head to 0 and create the functions needed to manage that global object. Upon the first instantiation of the node, simply assign the head to that pointer.
You've already created a struct that represents a node. Now create another one that represents the list which contains nodes. Within that struct you'd want attributes such as a head that pointers to the first node object or null if it is empty. You can give it a default constructor.
Since this looks like an assignment I'm only giving you some hints and not a complete example, purposefully.
struct SinglyLinkList {
receipt* head;
SinglyLinkList() : head(0) {}
~SinglyLinkList() { // code to iterate and destroy all node objects }
// now define copy constructor and assignment operators if you want or delete those
// possibly some methods to add, remove, print nodes
void print();
add(receipt* r); // could overload to insert at a position
remove(size_t n); // remove nth receipt or overload to remove by some other factor
void removeAll();
receipt
};
// somewhere above the main function you could just instantiate a global list
// Within the main function you may call methods that operate on the
// list and call its methods, or define other global functions if you
// prefer that the list be defined only with the attributes
SinglyLinkList list; // default constructed with head = 0 or head = nullptr if you prefer
First note that when struct receipt is constructed, price and link will be uninitialized (std::string name will be default constructed to an empty string, but double and pointers do not have such a default initialization). This problem will manifest with this line in main:
head = new receipt;
(the problem does not manifest when you create new_name_node because you manually initialized it after the allocation).
Therefore you should better handle struct receipt initialization. The minimum would be something like this:
struct receipt {
std::string name;
double price{ 0 };
receipt* link{ nullptr };
};
You can consider to add a custom constructor.
Now to answer you question:
The question title is how to avoid printing the first node.
To do this you just have to skip one node before starting the loop.
Add the following at the beginning of printList:
if (n != nullptr)
{
n = n->link;
}
However, "solving" the problem like this is not a good idea.
Having a "dummy" first node in a linked list is not the ideal design.
I suggest you redesign your code to avoid it. You can search the web for typical linked list implementations to get some ideas. Then the issue of printing (while skipping a node) will not arise at all.
On a side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
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);
...
};
Today i went back and investigated an error i got in an old project. It's not exactly an error, rather, i don't know how to do what i need to do. Don't really want to go into the details of the project as it is old and buggy and inefficient and more importantly irrelevant. So i coded a new sample code:
#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <string>
class myDoc;
class myElement
{
int myInt;
std::string myString;
myElement * nextElement;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : myInt(x), myString(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<myElement> elements;
public:
void load();
~myDoc()
{
//I believe i should delete the dynamic objects here.
}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand(time(0));
myElement * curElement;
for (int i = 0; i < 20; i++)
{
int randInt = rand() % 100;
std::string textInt = std::to_string(randInt);
curElement = new myElement(randInt,textInt);
//create a new element with a random int and its string form
if (i!=0)
{
elements[i-1].nextElement = curElement;
//assign the pointer to the new element to nextElement for the previous element
//!!!!!!!!!!!! this is the part that where i try to create a copy of the pointer
//that goes out of scope, but they get destroyed as soon as the stack goes out of scope
}
elements.push_back(*curElement);// this works completely fine
}
}
int main()
{
myDoc newDoc;
newDoc.load();
// here in newDoc, non of the elements will have a valid pointer as their nextElement
return 0;
}
Basic rundown: we have a document type that consists of a vector of element type we define. And in this example we load 20 random dynamically allocated new elements to the document.
My questions/problems:
When the void myElement::load() function ends, the pointer and/or the copies of it goes out of scope and get deleted. How do i keep a copy that stays(not quite static, is it?) at least until the object it points to is deleted?
The objects in the elements vector, are they the original dynamically allocated objects or are they just a copy?
I allocate memory with new, how/when should i delete them?
Here is a picture i painted to explain 1st problem(not very accurate for the specific example but the problem is the same), and thank you for your time.
Note: I assumed you want a vector of myElement objects where each one points to the element next to it. It is unclear if you want the objects in elements to point to copies of them, anyway it should be pretty easy to modify the code to achieve the latter
This is what happens in your code:
void myDoc::load()
{
..
curElement = new myElement(n,m); // Create a new element on the heap
...
// If this is not the first element we inserted, have the pointer for the
// previous element point to the heap element
elements[i-1].nextElement = curElement;
// Insert a COPY of the heap element (not the one you stored the pointer to)
// into the vector (those are new heap elements copied from curElement)
elements.push_back(*curElement);// this works completely fine
}
so nothing gets deleted when myDoc::load() goes out of scope, but you have memory leaks and errors since the pointers aren't pointing to the elements in the elements vector but in the first heap elements you allocated.
That also answers your second question: they're copies.
In order to free your memory automatically, have no leaks and point to the right elements you might do something like
class myElement
{
int a;
std::string b;
myElement *nextElement = nullptr;
//a pointer to the element that comes immediately after this one
public:
myElement(int x, std::string y) : a(x), b(y){};
friend myDoc;
};//an element type
class myDoc
{
std::vector<std::unique_ptr<myElement>> elements;
public:
void load();
~myDoc()
{}
};// a document class that has bunch of myElement class type objects as members
void myDoc::load()
{
srand((unsigned int)time(0));
for (int i = 0; i < 20; i++)
{
int n = rand() % 100;
std::string m = std::to_string(n);
//create a new element with a random int and its string form
elements.emplace_back(std::make_unique<myElement>(n, m));
if (i != 0)
{
//assign the pointer to the new element to nextElement for the previous element
elements[i - 1]->nextElement = elements[i].get();
}
}
}
Live Example
No need to delete anything in the destructor since the smart pointers will be automatically destroyed (and memory freed) when the myDoc element gets out of scope. I believe this might be what you wanted to do since the elements are owned by the myDoc class anyway.
I have a Town class which represents the nodes in my graph like this:
class Town
{
public:
Town();
public:
Town* _parent;
int _name;
int _row;
int _column;
State _state;
vector<Town*> _neighbors;
};
I have a Map class which contains a 2D vector of Towns and pretty much makes my random graph.
class Map
{
public:
Map(const int elements, const int size, const int seed);
public:
vector <vector<Town> > _map;
vector <Town*> _towns;
vector <vector<int> > _adjacency;
vector <vector<double> > _mDistance;
vector <Line> _edges;
const int _elements;
const int _size;
Town* _start;
Town* _exit;
};
Then my AI class receives a Map object and solves it depending on the algorithm, right now I am implementing Astar.
class AI
{
private:
struct TownWithCost
{
Town town;
double cost;
};
struct OrderByTotalCost
{
bool operator()(TownWithCost lfs, TownWithCost rhs)
{
return lfs.cost > rhs.cost;
}
};
public:
AI(Map map);
private:
bool AStar(Town* town);
double GetTotalCost(Town town);
public:
bool _success;
private:
Map _map;
};
Here is my Astar implementation:
bool AI::AStar(Town* town)
{
AI::OrderByTotalCost comparator;
vector<TownWithCost> priorityQueue;
TownWithCost currentTown = { *town, 0 };
Town temp = currentTown.town;
priorityQueue.push_back(currentTown);
SetEnvironment(temp, State::visited);
while (!priorityQueue.empty())
{
currentTown = priorityQueue.front();
Town temp = currentTown.town;
priorityQueue.erase(priorityQueue.begin());
SetEnvironment(temp, State::visited);
PrintEnvironment();
if (temp._name == _map._exit->_name)
{
return true;
}
vector <Town*> neighbors = town->_neighbors;
for each (Town* neighbor in neighbors)
{
Town tempNeighbor = *neighbor;
if (tempNeighbor._state == State::town)
{
tempNeighbor._parent = &temp;
TownWithCost neighborWithCost = { tempNeighbor, GetTotalCost(tempNeighbor) };
priorityQueue.push_back(neighborWithCost);
}
}
make_heap(priorityQueue.begin(), priorityQueue.end(), comparator);
}
return false;
}
As you can probably notice I don't have yet implemented looking inside the priorityQueue to see if I already have a Town in there and compare the costs to see which one I want to keep but I plan on implementing that after I solve my current problem.
What my problem is, is that I do not want to have pointers inside the priorityQueue. I am trying to make temp variables which will copy a Town and it's cost from a certain path.
Let's say I start from Town 9.
9 has neighbors 0, 7, 8, 3 specifically the priorityQueue at the first loop looks like this:
Then I get 3 as my currentTown and I am checking it's neighbors.
The moment I reach the line Town temp = currentTown.town; for the second time the parents of each element in the priorityQueue are being set to 3. Now I understand why this is happening, what I don't understand is how to prevent this.
What I basically need is priorityQueue to store the same Towns (not same memory addresses) with different parents and different costs (I have already taken care of the separate cost with the struct TownWithCost). So all in all make copies each time.
For example I can get from 9 to 0 directly with total cost 81 but I can also get to 0 through 3 (9 -> 3 -> 0) with total cost 50. I want to be able to differentiate these two.
How do I differentiate between them in my priorityQueue and how do I avoid resetting the parents or in other words how do I allocate another part of memory to the Town temp each time the loop runs so I can have different temps each time?
If you have another way (as newbie friendly as possible) of doing this then feel free to say it.
You're passing by value instances of Map and this class doesn't have a copy constructor or assignment operator. When this class is shallow copied (ala memcpy) vector instances will cause a crash when they are destroyed (multiple times).
Try working with pointers or references. Will also work faster.
You could also use a vector of index pointing to an array or vector of the towns. No need for pointers. But personally, I'd prefer to use std:shared_ptr instead.
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).