Let’s see...
I will list the observed errors one by one, separated by each function. Try to check if you can perceive them so that you learn for your future, OK?
cria_matriz(...)
1 - There’s no reason you should use the type Matriz *
for the function cria_matriz(...)
. Why? Simply because you passed the address of m
as argument the function. Every modification will be made on itself m
passed as argument. Thus, its function is defined thus:
void cria_matriz( Matriz *m, int mat[5][5] ){ ... }
2 - It’s always good practice to make a type casting type of pointer receiving memory allocation. Your allocations would be:
m->elementos = (int **) malloc( m->n_elementos * sizeof(int *) )
...
m->elementos[i] = (int *) calloc( m->n_elementos, sizeof(int) );
3 - m->n_elementos
was not defined when created. That’s why m
is a pointer. Therefore, we can assume that its size is 0
. This will make you create no memory for m->elementos
or m->elementos[n]
. So, before allocating memory with malloc(...)
or calloc(...)
, you need to set the size of m->n_elementos
:
m->n_elementos = 5 * 5; /* 5 linhas * 5 colunas */
4 - In fact, you don’t want to define the space of each row and column of the matrix m
with m->n_elementos
since this is the total of elements. Your matriz[5][5]
has a total of 25
elements but divided into 5 rows and 5 columns.
With that in mind, in malloc(...)
you should replace by 5 lines and in calloc(...)
should replace it with 5 columns. Effectively, you create space for 5 rows with malloc(...)
and each line receives 5 elements of calloc(...)
. Therefore:
m->elementos = (int **) malloc( 5 * sizeof(int *) ); /* 5 linhas */
...
m->elementos[i] = (int *) calloc( 5, sizeof(int) ); /* 5 colunas */
Each of the ties for
used also need to be changed:
for (int i = 0; i < 5; i++) {...} /* 5 linhas */
...
for (int j = 0; j < 5; j++) {...} /* 5 colunas */
5 - So much LINHAS
as COLUNAS
were created with the directive preprocessing #define
. They were used to make the code more readable. They are placed right after the #include
:
#include ...
#define LINHAS 5
#define COLUNAS 5
Were substitutes for m->n_elementos em
in malloc(...)
, calloc(...)
and ties for
, mentioned in the item 4, as follows:
m->elementos = (int **) malloc( LINHAS * sizeof(int *) );
...
for (int i = 0; i < LINHAS; i++) {...}
...
m->elementos[i] = (int *) calloc( COLUNAS, sizeof(int) );
...
for (int j = 0; j < COLUNAS; j++) {...}
The same was done for m->n_elementos
mentioned in item 3:
m->n_elementos = LINHAS * COLUNAS;
In the following cases, I will be more economical with examples of code. There is no reason to rain in the wet because the examples are the same. At the end will also be shown the complete and functional code.
imprimir_matriz(...);
1 - Here the recommendation is to change the print_array(...) parameter to pointer, avoiding creating extra memory. If you consider that the whole theme is dynamic allocation, even more correct. See:
void imprimir_matriz(Matriz *m){...}
2 - As now m
internally to imprimir_matriz(...)
is pointer, must be changed .
for ->
.
3 - Following the same logic pointed out in item 4 and improved in item 5 of cria_matriz(...)
, we would have changes in ties for
as pointed out.
main()
1 - I recommend changing the definition of matriz[5][5]
for matriz[LINHAS][COLUNAS]
.
2 - I recommend assigning the matrix values separated by each row and column. This is because -Wall
is widely used when compiling a C code as it provides warnings of structures not widely accepted by certain developers. We have:
int mat[LINHAS][COLUNAS] = {
{ 0, 185, 119, 152, 133 },
{ 185, 0, 121, 150, 200 },
{ 199, 121, 0, 174, 120 },
{ 152, 150, 174, 0, 199 },
{ 133, 200, 120, 199, 0 }
};
3 - You need to change the call from imprimir_matriz(...)
to provide the address of m
:
imprimir_matriz( &m );
4 - One of the first things we should create is the function that will release the memories of what was allocated because we have already planned the data structure to be created. I assume you’re on the to-do list.
Functional code
It follows its code in a functional way, with the problems fixed. It was a chain of errors that could be corrected by you but other factors may have hindered the perception of the present errors. Without further ado:
Pre-processing directives:
#include <stdio.h>
#include <stdlib.h>
#define LINHAS 5
#define COLUNAS 5
Data structure:
typedef struct matriz
{
int n_elementos;
int **elementos;
} Matriz;
Function cria_matriz(...)
:
void cria_matriz( Matriz *m, int mat[5][5] ){
int i, j;
m->n_elementos = LINHAS * COLUNAS;
m->elementos = (int **) malloc( LINHAS * sizeof(int *) );
for ( i = 0; i < LINHAS; i++ ){
m->elementos[i] = (int *) calloc( COLUNAS , sizeof(int) );
for ( j = 0; j < COLUNAS; j++ ) m->elementos[i][j] = mat[i][j];
}
}
Function imprimir_matriz(...)
:
void imprimir_matriz( Matriz *m ){
int i, j;
printf("\nMatriz\n\n");
for( i = 0; i < LINHAS; i++ ){
for( j = 0; j < COLUNAS; j++ ) printf("%d ", m->elementos[i][j]);
printf("\n");
}
printf("\n");
}
Function main()
:
int main(){
Matriz m;
int mat[LINHAS][COLUNAS] = {
{ 0, 185, 119, 152, 133 },
{ 185, 0, 121, 150, 200 },
{ 199, 121, 0, 174, 120 },
{ 152, 150, 174, 0, 199 },
{ 133, 200, 120, 199, 0 }
};
cria_matriz( &m, mat );
imprimir_matriz( &m );
/* Crie uma função limpar_matriz( &m ) */
return 0;
}
Exit:
Matriz
0 185 119 152 133
185 0 121 150 200
199 121 0 174 120
152 150 174 0 199
133 200 120 199 0
This code can be found in a version one little bit best and compilable with -pedantic -ansi -Wall -Wextra -Werror
here. I recommend looking only after doing your own memory cleaning function. I also recommend looking over the Valgrind (tutorial here) to assist in memory leak.
Thank you so much for your help, my friend.
– Gustavo RS
No problem. And if the answer solved your problem, mark the answer as correct so you can help more people with similar problems. Otherwise no further action will be required. Happy coding!
– José