debugging 如何调用包含多维数组的函数?

euoag5mw  于 2023-01-09  发布在  其他
关注(0)|答案(2)|浏览(107)
#include <iostream>
#define MAX 100
using namespace std;

void compute_minor_sums (int a[][MAX], int B[][MAX], int n1, int n2){
    int sum=0,row[n2],col[n1];
    for(int i=0;i<n1;i++){
        for(int j=0;j<n2;j++){
            cin>>a[i][j];
            sum+=a[i][j];
        }
    }
    for(int i=0;i<n1;i++){
        for(int j=0;j<n2;j++){
            row[i]+=a[i][j];
            col[j]=col[j]+a[i][j];
        }
    }
   for(int i=0;i<n1;i++){
        for(int j=0;j<n2;j++){
            B[i][j]=sum-row[i]-col[j]+a[i][j];
        }
    }

}

int main()
{
    int n1,n2;cin>>n1>>n2;
    int a[n1][n2],B[n1][n2];
     compute_minor_sums ( a, B,n1,n2);
    }

程序是关于计算一个n1*n2矩阵的子式。我试着调用一个函数来计算子式。但是我不知道为什么会出现这种错误。第一个错误是:

Cannot convert int (*)[n2] to int int (*)[100]

第二个错误是:

Initialising argument 1 of void compute_minor_sums (int a[][MAX], int B[][MAX], int n1, int n2)

我不能使用gdb,因为这些错误是语法错误。任何帮助将不胜感激

kd3sttzy

kd3sttzy1#

用vector重写代码。
(矩阵计算逻辑我不太清楚。)
如果矩阵不是正方形,则会出现内存限制错误。

#include <iostream>
#include <vector>
#define MAX 100
using namespace std;

void compute_minor_sums(vector<vector<int>>& a, vector<vector<int>>B, int n1, int n2) {
    int sum = 0;
    vector<int> row(n2);
    vector<int>col(n1);
    for (int i = 0; i < n1; i++) {
        for (int j = 0; j < n2; j++) {
            cin >> a[i][j];
            sum += a[i][j];
        }
    }
    for (int i = 0; i < n1; i++) {
        for (int j = 0; j < n2; j++) {
            row[i] += a[i][j];
            col[j] = col[j] + a[i][j];
        }
    }
    for (int i = 0; i < n1; i++) {
        for (int j = 0; j < n2; j++) {
            B[i][j] = sum - row[i] - col[j] + a[i][j];
        }
    }

}

int main()
{
    int n1, n2;
    cin >> n1 >> n2;
    vector<vector<int>> a(n1, vector<int>(n2)); // n1 x n2 matrix
    vector<vector<int>> B(n1, vector<int>(n2)); // n1 x n2 matrix
    compute_minor_sums(a, B, n1, n2);
}
0kjbasz6

0kjbasz62#

你的代码有很多问题,我将从一些可见的问题开始。正如其他用户在评论中提到的- VLA在C++中不存在。什么是VLA?
VLA的大小是在runtime期间确定的,而不是在compilation期间确定的。因此,以下代码不会编译,因为值n1n2是在runtime期间由用户确定的

int main()
{
  int n1,n2;
  std::cin >> n1 >> n2; // <-- we get values n1 and n2 during runtime from user input
  int a[n1][n2],B[n1][n2];
  //...
}

将编译以下代码:

int main()
{
  const int n1 = 1;
  const int n2 = 2; // known during compilation and guaranteed not to change
  int a[n1][n2],B[n1][n2];
  int c[1][2]; // the same as using const ints - 1 and 2 are known during compilation
  //...
}

所以你可能会问:

如果在编译期间不知道C样式数组的大小,我们该怎么办?

答案是,你可以在上分配数组,但是拥有一个2D数组不再简单,即:

int main()
{
  int n1,n2;
  std::cin >> n1 >> n2; // <-- we get values n1 and n2 during runtime from user input
  int **a = new int*[n1];
  for (int i = 0; i < n1; ++i) {
    a[i] = new int[n2];
  }
}

正如你所看到的,我们创建了指向int的指针,因为数组就是这样的,指向int的指针,它是int数组的开始,其余的值是前一个元素的偏移量。
我们还可以通过以下方式简化上述内容:

int* a = new int[n1 * n2];

// a[i][j] is then
a[i * n1 + j]

您的代码还有其他问题,但一次只解决一个问题。
如果你想把它传递给函数,那么你现在有更多的选择,除了简单地传递指针到数组的开头(即a)就足够了,但是你必须添加一些额外的边界检查逻辑。因此,为什么其中一个答案建议使用std容器std::vector,因为这些容器为你做了所有这些事情,具有最小的开销。
编辑:代码的其他问题如下所示:

row[i]+=a[i][j];
col[j]=col[j]+a[i][j];

你没有在你的代码中初始化这些数组,老实说,我不确定非VLA的默认定义行为是什么,但是当你在我的答案中提到的 heap 上分配一些东西时。你将(很可能)进入一个带有随机值的未定义行为的区域。所以一定要用默认值初始化row/col(因为你主要是做加法,你想用0s初始化)

相关问题