Create an array of an array of structs? - c++

this question is regarding the syntax of an array of array of structs.
I have a struct that takes in two ints:
struct point
{
int x, y;
};
I have created another struct that takes in 8 of these structs:
//Creating an Array of Array of structs
struct Arraypoint
{
point variable[8];
};
//Not sure if this is the correct way to do it.
Now, in main, I want to declare an array variable of type Arraypoint with 8 indices, so effectively I will have 8 * 8 = 64 elements of struct point and 128 ints (64 x and 64 y).
Also, how would I access an individual element struct point from the array Arraypoint?
Okay after having declared in main lets say Arraypoint is 2.
Arraypoint arr[2];
How do I initialize the elements without having to type in arr[0].variable[0].x = ... or without using for loops.
Why can't I do the following, it doesn't seem to work.
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }//xy are rand
I have used curly braces in my code, the error returned is missing braces around initializer for type point and too many initializers for type Arraypoint.

In C++, you'd just write:
Arraypoint arr[8];
An individual point could then be accessed via:
arr[i].variable[j];
More practically, though, you'd probably be better off using e.g.
std::vector<std::vector<point> >
or writing your own class with an overloaded operator(int i, int j). For example:
class PointMatrix
{
private:
std::vector<point> m_points;
public:
PointMatrix() : m_points(64) {}
point& operator()(int i, int j) { return m_points[8 * i + j]; }
const point& operator()(int i, int j) const { return m_points[8 * i + j]; }
};
PointMatrix mat;
m(3, 4).x = 23;

got it: ideone.com/ix3hC. Arraypoint::variable has to have it's own { } pair.
struct point
{
int x, y;
};
#define P {0, 0}
struct Arraypoint
{
point variable[8];
};
#define V { P, P, P, P, P, P, P, P}
#define AP { V } //this is the pair you missed
int main() {
Arraypoint arr[2] = { AP, AP };
}

struct Arraypoint arraypoints[8];
is what you're after, I think. To use them:
int firstx = arraypoints[0].variable[0].x;
This isn't so pretty though
struct point { int x, y; };
struct point[8][8] arraypoints;
Is probably better? Don't know what exactly you're after though.

To create an array of Arraypoints, you can do:
Arraypoint arr[8];
To access an element:
arr[i]
will return the i'th Arraypoint element
arr[i].variable[j]
will return the j'th point in the element
arr[i].variable[j].x
will return the x coordinate of that point.

So I realized why I couldn't declare my array as such,
Arraypoint arr[2] = { {(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)},
{(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y),(x,y)} }
//xy are randomn integer values
its because in my struct declaration of Arraypoint, it takes in 8 elements of type point. So
I have to create variables of type point to store(x,y) and then i could store this variable in Array point.
point point1 = {x,y}, ...;
Arraypoint arr[2] = { {point1,point2,point3,point4,point5,....} };
Just for anyone in the future who stumbles across the same problem.

Related

How do I point to multi-dimensional array values?

