manipulating multidimensional arrays with function

2019-01-26 01:24发布

问题:

I am trying to modify the contents of a 2D array in C++ using a function. I haven't been able to find information on how to pass a 2D array to a function by reference and then manipulate individual cells.

The problem I am trying to solve has the following format. I have made a simple program for brevity.

#include<cstdlib>
#include<iostream>
using namespace std;

void func(int& mat) {
    int k,l;
    for(k=0;k<=2;k++) {
    for(l=0;l<=2;l++) {
    mat[k][l]=1;  //This is incorrect because mat is just a reference, but
                  // this is the kind of operation I want. 
    }
}

return; 
}

int main() {
int A[3][3];
int i, j;
char jnk;

for(i=0;i<=2;i++) {
    for(j=0;j<=2;j++) {
        A[i][j]=0;
    }
}

    func(A);

cout << A[0][0];
    return 0;
}

So the value of A[0][0] should change from 0 to 1. What is the correct way to do this? Many thanks in advance...

回答1:

Arrays are not passed by value, so you can simply use

void func(int mat[][3])

and, if you modify the values of mat inside func you are actually modifying it in main.

You can use that approach if you know a priori the size of your matrix, otherwise consider working with pointers:

#include <iostream>

void f(int **m, int r, int c) {
    m[0][0]=1;
}

int main () {

    int **m;
    int r=10,c=10;
    int i;

    m = (int**)malloc(r*sizeof(int*));

    for (i=0; i<r;i++)
        m[i] = (int*)malloc(c*sizeof(int));

    f(m,r,c);

    printf("%d\n",m[0][0]);

    for(i=0;i<r;i++)
        free(m[i]);

    free(m);

    return 0;

}


回答2:

C++ allows you to encapsulate code structures like this into an object, for example an array has the std::vector and std::array object.

I personally roll my own matrix containers. This way you don't have to worry about the details of how they are passed.

A basic example of a matrix implemenation could be:

template<typename T>
class matrix
{
public:                     //TYPEDEFS
    typedef                         T                                                       value_type;
private:
    typedef                 std::vector<value_type>         vect_type;
public:
    typedef typename        vect_type::iterator             iterator;
    typedef typename        vect_type::const_iterator       const_iterator;

private:            //DATAMEMBERS
    vect_type values;
    size_t x_sz, y_sz;/not const for assingment reasons

public:                     //MEMBER FUNCTIONS
    matrix(const matrix&)           =default;
    matrix(matrix&&)                =default;
    matrix& operator=(const matrix&)=default;
    matrix& operator=(matrix&&)     =default;

    matrix(size_t x_sz_=0u, size_t y_sz_=0u, value_type t=value_type())
    : values(x_sz_*y_sz_, t)
    , x_sz(x_sz_)
    , y_sz(y_sz_)
    { }

    //return        symbol          const   body
    size_t          x_size()        const   { return x_sz; }
    size_t          y_size()        const   { return y_sz; }

    iterator        begin()                 { return values.begin();        }
    iterator        end()                   { return values.end();          }
    const_iterator  begin()         const   { return values.cbegin();       }
    const_iterator  end()           const   { return values.cend();         }
    const_iterator  cbegin()        const   { return values.cbegin();       }
    const_iterator  cend()          const   { return values.cend();         }

    value_type& at(size_t x, size_t y)
    {
            return values.at(y*x_sz+x);
    }

    const value_type& at(size_t x, size_t y) const
    {
            return values.at(y*x_sz+x);
    }
};  //class matrix

Then you simply do the following:

 void func(const mat& m)....
 :::

 matrix<int> mat(3,3);

 //this isn't necessary as the ctor take a default value,
 // however it show you how you might iterate through the values.
 for(size_t y=0; y!=mat.y_size(); ++y)
    for(size_t x=0; x!=mat.x_size(); ++x)
        mat.at(x, y)=0; 

func(mat); //as param


回答3:

can you check on this:

#include <cstdio>
#include <cstdlib>

void printArrays(int* array[], int len1, int len2) {
  for (int i=0; i<len1; i++) {
    for (int j=0; j<len2; j++) {
      printf("%d ", array[i][j]);
    }
    printf("\n");
  }
}

void modify(int* array[], int len1, int len2) {
  for (int i=0; i<len1; i++) {
    for (int j=0; j<len2; j++) {
      array[i][j]*=(i+j);
    }
  }
}

int main() {
  int arr1[3] = {4, 5, 5};
  int arr2[3] = {6, 1, 5};
  int arr3[3] = {7, 5, 1};
  int *array[3] = {arr1, arr2, arr3};
  printArrays(array, 3, 3);
  printf("After modify:\n");
  modify(array, 3, 3);
  printArrays(array, 3, 3);
  return 0;
}


回答4:

Here's the conventional way. You can use either version of function "f":

#include <cstdlib>

const size_t cols = 10; // You can hardcode this below if you want

// Can only be called if you know "cols" at compile-time
void f(int pArray[][cols], size_t rows)
{
    for(size_t i = 0; i < rows; ++i)
    {
        for(size_t j = 0; j < cols; ++j)
        {
            pArray[i][j] = 1;
        }
    }
}

// Use this if you don't know "cols" at compile-time (good for any arbitrary 2D array)
void f(int *pArray, size_t rows, size_t cols)
{
    for(size_t i = 0; i < rows; ++i)
    {
        const size_t RowOffset = (i * cols);
        for(size_t j = 0; j < cols; ++j)
        {
            pArray[RowOffset + j] = 1;
        }
    }
}

int main()
{
    int array[][cols]= {{   5,  10,  15,  20,  25,  30,  35,  40,  45,  50 },
                        {  55,  60,  65,  70,  75,  80,  85,  90,  95, 100 },
                        { 105, 110, 115, 120, 125, 130, 135, 140, 145, 150 },
                        { 155, 160, 165, 170, 175, 180, 185, 190, 195, 200 },
                        { 205, 210, 220, 225, 230, 235, 240, 245, 250, 255}};

    const size_t rows = sizeof(array) / sizeof(array[0]); // 5 in this example but you can hardcode it if you want
    f(array, rows);
    f(array[0], rows, cols);

    return 0;
}