为什么在C中矩阵加法的有效结果之间添加零?

u7up0aaq  于 2023-02-18  发布在  其他
关注(0)|答案(2)|浏览(139)

我目前正在构建一个矩阵计算器来添加矩阵,由于某种原因,当我将两个矩阵加在一起时,矩阵加法中每个点的正确答案都会变得间隔开,它们之间是零。
例如,
导致

2 0 2
0 2 0
2 0 2

而不是全是二的矩阵。
这是打印和添加矩阵函数的代码

void printMatrix(int matriks,int matrix[3][3]) {

    int row;
    int column;

    printf("matriks %d:\n",matriks);
    for (row = 0; row < 3; row++) {
        for (column = 0; column < 3; column++) {
            printf(" %d", matrix[row][column]);
        }

        printf("\n");
    }

}

void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3])  {

   int row;
   int col;
    for (row=0; row < 3; row++) {
        for (col=0; col<3;col++) {
            result[row][col] = m1[row][col] + m2[row][col];
        }
    }

}

这就是在main()中调用它们的方式

int result[3][3];
 int sampleM1[3][3] = {{1,1,1}, {1,1,1}, {1,1,1}};
 int sampleM2[3][3] = {{1,1,1}, {1,1,1}, {1,1,1}};
 addMatrices(sampleM1,sampleM2,&result);
 printMatrix(0,result);

任何帮助都将不胜感激。谢谢!

1qczuiv0

1qczuiv01#

不要把result当作一个指向二维数组的指针,数组在传递给函数时,会隐式地转换成指向数组第一个元素的指针,所以你在做一个额外的间接层。
换句话说,函数声明应该是:

void addMatrices(int m1[3][3], int m2[3][3], int result[3][3]) {

呼叫应该是:

addMatrices(sampleM1,sampleM2,result);

一个好的编译器应该警告你这一点:

prog.c: In function ‘addMatrices’:
prog.c:21:30: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   26 |             result[row][col] = m1[row][col] + m2[row][col];
      |                              ^
prog.c: In function ‘main’:
prog.c:30:32: error: passing argument 3 of ‘addMatrices’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   37 |  addMatrices(sampleM1,sampleM2,&result);
      |                                ^~~~~~~
      |                                |
      |                                int (*)[3][3]
prog.c:16:51: note: expected ‘int * (*)[3]’ but argument is of type ‘int (*)[3][3]’
   20 | void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3])  {
      |                                              ~~~~~^~~~~~~~~~~~

还有一点建议:一旦你开始创建更高层次的数据结构,最好让它们像C++类一样工作。2换句话说,把它们作为特定的类型放在它们自己的头文件和源文件中,而不是处理C提供的一般类型(如数组)。
例如,具有如下结构:

// Everything you need to know about a matrix (of integers).

typedef struct {
    size_t rows, cols;
    int *data;
} tIntMatrix; // Poor man's template :-)

并提供直接操作专用类型的函数:

// Allocate and de-allocate functions.
tIntMatrix *IntMatrixCreate(size_t rows, size_t cols);
tIntMatrix *IntMatrixCreateAndInit(size_t rows, size_t cols, int *values);
void IntMatrixDestroy(tMatrix *matrix);

// Get and set functions.
int IntMatrixGet(size_t row, size_t col);
void IntMatrixSet(size_t row, size_t col, int value);
void IntMatrixSetRow(size_t row, int *values);
void IntMatrixSetCol(size_t col, int *values);
void IntMatrixSetAll(int *values);

// Matrix manipulation functions, whatever is needed.
void IntMatrixAdd(tMatrix *m1, tMatrix *m2, tMatrix *sum);
void IntMatrixMult(tMatrix *m1, tMatrix *m2, tMatrix *product);
void IntMatrixInvert(tMatrix *m1, tMatrix *inversion);

// Traverse cells with a callback function.
// Function receives, for each cell: rows, cells, row, cell, value.
typedef void (*)(size_t, size_t, size_t, size_t, int) IntMatrixCb;
void  IntMatrixProcess(tIntMatrix *matrix, IntMatrixCb callback);

C * 可以(至少部分地)是面向对象的,它只需要多做一点工作,但这样做提供了与那些固有地面向对象的语言相同的安全性,比如这种情况下的封装。
我的意思是,内部数据结构对你是隐藏的〈sup(a),为了能够使用矩阵,你所需要知道的就是API。
然后,使用回调函数:

void cbPrint(int size_t rows, size_t cols, size_t row, size_t col, int value) {
    printf("%d", value);
    putchar(col == cols - 1 ? '\n' : ' ');
}

主代码将变为如下形式:

tIntMatrix *sampleM1 = IntMatrixCreateAndInit(3, 3, {
    1, 1, 1,
    1, 1, 1,
    1, 1, 1
});
tIntMatrix *sampleM2 = IntMatrixCreateAndInit(3, 3, {
    1, 1, 1,
    1, 1, 1,
    1, 1, 1
});
tIntMatrix *result = IntMatrixCreate(3, 3);

IntMatrixAdd(sampleM1, sampleM2, result);

puts("Matriks 0:"); IntMatrixProcess(result, cbPrint);

〈sup(a)是的,我知道你可以 * 看到 * rows/cols/data结构,但是如果API很好的话,你不需要 * 使用 * 它。而且,如果你 * 真的 * 想隐藏它,你可以把它隐藏在一个不透明的指针后面。

s5a0g9ez

s5a0g9ez2#

当你编译的时候,打开警告,例如通过-Wall打开gcc。
如果您这样做了,您会看到一堆警告,如下所示:https://godbolt.org/z/79a7drWar
你应该知道,数组将衰减为指针,如果作为参数传递给一个函数(见:https://en.cppreference.com/w/c/language/array#Array_to_pointer_conversion).
变更

void addMatrices(int m1[3][3], int m2[3][3], int *result[3][3]);

void addMatrices(int m1[3][3], int m2[3][3], int result[3][3]);

并在没有接线员地址的情况下呼叫它

addMatrices(sampleM1,sampleM2,result);

相关问题