Como excluir um contato da agenda de aniversário salva em arquivo texto? É esta dúvida que vamos resolver na aula de hoje sobre arquivo texto na Linguagem C.
Se você está acompanhando o Curso de Programação C desde o início, você deve se lembrar que lá na aula 215 nós iniciamos a criação de uma agenda de aniversários para praticar o uso de arquivos em C. Hoje vamos acrescentar uma função ao nosso código para realizar a exclusão de um contato da nossa agenda.
A exclusão ela não ocorre propriamente no arquivo, mas no vetor em memória. Assim, precisamos carregar todos os contatos salvos no arquivo para a memória. Feito isso, podemos agora fazer uma função que irá imprimir todos os contatos na tela e perguntar ao usuário qual contato ele deseja excluir.
Como o primeiro índice válido do vetor é o 0 e nosso procedimento imprimir inicia a partir do 1, precisamos subtrair 1 no valor que o usuário digitar e verificar se é um índice válido, ou seja, se está entre 0 e quant – 1, sendo quant a quantidade de contatos no vetor.
Se for um índice válido, liberamos a memória alocado para o contato daquela posição e, como é um vetor, não podemos deixar um “buraco” ou uma posição vazia no meio do vetor, então copiamos o último contato (que está na posição quant – 1) para a posição onde acabamos de remover o contato.
Esta lógica é implementada no trecho de código a seguir.
/* Procedimento para excluir um contato */ int excluir_contato(Contato **c, int quant){ int id; imprimir(c, quant); printf("\n\tDigite o codigo do contato que deseja excluir: \n"); scanf("%d", &id); getchar(); id--; if(id >= 0 && id < quant){ // apagar contato free(c[id]); if(id < quant - 1) c[id] = c[quant - 1]; return -1; // excluído com sucesso } else{ printf("\n\tCodigo invalido!\n"); return 0; // nenhum contato excluído } }
Observe que o contato foi excluído apenas do vetor de contatos em memória. Para que isso se reflita no arquivo texto é necessário escrever os contatos novamente no arquivo, salvando assim as alterações.
Código de exemplo completo em C para a Agenda de Aniversários
#include <stdio.h> #include <stdlib.h> /* AGENDA DE ANIVERSÁRIOS - Como excluir um contato Código escrito por Wagner Gaspar Outubro de 2021 */ typedef struct{ char nome[50]; int dia, mes, ano; }Contato; void imprimir(Contato **c, int quant){ int i; printf("\n\t\tLista de Contatos:\n"); printf("\t--------------------------------\n"); for(i = 0; i < quant; i++){ printf("\t%d = %2d/%2d/%4d\t%s\n", i+1, c[i]->dia, c[i]->mes, c[i]->ano, c[i]->nome); } printf("\t--------------------------------\n"); } int cadastrar_contato(Contato **c, int quant, int tam){ if(quant < tam){ Contato *novo = malloc(sizeof(Contato)); printf("\nDigite o nome do contato: "); scanf("%50[^\n]", novo->nome); printf("\nDigite a data de aniversario dd mm aaaa: "); scanf("%d%d%d", &novo->dia, &novo->mes, &novo->ano); getchar(); c[quant] = novo; return 1; } else{ printf("\n\tImpossivel novo cadastro. Vetor cheio!\n"); return 0; } } void alterar_contato(Contato **c, int quant){ int id; imprimir(c, quant); printf("\n\tDigite o codigo do contato que deseja alterar: \n"); scanf("%d", &id); getchar(); id--; if(id >= 0 && id < quant){ Contato *novo = malloc(sizeof(Contato)); printf("\nDigite o nome do contato: "); scanf("%50[^\n]", novo->nome); printf("\nDigite a data de aniversario dd mm aaaa: "); scanf("%d%d%d", &novo->dia, &novo->mes, &novo->ano); getchar(); c[id] = novo; } else printf("\n\tCodigo invalido!\n"); } // -------- excluir contato ------------------------------ int excluir_contato(Contato **c, int quant){ int id; imprimir(c, quant); printf("\n\tDigite o codigo do contato que deseja excluir: \n"); scanf("%d", &id); getchar(); id--; if(id >= 0 && id < quant){ // apagar contato free(c[id]); if(id < quant - 1) c[id] = c[quant - 1]; return -1; // excluido com sucesso } else{ printf("\n\tCodigo invalido!\n"); return 0; // nenhum contato excluido } } void salvar(Contato **c, int quant, char arq[]){ FILE *file = fopen(arq, "w"); int i; if(file){ fprintf(file, "%d\n", quant); for(i = 0; i < quant; i++){ fputs(c[i]->nome, file); fputc('\n', file); fprintf(file, "%d %d %d\n", c[i]->dia, c[i]->mes, c[i]->ano); } fclose(file); } else printf("\n\tNAO FOI POSSIVEL ABRIR/CRIAR O ARQUIVO!\n"); } int ler_arquivo(Contato **c, char arq[]){ FILE *file = fopen(arq, "r"); int quant = 0, i; Contato *novo = malloc(sizeof(Contato)); if(file){ fscanf(file, "%d\n", &quant); for(i = 0; i < quant; i++){ //fgets(novo->nome, 50, file); fscanf(file, "%50[^\n]", novo->nome); fscanf(file, "%d %d %d\n", &novo->dia, &novo->mes, &novo->ano); c[i] = novo; novo = malloc(sizeof(Contato)); } fclose(file); } else printf("\n\tNAO FOI POSSIVEL ABRIR/CRIAR O ARQUIVO!\n"); return quant; } int main(){ Contato *agenda[50]; char arquivo[] = {"agenda.txt"}; int opcao, tam = 50, quant = 0; do{ printf("\n\t0 - Sair\n\t1 - Cadastrar\n\t2 - Alterar\n\t3 - Imprimir\n\t4 - Salvar\n\t5 - Ler arquivo\n\t6 - Excluir Contato\n"); scanf("%d", &opcao); getchar(); switch(opcao){ case 1: quant += cadastrar_contato(agenda, quant, tam); break; case 2: alterar_contato(agenda, quant); break; case 3: imprimir(agenda, quant); break; case 4: salvar(agenda, quant, arquivo); break; case 5: quant = ler_arquivo(agenda, arquivo); break; case 6: quant += excluir_contato(agenda, quant); break; default: if(opcao != 0) printf("\n\tOpcao invalida!!!\n"); } }while(opcao != 0); return 0; }