-1

I have seen many questions of this type on SO, but nothing really helped.I'm a newbie in C++.

#include<iostream>
using namespace std;

int func(int i,int j,int r,int c,int **A)
{
    //do something
}

int main(void)
{
    int r,c;
    cin>>r>>c;
    int A[r][c];
    //read array
    for(int i=0;i<r;i++){
        for(int j=0;j<c;j++){
            cin>>A[i][j];
        }
    }
    if(func(0,0,r,c,A)){
        cout<<1<<endl;
    }
    else{
        cout<<0<<endl;
    }
}

this gives the following error

error: cannot convert ‘int (*)[c]’ to ‘int**’ for argument ‘5’ to ‘int func(int, int, int, int, int**)’ if(func(0,0,r,c,A)){

Novice
  • 73
  • 5
  • `cin>>r>>c; int A[r][c];` -- This is not valid C++. Arrays must be declared using constants to denote the number of entries, not variables. Second, your function requires an `int**`, but you're passing it something that is not compatible with that type. So start with an `int **` and *build* the array from there. – PaulMcKenzie Nov 02 '17 at 15:38
  • You say you couldn't find anything on SO. [Does this help](https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048)? You *build* the array from scratch, and there are **many** links on SO showing various ways of building a `T**` based 2D array (in your case, `T` is an `int`) – PaulMcKenzie Nov 02 '17 at 15:42
  • Your array is 2 dimension. This does not make it double pointer! You must pass &A – Philip Brack Nov 02 '17 at 15:43
  • @PhilipBrack No, what should be passed is what is asked for, and that is an `int**`. – PaulMcKenzie Nov 02 '17 at 15:44
  • 1
    Why don't you use std::vector? – BartekPL Nov 02 '17 at 15:47
  • If you want to rely on a compiler extension, you have to change your function to `int func(int i,int j,int r,int c,int (*A)[c])`, which would be the correct prototype for the shown call. – mch Nov 02 '17 at 15:48
  • 1
    Yes, the better way is to skip this and just use `std::vector>` or `std::vector` and simulate a 2D array using only one dimension. – PaulMcKenzie Nov 02 '17 at 15:49

5 Answers5

2

The easiest way without using additional template libraries is pointer to pointer.

int **A;
A = new int *[r];
for(int i = 0; i <r; i++)
    array[i] = new int[c];

for(int i=0;i<r;i++){
    for(int j=0;j<c;j++){
        cin>>A[i][j];
    }
}

if(func(0,0,r,c,A)){
    cout<<1<<endl;
} else {
    cout<<0<<endl;
}
Victor
  • 461
  • 1
  • 5
  • 14
  • Why no mention that this has to be deallocated at some point? The implementation I linked to handles this, plus doesn't potentially fragment the memory that this solution can cause. [Link](https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048) – PaulMcKenzie Nov 02 '17 at 18:46
  • @PaulMcKenzie sure you have to clean up when you're dealing with heap allocation. Just a basic rule of thumb. I thought that not the scope of this question, besides there are many more improvements to-be here, compared to which not cleaning up heap memory, allocated within main() is quite forgivable. – Victor Nov 02 '17 at 19:46
1

For starters Variable Length Arrays is not a standard C++ feature. It can be a language extension of the compiler that can not be supported by other compilers.

So instead of a variable length array use standard container std::vector.

To solve your problem with using arrays you can define a template function. For example

template <size_t M, size_t N>
int func( int i, int j, int ( &a )[M][N] )
{
    //do something
}

If to use the compiler that supports VLAs then at least the function could look like

int func(int i,int j,int r,int c, int A[r][c] )
{
    //do something
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • @TomazCanabrava You did not understand my answer. The template function does not designed to be used with VLAs. If he is going to use VLAs then I showed a non-template function for such arrays. – Vlad from Moscow Nov 02 '17 at 16:40
0

The old fashioned method is to allocate your array as a one dimensional array, then index it as a 2d array:

int * my_array = new int[m * n];

Next, passing to a function, you can pass by pointer to the first element, then pass the row and column capacities:

void Process_Array(int * array, size_t max_rows, size_t max_columns);

//...
Process_Array(my_array, m, n);

The index can be calculated as:

size_t array_index = row * n + column;
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

This is not a direct answer, as others have already presented actual solutions, but more an explanation on the why it is so complex and what are the idiomatic C++ alternatives to dynamic multi-dimensional arrays.

C++ fellows say that raw array management is not for common programmers but should be reserved to library implementers. For that reason, nothing is done to easily pass multi dimensional arrays along with their sizes to functions, while it used to be common in Fortran IV in the 80s.

The C++ ways are (from the simpler to the harder):

  • use a vector<vector<int>> a vector can be used like a dynamic size array, so a vector can be used like a 2D array, provided you do not need contiguous allocation
  • implement a wrapper class around a contiguous 1D array of size r*c that presents access to cells with a function returning a reference:

    int& cell(int i, int j) { return (arr + i * c)[j]; }
    

    I say it is easier because it can be extended to multi dimension arrays (more than 2D)

  • implement a wrapper class around a contiguous 1D array of size r*c that present a 2D array interface (arr[i][j] = x;). In fact it is enough to implement an operator[] that returns a pointer to the first element of a row. It can still be extended to n-D arrays (n>2) but it becomes tougher.

Finally, one of the major reasons is that there are few real use cases for contiguous n-D arrays of variable size. So you should wonder whether a vector<vector>, or a plain 1D array of size r*c are not enough.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

You can create matrixes in runtime on C++ if you think a matrix as a vector of vectors, and put a bit of memory allocation on it.

using a bit of C:

int **createMatrix(int cols, int rows) {
    int **matrix = malloc(sizeof(int*) * cols);
    for(int i = 0; i < cols; ++i) {
        matrix[i] = malloc(sizeof(int) * rows;
    }
    return matrix;
}

then you can use your newly created matrix just you would use any other matrix created with [][].

Tomaz Canabrava
  • 2,320
  • 15
  • 20