Como faço para colocar a opção excluir em lista simples encadeada em C

1. Como faço para colocar a opção excluir em lista simples encadeada em C

Robson Nunes
Robson_nunes88

(usa Outra)

Enviado em 26/11/2020 - 20:12h

Boa noite, alguém pode me ajudar a colocar a opção excluir nesse código, tem que procurar pelo nome da pessoa e fazer a exclusão, segue o que eu conseguir fazer até agora.

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


struct stNo {
int info, idade, celular;
char nome[100],endereco[100], sexo, cidade[80], email[40];
struct stNo *prox;
};


struct stNo *cria_no() {
struct stNo *p;
if ((p = (struct stNo *) malloc(sizeof(struct stNo))) == NULL)
return NULL;
else {
p->prox = NULL;
return p;
}
}

void insereLista(struct stNo **list){
struct stNo *p,*q;
int n, idade, celular;
char name[100], endereco[100], sexo, cidade[80], email[40];
fflush(stdin);
printf("\nDigite o valor do nó:");
scanf("%i",&n);
fflush(stdin);
printf("\nDigite o nome:");
gets(name);
fflush(stdin);
//printf("\nDigite o seu sexo [F][M]:");
//scanf("%c",&sexo);
//fflush(stdin);
//printf("\nDigite sua idade:");
//scanf("%i",&idade);
//fflush(stdin);
//printf("\nDigite seu endereço:");
//gets(endereco);
//fflush(stdin);
//printf("\nDigite sua cidade:");
//gets(cidade);
//fflush(stdin);
//printf("\nDigite seu celular:");
//scanf("%i",&celular);
//fflush(stdin);
//printf("\nDigite seu e-mail:");
//gets(email);
//fflush(stdin);
if(*list==NULL){ //lista vazia
p = cria_no();
*list = p;
p->prox = NULL;
p->info = n;
strcpy(p->nome,name);
p->sexo=sexo;
p->idade=idade;
strcpy(p->endereco,endereco);
strcpy(p->cidade,cidade);
p->celular=celular;
strcpy(p->email,email);
}
else{
p=*list;
while(p->prox!=NULL)
p=p->prox;// posiciona no final da lista
q = cria_no();
p->prox = q;
q->prox = NULL;
q->info = n;
strcpy(q->nome,name);
*list = q;
};
};
void mostraLista(struct stNo **list){
struct stNo *p;
if(*list!=NULL){
p=*list;
while(p->prox!=NULL){
printf(" %d->",p->info);
p = p->prox;
};
printf(" %d->",p->info);
}
else printf("\nLista Vazia");
};
void excluirLista(struct stNo **list){
struct stNo *p,*q;
int n;
char name[100];
if(*list!=NULL){ //lista vazia
p = *list;
while (p->prox!=NULL && strcmp(p->nome, name) != 0) {
p = p->prox;
};
if(strcmp(p->nome, name) == 0){
printf("\nCódigo: %d",p->info);
printf("\nNome: %s",p->nome);
if(p->prox==NULL){
free(p);
*list =NULL;
}else{
while(p->prox!=NULL){
q=p;
p=p->prox;
}
q->prox=NULL;
free(p);

else{
q=p->prox;
free(p);
*list=q;
}
else{
q->prox=NULL;
free(p);
}
}else{
printf("\nLista Vazia");
}
};


void visualizarLista(struct stNo **list){
struct stNo *p;
int n;
char name[100];
fflush(stdin);
printf("\nDigite o nome:");
gets(name);
fflush(stdin);
if (*list!=NULL) {
p = *list;
while (p->prox!=NULL && strcmp(p->nome, name) != 0) {
p = p->prox;
};
if(strcmp(p->nome, name) == 0){
printf("\nCódigo: %d",p->info);
printf("\nNome: %s",p->nome);
//printf("\nSexo: %c",p->sexo);
//printf("\nIdade: %d",p->idade);
//printf("\nEndereço: %s",p->endereco);
//printf("\nCidade: %s",p->cidade);
//printf("\nCelular: %i",p->celular);
//printf("\nE-mail: %s",p->email);
};
}
else printf("\nLista Vazia");
};

main(){
setlocale(LC_ALL,"Portuguese");
struct stNo *lista;
int menu;
lista = NULL; // inicializando a lista vazia

do{
system("cls");
printf("\n");
mostraLista(&lista);
printf("\n\n");
printf("[1-Inserir] ");
printf("[2-Visualizar] ");
printf("[3-Excluir] ");
printf("[4-Sair] ");
printf("Opção:");
scanf("%i",&menu);
switch(menu){
case 1 : insereLista(&lista);
break;
case 2 : visualizarLista(&lista);
break;
case 3 : excluirLista(&lista);
break;
case 4 : printf("\nSaindo...");
break;
default: printf("\nCódigo Inválido");
}
printf("\n");system("pause");
}while(menu!=3);
}



  


2. Re: Como faço para colocar a opção excluir em lista simples encadeada em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 01/12/2020 - 05:24h

Robson_nunes88 escreveu:

Boa noite, alguém pode me ajudar a colocar a opção excluir nesse código, tem que procurar pelo nome da pessoa e fazer a exclusão, segue o que eu conseguir fazer até agora.


Se me permite, vou comentar o código inteiro, falando da questão específica no contexto adequado.

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


struct stNo {
int info, idade, celular;
char nome[100],endereco[100], sexo, cidade[80], email[40];
struct stNo *prox;
};


struct stNo *cria_no() {


Em C, uma função que não receber argumentos deve especificar uma lista de argumentos contendo a palavra chave void. Por exemplo, a declaração da função cria_no() deveria ter sido feita do seguinte modo.
struct stNo *cria_no(void) 


Ao deixar a lista de argumentos vazia, o compilador C entende que a função pode receber uma quantidade qualquer de argumentos de quais tipos. Isso pode soar um tanto contra-intuitivo, e é especificamente diferente de outras linguagens, tais como C++ e Java, mas é assim que funciona em C.

  struct stNo *p;
if ((p = (struct stNo *) malloc(sizeof(struct stNo))) == NULL)


Essa conversão do tipo de ponteiro retornado por malloc() é desnecessária em C, uma vez que um ponteiro do tipo void * é automaticamente conversível em ponteiro para qualquer outro tipo. Como qualquer pedaço de código que não é necessário, o melhor que você pode fazer é removê-lo, para não ficar com código no seu programa que só vai servir para torná-lo maior e dificultar a manutenção.

De novo, esse comportamento do C é diferente de outras linguagens. Se você tentar compilar seu programa com um compilador C++, a conversão implícita e automática de void * para outro tipo de ponteiro não vai funcionar. Então, se você estiver usando, por exemplo, o Dev-C++ ou Code::Blocks e não tiver tomado o cuidado de mandar compilar o programa como um programa em C, em vez de C++, pode ser que o compilador reclame se você remover o código que é desnecessário em C. Mas a forma de consertar não é reinserir o código desnecessário. Em vez disso, ajuste o compilador para compilar o programa como um programa em C, usando as regras do C.

A não ser que você não queira usar C, mas sim C++. Aí, num caso desses, você provavelmente não teria colocado “em C” no título deste tópico. E a maneira de tornar o código em C++ não seria colocar essa conversão explícita de volta, pois não apenas essa conversão não segue o estilo do C++, mas o próprio uso da função malloc() não seria a forma mais natural de alocar memória em C++; em C++, ou você usaria o operador new, ou uma classe de container, ou criaria uma classe com seu próprio construtor.

    return NULL;
else {
p->prox = NULL;
return p;
}
}


Essa função inteira poderia ser simplificada. Veja se o código abaixo não é equivalente ao que você fez.
struct stNo *cria_no(void){
struct stNo *p=malloc(sizeof *p);
if(p)
p->prox=NULL;
return p;
}



void insereLista(struct stNo **list){


Note que esta função não faz exatamente o que o nome indica: ela não apenas insere um nó na lista, mas ela também lê os dados do nó a ser inserido. Pior ainda, faz a leitura a partir de uma fonte fixa (stdin). Esse tipo de construção não é muito adequada porque acaba acoplando operações distintas.

Seria bom que você aprendesse desde cedo a escrever código que possa ser facilmente reutilizado, e entre os fatores que mais contribuem para reutilização de código estão a eliminação de acoplamentos e a modularização.

No seu caso, eu sugiro separar a entrada de dados da colocação de novos dados na lista. Desse modo, se o seu próximo exercício pedir que você popule a lista encadeada a partir de dados recebidos de um arquivo (ler do disco em vez de pelo teclado) ou a partir de dados gerados aleatoriamente ou por meio de simulação, você poderia aproveitar a parte de colocar na lista, e focar apenas nas partes novas.


struct stNo *p,*q;
int n, idade, celular;
char name[100], endereco[100], sexo, cidade[80], email[40];
fflush(stdin);


fflush(stdin)” é uma prática de programação questionável. O padrão do C só define o comportamento de fflush() para fluxos de saída (escrita) de dados, não para fluxos de entrada (leitura) como stdin. Algumas implementações, especialmente no mundo MS-DOS e Windows, estendem a função de modo a funcionar também com fluxos de entrada, mas não é saudável contar com isso.

Se você, como a maioria das pessoas que usam essa construção, quer apenas evitar a inconveniência de caracteres não desejados no fluxo de entrada, então a maneira mais adequada e segura de o fazer é usar operações de leitura adequadas, testando sempre seu valor de retorno e condições de contorno, e agindo de acordo.

  printf("\nDigite o valor do nó:");
scanf("%i",&n);
fflush(stdin);


Eis aqui um exemplo de leitura descuidada, uma vez que nem ao menos verifica se foi bem-sucedida, e que você acaba seguindo com um “fflush(stdin)”, digamos, “só por garantia”.

O chato é que dá mesmo um certo trabalho fazer leituras seguras, especialmente com uma função altamente complexa, como é o caso de scanf(), que eu reputo como uma das mais complexas funções — se não a mais complexa de todas — da biblioteca padrão do C. Por isso, eu sempre recomendo que as pessoas leiam cuidadosamente sua documentação, pois o simples fato de saber quando começa e quando termina a extração de caracteres da entrada e quais conversões de dados cuidam de fazer automaticamente o descarte de espaços em branco (incluindo quebras de linha) e quais não a fazem, além de elementos que podem ser colocados como parte da string de formatação para eliminar elementos indesejáveis e diagnosticar quanto da entrada foi consumida e com qual grau de sucesso, já ajuda a eliminar muitos dos pontos em que, de outro modo, você poderia desejar fazer apenas o descarte de caracteres indesejados.

Mas mesmo que você eventualmente venha a precisar de uma alternativa de descarte de caracteres indesejados, “fflush(stdin)” é uma opção ruim. Prefira outras opções, que não dependam de comportamentos que não estão de acordo com o padrão do C. Algumas alternativas incluem:

  • “{ int ch; while((ch=fgetc(stdin))!='\n' && ch!=EOF){ } }”, que descarta todos os caracteres até a próxima quebra de linha (ou erro de leitura);

  • “r=scanf(" ");” (sendo r uma variável do tipo int, usada para que você possa verificar se ocorreu erro de leitura, e com um espaço entre as aspas da string de formatação), que serve para pular todos os espaços em branco (incluindo quebras de linha), até ter o próximo caráter que não seja espaço pronto pra ser consumido pela próxima operação de leitura.

  printf("\nDigite o nome:");
gets(name);


A função gets() foi removida da biblioteca padrão do C, de acordo com o padrão em 2011. Antes disso, ela já tinha sido marcada como obsoleta e desincentivada para uso pelo padrão de 1999.

A razão para isso é que essa função é insegura, pois não oferece uma forma de limitar a quantidade de caracteres lidos, a fim de não exceder o tamanho máximo do vetor que deve armazená-los. A consequência, por exemplo, de ter um vetor de 40 posições, mas, na hora em que o programa rodar, o usuário resolver digitar mais do que 40 caracteres (na verdade, basta que sejam mais do que 39) é que gets() continuaria gravando caracteres recebidos em posições de memória que estão além do fim do vetor, possivelmente corrompendo os valores de outras variáveis que estivessem em regiões de memória adjacentes, ou mesmo outras partes do programa, ou, ainda, violando os limites do próprio programa, provocando erros ainda mais graves.

Em lugar de gets(), use fgets() ou scanf() com uma string de formatação inteligente e que lhe dê condições de analisar se a entrada foi satisfatória. Se você estivesse num sistema POSIX, outra possibilidade seria usar getline(), mas, até onde eu sei, getline() não está disponível no mundo Windows.

  fflush(stdin);
//printf("\nDigite o seu sexo [F][M]:");
//scanf("%c",&sexo);
//fflush(stdin);
//printf("\nDigite sua idade:");
//scanf("%i",&idade);
//fflush(stdin);
//printf("\nDigite seu endereço:");
//gets(endereco);
//fflush(stdin);
//printf("\nDigite sua cidade:");
//gets(cidade);
//fflush(stdin);
//printf("\nDigite seu celular:");
//scanf("%i",&celular);
//fflush(stdin);
//printf("\nDigite seu e-mail:");
//gets(email);
//fflush(stdin);
if(*list==NULL){ //lista vazia


Outro acoplamento aqui, e bem profundo.

A bem da modularização, em geral faz sentido ter a criação da lista como operação separada da operação de inserção. No momento da inserção, você já poderia (deveria?) ter certeza de que a lista está criada.

Mais que isso, quando se trata da lista encadeada, eu normalmente acho mais didático criar (pelo menos) dois tipos distintos: um para representar os nós da lista, e outro para representar a lista em si. Como esse segundo tipo, você podeira ter algo que mantivesse um controle geral sobre a lista, de modo a ter, por exemplo, um contador da quantidade de nós em uso e um ponteiro para o último elemento, a fim de economizar tempo com algumas operações, e não ter, por exemplo, de varrer a lista inteira a cada novo elemento que você quisesse incluir na lista.

Imagine.
struct list_node {
struct XYZ dados;
struct list_node *next;
};

struct list {
struct list_node *first, *last;
size_t size;
};

struct list *create_list(void){
struct list *nl=malloc(sizeof *nl);
if(nl){
nl->first=nl->last=NULL;
nl->size=0;
}
return nl;
}

bool insert_list_end(struct list *l, const struct XYZ *p_data){
struct list_node *ln
if(!l || !p_data || !(ln=malloc(sizeof *ln))
return false;
ln->data=*p_data;
ln->next=NULL;
if(list->first==NULL)
list->first=list->last=ln;
else
list->last->next=ln;
++list->size;
return true;
}

bool insert_list_start(struct list *l, const struct XYZ *p_data){
struct list_node *ln
if(!l || !p_data || !(ln=malloc(sizeof *ln))
return false;
ln->data=*p_data;
ln->next=list->first;
list->first=ln;
if(list->last==NULL)
list->last=list->first;
++list->size;
return true;
}

/* etc. */


    p = cria_no();
*list = p;
p->prox = NULL;
p->info = n;
strcpy(p->nome,name);
p->sexo=sexo;
p->idade=idade;
strcpy(p->endereco,endereco);
strcpy(p->cidade,cidade);
p->celular=celular;
strcpy(p->email,email);
}
else{
p=*list;
while(p->prox!=NULL)
p=p->prox;// posiciona no final da lista
q = cria_no();
p->prox = q;
q->prox = NULL;
q->info = n;
strcpy(q->nome,name);
*list = q;
};
};


Esse ponto-e-vírgula após a definição da função não é necessário. É errado, aliás. Se fosse uma definição de estrutura (struct), união (union) ou enumeração (enum), ele seria necessário. Para funções, não deve existir.

Este mesmo erro acontece com outras funções abaixo.

void mostraLista(struct stNo **list){ 


Como esta função não altera a lista, o ponteiro para ponteiro não é necessário. Poderia ser um ponteiro simples. Mais que isso, poderia ser um ponteiro para dados constantes (i.e. “const struct stNo *list”). E, obviamente, sendo um ponteiro para dados constantes, p, abaixo, poderia ser do mesmo tipo.

  struct stNo *p;
if(*list!=NULL){
p=*list;
while(p->prox!=NULL){
printf(" %d->",p->info);
p = p->prox;
};
printf(" %d->",p->info);
}
else printf("\nLista Vazia");
};


Não vou apontar todos os problemas com a função abaixo, até porque parece que falta um pedaço (incluindo um fechamento de chaves).

Algumas dicas que posso dar com relação à função que você tem de implementar:

  • A lista será alterada, então você tem de passar um ponteiro para um ponteiro.

  • Se houver três nós consecutivos A, B e c (ou seja: A.prox==B e B.prox==C) e você quer apagar o nó B, então você terá de garantir que, antes de apagar (i.e. liberar a memória de) B, A.prox passe a apontar para C.

  • Como você quer apagar uma coisa e alterar outra coisa, então você terá de percorrer a lista com dois ponteiros: um para a coisa a ser apagada, e outro para a coisa a ser alterada.

  • A coisa a ser alterada é um é o campo prox do nó anterior àquele que será apagado. A variável usada para pular entre os sucessivos campos prox dentro de cada nó tem de garantir que a alteração acontecerá dentro do campo prox do nó, então a variável de rastreamento terá de ser um ponteiro para campos prox. Como o tipo do campo prox é um ponteiro, então o tipo da variável de rastreamento terá de ser ponteiro para ponteiro.

void excluirLista(struct stNo **list){
struct stNo *p,*q;
int n;
char name[100];
if(*list!=NULL){ //lista vazia
p = *list;
while (p->prox!=NULL && strcmp(p->nome, name) != 0) {
p = p->prox;
};
if(strcmp(p->nome, name) == 0){
printf("\nCódigo: %d",p->info);
printf("\nNome: %s",p->nome);
if(p->prox==NULL){
free(p);
*list =NULL;
}else{
while(p->prox!=NULL){
q=p;
p=p->prox;
}
q->prox=NULL;
free(p);

else{
q=p->prox;
free(p);
*list=q;
}
else{
q->prox=NULL;
free(p);
}
}else{
printf("\nLista Vazia");
}
};


void visualizarLista(struct stNo **list){


Outra função que não altera a lista, de modo que você pode usar ponteiro para nó constante como argumento, em lugar de ponteiro para ponteiro para nó.

  struct stNo *p;
int n;
char name[100];
fflush(stdin);
printf("\nDigite o nome:");
gets(name);
fflush(stdin);
if (*list!=NULL) {
p = *list;
while (p->prox!=NULL && strcmp(p->nome, name) != 0) {
p = p->prox;
};
if(strcmp(p->nome, name) == 0){
printf("\nCódigo: %d",p->info);
printf("\nNome: %s",p->nome);
//printf("\nSexo: %c",p->sexo);
//printf("\nIdade: %d",p->idade);
//printf("\nEndereço: %s",p->endereco);
//printf("\nCidade: %s",p->cidade);
//printf("\nCelular: %i",p->celular);
//printf("\nE-mail: %s",p->email);
};
}
else printf("\nLista Vazia");
};

main(){


Essa forma de declarar main() é obsoleta. Modernamente, o tipo de retorno implícito int não é mais aceito, obrigando-o a declará-lo explicitamente.

Além disso, como já mencionado anteriormente, uma lista de parâmetros vazias implica que a função poderia eventualmente ser chamada de outras partes do programa com uma quantidade qualquer de argumentos de quaisquer tipos. Entretanto, o padrão do C determina que, para implementações do C em ambientes hospedados (hosted implementations, na qual, grosseiramente falando, significa que existe algo semelhante a um sistema operacional dando suporte ao programa em C, inclusive iniciando sua execução e tomando as medidas necessárias após seu encerramento), main() deve ser declarada uma das seguintes maneiras:

  • int main(void) (i.e. uma lista de parâmetros vazia, que não permite passar argumentos à função), se o seu programa não quiser receber eventuais argumentos do ambiente hospedeiro; ou

  • int main(int agrc, char **argv)[i] (ou a declaração sinônima “[i]int main(int argc, char *argv[])”), caso seu programa queira permitir ao sistema hospedeiro passar-lhe argumentos — nesse caso, tais argumentos serão passados na forma de um vetor de strings, sendo que a quantidade de elementos nesse vetor será passada através do valor de argc (ou outro nome, se você preferir, desde que mantenha o tipo int) e os sucessivos argumentos estarão dispostos, sucessivamente, em argv[0]argv[argc-1], sendo que, por convenção, argv[0] contém o nome usado para invocar o programa, e argv[1]argv[argc-1] contém os argumentos propriamente ditos; além disso, por conveniência, argv[argc]==NULL, e também o nome argv pode ser alterado, desde que você mantenha o tipo correto.

O tipo de retorno int é uma forma do programa informar ao sistema operacional um resultado da execução do programa. Por convenção, um programa que tenha uma execução bem sucedida tipicamente retorna o valor 0, e outros avlores podem indicar diferentes tipos de erros ou condições lógicas que não foram atendidas.

(NOTA: Apesar do tipo de retorno ser int, muitos sistemas, incluindo o Linux, só trabalham com valores não-negativos, na mesma faixa que um unsigned char (tipicamente de 0 a 255), de modo que usar “exit(-1)” ou “return 100000;” (dentro de main()) normalmente não fará com que o sistema operacional recebe -1 ou 100000, mas provavelmente truncamentos de tais valores de modo a caber em um byte sem sinal.)

  setlocale(LC_ALL,"Portuguese");
struct stNo *lista;
int menu;
lista = NULL; // inicializando a lista vazia

do{
system("cls");


Cuidado com essas chamadas a system(), pois, além de deixarem seu programa mais lento (porque recorrem a programas externos para executar ações que afetam o seu programa), elas amarram o seu programa a um ambiente de execução que seja idêntico ao que você está usando. Por exemplo, o comando CLS é uma peculiaridade de sistemas Windows e MS-DOS, não existindo no mundo Linux. Aliás, mesmo na sua própria máquina, alguns comandos que funcionam hoje podem não funcionar amanhã, se alguma condição do ambiente de execução mudar.

No seu caso, você parece usar o comando externo apenas por uma questão estética. Outra chamada semelhante, especialmente para quem programa no Windows, é a infame “system("pause")”. Essas coisas não chegam a ser propriamente erradas, mas certamente não são o principal foco do seu aprendizado.

Por um lado, é interessante que você tenha empregado isso neste programa. Serviu para o alerta de que é negativo em termos de desempenho e de fazer com que o código esteja pronto para ser levado a um sistema diferente do seu, ou mesmo um sistema cujas condições de execução variem ao longo do tempo.

Mas ainda, estética por estética, acho que é melhor, nesta fase de aprendizado de algoritmos, você se preocupar com a estética do programa em si do que com a estética de sua saída — desde, é claro, que a saída também não fique excessivamente avacalhada, a ponto de não se conseguir ler com clareza o resultado.

    printf("\n");
mostraLista(&lista);
printf("\n\n");
printf("[1-Inserir] ");
printf("[2-Visualizar] ");
printf("[3-Excluir] ");
printf("[4-Sair] ");
printf("Opção:");
scanf("%i",&menu);
switch(menu){
case 1 : insereLista(&lista);
break;
case 2 : visualizarLista(&lista);
break;
case 3 : excluirLista(&lista);
break;
case 4 : printf("\nSaindo...");
break;
default: printf("\nCódigo Inválido");
}
printf("\n");system("pause");
}while(menu!=3);
}




... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


3. RE

Robson Nunes
Robson_nunes88

(usa Outra)

Enviado em 01/12/2020 - 19:37h

Muito obrigado pelas dicas Paulo, sabe que grande parte desse código foi o professor que passou para a gente. Você poderia me ajudar em outra duvida??


4. Re: Como faço para colocar a opção excluir em lista simples encadeada em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 02/12/2020 - 03:31h

Pergunte


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


5. RE

Robson Nunes
Robson_nunes88

(usa Outra)

Enviado em 02/12/2020 - 11:54h

Como eu faço para fazer esse código com lista duplamente encadeada que também seja arquivo, A lista deve ser salva em arquivo ao sair e ao entrar ler os registros do arquivo. E como coloco essa opção no Menu visualizar mostrando todos os registros da agenda (um por tela). Muito obrigado pela sua atenção!!


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

struct stNo {
int info;
char nome[50];
int idade;
char sexo;
char endereco[100];
char cidade[40];
char celular[11];
char email[60];
struct stNo *ant,*pos;
};


struct stNo *cria_no() {
struct stNo *p;
if ((p = (struct stNo *) malloc(sizeof(struct stNo))) == NULL)
return NULL;
else
return p;
};

void insereLista(struct stNo **list){
struct stNo *p,*q;
int idade;
char name[60],sex,end[60],city[40],cel[11],mail[60];

fflush(stdin);
printf("\nDigite o nome: ");
gets(name);
fflush(stdin);
printf("\nDigite a idade:");
scanf("%i",&idade);
do{
printf ("\nDigite o sexo F/M:");
fflush(stdin);
sex=getche();
sex=toupper(sex);
}while(sex!='F' && sex!='M');

fflush(stdin);
printf("\n\nDigite o endereco:");
fflush(stdin);
gets(end);
fflush(stdin);
printf("\nDigite a cidade:");
gets(city);
fflush(stdin);
printf("\nDigite o celular:");
gets(cel);
fflush(stdin);
printf("\nDigite o email:");
gets(mail);

if(*list==NULL){
p = cria_no();
*list = p;
p->ant = NULL;
p->pos = NULL;
strcpy(p->nome,name);
p->idade = idade;
p->sexo = sex;
strcpy(p->endereco,end);
strcpy(p->cidade,city);
strcpy(p->celular,cel);
strcpy(p->email,mail);
}
else{
p=*list;
while(p->pos!=NULL)
p=p->pos;
q = cria_no();
p->pos = q;
q->pos = NULL;
strcpy(q->nome,name);
q->idade = idade;
q->sexo = sex;
strcpy(q->endereco,end);
strcpy(q->cidade,city);
strcpy(q->celular,cel);
strcpy(q->email,mail);
};
};

void insereListaInicio(struct stNo **list){
struct stNo *p,*q;
int idade;
char name[60],sex,end[60],city[40],cel[11],mail[60];

printf("\nLista Inicio\n");
fflush(stdin);
printf("\nDigite o nome inicio: ");
gets(name);
fflush(stdin);
printf("\nDigite a idade:");
scanf("%i",&idade);
do{
printf ("\nDigite o sexo F/M:");
fflush(stdin);
sex=getche();
sex=toupper(sex);
}while(sex!='F' && sex!='M');

fflush(stdin);
printf("\n\nDigite o endereco:");
fflush(stdin);
gets(end);
fflush(stdin);
printf("\nDigite a cidade:");
gets(city);
fflush(stdin);
printf("\nDigite o celular:");
gets(cel);
fflush(stdin);
printf("\nDigite o email:");
gets(mail);

if(*list==NULL){
p=cria_no();
*list=p;
strcpy(p->nome,name);
p->idade=idade;
p->sexo=sex;
strcpy(p->endereco,end);
strcpy(p->cidade,city);
strcpy(p->celular,cel);
strcpy(p->email,mail);
p->ant = NULL;
p->pos = (*list);
}
else{
p=*list;
q=cria_no();
strcpy(q->nome,name);
q->idade=idade;
q->sexo=sex;
strcpy(q->endereco,end);
strcpy(q->cidade,city);
strcpy(q->celular,cel);
strcpy(q->email,mail);
q->pos = p;
q->ant = NULL;
(*list)=q;
}
};

void excluirListaInicio(struct stNo **list){
struct stNo *p,*q;
char name[60];

printf("\nExcluir Inicio\n");
printf("\nDigite o primeiro nome da lista para ser excluido: ");
fflush(stdin);
gets(name);


if(*list!=NULL){
p=*list;
if(p->pos==NULL && strcmp(p->nome,name)==0){
free(p);
*list=NULL;
}else{
if(p->pos!=NULL && strcmp(p->nome,name)==0 ){
q=p->pos;
q->ant=NULL;
*list = q;
free(p);

}

}
}else{
printf("\nLista Vazia");
}
};

void alterarLista(struct stNo **list){
struct stNo *p;
char name[60];

printf("\nDigite o nome para pesquisar: ");
fflush(stdin);
gets(name);

if(*list!=NULL){
p=*list;
while(p->pos!=NULL && strcmp(p->nome,name)!=0)
p=p->pos;

if(strcmp(p->nome,name)==0){

fflush(stdin);
printf("\nDigite o nome: ");
gets(p->nome);
fflush(stdin);
printf("\nDigite a idade:");
scanf("%i",&p->idade);
do{
printf ("\nDigite o sexo F/M:");
fflush(stdin);
p->sexo=getche();
p->sexo=toupper(p->sexo);
}while(p->sexo!='F' && p->sexo!='M');

fflush(stdin);
printf("\n\nDigite o endereco:");
fflush(stdin);
gets(p->endereco);
fflush(stdin);
printf("\nDigite a cidade:");
gets(p->cidade);
fflush(stdin);
printf("\nDigite o celular:");
gets(p->celular);
fflush(stdin);
printf("\nDigite o email:");
gets(p->email);

printf("\nCadastro alterado!!!");
}
}
else printf("\nLista Vazia");
};



void mostraLista(struct stNo **list){
struct stNo *p;
if(*list!=NULL){
p=*list;
while(p->pos!=NULL){
printf("\nNome: %s",p->nome);
p = p->pos;
};
printf("\nNome: %s", p->nome);
}
else printf("\nLista Vazia");
};

void visualizarLista(struct stNo **list){
struct stNo *p;
char name[60];

printf("\nDigite o nome: ");//procurar pelo nome
fflush(stdin);
gets(name);


if(*list!=NULL){
p=*list;
while(p->pos!=NULL&&(strcmp(p->nome,name)!=0)){
p = p->pos;
};
if(strcmp(p->nome,name)==0){
printf("\nNome...: %s",p->nome);
printf("\nIdade...: %d",p->idade);
printf("\nSexo...: %c",p->sexo);
printf("\nEndereco...: %s",p->endereco);
printf("\nCidade...: %s",p->cidade);
printf("\nCelular...: %s",p->celular);
printf("\nEmail...: %s",p->email);
};
}
else printf("\nLista Vazia");
};

int main(){
setlocale(LC_ALL,"Portuguese");
struct stNo *lista;
int menu;
lista = NULL;

do{
system("cls");
printf("\n");
mostraLista(&lista);
printf("\n\n");
printf("\n1-Inserir Lista ");
printf("\n2-Inserir Inicio ");
printf("\n3-Visualizar ");
printf("\n4-Alterar ");
printf("\n5-Excluir Inicio ");
printf("\n[6-Sair ");
printf("\nOpção: ");
scanf("%i",&menu);
switch(menu){
case 1 : insereLista(&lista);
break;
case 2 : insereListaInicio(&lista);
break;
case 3 : visualizarLista(&lista);
break;
case 4 : alterarLista(&lista);
break;
case 5 : excluirListaInicio(&lista);
break;
case 6 : printf("\nSaindo...");
break;
default: printf("\nCódigo Inválido");
}
printf("\n");system("pause");
}while(menu!=6);
return 0;
};



6. Re: Como faço para colocar a opção excluir em lista simples encadeada em C

Paulo
paulo1205

(usa Ubuntu)

Enviado em 07/12/2020 - 02:28h

Boa noite, prezado.

Como a pergunta é sobre outro programa, provavelmente teria sido melhor se você tivesse aberto outro tópico, mas tudo bem.

Eis aí um caso que exemplifica o que eu disse sobre separar operações distintas e modularizar o programa. Se em vez de ter, por exemplo, uma só função que faz tanto a entrada de dados do teclado quanto a inserção desses dados na lista você tivesse um função que faz a leitura e retorna os dados lidos e outra que insere dados lidos na lista, seria muito fácil reaproveitar a segunda função para inserir na lista dados que sejam lidos a partir do arquivo.

Em todo caso, a remoção na lista duplamente encadeada é análoga à da simplesmente encadeada, só que com duas cadeias. Se você tem, em ordem, os nós A, B e C, tem A->next==B, B->previous=A, B->next==C e C->prevous==B; remover B implica, primeiro, em fazer A->next=C (lembrando que C==B->next)) e C->previous=A (lembrando que A==B->previous), e depois remover B.

De certa maneira, é até mais fácil do que a lista simplesmente encadeada, pois você só precisa de um ponteiro para rastrear a lista, podendo usá-lo para chegar tanto ao nó anterior quanto ao seguinte, a fim de alterar os respectivos campos. Com a lista simplesmente encadeada, você tinha de ter um segundo ponteiro para conseguir saber o nó anterior, a fim de alterar o campo que aponta para o nós que será removido.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)