Error in Structure Memory Allocation

Asked

Viewed 79 times

-2

PROGRAM
The program highlights memory as more students or more grades are added, but in certain tests depending on the number of students or grades it takes "dirty" values from memory and plays for the first values already allocated.

ERROR
1 - Register two students in option 1 of the menu, each with 2 grades;
2 - Shows the average in menu option 2 (up to here OK);
3 - Register two more students in option 1 of the menu, each with 2 grades;
4 - Here there is error in the value of student’s grade 2 1, consequently the values of the highest grade and general average are also incorrect.

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

struct Aluno
{
    int matricula;
    int *nota;
};

void cadastraAluno(struct Aluno* cadastro, int aluno)
{
    printf("\nAluno(%d)\n- Informe a matricula: ", aluno + 1);
    scanf("%d", &cadastro[aluno].matricula);
}

void cadastraNotas(struct Aluno* cadastro, int aluno, int *qtdNotas)
{
    printf("- Informe a quantidade de notas para cadastrar: ");
    scanf("%d", &qtdNotas[aluno]);

    cadastro[aluno].nota = malloc(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]);
    }
}

void verificaNotas(struct Aluno* cadastro, int alunosTotal, int *maiorNt, int *menorNt, int *qtdNotas)
{
    for(int i = 0; i < alunosTotal; i++)
    {
        for(int j = 0; j < qtdNotas[i]; j++)
        {
            if(cadastro[i].nota[j] > *maiorNt)
            {
                *maiorNt = cadastro[i].nota[j];
            }
            if(cadastro[i].nota[j] < *menorNt)
            {
                *menorNt = cadastro[i].nota[j];
            }
        }
    }
}

void mediaNotas(struct Aluno* cadastro, int alunosTotal, int *qtdNotas, float *media)
{
    float somaNotas = 0, somaTotal = 0, qtdNt = 0;

    for(int i = 0; i < alunosTotal; i++)
    {
        printf("\n-> Aluno(%d)\nMatricula %d", i + 1, cadastro[i].matricula);
        somaNotas = 0;

        for(int j = 0; j < qtdNotas[i]; j++)
        {
            printf("\nNota %d: %d", j + 1, cadastro[i].nota[j]);
            somaNotas = somaNotas + cadastro[i].nota[j];
            qtdNt++;
        }
        somaTotal = somaNotas + somaTotal;
        printf("\n");
    }
    *media = somaTotal / qtdNt;
}

void imprimirInfo(float media, int maiorNt, int menorNt, int alunos)
{
    printf("\n------------------------------\n");
    printf("- Total de Alunos: %d\n", alunos);
    printf("- Menor Nota: %d\n", menorNt);
    printf("- Maior Nota: %d\n", maiorNt);
    printf("- Media Geral: %.0f", media);
    printf("\n------------------------------\n");
}


int main()
{
    int alunos = 0, op, maiorNota = 0, menorNota = 10, aux = 0, alunosTot = 0, pos = 0, *qtdNotas, *qtdNotas1;
    struct Aluno *cadastro;
    struct Aluno *cadastro1;
    float mediaTotal;

    do
    {
        printf("\nEscolha uma opcao abaixo:");
        printf("\n0 - Encerrar o Programa\n");
        printf("1 - Cadastrar Aluno\n");
        printf("2 - Calcular Media da Turma\n");
        scanf("%d", &op);

        switch (op)
        {
        case 1:
            printf("Informe o numero de alunos: ");
            scanf("%d", &alunos);

            if (aux == 0)
            {
                qtdNotas = (int*) malloc(alunos * sizeof(int));
                cadastro = (struct Aluno*) malloc(alunos * sizeof(struct Aluno));
            }
            else
            {
                qtdNotas1 = (int*) realloc(qtdNotas, alunos * sizeof(int));
                cadastro1 = (struct Aluno*) realloc(cadastro, alunos * sizeof(struct Aluno));

                if (qtdNotas1 != NULL)
                {
                    qtdNotas = qtdNotas1;
                }
                if (cadastro1 != NULL)
                {
                    cadastro = cadastro1;
                }
            }

            for(int i = 0; i < alunos; i++)
            {
                cadastraAluno(cadastro, pos);
                cadastraNotas(cadastro, pos, qtdNotas);

                pos++;
            }
            aux++;
            alunosTot += alunos;

            break;

        case 2:
            if(alunos == 0)
            {
                printf("\nVoce precisa cadastrar um ou mais alunos\n\n");
            }
            else
            {
                printf("\n------------------------------");
                verificaNotas(cadastro, alunosTot, &maiorNota, &menorNota, qtdNotas);
                mediaNotas(cadastro, alunosTot, qtdNotas, &mediaTotal);
                imprimirInfo(mediaTotal, maiorNota, menorNota, alunosTot);
            }
            break;
        }
    }
    while(op != 0);

    free(cadastro);
    free(qtdNotas);

    return 0;
}
  • If nota is a pointer to int what the sense of doing: cadastro[aluno].nota = malloc(qtdNotas[aluno] * sizeof(struct Aluno));? Why do you make one realloc but assigns a different pointer?

  • The meaning of malloc would be to register more than one grade, because for each student can see one or more grades. This is asked in the system to each student who is registered. The realloc pointing to another pointer would be to avoid losing data from the first pointer in case of error.

  • But why multiply by sizeof(struct Aluno)?

  • I get it, the correct would be sizeof(int), would that be it? Because note is type int.

