Delete a record in struct

1

I am creating a registry using struct , where I should have a menu to insert, display, delete and exit the program.

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

The code is a bit messy, as 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");
        }
    }   
}
    
asked by anonymous 05.08.2016 / 02:05

2 answers

1

Fixes

The code does indeed show some error warnings of things that need to be fixed.

One of them is typedef that does not have the name of the type to be renamed:

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

What should be:

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

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

char opcao,op;

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

int opcao;
char op;

No exibe() one of printf has one missing argument:

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

Should this stay:

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

And the main subscription itself:

main()
{ 

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

Function to remove

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

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 guarantees the order of the elements that the array already had. If the order of the elements is not relevant, you can pick up the last element, replace it with the position to be removed and do the realloc directly, 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 cadastra() function could be simplified because when you have already done a reallocation, in 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 loop to always add only one position, since num_old=num; num=num+1; will cause num to always be 1 more than num_old . So the cycle is not necessary, so the else can be just like this:

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

Neither the realoca variable would be required. To not use it, you could start the array p with the appropriate value, NULL , and test that value directly in 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 just listed the ones above to make the code look similar to the one I had.

Code with all the reviews I listed online to test

Note: I had to make some adjustments to this online version so that the values input work correctly, such as replacing getchar and gets with the corresponding scanf .

    
06.08.2017 / 17:14
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 the position and shifting the vector.

    
21.10.2016 / 00:54