Hello great people, I have a challenge passing array into functions..
I will be very grateful for quick responses.. THANKS

Recommended Answers

All 10 Replies

what do you have right now?

One way is by value, as in

void function( int array[SIZE1][SIZE2] )
{
    // We were passed a 2-dim array of ints.
    for (int i = 0; i < SIZE1; i++)
    {
        for (int j = 0; j < SIZE2; j++)
        {
            cout << "array[" << dec << i << "][" << dec << j << "] == "
                 << dec << array[i][j] << endl;
        }
    }
}

This is the easiest way. However, with C++ you can also use vectors of vectors.

@rubberman: passing by value... not a good idea, unless the arrays are extremly small...

Since someone already post their code, I'll post mine too. Since an array is essentially a pointer, an array of arrays is an array of pointers, so a pointer to pointer (as far, as types are concerned) AFAIK the standard way for passing a two-dimensional arrays is using a pointer to pointer, like this:

void function(int **arr,int width, int height){
    for (int i=0; i<width; i++)
        for(int j=0; j<height; j++)
            cout<<arr[i][j];
}

then, in your code you can call the function it like this:

const int width=5;
const int height=7;
int arr[width][height];
function(arr,width,height);

although I never actually did it that way, so I might be wrong. There's a ton of better things, like vector of vectors, or a single vector and offsetting it, so you call it likearr[y*width+x].
Should you use vectors, remember to pass it by reference.

Anyways, remember, that passing by value anything of any decent size is not a good idea. We don't want our program to allocate (and free, calling destructors in the case of classes) additional 100kB of data every time the function is called, simply because you didn't bother to pass an argument as a reference.

Quoting the above people, its very simple... Two ways:
1) Passing through Arrays
2) Passing using pointers

First Method :
void function( float a [ ][ ] , float b [ ][ ] )

Second Method :
void function (float *a, float *b)

It's impossible to pass a C array by value (see why here).
If you want a function that can handle 2x2 and 3x3 and,
in general, MxN arrays, you could use a function template.

#include <iostream>

using namespace std;

void print2x2(int array[2][2])
{
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
            cout << array[i][j] << ' ';
        cout << '\n';
    }

    cout << endl;
}

void dec2x2(int array[2][2])
{
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            array[i][j]--;
}

template <class T, int M, int N>
void print(T (& array)[M][N])
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
            cout << array[i][j] << ' ';
        cout << '\n';
    }

    cout << endl;
}

template <class T, int M, int N>
void dec(T (& array)[M][N])
{
    for (int i = 0; i < M; i++)
        for (int j = 0; j < N; j++)
            array[i][j]--;
}

int main()
{
    int arr2x2[2][2] = {{1, 2}, {3, 4}};
    double arr3x3[3][3] = {{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}, {7.7, 8.8, 9.9}};

    print2x2(arr2x2);
    dec2x2(arr2x2);
    print2x2(arr2x2);

    print(arr3x3);
    dec(arr3x3);
    print(arr3x3);

    cout << "hit enter to quit...";
    cin.get();
}

Yea, sure u could do that.. But the simplest thing to do is using pointers... That way u dont have to change ur function template everytime if u wish to change the m x n of ur array... Its faster and can be generalised..

But note that T** is not a compatible type with T[M][N], so a function expecting the former will not accept an object of the latter.

That way u dont have to change ur function template everytime if u wish to change the m x n of ur array...

This doesn't make sense. You never have to change your function template.

Its faster

No, it's not.

#include <iostream>
#include <boost/timer.hpp>

using namespace std;

double global;

template <int M, int N>
void speedTest(int (& array)[M][N])
{
    for (int i = 0; i < M; ++i)
        for (int j = 0; j < N; ++j)
            array[i][j] = 0;

    global++;
}

void speedTestPtr(int * array, int M, int N)
{
    for (int i = 0; i < M; ++i)
        for (int j = 0; j < N; ++j)
            array[i*N + j] = 0;

    global++;
}

int main()
{
    int arr2x2[2][2] = {{1, 2}, {3, 4}};

    boost::timer timer;

    timer.restart();

    for (long i = 0; i < 10000000; ++i)
    for (long j = 0; j < 15; ++j)
        speedTest(arr2x2);

    cout << "time 1: " << timer.elapsed() << endl;

    timer.restart();

    for (long i = 0; i < 10000000; ++i)
    for (long j = 0; j < 15; ++j)
        speedTestPtr(&arr2x2[0][0], 2, 2);

    cout << "time 2: " << timer.elapsed() << endl;

    cout << global << endl;

    cin.get();
}

I tested the above with zero, -O1, -O2 and -O3 speed optimizations. The results I got were, respectively:

time 1: 3.5
time 2: 4.1

time 1: 0.7
time 2: 1.7

time 1: 0.234
time 2: 0.281

time 1: 0.187
time 2: 0.187

can be generalised

In what way can the pointer version be generalized that the template version can't?

the simplest thing to do is using pointers

Simplest in what way? Here are a couple of problems I see with the pointer version:

(a) The calling syntax is verbose.
(b) The calling site is error prone (you could provide wrong arguments by mistake and your compiler would not complain).
(c) You are responsible for consistency in the way you store data in your arrays (e.g. you'll have a serious problem if some of your functions use row major order and others use column major order -- and this problem gets bigger and bigger as you add dimensions to your array).

Thank u guys, but I want the arrays to be declared dynamically in the main() and then passed to the function

If you allocated the arrays dynamically, then you don't have an array object to pass to the function, you only have a pointer to the first element of an array. In other words, the only option you have is to pass by pointer. If you store your 2x2 or 3x3 arrays as arrays of arrays, then you must have a pointer to a pointer. In other words, you'll have code that looks like this:

void printArray(float** p, int N, int M) {
  for(int i = 0; i < N; ++i) {
    for(int j = 0; j < M; ++j)
      std::cout << " " << p[i][j];
    std::cout << std::endl;
  };
};

int main() {
  float** p = new float*[3];
  for(int i = 0; i < 3; ++i)
    p[i] = new float[3];

  for(int i = 0; i < 3; ++i)
    for(int j = 0; j < 3; ++j)
      p[i][j] = i * 3 + j;

  printArray(p,3,3);

  for(int i = 0; i < 3; ++i)
    delete[] p[i];
  delete[] p;

  return 0;
};

That's about all there is to it. If you have any questions, please ask.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.