Reputation: 29
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
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
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