I need some help on multi-dimensional arrays... I cannot find out how to assign a value to an array in a void task, that was created in main.
i tried to find help all over the place, but the longer i keep reading the less i understand
Please help
void addValue(a,b)
{
//somehow assign value to a[2][6] using pointers and such
void main()
{
int dest[7][7] = { 0 };
int a = 2;
int b = 6;
addValue(a,b);
}
Like this:
void addValue( int (*dest)[7], int a, int b )
{
dest[2][6] = 12;
}
int main()
{
int dest[7][7] = { 0 };
addValue(dest, a, b);
}
Consider using std::array instead of C-style arrays; the latter are an anachronism in C++. You can make the 7 a template parameter in addValue if you want to support other dimensions of array.

how to set a int array inside a struct in c++

I have
struct board{
int x[3];
int y[3];
};
// in the class PatternReader
board PatternReader::testPattern1DX() {
struct board aBoard;
int x[3] = { 1,1,1 };
aBoard = x;
return aBoard;
}
Error is "incompatible types in assignment of int *".
How do you set arrays that are inside a struct?
You cannot assign arrays. However, you can can initialize the struct:
board PatternReader::testPattern1DX()
{
board aBoard = {
{1, 1, 1},
{2, 2, 2}
};
return aBoard;
}
This initializes y as well as x.
Add an initializer function to the board struct:
struct board
{
int x[3];
int y[3];
void initX(int* values)
{
for(int i = 0; i < 3; i++)
x[i] = values[i]
}
};
Then use it:
board PatternReader::testPattern1DX()
{
struct board aBoard;
int x[3] = { 1,1,1 };
aBoard.initX(x);
return aBoard;
}
Your code
int x[3] = { 1,1,1 };
aBoard = x;
is creating a variable of type int* with the initial values 1,1,1. You are then trying to assign that to a variable of type board. You don't want to do that. I think you intended:
int x[3] = { 1,1,1 };
aBoard.x = x;
Note the .x at the end of aBoard. However, this is still wrong. You can't assign arrays like that. Look up "copying arrays" instead. Is there a function to copy an array in C/C++?
Honestly, I would suggest making board a class with constructors and and then you can make the constructors behave as you want, and also look into overloading assignment operators. But for now, trying copying from x to aBoard.x is probably what you want.

Multi-dimensional array

I need to create a function that has a parameter which is a multi-dimensional array with two dimensions being user-specified, e.g.
int function(int a, int b, int array[a][b])
{
...
}
How would I do that in C++ ?
Are the dimensions known at compile-time? In that case, turn them into template parameters and pass the array by reference:
template<int a, int b>
int function(int(&array)[a][b])
{
...
}
Example client code:
int x[3][7];
function(x);
int y[6][2];
function(y);
Assuming the dimensions are not known at compile time, you emulate a two dimensional array with a one dimensional array:
int& getat(int x, int y, int r, int c, int *array) {return array[y*c+x];}
int function(int a, int b, int *array) {
getat(4, 2, a, b, array) = 32; //array[4,2] = 32
}
or, for safety, wrap it all in a class:
template <class T>
class array2d {
std::vector<T> data;
unsigned cols, rows;
public:
array2d() : data(), cols(0), rows(0) {}
array2d(unsigned c, unsigned r) : data(c*r), cols(c), rows(r) {}
T& operator()(unsigned c, unsigned r) {
assert(c<cols&&r<rows);
return data[r*cols+c];
}
};
or, best yet, use Boost's Multidimensional Array, which will be better than anything mere mortals could write.
I'm not sure if this work, because your question and code are not the same, according to your code the function can have 3 parameters, so this would work:
int function(int a, int b, int** &array)
{
array = new int*[a];
for (int i =0;i<a;i++)
array[i] = new int[b];
// I don't know why you are returning int, probably doing something here....
}
However your question says that your function can take only one parameter, so:
if the dimensions are known at compile time, then Fred's Answer is the best (it charmed me in fact! :) ).
if not, I can't see any possible solution that allows passing more than one user-specified value other than encapsulating all these values in one object.
Like this:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
int a,b;
int** array;
};
int function(Foo &f)
{
f.array = new int*[f.a];
for (int i = 0;i<f.a;i++)
f.array[i] = new int[f.b];
// I don't know why you are returning int, probably doing something here....
}
Though I find it a bad idea, in fact the function could be a parameterless method instead:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
void Create() // Or could do this right in the Constructor
{
array = new int*[a];
for (int i = 0;i<a;i++)
array[i] = new int[b];
}
private:
int a,b;
int** array;
};
Still this is a bad idea, because you are reinventing the wheel, as there are a perfect class in the STL to do all the work for you:
vector< vector<int> > v; // Now v is a 2D array

How can I use 3-dimensional data as a class property?

