Problem with adjacency matrix

Asked

Viewed 68 times

1

I’m having a hard time printing the data from an array, I believe I’m saving the data the wrong way, so you notice the data was not saved because when I go to print no data comes back that I added, i tried to avoid adding data by reading files.

#include <stdio.h>
#include <stdlib.h>

typedef struct matriz
{
    int n_elementos;
    int **elementos;
} Matriz;

Matriz * cria_matriz(Matriz *m, int mat[5][5])
{
    m->elementos = malloc(m->n_elementos * sizeof(int *));

    for (int i = 0; i < m->n_elementos; i++)
    {
        m->elementos[i] = calloc(m->n_elementos , sizeof(int));
        for (int j = 0; j < m->n_elementos; j++)
        {
            m->elementos[i][j] = mat[i][j];
        }
    }
    return m;
}

void imprimir_matriz(Matriz m)
{
   printf("Matriz\n\n");

    for (int i = 0; i < m.n_elementos; i++)
    {
        for (int j = 0; j < m.n_elementos; j++)
        {
            printf("%d ", m.elementos[i][j]);
        }

        printf("\n");
    }
}

int main()
{
    Matriz m;
    int mat[5][5] = {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);
    return 0;
}

1 answer

1


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.

  • 1

    Thank you so much for your help, my friend.

  • 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!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.