【问题标题】:Define a matrix and pass it to a function in C定义一个矩阵并将其传递给 C 中的函数
【发布时间】:2009-08-14 07:33:30
【问题描述】:

我想创建一个程序,在其中我可以使用指针将矩阵传递给函数。 我初始化并扫描了void main() 中的2 个矩阵,然后我尝试将它们传递给void add 函数。我认为我在声明和调用函数的语法上出错了。我分配了一个指向矩阵基地址的指针。 (例如:int *x=a[0][0], *y=b[0][0])。什么是正确的声明?如何指定尺寸?

【问题讨论】:

  • @caf 你怎么知道它不是 C++,在这种情况下他的选择变得更多。让 OP 提供信息而不是假设它是个好主意。
  • @Yash,发布你到目前为止的代码。它使每个人的生活变得更加轻松。
  • 您使用的是固定大小的矩阵吗?或者你能传入任何大小的矩阵吗?
  • 好点。 (似乎也不是,因为他使用的是void main;)

标签: c matrix


【解决方案1】:

这样的事情应该可以解决问题。

#define COLS 3
#define ROWS 2

/* Store sum of matrix a and b in a */
void add(int a[][COLS], int b[][COLS])
{
    int i, j;

    for (i = 0; i < ROWS; i++)
        for (j = 0; j < COLS; j++)
            a[i][j] += b[i][j];
}

int main()
{
    int a[ROWS][COLS] = { { 5, 10, 5} , { 6, 4, 2 } };
    int b[ROWS][COLS] = { { 2, 3, 4} , { 10, 11, 12 } };

    add(a, b);

    return 0;
}

编辑:除非您想在运行时指定维度,否则您必须使用平面数组并自己进行二维数组运算:

/* Store sum of matrix a and b in a */
void add(int rows, int cols, int a[], int b[])
{
    int i, j;

    for (i = 0; i < rows; i++)
        for (j = 0; j < cols; j++)
            a[i * cols + j] += b[i * cols + j];
}

【讨论】:

  • 谢谢!!对此,我真的非常感激 !!!但据此我无法从用户那里得到矩阵的顺序??它必须被定义?
  • 您可以在运行时指定矩阵维度,但随后您将失去让编译器为您索引数组的能力。我已经用一个例子更新了我的答案。
【解决方案2】:

给定一个二维数组

T a[N][M];

指向该数组的指针看起来像

T (*ap)[M];

所以你的添加函数原型应该是这样的

void add(int (*a)[COLS], int (*b)[COLS]) {...}

被称为

int main(void)
{
  int a[ROWS][COLS];
  int b[ROWS][COLS];
  ...
  add(a, b);

然而,这段代码突出了几个问题。首先是您的 add 函数依赖的信息不是通过参数列表传递,而是通过全局变量或符号常量传递;即行数(列数在参数类型中明确提供)。这将 add 函数与这个特定的程序紧密耦合,并使其难以在其他地方重用。出于您的目的,这可能不是问题,但通常您只希望您的函数通过参数列表和返回值与其调用者进行通信。

第二个问题是,如所写,您的函数仅适用于 ROWS 行和 COLS 列的矩阵;如果你想在同一个程序中添加不同大小的矩阵,这种方法是行不通的。理想情况下,您需要一个可以处理不同大小矩阵的 add 函数,这意味着您需要将大小作为单独的参数传递。这也意味着我们必须改变我们传入的指针的类型。

一种可能的解决方案是将矩阵视为指向 int 的简单指针并手动计算偏移量而不是使用下标:

void add (int *a, int *b, size_t rows, size_t cols)
{
  size_t i;
  for (i = 0; i < rows; i++)
  {
    size_t j;
    for (j = 0; j < cols; j++)
    {
      *(a + cols * i + j) += *(b + cols * i + j);
    }
  }
}

然后这样称呼它:

int main(void)
{
  int a[ROWS][COLS] = {...};
  int b[ROWS][COLS] = {...};
  int c[ROWS2][COLS2] = {...};
  int d[ROWS2][COLS2] = {...};
  ...
  add(a[0], b[0], ROWS, COLS);
  add(c[0], d[0], ROWS2, COLS2);
  ...
}

a[0] 和 b[0] 的类型是“int 的 COLS 元素数组”;在这种情况下,它们都将被隐式转换为“指向 int 的指针”。类似地,c[0] 和 d[0] 也隐式转换为 int *。 add() 函数中的偏移量有效,因为二维数组是连续的。

编辑我刚刚意识到我是在响应 caf 的示例,而不是 OP,并且 caf 编辑了他的响应以显示与我的示例非常相似的内容。 C'est la guerre。我将保留我的示例,只是为了展示一种稍微不同的方法。我还认为关于在函数和调用者之间传递信息的措辞很有价值。

【讨论】:

    【解决方案3】:

    @caf 展示了一个很好的代码示例。

    我想指出:

    我分配了一个指向基址的指针 我的矩阵的地址。 (例如:int *x=a[0][0],*y=b[0][0])。

    您没有将指针指向矩阵的底部。它的作用是赋值给 x 和 y 所指向的值,分别是 a 和 b 中的基值。

    正确的方法是

    int  (*x)[] = a;
    int  (*y)[] = b;
    

    或者

    int *x = &a[0][0];
    int *y = &b[0][0];
    

    【讨论】:

    • @ neil butterworth - 我正在使用 C 语言,但我不了解 C++ @其他人 - 我是编程新手。我被分配了一个任务,其中我必须接受 2 个矩阵并对它们执行加法、转置、乘法并找到鞍点(如果有)。我试图使用指针将这些矩阵传递给它们各自的函数。这是我这样做的尝试-
    • #include #include void add();无效转置(int *,int,int);无效乘法();无效鞍(); void main() { int a[10],b[10],i,j,r,c,p,q,n,*x=&a[0][0],*y=&b[0][0 ]; clrscr(); printf("输入矩阵a的顺序"); scanf("%d%d",&r,&c); printf("逐行输入矩阵的元素"); for(i=0;i
    • printf("输入您的选择:\n1:add\n2:transpose\n3:multiply\n4:saddle point\n5:exit"); scanf("%d",&n); switch(n) { case 1: add(a[10][10],b[10][10],c[10][10]);休息;案例2:转置(x,r,c);转置(y,p,q);休息;案例3:乘法(a[10][10],b[10][10],c[10][10]);休息;案例4:鞍(a[10][10]);鞍(b[10][10]);休息;案例5:中断; } getch(); }
    • void transpose(int *k,int l,int m) { if(l==m) { for(i=0,j=0;i
    • Tom:这不正确 - &a[0][0] 的类型是 int *,而不是 int **
    猜你喜欢
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 2013-07-27
    相关资源
    最近更新 更多