Delete a struct record

Asked

Viewed 5,011 times

1

I’m creating a record using struct, where I must have a menu to insert,.

My difficulty is to create the delete function, I put a null value on the pointer of the position that will be deleted, indent all records one position, then use the realloc to decrease a vector position. But that allocated space, which after I deleted, will be available for use of other variables?

The code is a little messy because I’m still learning dynamic allocation.

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

typedef struct cadastro{
    char nome[20];
    int idade;
};

cadastro *p;

int num, num_novo, num_old, realoca=0;
char opcao,op;
void cadastra();
void exibe();
void menu();

main()
{       
    do{
        menu();

        printf("\tOpcao: "); scanf("%d",&opcao); fflush(stdin);

            switch(opcao){
                case 0:
                    break;

                case 1:{
                    do{
                        cadastra();
                        printf("Deseja cadastrar mais (s/n): "); op=getchar(); fflush(stdin);

                    }while(toupper(op)!='N');
                    break;
                }

                case 2:
                    exibe();
                    break;

                default:
                    printf("Opcao invalida.\n\n");
            }   
    }while(opcao!=0);

    getchar();

    return 0;
}

void menu()
{
    printf("\t[0] Sair\n\t[1] Cadastrar\n\t[2] Exibe\n\t[3] Excluir\n");

}

void cadastra()
{
    if(realoca==0){
        printf("Numero de cadastros: "); scanf("%d",&num); fflush(stdin);

        p = (cadastro *)calloc(num, sizeof(cadastro));

        int i;
        for(i=0; i<num; i++){
            printf("Cadastro %d\n",i+1);
            printf("Nome: "); gets(p[i].nome);
            printf("Idade: "); scanf("%d",&p[i].idade);fflush(stdin);
            printf("\n\n");

        }
        realoca = 1;
    }else{

        num_old=num;
        num=num+1;

        p = (cadastro*)realloc(p,num);

        int i;

        for(i=num_old; i<num; i++){
            printf("Cadastro %d\n",i+1);
            printf("Nome: "); gets(p[i].nome);
            printf("Idade: "); scanf("%d",&p[i].idade);fflush(stdin);
        }
    }
}

void exibe()
{
    int j;
    if(p==NULL)
        printf("\t -- Cadastro vazio. --\n\n");


    else{

        for(j=0; j<num;j++){

            printf("Pessoa %d\n\n");
            printf("Nome: %s\n",p[j].nome);
            printf("Idade: %d",p[j].idade);
            puts("\n\n");
        }
    }   
}

2 answers

1

Corrections

The code does present some error warnings of things that need to be corrected.

One of them is the typedef who doesn’t have the name of the guy to be renamed:

typedef struct cadastro{
    char nome[20];
    int idade;
};

That should be:

typedef struct cadastro{
    char nome[20];
    int idade;
} cadastro; //faltava nome de renomeação para completar o typedef

To opcao is being used as an integer both in reading scanf("%d",&opcao); as in the switch, however it was declared as char:

char opcao,op;

It should then be changed to int to be consistent with its use:

int opcao;
char op;

In the exibe() one of the printf has an argument missing:

void exibe()
{
    ...
        for(j=0; j<num;j++){
            printf("Pessoa %d\n\n"); 
        ...

Should this one stay:

printf("Pessoa %d\n\n", j); //agora com j para indicar o numero da pessoa 

And the main signature itself:

main()
{ 

It must be at least become int main() {, to be consistent with the return 0 that is being done within it.

Function to remove

When to function deletar which indicates, can be done exactly with the logic you indicated, walking all the elements back from the intended position and calling the realloc to reduce the array size by 1 unit, thus:

void deletar(){
    printf("Qual a posição a excluir?");
    int pos;
    scanf("%d", &pos);
    pos-- ; //para ajustar aos indices que começam em 0

    if (pos >= 0 && pos < num){ //se a posição é valida
        int i;

        //andar todos um para trás a partir da posição a remover
        for (i = pos;i < num - 1; ++i){ 
            p[i] = p[i + 1];
        }

        p = realloc(p, --num * sizeof(cadastro)); //reduzir o tamanho do array em 1 unidade
    }
}

This removal solution ensures the order of the elements the array already had. If the element order is not relevant, you can take the last element, replace it with the position to be removed, and directly do the realloc, which is more efficient:

if (pos >= 0 && pos < num){ //se a posição é valida
    p[pos] = p[--num];
    p = realloc(p, num * sizeof(cadastro));
}

Improvements

The function cadastra() could be simplified, because when you’ve done a relocation, else:

else{
    num_old=num;
    num=num+1;

    p = (cadastro*)realloc(p,num);

    int i;

    for(i=num_old; i<num; i++){
        printf("Cadastro %d\n",i+1);
        printf("Nome: "); gets(p[i].nome);
        printf("Idade: "); scanf("%d",&p[i].idade);fflush(stdin);
    }
}

You are using a cycle to always add only one position, once num_old=num; num=num+1; will cause num always be 1 more than num_old. Therefore the cycle is not necessary, and the else simply like that:

else{
    num_old = num++;
    p = realloc(p,num);
    printf("Cadastro %d\n",num_old);
    printf("Nome: "); gets(p[num_old].nome);
    printf("Idade: "); scanf("%d",&p[num_old].idade);fflush(stdin);
}

Nor the variable realoca would be necessary. Not to use it could start the array p with the appropriate value, NULL, and test this value directly on if:

int num, num_novo, num_old /*, realoca=0*/;
cadastro *p = NULL;

...

void cadastra()
{
    if(p == NULL){ //calloc
        ...
        //realoca = 1; também deixa de ser necessária
    }else{ //realloc
        ...
    }
}

Other improvements could be made, but I only indicated the top ones to make the code look similar to the one I had.

Code with all the revisions I indicated online to test

Note: I had to make some adjustments in this online version for the input values to work correctly, such as replacing getchar and gets for scanf correspondent.

0

This is the simplest solution:

void remove(){
int n_remover;
exibe()
printf("Digite o numero de quem voce quer remover");
scanf("%d",&n_remover);
p[d] = p[num-1] //coloca o ultimo no lugar do q você quer remover
num--; //você diminui o tamanho do vetor
p = (cadastro*) realloc(p,num*sizeof(cadastro)); //desaloca o espaço que sobrou
}

Another solution would be to remove the element from position and shift the vector.

Browser other questions tagged

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