My program multiplies a matrix 1 by a matrix 2. The matrix 3 is the result. I can display matrix 1 and matrix 2 with the correct values but I am not able to display though the same function the expected values of matrix 3, although the calculated values are good.
here my code which can compile.
#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;
};
Here an output :
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]
Here is the wrong result. To your mind, what is the issue? Thanks a lot.
PS: if you have some ideas for improving my code, don't hesitate to tell me because I am a beginner.
PS2: as said below, I had forgotten * for int in multiply for the first malloc. But I still have the issue... after correcting.
There are multiple problems:
deleteMatrix
only frees the array of row pointers. You should pass the number of rows (dim1
) so it frees the individual rows that hold the matrix values.
displayMatrix
should be simplified: you should output the newline unconditionally at the end of the inner loop.
enterDimensions
and createMatrix
should detect and report input errors and allocation failures.
multiplyMatrix
does not allocate the result matrix properly: its rows are allocated multiple times for each resulting cell value. The net result is a massive memory leak and only the last value of each row appears correct in the final result matrix.
Here is a modified version:
#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;
}
Note that it seems safer to store the dimensions and data into a Matrix
structure. Here is a modified version using this approach:
#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;
}