Multidimensional vector of class type - c++

i would need a little help with vector of vector when type is class. "loadTruck" is my class. I want to store values from my class "loadTruck" into 2D vector in this order: vector(truck ,print). Both "truck" and "print" are type of class "loadTruck". I want acces to this vector: for example lets say that "print" is package and "truck" is truck. I want to get information about package in truck 1, with package id 20. I am absolutely confused with this.
vector<vector <loadTruck>> jedinecTruck;
loadTruck truck;
while (warehouseIsEmpty == False)
{
truck.resetTruck();
for (int i = 0; i < numOfPackages; i++)
{
vector<loadTruck> print;
if (store2D[i].checkIfPackageIsThere() == true)
{
truck.setPackageSize(store2D[i].getPackageWidth(), store2D[i].getPackageHeight());
if (truck.checkIfPackageCanBeLoaded() == true)
{
print.push_back(truck);
truck.loadPackageInTruck();
store2D[i].deletePackage();
}
}
}
jedinecTruck.push_back(truck);
}
Version with 3D array,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
now programm is running well, but array is not good idea but i hope that it will help you to understand what i want to do. I need to use vector because i am not able to define first 2 elements of array, it depends on algorythm and is always changing. For this example i suppose that first two elements will be defined statically. 3 rd element got always 4 components.
vector<loadTruck> jedinecTruck;
loadTruck truck;
int array[1][3][4];
while (wharehouseIsEmpty == false)
{
truck.resetTruck();
for (int i = 0; i < numOfPackages; i++)
{
if (store2D[i].checkIfPackageIsThere() == true)
{
truck.setPackageSize(store2D[i].getPackageWidth(), store2D[i].getPackageHeight());
if (truck.checkIfPackageCanBeLoaded() == true)
{
truck.loadPackageInTruck();
store2D[i].deletePackage();
array[0][i][0] = truck.getActualX1();
array[0][i][1] = truck.getActualX2();
array[0][i][2] = truck.getActualY1();
array[0][i][3] = truck.getActualY2();
}
}
}
jedinecTruck.push_back(truck);
}
Regards

Perhaps this is closer to what you're trying to do:
vector<vector <loadTruck>> jedinecTruck;
loadTruck truck;
while (warehouseIsEmpty == False)
{
truck.resetTruck();
vector<loadTruck> print;
for (int i = 0; i < numOfPackages; i++)
{
if (store2D[i].checkIfPackageIsThere() == true)
{
truck.setPackageSize(store2D[i].getPackageWidth(), store2D[i].getPackageHeight());
if (truck.checkIfPackageCanBeLoaded() == true)
{
print.push_back(truck);
truck.loadPackageInTruck();
store2D[i].deletePackage();
}
}
}
jedinecTruck.push_back(print);
}
It's difficult to tell from your question, though.

Related

How can I optimize Astar for vast empty spaces?

