Sign in to follow this  
OakWood

Passing a multi dimensional array to a function

Recommended Posts

I'm extremely new to this, so I'll apologise in advance if this is a stupid question. I can't work out how to pass a multi-dimensional array to a function through a pointer (not sure if that makes sense). I'm also not sure how I would refer to the array through the pointer. I would also like to mention that the funcion will have different sized arrays passed to it and so has to be flexible. I've tried something like this:
void main()
{
   int tile[5][5];
   //give tile its values here
   ...
   //pass to function
   check(&tile[0][0]);

   return;
}

void check(int *tilePointer)
{
   cout << *tilePointer[2][2]
return;}
Sorry if I haven't explained it very well

Share this post


Link to post
Share on other sites
wrap it in a class/struct and pass that by reference or something. much cleaner. there's really no good way to pass an array otherwise without also passing its dimensions as seperate parameters.

Share this post


Link to post
Share on other sites
It should work if you fix your check function


int main()
{
int tile[5][5];

tile[0][0] = 6;
check (&tile[0][0]);

return 0;
}
void check(int * tilePointer)
{
cout << *tilePointer;
}


That will print out whatever element of the array you throw in there...(in this case 6)

I don't know if that's what your looking for...but what you did is pass to the function element [0][0], and then tried to print out element [2][2] (which doesn't exist in tilePointer when you pass it tile[0][0])

Share this post


Link to post
Share on other sites
Sorry, my bad example didn't help. I wanted to have a pointer to the entire array. Thanks for the pointing that out ArchG.

Thanks DrEvil, I'll give that a go, sounds like just what I'm looking for:)

Share this post


Link to post
Share on other sites
It is a hell of a lot easier to just avoid multidimensional arrays, IMHO.


void main()
{
int x[5*5];

f(x);
}

void f(int *p)
{
cout << p[(2*5)+2] << endl;
}



But of course you can still go out of bounds, or run into other array-associated errors. Use of raw arrays like this should be discouraged really. A vector of vectors would probably be a better approach.

Share this post


Link to post
Share on other sites
So, if I was using easily confused's method, it is just making it into a single dimension array, and that formula (x*width)+y helps you find it as if it were a still 2d.

Hmmm, that does seem messy. I've not really had cause to use vectors much, finding arrays to be more than adequate up until now.

Are vectors a better solution in general or is it a case of different ones for different tasks?

edited because I was talking rubbish.

Share this post


Link to post
Share on other sites
Quote:
Original post by OakWood
So, if I was using easily confused's method, it is just making it into a single dimension array, and that formula (x*width)+y helps you find it as if it were a still 2d.

Hmmm, that does seem messy. I've not really had cause to use vectors much, finding arrays to be more than adequate up until now.

Are vectors a better solution in general or is it a case of different ones for different tasks?

edited because I was talking rubbish.


Nooo. (y*width)+x! But yes, it is a bit messy. You can tidy it up with a little class if you want:


template<class T> class grid
{
private:
T *p; int w,h;

public:
grid(int width,int height) : w(width),h(height) { p=new T[w*h]; }
~grid(){ delete [] p; }

T &operator()(int x,int y){ return p[(y*width)+x]; }
const T &operator()(int x,int y) const { return p[(y*width)+x]; }
};

void main()
{
grid<int> g(5,5);

f(g);
}

void f(grid<int> &g)
{
cout << g(2,2) << endl;
}






Obviously the class wants bound checking put in.

Share this post


Link to post
Share on other sites
Rigth, thanks a lot EasilyConfused, great help. I'll make that class for now and probably mess arounbd with vectors and convert it in a while. Thanks

Share this post


Link to post
Share on other sites
DISCLAIMER: That was a very quick off-the-cuff class and I would recommend you look into vectors FIRST, or at least have a look at an existing proper solution. I assume there is a boost::multidimensional_array or something?

Share this post


Link to post
Share on other sites
multi-dimensional vectors are slower than normal arrays(they are not contiguous memory), and you can still go out of bounds, though it might present you with a better error message. boost has a class that does this and more, and I believe the memory is contiguous, making it up there with normal arrays in terms of speed. If you don't want to bother with boost, a custom array wrapper is trivial. There's nothing hard about bounds checking yourself and not allowing someone to access the array memory directly.

http://www.boost.org/libs/multi_array/doc/index.html

Share this post


Link to post
Share on other sites
Of course, if you really feel like using multi-dimensional arrays you can use template functions and array references to handle multi-dimensional arrays of arbitrary size.

template <size_t i, size_t j>
bool check(int (&array)[i][j]) {
// do stuff
for (size_t k = 0; k < i; k++) {
for (size_t l = 0; l < j; l++) {
std::cout << array[k][l];
}
}
return true;
}

int main(int, char **) {
int a[5][5];
int b[6][4];

check(a);
check(b);

return 0;
}


This, of course, depends on your compiler grokking non-type template argument deduction.

Share this post


Link to post
Share on other sites
How about


#include <vector>

template<class T> class grid
{
public:
class bounds_error{ };

private:
std::vector<T> v; int w,h;

void check(int x,int y)
{ if(x<0 || x>=w || y<0 || y>=h) throw bounds_error(); }

public:
grid(int width,int height) : w(width),h(height),v(width*height) { }

T &operator()(int x,int y){ check(x,y); return v[(y*w)+x]; }
const T &operator()(int x,int y) const { check(x,y); return v[(y*w)+x]; }

int width() const { return w; }
int height() const { return h; }

void resize(int width,int height)
{ v.resize(width*height); w=width; h=height; }
};



Share this post


Link to post
Share on other sites
Possible, but I prefer something more like:


template <typename T, size_t size>
class Array {
T data[size];
public:
T& operator[](size_t index) { return data[index]; }
const T& operator[](size_t index) const { return data[index]; }
};

template <typename T, size_t r, size_t c>
class Grid : public Array<Array<T, r>, c> {};


Of course, it exists already: see [boost]::array.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this