如何将未知大小的二维数组传递给函数

19

我想要创建一个类库,这个库里面有一个函数,它的参数是一个未知大小的矩阵。用户将会自己创建一个具有特定大小的矩阵,并将其传递给这个函数,以对该矩阵进行一些操作,函数应该如下所示:

calculateDeterminantOfTheMatrix( int matrix[][])
{
   some Operations to do on matrix 
}

你要找的语法是 int ** matrix。 - Steve Howard
1
如果你要让人们传递任意大小的矩阵,请让他们同时传递行数和列数。或者,可以使用std::vector<std::vector<int>> - wkl
2
@SteveHoward 在C++中,2D数组不会退化为指向指针的指针。 - Mahesh
你可以使用boost/multiarray - Ruggero Turra
6个回答

24

在C和C++的内置组件中,对多维数组的支持并不是很好。只有在编译时你已经知道 N-1 维的情况下,才能传递一个 N 维数组:

calculateDeterminantOfTheMatrix( int matrix[][123])

然而,标准库提供了std::vector容器,非常适用于多维数组:在您的情况下,传递vector<vector<int> > &matrix将是在C++中处理该任务的正确方式。

int calculateDeterminantOfTheMatrix(vector<vector<int> > &matrix) {
    int res = 0;
    for (int i = 0 ; i != matrix.size() ; i++)
        for(int j = 0 ; j != matrix[i].size() ; j++)
            res += matrix[i][j];
    return res;
}
作为额外的好处,您不需要将矩阵的维度传递给函数:matrix.size()表示第一维,matrix[0].size()表示第二维。

如果我声明了以下这个函数: calculateDeterminantOfTheMatrix(vector<vector<int> > &matrix) 那么我能否像这样循环它: for(matrix[rowNumber][columnNumber] - user1308378
@AhmedZainElDein 我添加了一个关于循环遍历矩阵元素的例子,以防你传入一个 vector<vector<int> > - Sergey Kalinichenko
@AhmedZainElDein 你可以让它工作,但这会更加困难:你需要以不同的方式分配它,将大小作为单独的参数传递,并在完成后释放所有内容。 - Sergey Kalinichenko
1
@AhmedZainElDein 这里是一个展示指向指针技术的答案的链接 - Sergey Kalinichenko
请注意,对于一个向量的向量,每个访问需要3个指针解引用,而不是使用二维数组(在运行时已知尺寸)时得到的一次。您可以解引用外部向量以查找指向向量内存的指针,然后再解引用该指针以访问内部向量,然后再解引用以查找实际整数。传统上它只需要乘法和单个解引用。 - mdenton8

8

C解决方案:

在C语言中,当作为函数参数传递时,你不能省略数组大小(除了最左边的)。你可以写成: int a[]

但是不可以这样写: int a[][]

举个例子,你可以这样写: int a[][20]

这个限制存在是因为编译器需要确定访问数组元素的正确偏移量。然而,你可以这样做:

void print_arbitrary_2D_array(void *arr, int y, int x)
{
    /* cast to 2D array type */
    double (*p_arr)[y][x] = (double (*)[y][x]) arr;

    int i, j;

    for (i = 0; i < y; ++i) {
        for (j = 0; j < x; ++j)
            printf(" %lf", (*p_arr)[i][j]);
        putchar('\n');
    }
}

double arr_1[4][3] = {
    { 3.3, 5.8, 2.3 },
    { 9.1, 3.2, 6.1 },
    { 1.2, 7.9, 9.4 },
    { 0.2, 9.5, 2.4 }
};
double arr_2[2][5] = {
    { 3.6, 1.4, 6.7, 0.1, 4.2 },
    { 8.4, 2.3, 5.9, 1.4, 8.3 }
};

print_arbitrary_2D_array(arr_1, 4, 3);
putchar('\n');
print_arbitrary_2D_array(arr_2, 2, 5);

int (*q)[m][n]=( int(*)[m][n])p; This casting is not working in Clion. Neither this int (*q)[n]=( int(*)[n])p; - Abhishek Mane

1

你可以采用多种方法。

  1. C语言的方式 -> 传递一个 int**,但是在这里要非常小心。这不是一个真正的二维数组。你必须正确地为这个指针分配内存,或者,另外一种方法是,在编译时知道大小。(例如静态分配一个大小为M * N的数组,然后禁止任何更大的数组)。为了动态分配内存,你需要知道行数和列数。

  2. C++的方式 -> 在 #include <vector> 后,你可以简单地使用 vector<vector<int> > &matrix(注意在 <int> 后面的空格,除非你使用c++11编译器),它将分配一个 int 向量的向量,即一个二维数组。在这种情况下,内存管理将由系统自动处理。


当考虑到二维数组可以按行或列存储时,C语言的处理方式也变得复杂。 - mdenton8

1
我会为矩阵编写一个简单的类包装器,定义列和行。
template <typename T>
class Mat {
  std::size_t _row;
  std::size_t _col;

  T *_mat_elem;
public:
  Mat(std::size_t r, std::size_t c)
   :  _row(r), _col(c), _mat_elem(new T[r*c] {}
  ~Mat() {/* remember to do delete [] here */}

  // element access, for example
  T& at(std::size_t r, std::size_t c)
  {
    return *(_mat_elem+r*_col+c);
  }
};

但实际上你正在重新发明轮子。有很好的矩阵处理库可供使用。


这个答案比其他两个好多了。 - mdenton8

0

使用这个方法 声明一个指针数组 例如:int *a[n]; 然后使用for循环为它们分配内存 例如:

for( int i=0 ; i<n ; i++ )
        a[i] = new int[n];

现在像普通数组一样传递参数。 例如:print_array(a,n); 而print_array函数看起来像这样

print_array(int **a,int n)//the prototype for the print_array
{
 //access the array using index such as
std:: cout<<a[1][1]<<endl;
}

以上情况是针对nxn数组的,如果需要mxn,则应该像下面这样分配内存:

for( int i=0 ; i<m ; i++ )
        a[i] = new int[n];

然后将m和n一起传递到函数中,在for循环中访问数组。


0

到目前为止,我发现在函数中使用二维数组的最佳方法是使用映射函数。就像下面的例子一样,我使用映射函数来打印二维数组

void Print2D(int x[],int ROWS,int COLS)
{
    for(int i=0;i<ROWS;i++)
{
    for(int j=0;j<COLS;j++)
    cout << x[i*COLS+j] << ' ';
    cout << endl;

}
}

这是如何在主函数中使用它的方法

int main(){

    int x[3][3];
    Print2D(&x[0],3,3);

}

这里的&x[0]是二维数组第一行的起始地址,更准确地说是二维数组的起始地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接