2D-Array as Argument to Function

Passing a 2D array to a C++ function

There are three ways to pass a 2D array to a function:

  1. The parameter is a 2D array

    int array[10][10];
    void passFunc(int a[][10])
    {
    // ...
    }
    passFunc(array);
  2. The parameter is an array containing pointers

    int *array[10];
    for(int i = 0; i < 10; i++)
    array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
    // ...
    }
    passFunc(array);
  3. The parameter is a pointer to a pointer

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
    array[i] = new int[10];
    void passFunc(int **a)
    {
    // ...
    }
    passFunc(array);

How to pass 2D array (matrix) in a function in C?

C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:

1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:

#define ROWS 4
#define COLS 5

void func(int array[ROWS][COLS])
{
int i, j;

for (i=0; i<ROWS; i++)
{
for (j=0; j<COLS; j++)
{
array[i][j] = i*j;
}
}
}

void func_vla(int rows, int cols, int array[rows][cols])
{
int i, j;

for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}

int main()
{
int x[ROWS][COLS];

func(x);
func_vla(ROWS, COLS, x);
}

2) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.

void func(int** array, int rows, int cols)
{
int i, j;

for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i][j] = i*j;
}
}
}

int main()
{
int rows, cols, i;
int **x;

/* obtain values for rows & cols */

/* allocate the array */
x = malloc(rows * sizeof *x);
for (i=0; i<rows; i++)
{
x[i] = malloc(cols * sizeof *x[i]);
}

/* use the array */
func(x, rows, cols);

/* deallocate the array */
for (i=0; i<rows; i++)
{
free(x[i]);
}
free(x);
}

3) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:

void func(int* array, int rows, int cols)
{
int i, j;

for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
{
array[i*cols+j]=i*j;
}
}
}

int main()
{
int rows, cols;
int *x;

/* obtain values for rows & cols */

/* allocate the array */
x = malloc(rows * cols * sizeof *x);

/* use the array */
func(x, rows, cols);

/* deallocate the array */
free(x);
}

4) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);

void func_vla(int rows, int cols, int array[rows][cols])
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
array[i][j] = (i + 1) * (j + 1);
}
}
}

int main(void)
{
int rows, cols;

get_rows_cols(&rows, &cols);

int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
/* error check omitted */

func_vla(rows, cols, array);
dump_array("After initialization", rows, cols, array);

free(array);
return 0;
}

void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
printf("%s (%dx%d):\n", tag, rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%4d", array[i][j]);
putchar('\n');
}
}

void get_rows_cols(int *rows, int *cols)
{
srand(time(0)); // Only acceptable because it is called once
*rows = 5 + rand() % 10;
*cols = 3 + rand() % 12;
}

(See srand() — why call it only once?.)

Use of a function on a 2d array

  • The function int function(int **arr) does not return an int so make it void.
  • When you call it, a = function(&arr[i][0]);, you do not use a after the assignment. I suggest that you remove a from the program completely since it's not used anywhere.
  • The call to the function, function(&arr[i][0]);, should simply be function(arr);
  • The function signature needs to include the extent of all but the outermost dimension:
    void function(int arr[][M])
  • Inside the function, you use 3 and 5 instead of N and M. That accesses the array out of bounds.
  • In function, the i and j you declare at the start of the function are unused. Remove them.
  • arr[i][j] = arr[i][j] + 50; is better written as arr[i][j] += 50;
  • When initializing a multidimensional array, use braces to make it simpler to read the code:
    int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
  • In main you mix int and size_t for the indexing variables. I suggest you settle for one type.
  • Remove unused header files (string.h)

Example:

#include <stdio.h>

#define N 2
#define M 4

void function(int arr[][M]) {
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
arr[i][j] += 50;
}
}
}

int main() {
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};

for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}

printf("\n ***values after modification***\n");

function(arr);

// int array print results
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}

Since you print the array more than once, you could also add a function to do so to not have to repeat that code in main:

void print(int arr[][M]) {
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}

To pass 2D Dimensional array as an argument?

