Моя программа умножает матрицу 1 на матрицу 2. Результатом является матрица 3. Я могу отобразить матрицу 1 и матрицу 2 с правильными значениями, но я не могу отобразить с помощью той же функции ожидаемые значения матрицы 3, хотя рассчитанные значения хорошие.
вот мой код, который можно скомпилировать.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Dimensions {
int dim1, dim2;
};
struct Dimensions enterDimensions(void);
int **createMatrix(int, int);
void deleteMatrix(int **);
void displayMatrix(int **, int, int);
int **multiply(int **, int **, int, int, int);
int main(void) {
struct Dimensions dimensions1 = enterDimensions();
int **matrix1 = createMatrix(dimensions1.dim1, dimensions1.dim2);
displayMatrix(matrix1, dimensions1.dim1, dimensions1.dim2);
struct Dimensions dimensions2 = enterDimensions();
int **matrix2 = createMatrix(dimensions2.dim1, dimensions2.dim2);;
displayMatrix(matrix2, dimensions2.dim1, dimensions2.dim2);
if (dimensions1.dim2 != dimensions2.dim1) {
printf("the product of these matrixes does not exist");
} else {
int **matrix3 = multiply(matrix1, matrix2, dimensions1.dim1, dimensions1.dim2, dimensions2.dim2);
displayMatrix(matrix3, dimensions1.dim1, dimensions2.dim2);
deleteMatrix(matrix3);
}
deleteMatrix(matrix1);
deleteMatrix(matrix2);
return 0;
}
struct Dimensions enterDimensions(void) {
int dim1;
int dim2;
struct Dimensions dimensions;
printf("dim 1 : \n");
scanf("%d", &dim1);
printf("dim 2 : \n");
scanf("%d", &dim2);
dimensions.dim1 = dim1;
dimensions.dim2 = dim2;
return dimensions;
}
int **createMatrix(int dim1, int dim2) {
printf("%s", "\ncreate matrix\n");
int **matrix = malloc(dim1 * sizeof(int *));
for (int i = 0; i < dim1; i++) {
matrix[i] = malloc(dim2 * sizeof(int));
}
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
printf("enter (%d,%d)\n", i, j);
scanf("%d", &matrix[i][j]);
printf("%d\n", matrix[i][j]);
}
}
return matrix;
}
void deleteMatrix(int **matrix) {
printf("%s", "\ndelete matrix\n");
free(matrix); // /!\ Warning : Parameter 'matrix' may point to deallocated memory when called from function 'main'
}
void displayMatrix(int **matrix, int dim1, int dim2) {
if (matrix == NULL) {
exit(1);
}
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
if (j == dim2 - 1) {
printf("[%d]\n", matrix[i][j]);
} else {
printf("[%d]", matrix[i][j]);
}
}
}
}
int **multiply(int **matrix1, int **matrix2, int dim11, int dim12, int dim22) {
int **matrix3 = malloc(dim11 * sizeof(int));
for (int i = 0; i < dim11; i++) {
for (int j = 0; j < dim22; j++) {
int cij = 0;
for (int k = 0; k < dim12; k++) {
if (matrix1 == NULL || matrix2 == NULL) {
exit(3);
}
cij += matrix1[i][k] * matrix2[k][j];
}
for (int l = 0; l < dim11; l++) {
matrix3[l] = malloc(dim22 * sizeof(int));
}
matrix3[i][j] = cij;
printf("cij : %d\n", matrix3[i][j]);
}
}
return matrix3;
};
Вот вывод:
dim 1 :
2
dim 2 :
2
create matrix
enter (0,0)
1
1
enter (0,1)
0
0
enter (1,0)
0
0
enter (1,1)
1
1
[1][0]
[0][1]
dim 1 :
2
dim 2 :
2
create matrix
enter (0,0)
3
3
enter (0,1)
3
3
enter (1,0)
3
3
enter (1,1)
3
3
[3][3]
[3][3]
cij : 3
cij : 3
cij : 3
cij : 3
[-253143104][428]
[-253143104][3]
delete matrix
delete matrix
delete matrix
Process finished with exit code 0
[-253143104][428]
[-253143104][3]
Вот неправильный результат. На ваш взгляд, в чем проблема? Большое спасибо.
PS: если у вас есть идеи по улучшению моего кода, не стесняйтесь сообщать мне, потому что я новичок.
PS2: как сказано ниже, я забыл * для int в умножении для первого malloc. Но у меня все еще есть проблема... после исправления.
Большое спасибо. Действительно, я забыл * вместо int...
но на самом деле у меня всегда одна и та же проблема.. :/
Почему внутри циклов 3
выделяются i
, j
и l
? Выделяйте только внутренний цикл i
.
Есть несколько проблем:
deleteMatrix
освобождает только массив указателей строк. Вам следует передать количество строк (dim1
), чтобы освободить отдельные строки, содержащие значения матрицы.
displayMatrix
следует упростить: вы должны безоговорочно выводить новую строку в конце внутреннего цикла.
enterDimensions
и createMatrix
должны обнаруживать и сообщать об ошибках ввода и сбоях распределения.
multiplyMatrix
неправильно распределяет результирующую матрицу: ее строки распределяются несколько раз для каждого результирующего значения ячейки. Конечным результатом является огромная утечка памяти, и только последнее значение каждой строки выглядит правильным в окончательной матрице результатов.
Вот модифицированная версия:
#include <stdio.h>
#include <stdlib.h>
struct Dimensions {
int dim1, dim2;
};
struct Dimensions enterDimensions(void);
int **allocateMatrix(int rows, int cols);
int **createMatrix(int rows, int cols);
void deleteMatrix(int **mat, int rows);
void displayMatrix(int **mat, int rows, int cols);
int **multiply(int **mat1, int **mat2, int dim11, int dim12, int dim22);
int main(void) {
struct Dimensions dimensions1 = enterDimensions();
int **matrix1 = createMatrix(dimensions1.dim1, dimensions1.dim2);
printf("matrix1:\n");
displayMatrix(matrix1, dimensions1.dim1, dimensions1.dim2);
struct Dimensions dimensions2 = enterDimensions();
int **matrix2 = createMatrix(dimensions2.dim1, dimensions2.dim2);;
printf("matrix2:\n");
displayMatrix(matrix2, dimensions2.dim1, dimensions2.dim2);
if (dimensions1.dim2 != dimensions2.dim1) {
printf("cannot compute the product of these matrices: dimensions do not match\n");
deleteMatrix(matrix1, dimensions1.dim1);
deleteMatrix(matrix2, dimensions2.dim1);
return 1;
} else {
int **matrix3 = multiply(matrix1, matrix2, dimensions1.dim1, dimensions1.dim2, dimensions2.dim2);
printf("matrix3:\n");
displayMatrix(matrix3, dimensions1.dim1, dimensions2.dim2);
deleteMatrix(matrix3, dimensions2.dim2);
deleteMatrix(matrix1, dimensions1.dim1);
deleteMatrix(matrix2, dimensions2.dim1);
return 0;
}
}
struct Dimensions enterDimensions(void) {
struct Dimensions dimensions;
printf("enter dim 1: ");
if (scanf("%d", &dimensions.dim1) != 1) {
printf("invalid input\n");
exit(1);
}
printf("enter dim 2: ");
if (scanf("%d", &dimensions.dim2) != 1) {
printf("invalid input\n");
exit(1);
}
return dimensions;
}
int **allocateMatrix(int dim1, int dim2) {
if (dim1 <= 0 || dim2 <= 0) {
printf("invalid dimensions: %d,%d\n", dim1, dim2);
exit(1);
}
int **matrix = calloc(dim1, sizeof(int *));
if (!matrix) {
printf("allocation failed\n");
exit(1);
}
for (int i = 0; i < dim1; i++) {
matrix[i] = calloc(dim2, sizeof(int));
if (!matrix[i]) {
printf("allocation failed\n");
exit(1);
}
}
return matrix;
}
int **createMatrix(int dim1, int dim2) {
int **matrix = allocateMatrix(dim1, dim2);
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
printf("enter (%d,%d): ", i, j);
if (scanf("%d", &matrix[i][j]) != 1) {
printf("invalid input\n");
exit(1);
}
//printf("%d\n", matrix[i][j]);
}
}
return matrix;
}
void deleteMatrix(int **matrix, int dim1) {
if (matrix == NULL)
return;
for (int i = 0; i < dim1; i++) {
free(matrix[i]);
}
free(matrix);
}
void displayMatrix(int **matrix, int dim1, int dim2) {
if (matrix == NULL)
return;
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
printf("[%d]", matrix[i][j]);
}
printf("\n");
}
}
int **multiply(int **matrix1, int **matrix2, int dim11, int dim12, int dim22) {
if (matrix1 == NULL || matrix2 == NULL)
return NULL;
int **matrix3 = allocateMatrix(dim11, dim22);
for (int i = 0; i < dim11; i++) {
for (int j = 0; j < dim22; j++) {
int cij = 0;
for (int k = 0; k < dim12; k++) {
cij += matrix1[i][k] * matrix2[k][j];
}
matrix3[i][j] = cij;
}
}
return matrix3;
}
Обратите внимание: кажется безопаснее хранить измерения и данные в структуре Matrix
. Вот модифицированная версия, использующая этот подход:
#include <stdio.h>
#include <stdlib.h>
typedef struct Matrix {
int dim1, dim2;
int **data;
} Matrix;
Matrix *matrix_allocate(int rows, int cols);
Matrix *matrix_input(void);
void matrix_delete(Matrix *matrix);
void matrix_display(Matrix *matrix);
Matrix *matrix_multiply(Matrix *mat1, Matrix *mat2);
int main(void) {
Matrix *matrix1 = matrix_input();
if (!matrix1)
return 1;
printf("matrix1:\n");
matrix_display(matrix1);
Matrix *matrix2 = matrix_input();
if (!matrix2)
return 1;
printf("matrix2:\n");
matrix_display(matrix2);
if (matrix1->dim2 != matrix2->dim1) {
printf("cannot compute the product of these matrices: dimensions do not match\n");
matrix_delete(matrix1);
matrix_delete(matrix2);
return 1;
} else {
Matrix *matrix3 = matrix_multiply(matrix1, matrix2);
if (!matrix3)
return 1;
printf("matrix3:\n");
matrix_display(matrix3);
matrix_delete(matrix3);
matrix_delete(matrix1);
matrix_delete(matrix2);
return 0;
}
}
Matrix *matrix_allocate(int dim1, int dim2) {
if (dim1 <= 0 || dim2 <= 0) {
printf("invalid dimensions: %d,%d\n", dim1, dim2);
return NULL;
}
Matrix *matrix = calloc(1, sizeof(Matrix));
if (!matrix)
return NULL;
matrix->dim1 = dim1;
matrix->dim2 = dim2;
matrix->data = calloc(dim1, sizeof(int *));
if (!matrix->data) {
printf("allocation failed\n");
free(matrix);
return NULL;
}
for (int i = 0; i < dim1; i++) {
matrix->data[i] = calloc(dim2, sizeof(int));
if (!matrix->data[i]) {
printf("allocation failed\n");
while (i-- > 0) {
free(matrix->data[i]);
}
free(matrix->data);
free(matrix);
return NULL;
}
}
return matrix;
}
void matrix_delete(Matrix *matrix) {
if (matrix != NULL) {
for (int i = 0; i < matrix->dim1; i++) {
free(matrix->data[i]);
}
free(matrix->data);
free(matrix);
}
}
Matrix *matrix_input(void) {
int dim1, dim2;
printf("enter dim 1: ");
if (scanf("%d", &dim1) != 1) {
printf("invalid input\n");
return NULL;
}
printf("enter dim 2: ");
if (scanf("%d", &dim2) != 1) {
printf("invalid input\n");
return NULL;
}
Matrix *matrix = matrix_allocate(dim1, dim2);
if (!matrix)
return NULL;
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
printf("enter (%d,%d): ", i, j);
if (scanf("%d", &matrix->data[i][j]) != 1) {
printf("invalid input\n");
matrix_delete(matrix);
return NULL;
}
}
}
return matrix;
}
void matrix_display(Matrix *matrix) {
if (matrix == NULL)
return;
for (int i = 0; i < matrix->dim1; i++) {
for (int j = 0; j < matrix->dim2; j++) {
printf("[%d]", matrix->data[i][j]);
}
printf("\n");
}
}
Matrix *matrix_multiply(Matrix *matrix1, Matrix *matrix2) {
if (matrix1 == NULL || matrix2 == NULL || matrix1->dim2 != matrix2->dim1)
return NULL;
Matrix *matrix3 = matrix_allocate(matrix1->dim1, matrix2->dim2);
if (!matrix3)
return NULL;
for (int i = 0; i < matrix1->dim1; i++) {
for (int j = 0; j < matrix2->dim2; j++) {
int cij = 0;
for (int k = 0; k < matrix1->dim2; k++) {
cij += matrix1->data[i][k] * matrix2->data[k][j];
}
matrix3->data[i][j] = cij;
}
}
return matrix3;
}
Большое спасибо ! Очень полезный ответ :) Я посмотрю, чтобы повысить свой уровень. Спасибо !
Спасибо за вашу реализацию с матричной структурой!
У вас неправильное распределение
matrinx3
. ВcreateMatrix
вы выделяете указательint **
, затем в цикле выделяете группу указателейint *
. Это работает. Но вmultiply
вы делаетеint **matrix3=malloc(dim11*sizeof(int));
Даже само по себе это противоречиво: вы выделяете массивint
, а неint *
, но затем пытаетесь обработать результат какint **
, а неint *
. Вы должны делать то же самое, что и вcreateMatrix
, чтобы выделить матрицу.