Matg0d
Matg0d

Reputation: 29

Save pointer to structure into an array of pointers

I am having a hard time getting an array of pointer to structures to save and retrieve the data I filled, the code snippet has the core of my program.

I was able to make the program itself work using an array of struct, but I figure that is more memory intensive and I am trying to only realloc the array of pointers to the structures instead of all the structs at each loop.

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

typedef struct dados_aluno {
    int matricula;
    char nome[60];
    int situacao;
    float nota1, nota2, nota3, media;
}dados_aluno;

int main(void){
    int done = 0;
    int i;
    int n_alunos = 0;
    int matricula_atual;

    dados_aluno *novo_aluno;
    dados_aluno **alunos_da_turma;
    alunos_da_turma = malloc(sizeof(dados_aluno*));
    while (done == 0){
        printf("Matricula: ");
        scanf("%d", &matricula_atual);
        fflush(stdin);//scanf followed by gets = bad time!
        if (matricula_atual == -1){
            done = 1;
            continue;
        }
        n_alunos++;
        novo_aluno = calloc(1, sizeof(dados_aluno));
        novo_aluno->matricula = matricula_atual;

        printf("\nNome: ");
        gets(novo_aluno->nome);

        //the code below rises warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
        //and returns garbage on the for loop at the end of the program
        alunos_da_turma[n_alunos - 1] = &novo_aluno;
        //using memcpy instead doesnt rise an error, but the first field is garbage and the 3º interation of the loop crashes
        //memcpy(alunos_da_turma[n_alunos -1],&novo_aluno,sizeof(dados_aluno *));
        alunos_da_turma = realloc(alunos_da_turma, (sizeof(dados_aluno *) * (n_alunos + 1)));
    }
    for (i=0;i<(n_alunos);i++){
            printf("%d  %s\n",alunos_da_turma[i]->matricula,alunos_da_turma[i]->nome);
    }
}

I expect to dynamic allocate a struct "dados_alunos" and also dynamic allocate an array of pointers to said structs, insert user input "nome" and "matricula_atual" to the fields of the struct "dados_alunos" and be able to read them after exiting the while loop. On trying to save the address to the current struct to the array using

alunos_da_turma[n_alunos - 1] = &novo_aluno;

gives the warning "assignment from incompatible pointer type [-Wincompatible-pointer-types]" and seems to save to all the positions of the array the first pointer/garbage written to it no matter how many interactions. Using memcpy instead store garbage on the first field if I only try one interaction and crashes within 2 interactions or more on the while loop.

Upvotes: 0

Views: 201

Answers (2)

bruno
bruno

Reputation: 32596

alunos_da_turma[n_alunos - 1] = &novo_aluno;

is refused because alunos_da_turma is a dados_aluno ** so alunos_da_turma[n_alunos - 1] is a dados_aluno *, but novo_aluno is a dados_aluno * so &novo_aluno is a dados_aluno **

you wanted

alunos_da_turma[n_alunos - 1] = novo_aluno;

Warning

gets(novo_aluno->nome);

is dangerous (and deprecated since years) because if the input string is greater than 59 characters you write out of the field with an unexpected behavior, do

fgets(novo_aluno->nome, sizeof(novo_aluno->nome), stdin);

However except if you enter the name on the same line you enter the matricula you will get an empty line because the rest of the line/newline is not flush by fflush(stdin);, fflush does not work out of a file

If the name cannot contain separator use scanf("%59s", novo_aluno->nome); rather than fgets, else bypass characters up to the newline explicitely

Note also in

alunos_da_turma = realloc(alunos_da_turma, (sizeof(dados_aluno *) * (n_alunos + 1)));

you reallocate with one extra element, you already increased n_alunos

Doing

int done = 0;
...
while (done == 0){
    ...
    if (matricula_atual == -1){
        done = 1;
        continue;
    }
    ...
}

is quite complicated for nothing and can be replaced by

for (;;) {
  ...
  if (matricula_atual == -1)
    break;
  ...
}

Upvotes: 2

user10937260
user10937260

Reputation:

alunos_da_turma[X] is a pointer to struct dados_aluno, not a pointer to a pointer to a struct dados_aluno. What would be valid is alunos_da_turma[n_alunos-1] = novo_aluno

So, some solution for general problem:

dados_alunos** alunos_da_turma = malloc (10 * sizeof(dados_aluno*)); //array for 10 pointers
int length = 0;  //number of inserted alunos_dados elements
int size = 10;  //number of allocated pointers spaces
while(done == 0){
//ask for input
    dados_aluno* novo_aluno = malloc (sizeof(dados_aluno));
    novo_aluno->matricula = //input
    //etc
    dados_alunos[length] = novo_aluno;
    length++;
    if (length == size){
         dados_alunos = realloc(dados_alunos, 2 * size * sizeof(dados_aluno*));
         size += size; //doubles size
    }
}

Upvotes: 1

Related Questions