This is how to pass in a 2d array to a function. This is about as simple as I can make it. There's no need to define the type (i.e. don't do data[][]) when defining the function (I think that's where you were going wrong).

// define 2d array
var data = [[0,1],[1,3],[2,6]];

// define function
function myFunction(foobar){
// ... do something with 2d array "foobar" ...
}

// invoke function, passing in 2d array
myFunction(data);

Example: Try it out using a tool like jsbin!

2D-array as argument to function

You can't write void Foo(int bar[][]), because bar decays to a pointer. Imagine following code:

void Foo(int bar[][]) // pseudocode
{
bar++; // compiler can't know by how much increase the pointer
// as it doesn't know size of *bar
}

So, compiler must know size of *bar, therefore size of rightmost array must be provided.

pass 2d array to a function in c++

Problems in your code:

Problem 1

void input(int matrix[][],int num_h){

is not valid C++. In a multi-dimensional array, all but the first dimension must be constants. A valid declaration would be:

// Define a constant at the start of the file.
const int MATRIX_SIZE 200;

void input(int matrix[][MATRIX_SIZE],int num_h){

Problem 2

int matrix[num_h][num_h];

is not valid C++. VLA are not supported in C++.

Suggested Solution

Use std::vector<std::vector<int>> to capture the 2D array.

Change

void input(int matrix[][],int num_h){

to

void input(std::vector<std::vector<int>>& matrix){
// You can get the size by calling matrix.size()
// There is no need to pass num_h as an argument.

Change the calling code to:

int main(){
Graph g;
int num_h;
cout<<"Enter the number of houses: ";
cin>>num_h;

// Construct a 2D array of size num_h x num_h using std::vector
std::vector<std::vector<int>> matrix(num_h, std::vector<int>(num_h));

g.input(matrix);
return 0;
}

Passing a 2D array to a function / constructor

2D arrays are stored contigously, so you should probably do something like this example:

#include <iostream>

template<size_t N1, size_t N2>
void output(const float (&elements)[N1][N2])
{
for (size_t i = 0; i < N1; i++)
{
for (size_t j = 0; j < N2; j++)
std::cout << elements[i][j] << ' ';
std::cout << std::endl;
}
}
int main()
{

float elements[3][3] = {
{1,2,3},
{1,2,3},
{1,2,3}
};
output<3, 3>(elements);
}

Note how I've used templates because the array size is static, which is another mistake you did

Edit: I understand what you're trying to do, here's how:

Make the Matrix class a template class taking the template parameters rows and columns, and change the elements parameter into float elements[rows][columns]

template<size_t rows, size_t columns>
class Matrix
{
private:
MatrixData _matrix = MatrixData();
public:
Matrix(float elements[rows][columns])
{
_matrix.rows = rows;
_matrix.columns = columns;

_matrix.elements = new float[rows * columns];

for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
_matrix.elements[(i * columns) + j] = elements[i][j];

}
};

Then you have to remove the rows and columns constructor parameters because you already have them as template parameters.

Now the object declaration should look like this:

int main()
{
float Identity[3][3] =
{
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
};

Matrix<3, 3> identity(Identity);
}

Passing a 2D array as Function Argument

You could do this using templates. In particular, using nontype template parameters as shown below:


#include <iostream>
//make func a function template
template<std::size_t N, std::size_t M>
void func(int (&arr)[N][M])
{
std::cout<<"func called with: "<<N<<" rows and "<<M<<" columns"<<std::endl;
}
int main()
{
int arr2[10][15];
func(arr2);
return 0;
}

In the above example N and M are called nontype template parameters.

Using templates we can even make the type of elements in the array arbitrary, as shown below:

//make func a function template
template<typename T, std::size_t N, std::size_t M>
void func(T (&arr)[N][M])
{
std::cout<<"func called with: "<<N<<" rows and "<<M<<" columns"<<std::endl;
}
int main()
{
int arr2[10][15];
func(arr2);

float arr3[3][4];
func(arr3);//this works too
return 0;
}


Related Topics



Leave a reply



Submit