I am creating a game with a 3D grid for flying entities, So I have a lot of points and connections in the air where there aren't any obstructions. I didn't want to decrease the resolution of my grid so I thought I could just skip over chunks (or empties as I call them) of the Astar map while they're not containing any obstructions, and I modified Godot's Astar algorithm to do this.
Unfortunately this ended up being slower than looping through points one at a time due to the way I implemented this modification, which needs to loop through all the edge points of an empty.
2D representation of how one edge point of an empty connects to all other edge points:
This ends up looping through a larger number of points than letting the A* algorithm work it's way through the empty.
So I'm sorta stumped on how to make this more efficient while still preserving the most optimal path.
I could potentially narrow down what faces of the empty should be scanned over by first comparing the center points of all 8 faces of the empty (as my grid consists of hexagonal prisms). Or maybe I should somehow use the face center points of the empty's faces exclusively instead of all edge points.
I mainly want to know if anyone has worked on an issue like this before, and if so what would be the recommended solution?
Here is the astar loop for reference:
bool AStar::_solve(Point *begin_point, Point *end_point, int relevant_layers) {
pass++;
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
bool supported = relevant_layers == 0 || (relevant_layers & end_point->parallel_support_layers) > 0;
if (!end_point->enabled || !supported) {
return false;
}
bool found_route = false;
Vector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
open_list.push_back(begin_point);
while (!open_list.empty()) {
Point *p = open_list[0]; // The currently processed point
if (p == end_point) {
found_route = true;
break;
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
open_list.remove(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
//if the point is part of an empty, look through all of the edge points of said empty (as to skip over any points within the empty).
OAHashMap<int, Point*> connections;
PoolVector<Empty*> enabled_empties;
int size = p->empties.size();
PoolVector<Empty*>::Read r = p->empties.read();
for (int i = 0; i < size; i++) {
Empty* e = r[i];
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
//if the empty is enabled and the end point is not within the empty
if (e->enabled && supported && !end_point->empties.has(e)) {
enabled_empties.append(e);
//can travel to any edge point
for (OAHashMap<int, Point*>::Iterator it = e->edge_points.iter(); it.valid; it = e->edge_points.next_iter(it)) {
int id = *it.key;
Point* ep = *(it.value);
ep->is_neighbour = false;
//don't connect to the same point
if (id != p->id && (i == 0 || !connections.has(id))) {
connections.set(id, ep);
}
}
}
}
//add neighbours to connections
for (OAHashMap<int, Point*>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
int id = *it.key;
Point* np = *(it.value);// The neighbour point
np->is_neighbour = true;
//don't need to check for duplicate point connections if no empties
if (size == 0 || !connections.has(id)) {
//don't add points within enabled empties since they're meant to be skipped over
if (np->empties.size() > 0 && !np->on_empty_edge) {
bool in_enabled_empty = false;
PoolVector<Empty*>::Read r1 = np->empties.read();
for (int i = 0; i < np->empties.size(); i++) {
if (enabled_empties.has(r1[i])) {
in_enabled_empty = true;
break;
}
}
if (!in_enabled_empty) {
connections.set(id, np);
}
}
else {
connections.set(id, np);
}
}
}
for (OAHashMap<int, Point *>::Iterator it = connections.iter(); it.valid; it = connections.next_iter(it)) {
Point *e = *(it.value); // The neighbour point
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
if (!e->enabled || e->closed_pass == pass || !supported) {
continue;
}
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
bool new_point = false;
if (e->open_pass != pass) { // The point wasn't inside the open list.
e->open_pass = pass;
open_list.push_back(e);
new_point = true;
} else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous.
continue;
}
e->prev_point = p;
e->prev_point_connected = e->is_neighbour;
e->g_score = tentative_g_score;
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
if (new_point) { // The position of the new points is already known.
sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
} else {
sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
}
}
}
return found_route;
}
Note: I'm still not exactly sure what the sorter does.
the entire code can be seen here in a_star.cpp and a_star.h
Edit:
if anyone wants to reference or use this, I've modified the Astar code to add user-defined octants and to use a user-defined straight line function (they are user-defined so they can work with any type of grid) to be used between octants when possible to further decrease runtime, and it works very well in terms of speed. Though the pathing is not optimal, especially when adding a lot of obstacles/restricting the available positions.

MariaDB Connector C, mysql_stmt_fetch_column() and memory corruption

I'm working on a wrapper for MariaDB Connector C. There is a typical situation when a developer doesn't know a length of a data stored in a field. As I figured out, one of the ways to obtain a real length of the field is to pass a buffer of lengths to mysql_stmt_bind_result and then to fetch each column by calling mysql_stmt_fetch_column. But I can't understand how the function mysql_stmt_fetch_column works because I'm getting a memory corruption and app abortion.
Here is how I'm trying to reach my goal
// preparations here
...
if (!mysql_stmt_execute(stmt))
{
int columnNum = mysql_stmt_field_count(stmt);
if (columnNum > 0)
{
MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt);
MYSQL_FIELD* fields = mysql_fetch_fields(metadata);
MYSQL_BIND* result = new MYSQL_BIND[columnNum];
std::memset(result, 0, sizeof (MYSQL_BIND) * columnNum);
std::vector<unsigned long> lengths;
lengths.resize(columnNum);
for (int i = 0; i < columnNum; ++i)
result[i].length = &lengths[i];
if (!mysql_stmt_bind_result(stmt, result))
{
while (true)
{
int status = mysql_stmt_fetch(stmt);
if (status == 1)
{
m_lastError = mysql_stmt_error(stmt);
isOK = false;
break;
}
else if (status == MYSQL_NO_DATA)
{
isOK = true;
break;
}
for (int i = 0; i < columnNum; ++i)
{
my_bool isNull = true;
if (lengths.at(i) > 0)
{
result[i].buffer_type = fields[i].type;
result[i].is_null = &isNull;
result[i].buffer = malloc(lengths.at(i));
result[i].buffer_length = lengths.at(i);
mysql_stmt_fetch_column(stmt, result, i, 0);
if (!isNull)
{
// here I'm trying to read a result and I'm getting a valid result only from the first column
}
}
}
}
}
}
If I put an array to the mysql_stmt_fetch_column then I'm fetching the only first field valid, all other fields are garbage. If I put a single MYSQL_BIND structure to this function, then I'm getting an abortion of the app on approximately 74th field (funny thing that it's always this field). If I use another array of MYSQL_BIND then the situation is the same as the first case.
Please help me to understand how to use it correctly! Thanks
Minimal reproducible example

What's the best way to change the size of a list in Dart?

I have a list with oldLength items.
I want it to have newLength items.
If newLength < oldLength, I just want to cut the extra items.
If newLength > oldLength, I want to fill it with nulls.
I wrote this:
List<T> cutList<T>(List<T> oldList, int newLength) {
return new List.generate(newLength, (index) {
if (index < oldList.length) return oldList[index];
else return null;
});
}
Is there a better way, in terms of simplicity? And in terms of efficiency?
If it's a growable list and you don't mind mutating it:
List<T?> cutList<T>(List<T?> oldList, int newLength) {
oldList.length = newLength;
return oldList;
}
Notice that after Dart introduced Null Safety, you can only grow a list like this if its element type is nullable (because otherwise it can't assign null to the new element positions). Since you ask to grow with null values, that should be the case.
The declaration of cutList here ensures that the list type is nullable.
If you want to create a new list, then you still need to know that T is nullable (otherwise you can't create a larger list):
List<T?> cutList<T>(List<T?> oldList, int newLength) {
return List<T?>.filled(newLength, null)
..setRange(0, min(newLength, oldList.length), oldList);
}
(where min is imported from dart:math).
For a more modern-Dart approach, I'd probably go with:
List<T?> cutList<T>(List<T?> oldList, int newLength) {
return <T?>[...oldList.take(newLength),
for (var i = oldList.length; i < newLength; i++) null];
There are so many ways. Anything that only copies each element once is good.
Same as Above but It's an extension so you can use it on any List anytime you want
Without Math Library
extension CutList<T> on List<T?> {
List<T?> cutList(List<T?> oldList, int newLength) {
return <T?>[
...oldList.take(newLength),
for (var i = oldList.length; i < newLength; i++) null
];
}
}
With Math
import 'dart:math';
extension CutList<T> on List<T?> {
List<T?> cutList(List<T?> oldList, int newLength) {
return List<T?>.filled(newLength, null)
..setRange(0, min(newLength, oldList.length), oldList);
}
}

Using enums and a for-loop to create instances of a class

enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}

invalid operands to binary expression - when removing object

I want to remove an object from an array.
The problem is that i don't know the index, so i try the remove method.
The method is definded like this:
void ofxDTangibleManager::updateList(vector<ofxDTangible> &oldList, vector<ofxDTangible> &newList) {
Here is the part where it goes wrong:
for(int i = 0; i < oldList.size(); i++) {
if(newList.size() == 0) {
break;
}
ofxDTangible &t = oldList[i];
ofxDTangible &closest = getClosestTangible(t, newList, false);
float d = distSquared(t, closest);
if(d < maxMoveDistSquared) {
refound[i] = true;
// copy values of new one over
// todo
// set as target so we can interpoplate if required
// remove it so we make sure we don't assign it to multiple tangibles
remove(newList.begin(), newList.end(), closest);
}
}
This are the errors:
How can i get around this problem?