1 answer

0


struct Aluno
{
    int matricula;
    int *nota;
}; 

This is the structure Student, but it seems to be also his registration to be judged by the statements in main()

    struct Aluno *cadastro;
    struct Aluno *cadastro1;

Only that’s not how it works. I’ll try to explain below. I think I’ve done it in relation to a problem identical to this but found no reference

Before:

  • If you are learning now avoid as many lines as this one below. Initialize all variables, but don’t declare more than one per line. It’s free. Help yourself and others. See
    int alunos = 0, op, maiorNota = 0, menorNota = 10, aux = 0, alunosTot = 0, pos = 0, *qtdNotas, *qtdNotas1;

And compare with this

    int alunos = 0;
    int op;
    int maiorNota = 0;
    int menorNota = 10;
    int aux = 0;
    int alunosTot = 0;
    int pos = 0; 
    int *qtdNotas, 
    int *qtdNotas1;

Don’t you find it easier to read? What if it’s you trying to read it in two weeks?

Why didn’t you just initialize the pointers, the most likely to give you a problem?

  • Always use main() as the first function of your program. So you help others and yourself to understand your program.

Back on the show

  • Aluno: its structure has a pointer to nota and that won’t give you access to more than one note. That’s after you allocate some space to it.
  • struct Aluno* register is also a pointer to a single Aluno. Do not create a Student Register. And for now it is only a pointer. You can allocate via malloc() 150 students using this pointer. The parameter of malloc() is just the size of the area. It is correct to write, as far as the compiler sees, struct Aluno* Sala = malloc(2048); and allocate 2K from Sala. But it won’t make you iterate for Sala, as in Sala[0], Sala[1] or something. It is the same case of the notes in the record of Aluno. The most flexible way to do that is to declare something like

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

}   Aluno;

typedef struct
{
    char*   turma;
    int     id;
    int     N;
    Aluno** al;

}   Sala;

Sala QuimicaI;
Aluno um;

Or something conservative, allocating a fixed number of Students and Grades, as in


typedef struct
{
    int     matricula;
    int     N;
    int     nota[5];

}   Aluno;

typedef struct
{
    char*   turma;
    int     id;
    int     N;
    Aluno   al[10];

}   Sala;

Sala QuimicaI;
Aluno um;

Nothing flexible but much simpler. I posted complete examples of using int** and char** that you can adapt to that case. I won’t repeat the code here but the links are for a C program creating uses and releases a char block** and that for a program that creates and uses an int block**

Maybe it helps if you look there. u can post something here if you don’t understand what’s there or have a specific question.

  • 1. Don’t you find it easier to read? What if it’s you trying to read it in two weeks. I appreciate the variable boot formatting tip, I will start using this way. 2. Why not just initialize the pointers, the most likely to give you a problem? True, I’ll initialize, I’ve forgotten. 3. Always use main() as the first function of your program. So you help others and yourself to understand your program. Okay, I’ll do it next time. Regarding the program I’ll use a predefined value even for the notes. I appreciate the explanation.

  • Look at those programs in the links I mentioned and compare how to create the memory blocks in your case. Probably what you want is the most flexible option, to use a vector of structures, and you should follow how it is there. If you need I can change an example when you have time here

  • Yes I took a look, if I may add an example of my case may be, but for now I have done so anyway: struct Aluno { int matricula; int nota[3]; };

  • Do not forget that with the registration and the same thing. Maybe you find it simpler to create a registration structure. After all the model is like this: the register has students who have grades

Browser other questions tagged

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