first question so please forgive my naiveness here.
I'm diving into a triangulation library for c++, which sorts an array of struct pointers before running it's triangulation method. I'm trying to keep track of one particular struct pointer (XYZ) throughout my app, which updates according to the mouse position. Problem is, whenever the qsort method is applied, this pointer changes. How do I identify or keep track of this struct XYZ pointer?
Here is the struct & sort...
struct XYZ{
double x, y, z;
};
int XYZCompare(const void *v1, const void *v2){
XYZ *p1, *p2;
p1 = (XYZ*)v1;
p2 = (XYZ*)v2;
if(p1->x < p2->x)
return(-1);
else if(p1->x > p2->x)
return(1);
else
return(0);
}
The array of XYZ structs (2 here for testing) with mouse pointer reference...
XYZ *allPointers = new XYZ[100];
allPointers[0].x = 100;
allPointers[0].y = 200;
allPointers[0].z = 0;
allPointers[1].x = 50;
allPointers[1].y = 80;
allPointers[1].z = 0;
XYZ *mousePointer = &allPointers[0];
Sort and update mouse methods.
mousePointer->x = mouseX;
mousePointer->y = mouseY;
// If I don't qsort here the reference is fine, but I need to.
qsort(allPointers, 2, sizeof(XYZ), XYZCompare);
// triangulate, etc
You have a couple of options:
You could search for your unique entry after sorting. If you add a marker member search linearly for the marker. If any entry with a matching X/Y coordinate is as good as any other you could bsearch for it in the sorted array. You could combine those by using bsearch to find the right X coordinate followed by a (shorter) linear search for the marker.
You can add a layer of indirection. Instead of sorting your array of XYZ structures, create a parallel list of indexes or pointers into that array and sort the XYZ * or int references instead. Your mousePointer reference will remain valid.
Shouldn't the third arg to qsort() be size(XYZ*)? You're sorting the pointers and not the objects being pointed to.
Related
I'm programming a level editor for a new game. The problem is, I am not sure what structure to use for storing my data.
It is a tile-based map engine, using x- and y coordinates and an id for the tile at that position.
I've got multiple layers, the map is resizeable, so an array may cause me some troubles, that's why I chose a std::vector for that case.
To prevent a lot of overload I only add a tile, when somebody placed it, so the vector size is zero if there are no tiles and increases the more tiles are placed.
struct tile {
unsigned short tile_id;
unsigned short tile_x;
unsigned short tile_y;
};
And my vector:
std::vector<tile> tiles;
The thing is, before adding a new tile I need to check if there's already a tile at that x- and y-position.
// Returns true/false if there is a tile at given position or not
bool Layer::has_tile_at(unsigned short x, unsigned short y) {
unsigned int i;
for (i = 0; i < tiles.size(); i++) {
if (tiles[i].tile_x == x && tiles[i].tile_y == y)
return true;
}
return false;
}
My problem is, that for every placed tile, I must loop through the whole vector, which is fast at the beginning, but really gets a pain in the ass after some tiles have been placed.
Do you think my approach is okay so far, or is there something smarter and more performant?
Data structure to use should depend mostly on the use cases: if you're doing mostly (x,y) reads, then perhaps you need a matrix (be it via a vector of vectors, or just array of arrays).
If you need indexed access AND easy iteration over tiles, perhaps keep the data within two data structures. You should be able to easily implement a 2d map with pointers to tiles within vector - initially empty, lazily loaded upon (x,y) access (remember about data safety!).
Consider for example:
class Map
{
public:
void addTile(std::shared_ptr<Tile> tile)
{
m_tiles.push_back(tile); // should probably remove old elements at (x,y) from the vector
m_map[{tile->x, tile->y}] = tile; // overwrites whatever was stored in there!
}
std::shared_ptr<Tile> getTile(int x, int y)
{
return m_tilesMap[{x, y}]; // if no tile there, returns default ctor-ed shared_ptr: nullptr
}
private:
std::vector<std::shared_ptr<Tile>> m_tiles;
using Index2D = std::pair<int, int>;
std::map<Index2D, std::shared_ptr<Tile>> m_tilesMap;
};
(extended comment with a brief code example: data is kept on the heap, while both vector and map keep copies of it - perhaps could be improved for easier removal)
Why not use multiple vectors? You could essentially create a growable 2-D vector by having a vector of vectors, then overload the [] operator to first check if the vector size could contain that element (returning false if not), and if it can, check if that element isn't a constructed value (whatever your default "tile" may be). This would allow nearly O(1) lookup like in regular vectors. Otherwise you can use a formula for your max col/row distance and do a O(1) look-up that way with some 2-D to 1-D conversions such as in 2-D arrays.
This is what I'm thinking:
vector< vector<tile> > tiles;
bool::Layer has_tile_at(unsigned short x, unsigned short y) {
if (tiles.size() <= x) {
return false;
} else if (tiles[x].size() > y) {
if (tiles[x][y] != tile()) {
return true;
}
}
return false;
}
Edit:
As another user pointed out, you could also use pointers and check if tiles[x][y] == nullptr; instead!
I want to have a void pointer to a vector.
void *para;
vector<double> x(2);
x[0] = 0;
x[1] = 1;
para = &x;
I can now use the vector like this.
vector<double> k = *(static_cast<vector<double>*>(para));
cout << k[0] << "\n";
Now I want to access the elements of the vectors through the pointer. How can I do that? But now I want to get the elements of the vector x, directly via the void pointer para, without using the new vector k. Something like this:
double k = ??? // here should be the element of x via para
Thank's in advance.
Now I want to access the elements of the vectors through the pointer.
This has two steps: reinterpret the pointer as a vector, then access elements.
How can I do that? But now I want to get the elements of the vector x, directly via the void pointer para, without using the new vector k.
void *para;
vector<double> x(2);
para = &x;
// step 1: reinterpret the pointer as a vector
auto *voidToVector = reinterpret_cast< vector<double>* >(para);
// step 2: access elements
double k = (*voidToVector)[0];
That said, please DON'T store data in your application as void*. Every time you do, you can assume that a developer will probably see it later and die a bit inside (and that developer may even be you).
Edit:
For the calculation in the function, I need to access the elements of the vector, vector>>> accel; Is there a better way????
Consider this:
class FourDimensionalVector
{
public:
FourDimensionalVector(std::size_t x, std::size_t y, std::size_t z, std::size_t a)
: d1{x}, d2{y}, d3{z}, d4{a}
, data{ d1 * d2 * d3 * d4 }
{
}
// ALL access to the vector elements can/should be done through this
double& operator()(std::size_t x, std::size_t y, std::size_t z, std::size_t a)
{
assert(d1 > x); // same for the other dimensions
return data[x * d1 + y * d2 + z * d3 + a];
}
// implement other interface elements here (iteration access, reading the size,
// resetting the values, etc.
private:
std::size_t d1, d2, d3, d4;
std::vector<double> data; // store flattened data
};
With this, you just pass a reference to the data as a parameter, and edit it as needed. I'm not sure the indexing logic is OK (and the code is incomplete), but the idea is the same.
Client code:
void YourFunction(FourDimensionalVector& fdv)
{
fdv[2, 3, 4, 0] = fdv[2, 3, 4, 0] + 0.38;
}
This solution is strongly typed, efficient and clean (it avoids the casting completely and the void*).
[edit by Jojia]: But what is the difference between your solution and this one
vector<vector<vector<vector<double>>>> Xaccel;
void initialize(&Xaccel); //This function initializes values for all elements of Xaccel
void myfunction(&Xaccel){
double x = Xaccel[0][0][0][0];
}
I don't see any difference to your solution. BUT: I thought passing these large objects to the function myfunction might be a problem. Is that correct?
[edit by utnapistim]:
From a semantical point of view, they are the same: both send the same data to the function and allocate the same memory (my solution also stores dimensions, but whatever).
From a maintenance/reusability/testability/modularity point of view, they are quite different: my solution abstracts away the fact that your four dimensional matrix is a vector (of vector of vector ... ).
This will allow you to write your client code using a 4d matrix interface (which you can implement to match the needs of your client code) instead of a vector, and allow you to define your operations in terms of a matrix.
For example, the vector<vector<vector<double>>> code can be used to create a sparse/asymetrical matrix (with the first line in the outer vector being three times longer than the second line and so on). The matrix class would prevent that by cutting access to the vector.
If you choose to keep the vector<vector...> solution, at least typedef it:
typedef vector<vector<vector<double>>> FourDMatrix;
FourDMatrix Xaccel;
void initialize(FourDMatrix& Xaccel);
void myfunction(FourDMatrix& Xaccel);
In this line you create a copy:
vector<double> k = *(static_cast<vector<double>*>(para));
So one of the solution would be to use reference instead:
vector<double> &k = *(static_cast<vector<double>*>(para));
k[0] = 123;
Or pointer
vector<double> *pk = static_cast<vector<double>*>(para);
(*pk)[0] = 123; // but usage is more explicit, so reference would be better
I assume you know what you are doing and you really need to pass vector through a void *. One of the reasons could be passing pointer to vector as a cookie to C API that expects void *. Note there is very low chance to have a good reason to use void * in c++ itself, you should use boost::any or boost::variant for type safety.
I'm new to C++ and I learned with different tutorials, in one of them I found an example of code:
I have pointed by numbers of lines, that I completely do not understand;
Does this array in array or something like that?
I can understand the second call, but what is the first doing? There is already
"coordinates[blocks[num]]", aren't there? Why need again blocks(i) ?
How do you make this part of the code easier? Did struct with this arrays
don't make easier getting value from arrays?
Thanks in advance!
// Global vars
Struct Rect {
float left;
}
Rectangle *coordinates;
int *blocks;
coordinates = new Rect[25];
blocks = new int[25];
// in method storing values
const int currentBlock = 0; //var in cycle
coordinates[currentBlock].left = column;
blocks[currentBlock] = currentBlock;
//get element method
const Rect& classA::Coords(int num) const
{
return coordinates[blocks[num]]; //(2)
}
//and calling this method like
Coords(blocks[i]); //(3)
Coords(i); //(3)
// (4)
No, not really. Lots of people will think of them as arrays and even describe them as arrays, but they're actually not. coordinates and blocks are both pointers. They just store a single address of a Rect and an int respectively.
However, when you do coordinates = new Rect[25];, for example, you are allocating an array of 25 Rects and setting the pointer coordinates to point at the first element in that array. So, while coordinates itself is a pointer, it's pointing at the first element in an array.
You can index coordinates and blocks like you would an array. For example, coordinates[3] will access the 4th element of the array of Rects you allocated. The reason why this behaves the same as arrays is because it actually is the same. When you have an actual array arr, for example, and you do arr[4], the array first gets converted to a pointer to its first element and then the indexing occurs.
No, this is not an array of arrays. What it is doing is looking up a value in one array (blocks[num]) and using that to index the next array (coordinates[blocks[num]]). So one array is storing indices into the other array.
I'll ignore that this won't compile, but in both cases you are passing an int to the Coords function. The first case looks incorrect, but might not be. It is taking the value at blocks[i], passing that to the function then using that value to index blocks to get another value, then using that other value to index coordinates. In the second case, you are just passing i, which is being used to index blocks to give you a value with which you index coordinates.
That's a broad question that I don't think I can answer without knowing exactly what you want to simplify and without seeing some real valid code.
I have created a dynamic matrix of class objects but i have made a big mess with handling the returned pointers.
My intention is to create a matrix of class Point( Int x,Int y) and later to use it in different ways in the program.
Everything is working but i can't figure out the returned pointers game between the functions.
class Point
{
private:
int x;
int y;
public:
Point(int x,int y);
void SetPoint(int x,int y);
};
In a second class I use a Point object as class member.
Init_Pallet() is used to Initialize the Matrix.
class Warehouse
{
private:
Robot r1,r2;
Point *Pallet_Matrix;
public:
Point* Init_Pallet();
};
This is the Init function
Point* Warehouse::Init_Pallet()
{
int rows =10,cols =10;
Point** Pallet_Matrix = new Point*[rows];
for (int i = 0; i < rows; i++)
Pallet_Matrix[i] = new Point[cols];
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; j++) //Pallet matrix Init, x point for robots amount in position and y for box amount
Pallet_Matrix[i][j].SetPoint(0,0);
return *Pallet_Matrix;
}
The Init function is called by WareHouse C'Tor (ignore the other vars)
Warehouse::Warehouse(Robot p_r1,Robot p_r2): r1(p_r1),r2(p_r2)
{
this->r1=p_r1;
this->r2=p_r2;
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
}
My question is: How do I return the address to the beginning of the matrix from the Init function to the C'Tor who called it?
And second question: how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix adress to the C'Tor.
Thank you in advance for all the help and your time.
You should just have Init_Pallet return a Point** and then do return Pallet_Matrix;. Currently you're copying one of the Point*s that you allocated out of the function, so the copy is no longer part of a contiguous array that you can index.
Don't forget to delete[] the dynamically arrays in your destructor.
However, you should much prefer to use the standard library containers like std::array or std::vector. Then you don't need to worry about the dynamic allocation yourself and no pointers to get in a mess with.
If I were doing it, I would just have:
class Warehouse
{
public:
Warehouse() : Pallet_Matrix() { }
private:
Robot r1,r2;
std::array<std::array<Point, 10>, 10> Pallet_Matrix;
};
And that's it. No init needed. No dynamic allocation. No assigning 0 to every element (if you give Point a default constructor that zero-initialises). Done.
How do I return the address to the beginning of the matrix from the Init function to the C'Tor?
In case you would really need just an address of first element, pretty straightforward would be:
return &Pallet_Matrix[0][0];
how do i access the matrix different locations in the format of Matrix[i][j] after returning the matrix address
Init_Pallet is a member function, which could simply work with the Pallet_Matrix member directly. Otherwise, the Init_Pallet function could actually return Point**, which should however make you feel that something's wrong with this code.
Better[1] solution would be:
Define the default constructor for Point:
class Point
{
public:
Point() : x(0), y(0){}
...
Use std::vectors instead of dynamically allocated arrays:
class Warehouse
{
private:
std::vector< std::vector<Point> > Pallet_Matrix;
and instead of:
Point *p =Init_Pallet();
this->Pallet_Matrix=p;
you would simply use std::vector's constructor:
int rows = 10, cols = 10;
Pallet_Matrix = std::vector< std::vector<Point> >(rows, cols);
[1] Better = You don't want to handle the memory management on your own.
The problem is that the returned type of Init_Pallet() is wrong — its a row, not a matrix. And in the last line of Warehouse::Init_Pallet() you dereference the proper pointer to matrix obtaining the pointer to the first row of the matrix.
You need to write Point **Pallet_Matrix; in Warehouse, use Point** Warehouse::Init_Pallet() definition of Init_pallet(), and return Pallet_Matrix in the last line of Init_Pallet().
The notation Point *row means the row is "the array of points" or "the pointer to the beginning of the array of points". The notation Point **matrix means the matrix is "the array of pointers to the beginnings of the arrays of points" or "the pointer to the beginning of such an array".
First: are the dimensions really constant, or is this just an
artifact of your having simplified the code for posting? If
they are really constant, there's no need for dynamic
allocation: you can just write:
Point palletMatrix[10][10];
and be done with it. (If you have C++11, it's even better; you
can use std::array, and palletMatrix will have full object
semantics.)
If you do need dynamic indexes, the only reasonable way of
doing this is to write a simple matrix class, and use it:
class Matrix
{
int m_rows;
int m_columns;
std::vector<Point> m_data;
public:
Matrix( int rows, int columns )
: m_rows( rows )
, m_columns( columns )
, m_data( rows * columns, Point( 0, 0 ) )
{
}
Point& operator()( int i, int j )
{
return m_data[ i * m_columns + j ];
}
// ...
};
Trying to maintain a table of pointers to tables is not a good
solution: it's overly complex, it requires special handling to
ensure that each row has the same number of columns, and it
generally has poor performance (on modern machines, at least,
where locality is important and multiplication is cheap).
Note too that the actual data is in an std::vector. There are
practically no cases where a new[] is a good solution; if you
didn't have std::vector (and there was such a time), you'd
start by implementing it, or something similar. (And
std::vector does not use new[] either.)
EDIT:
One other thing: if you're putting Point in a matrix, you might
want to give it a default constructor; this often makes the code
simpler.
I'm making an array of vectors to save as normals. Because we haven't learned how to do vectors in class yet, I've made a struct which serves just as well:
struct vector3
{
double xcoord;
double ycoord;
double zcoord;
};
Then, at the beginning of my function, I have this:
vector3 vector;
vector3* normalField = new vector3[x];
While the function loops through, in each loop, it applies new values to "vector" - at the end of the function, it sets a part of the array to be vector.
normalField[x] = vector;
The idea is to save memory by not creating a whole bunch of new vectors, and because I have no clue when and where I would be able to use the delete function on that group of vectors. Will this work? Or not? What's the best way of doing this?
The code is very wordy as a whole - I'm writing an algorithm to create a field of normals for procedurally generated terrain. I don't use the built-in vector class because we're not supposed to for some stupid reason. I blame the professor.
The assignment normalField[x] = vector is going to deep copy the data in vector; you will be creating as many vectors as there are elements in normalField[].
Remember too that in C++ the only difference between a struct and a class is that in a struct data members and functions are public by default, but in a class they are private by default.
What you want can be implemented either via array, and creating a new, bigger array when your need for vectors is increased (essentially replicating the behaviour of std::vector), or by using a linked list, which could look like this:
struct vector3List {
vector3 v;
vector3List * next;
};
More refined solutions exist, of course, but the choice depends on what you need to do on the vectors.
In case you are not sure how a list is used, here is an example:
vector3List * listBegin = new vector3List();
// Setup your vector
listBegin->v.coordX = 6;
// Set the end of the list
listBegin->next = 0;
// You need one more vector
listBegin->next = new vector3List();
// Use some kind of helper pointer to keep track of what vector you are examining
// if you need it
vector3List * iterator = listBegin->next;
// Setup this new second vector
iterator->v.coordX = 5;
// Remember to set the end of the list!
iterator->next = 0;
// Iterate throgh the list
iterator = listBegin;
while ( iterator != 0 ) {
// Do stuff
iterator = iterator->next;
}
This is, of course, a naive implementation, but you get the idea.