It's been a long time since I worked with C++, but I have a class that uses 3-dimensional data and I can't figure out how I can make this work. I need the sizes of the dimensions to be defined in the constructor. I tried this in the header:
class CImage
{
public:
float values[][][];
...
}
and this in the constructor:
CImage::CImage(int cols, int rows, int depth)
{
values[cols][rows][depth];
}
but this returns the error: "declaration of `values' as multidimensional array must have bounds for all dimensions except the first".
Also using this in the constructor does not work:
values = new float[cols][rows][depth];
I also tried using vector, but without much success. Header:
vector<vector<vector<float> > > values;
Nothing in constructor. No compiler errors, but when I try to set a value:
values[c][r][d] = value;
the program crashes.
It seems so basic, but I just can't figure it out...
The program crashes when accessing that vector because it is empty, i.e. there are no elements at those indexes.
The best way to go about this is to make a linear, one-dimensional, vector (or even an array), and access it with a pair of operator()'s, see C++FAQ Lite for details. Or use boost::multi_array.
For example:
#include <vector>
#include <iostream>
class CImage
{
int X, Y, Z;
std::vector<float> values;
public:
CImage(int cols, int rows, int depth)
: X(cols), Y(rows), Z(depth),
values(cols*rows*depth) {}
float operator()(int x, int y, int z) const
{
return values[Z*Y*x + Z*y + z];
// or you lay it out differently in memory
// if you please, transparent to the user:
// return values[x + X*y + X*Y*z];
}
float& operator()(int x, int y, int z)
{
return values[Z*Y*x + Z*y + z];
// likewise, in a different layout
// return values[x + X*y + X*Y*z];
}
};
int main()
{
CImage ci(3,3,3);
ci(2,2,2) = 7.0;
std::cout << ci(2,2,2) << '\n';
}
Just to poiny out why Cubbi is right, this would be the constructor of the 3d-vector:
vector<vector&ltvector&ltfloat>>> values;
// create vector [dim0][dim1][dim2]
// init value: init
size_t dim0 = 3;
size_t dim1 = 3;
size_t dim2 = 3;
float init = 0.42f;
values = vector<vector<vector<float>>>
(
dim0,
vector<vector<float>>
(
dim1,
vector<float>
(
dim0,
init
)
)
);
Nice, isn't it?
Besides, you cannot declare a float values[][][]; because arrays reside on the stack, so the compiler has to know at compile time what size that array has (exception to this: C99 variable length arrays, but this would'nt be C++). You could declare a float*** values; (using new float[c][r][d]; in the ctor), but this is awful, too.

a nicer way to create structs in a loop

I haven't coded in C++ in ages. And recently, I'm trying to work on something
involving structs. Like this
typedef struct{
int x;
int y;
} Point;
Then in a loop, I'm trying to create new structs and put pointers to them them in a list.
Point* p;
int i, j;
while (condition){
// compute values for i and j with some function...
p = new Point;
p* = {i, j}; //initialize my struct.
list.append(p); //append this pointer to my list.
}
Now, my question is it possible to simplify this? I mean, the pointer
variable *p outside of the loop and calling p = new Point inside the loop.
Isn't there a better/nicer syntax for this?
Sure:
Point * p = new Point;
You should probably also give your Point class a constructor:
struct Point { // note no need for typedef
int x;
int y;
Point( int ax, int ay ) : x( ax ), y( ay ) {}
};
so that you can say:
Point * p = new Point( i, j );
You may also want to make your list a list of Point values, rather than pointers, in which case you can avoid using dynamic allocation with new - always something to be avoided wherever possible in C++.
The struct can have a constructor like:
struct Point{
Point(int ax, int ay):x(ax), y(ay){}
int x;
int y;
};
and then the function can look like:
int i, j;
while (condition)
{
list.append(new Point(i,j));
}
As structs are classes with public members by default, you could even create a constructor within the struct and initialize your point object within the loop like this:
Point* p = new Point(i,j);
I would venture a guess that it is extremely unlikely you really need to allocate something like a Point dynamically.
Most likely you want to add a constructor and store them by value:
list<Point> list;
list.append(Point(x, y));
I recommend the Factory approach. Assuming that "Point" will be the base class of many objects, you can have a "Factory" that would return pointers.
Ex:
struct Point
{
Point(int mx, int my):x(mx),y(my) {}
int x;
int y;
};
// Circle, Polygon, etc.
class Factory
{
public:
static Point *getPoint(int mx, int my) { return new Point(mx, my); }
// Circle, Polygon, etc
};
Then in code someplace:
while(cond)
{
list.append(Factory::getPoint(i, j));
}