Allocate Attribute Memory in Structure

Asked

Viewed 34 times

0

I need to allocate more memory of the note attribute of the Student structure:

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

struct Aluno
{
    int matricula;
    int nota;
};

void cadastraNotas(struct Aluno* cadastro, int aluno, int *qtdNotas)
{
        printf("\nInforme a quantidade de notas do aluno %d: ", cadastro[aluno].matricula);
        scanf("%d", &qtdNotas[aluno]);

        if(qtdNotas[aluno] > 1) {
          
          //Aqui estou em dúvida como escrever
          cadastro[aluno].nota = realloc(cadastro[aluno].nota, qtdNotas[aluno] * sizeof(struct Aluno)); 
        }
        for(int i = 0; i < qtdNotas[aluno]; i++)
        {
            printf("Informe a nota %d: ", i + 1);
            scanf("%d", &cadastro[aluno].nota[i]);
        }
}
  • Note that you have declared note as int and not as a pointer to int.

  • It worked, I changed the note variable to pointer (int *note). Thanks!

  • 1

    There is a lot of code missing from the post, but it seems strange to me that your note pointer relocation, in particular this sizeof(struct Aluno).

1 answer

0

Post a whole program so that someone can easily test it if they think it can help you.

    struct Aluno
    {
        int matricula;
        int nota;
    };
    
    void cadastraNotas(struct Aluno* cadastro, int aluno, int *qtdNotas)
    
    ...

I think you should think more about the data and how you want to use it. In general Student can have some grades and a register can have some students. There are 3 common ways to treat this:

  • [a] set a maximum of grades for a Student and Students for a Class
  • [b] use a data structure, such as a linked list for example, and allocate grades and students as they run
  • [c] use dynamic allocation and allocate as needed notes and students, as the system does when setting up the list of parameters for main() which is declared
    int main( int argc, char** argv);

Simple example using fixed values

typedef struct 
{
    int matricula;
    int N; // quantas notas
    int nota[10];

}   Aluno;

typedef struct
{
    const char* codigo;
    int     N;
    Aluno   aluno[10];

}   Turma;

In this case you can have up to 10 grades per student and up to 10 students per class, but it’s all fixed, static. It’s easy to write but nothing flexible...

See an example of the case [a]:

#include <stdio.h>

typedef struct 
{
    int matricula;
    int N; // quantas notas
    int nota[10];

}   Aluno;

typedef struct
{
    const char* codigo;
    int     N;
    Aluno   aluno[10];

}   Turma;

int     mostra_turma(Turma*);

int main(int argc, char** argv)
{
    Turma turmaA =
    { .codigo = "Fisica II",
        .N = 0
    };
    mostra_turma(&turmaA); // vazia

    // poe uns alunos na turma
    Aluno um = { 128, 4, { 1, 2, 3, 4 } };
    Aluno outro =
    {
        .N = 3,
        .matricula = 1234,
        .nota = { 1, 1, 1 }
    };
    turmaA.aluno[turmaA.N] = um;
    turmaA.N += 1;
    turmaA.aluno[turmaA.N] = outro;
    turmaA.N += 1;
    mostra_turma(&turmaA);
    return 0;
};  // main()

int     mostra_turma(Turma* T)
{
    printf("Turma '%s' tem %d alunos\n\n",
        T->codigo, T->N);
    for (int i = 0; i < T->N; i += 1)
    {
        Aluno* al = &T->aluno[i];
        printf("Mat #%d\t%d Notas: ", al->matricula, al->N);
        for (int j = 0; j < al->N; j += 1)
            printf("%d ", al->nota[j]);
        printf("\n");
    };
    printf("\n");
    return T->N;
};  // mostra_turma()

This may be the only thing that fits you and at least shows you how to address class and student structures.

This program shows

Turma 'Fisica II' tem 0 alunos


Turma 'Fisica II' tem 2 alunos

Mat #128        4 Notas: 1 2 3 4
Mat #1234       3 Notas: 1 1 1

[b] using a linked list

Using a linked list would allow you to record students one by one and delete a guy more easily in the middle of the class for example, and it’s very flexible. It is slower clear, and more complicated. But with all static does not serve for almost anything.

In case I use a list I will not post a program here because it would just be a linked list of Turma where each Aluno would have a list of Nota. The same model. But I’ll post a structure that works, so you’ll know what to write if you need it. It’s very simple if you already have a list implementation on or if someone gives you one. Other languages already have this available. And if you write your first list you can do so in order to use in other cases without having to change anything: so they are called abstract data structures after all.

The linked list has nodes and has a control structure, things generically called metadata. You can write without it but you’ll work your ass off for nothing.

a possibility using linked lists

struct no
{
    void* item;
    struct no* proxima;
    struct no* anterior;
};  // no
typedef struct no Node;

struct a_propria_lista
{
    char* nome;
    unsigned  quantos;
    unsigned  maximo;
    Node* inicio;
    Node* fim;
};
typedef struct a_propria_lista Lista;

typedef struct
{
    int     matricula;
    Lista*  notas;

}   Aluno;

typedef struct
{
    const char* codigo;
    Lista*      alunos;

}   Turma;

To Turma could be just one Lista but it’s not very versatile. It’s best to leave the model like this, so you can add data to the Turma and leave the Lista only with students. Same case for notas. As the Lista always has the known size no longer need the size fields that were important in the case (a): if you stated

Turma* turma_dois;

So

size(turma_dois->alunos);

will always return the total of students in the class. And similarly for the grades.

Of course, you always write a minimum of functions to a list, and the minimum includes a function size() that returns the size.

As each node in the list is just a pointer to an item, void* item, the account closes and you can use the same list functions to read Turma and Aluno.

[c] Using a vector of structures

This is a very fast way to run and go, but it can be annoying if you will be editing Class while running or creating new notes. There is a choice.

Here’s an example


typedef struct
{
    int     matricula;
    int     N;
    int**   nota;

}   AlunoC;

typedef struct
{
    const char* codigo;
    int         N;
    AlunoC**    aluno;

}   TurmaC;

In this case it is possible to iterate for the students in the Class using

TurmaC    sala1;

and address students as a vector, using

*aluno[0], *aluno[1]... 

to the end of the list. Only you need to keep track of the end of the list, and therefore the parameter N is back. It’s like the argc of main(). Without it the thing does not walk because there is no way to know where the vector ends.

int**   nota;

for example declares a pointer. Nothing else. Only it is a pointer to a pointer to int.

  • nota is int**
  • *nota is int*
  • **nota is a int.

If you allocate 10 pointers to int and put the address in nota can iterate for students using *nota[0] until *nota[9] and this is very, very useful.

I posted here in the OR an example program that does this, with results and discussion. The program creates such a dynamic block, using strings, to explain what the system does to mount the block of arguments to main(), and moves to a function

    int nova_main(int argc, char** argv)

that lists the guys. I can’t now replicate here, maybe later.

I wrote another example using a vector of int** as is your case with the notes here.

You can see these two examples and if you find it useful and have any questions let me know and I can then edit an example for this case here.

Browser other questions tagged

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