Сохранить указатель на структуру в массив указателей - PullRequest
0 голосов
/ 12 мая 2019

Мне трудно получить массив указателей на структуры для сохранения и извлечения данных, которые я заполнил, фрагмент кода является ядром моей программы.

Мне удалось заставить саму программу работать с использованием массива struct, но я полагаю, что она требует больше памяти и пытаюсь перераспределить массив указателей на структуры вместо всех структур в каждом цикле.

#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);
    }
}

Я ожидаю динамическое выделение структуры "dados_alunos", а также динамическое выделение массива указателей на указанные структуры, вставку пользовательского ввода "nome" и "matricula_atual" в поля структуры "dados_alunos" и возможность их читать после выхода из цикла while. При попытке сохранить адрес в текущей структуре в массив, используя

alunos_da_turma[n_alunos - 1] = &novo_aluno;

выдает предупреждение «присваивание из несовместимого типа указателя [-Wincompatible-pointer-types]» и, похоже, сохраняет во всех позициях массива первый указатель / мусор, записанный в него, независимо от того, сколько взаимодействий. Используя memcpy, вместо этого сохраните мусор в первом поле, если я попробую только одно взаимодействие и произойдет сбой в течение двух или более взаимодействий в цикле while.

Ответы [ 2 ]

2 голосов
/ 12 мая 2019
alunos_da_turma[n_alunos - 1] = &novo_aluno;

отказано, потому что alunos_da_turma - это dados_aluno **, поэтому alunos_da_turma[n_alunos - 1] - это dados_aluno *, но novo_aluno - это dados_aluno *, поэтому &novo_aluno - это dados_aluno **

Вы хотели

alunos_da_turma[n_alunos - 1] = novo_aluno;

Внимание

gets(novo_aluno->nome);

опасно (и устарело с годами), потому что если длина входной строки превышает 59 символов, которые вы выводите из поля с неожиданным поведением, выполните

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

Однако, кроме того, что если вы введете имя в той же строке, в которую введете матрикулу, вы получите пустую строку, потому что остальная часть строки / новой строки не сброшена на fflush(stdin);, fflush не работает вне файла

Если имя не может содержать разделитель, используйте scanf("%59s", novo_aluno->nome); вместо fgets , иначе символы обхода до новой строки явно

Примечание также в

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

вы перераспределяете с одним дополнительным элементом, вы уже увеличились n_alunos

Ведение

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

довольно сложно, и его можно заменить на

for (;;) {
  ...
  if (matricula_atual == -1)
    break;
  ...
}
1 голос
/ 12 мая 2019

alunos_da_turma[X] - это указатель на структуру dados_aluno, а не указатель на указатель на структуру dados_aluno.Что бы быть действительным, это alunos_da_turma[n_alunos-1] = novo_aluno

Итак, какое-то решение для общей проблемы:

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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...