Pranjal
Pranjal

Reputation: 689

pass 2d array to a function in c++

I am trying to pass a 2d array to a function in c++. The problem is that its dimension is not universal constant. I take the dimension as an input from the user and then try to pass the array. Here is what i am doind:

/*
 * boy.cpp
 *
 *  Created on: 05-Oct-2014
 *      Author: pranjal
 */
#include<iostream>
#include<cstdlib>
using namespace std;


class Queue{
private:
    int array[1000];
    int front=0,rear=0;
public:
    void enqueue(int data){
        if(front!=(rear+1)%1000){
            array[rear++]=data;
        }
    }
    int dequeue(){
        return array[front++];
    }
    bool isEmpty(){
        if(front==rear)
            return true;
        else
            return false;
    }
};

class Graph{
public:
    void input(int matrix[][],int num_h){ //this is where I am passing the matrix
        int distance;
        char ans;

        for(int i=0;i<num_h;i++){
            for(int j=0;j<num_h;j++)
                matrix[i][j]=0;
        }
        for(int i=0;i<num_h;i++){
            for(int j=i+1;j<num_h;j++){
                cout<<"Is there route between houses "<<i<<" and "<<j<<": ";
                cin>>ans;
                if(ans=='y'){
                    cout<<"Enter the distance: ";
                    cin>>distance;
                    matrix[i][j]=matrix[j][i]=distance;
                }
            }
        }
        cout<<"The matrix is: \n";
        for(int i=0;i<num_h;i++){
            cout<<"\n";
            for(int j=0;j<num_h;j++)
                cout<<matrix[i][j]<<"\t";
        }
    }
};

int main(){
    Graph g;
    int num_h;
    cout<<"Enter the number of houses: ";
    cin>>num_h;
    int matrix[num_h][num_h];
    g.input(matrix,num_h); //this is where I get an error saying
                           // Invalid arguments ' Candidates are: void input(int (*)[], 
                           // int) '
    return 0;
}

Help much appreciated. Thank you.

Upvotes: 1

Views: 15463

Answers (3)

Erik Bowman
Erik Bowman

Reputation: 11

I had a similar problem, where I was trying to ingest an array that was specified as a double[4][4] into my own C++ matrix class which handled arbitrary dimensions, and thus stored the matrix internally as a double**. As everyone has stated earlier, these are not equivalent -- double ** can be fragmented, where double[4][4] occupies contiguous memory.

But if you realize that a double[4][4] is simply a double[16], where the array is written in row-major order (e.g. read across each row, then move to the second row, etc), you can pass the double[][] as a double* as an argument. Here is a subset of the code from my matrix class, and how I was able to pass a double[4][4] 2-D array into that class.

class CMatrix
{
  public:
    CMatrix(unsigned int nRows, unsigned int nCols);
    Set(unsigned int nRows, unsigned int nCols, double* array, bool columnMajor=false)
  protected:
   double** m_M;
}

CMatrix(unsigned int nRows, unsigned int nCols)
{
    unsigned int i = 0;

    m_M = new double*[nRows];
    for (i = 0;i<nRows;i++)
      m_M[i] = new double[nCols];
}

CMatrix::Set(unsigned int nRows, unsigned int nCols, double* array, bool columnMajor)
{
   unsigned int i = 0;
   unsigned int row = 0;
   unsigned int col = 0;

  if (columnmajor) // e.g. FORTRAN
  {
    // same as below but switch order between rows and columns
  }
  else // row major (e.g. C/C++)
  {
    for (i=0;i<nRows*nCols;i++)
    {
      m_M[row][col] = array[i];
      col++;
      if (col % nCols == 0)
      {
         row++;
         col = 0;
      }
    }
  }
}

int main()
{
   CMatrix M(4,4);
   double oldMat[4][4];

   M.Set(4,4,reinterpret_cast<double*>(oldMat));
}

Not pretty, but by reintrepreting the double[][] as a double*, I am able to pass the value. But when you do this, you lose the information about the # of rows and columns, which is why I made those explicit arguments in my Set() function. With that knowledge, you can now convert the 2-D array elements into whatever internal format you need. I added a flag for column-major (which defaults to row major if unspecified), because I am often converting FORTRAN code to C++, and unlike C/C++, FORTRAN converts 2-D arrays to 1-D arrays in column-major form (i.e. reads down a column before moving to the next column), while C/C++ converts using row-major form (reading across a row before moving to the next row).

Hopefully this provides another useful alternative to using the std::vector<> approach above. That approach didn't work for me, because I did not have the flexibility to change the structure of the initial matrix -- it was a member within a class created by someone else.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206717

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;
}

Upvotes: 7

Joao
Joao

Reputation: 619

Instead of passing the entire matrix, pass a pointer to the matrix. To do this effectively, you need to either treat the matrix as 2D, but manage it as a vector, or use a vector of vectors.

Considering the first case, you would:

int matrix[num_h * num_h];

and

g.input(matrix,num_h)

to

void input(int *matrix,int num_h)

and access the elements using

matrix[i * num_h + j] = 0;

Upvotes: -1

Related Questions