Eliminar nodo en lista enlazada: problema con el último nodo [C]

Iniciado por Rhessus, 19 Julio 2016, 21:30 PM

0 Miembros y 1 Visitante están viendo este tema.

Rhessus

Hola a todos.
A punto de terminar la bendita agenda de contactos, me encuentro con el problema que espero sea el último de esta magnitud: mi programa devuelve un error (violación de segmento) después de eliminar el último nodo.
Les comparto el código pertinente:

Código (bash) [Seleccionar]


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

#define N 30 //cantidad de caracteres para las cadenas

typedef struct contact {

char name[N];
char number[N];
char mail[N];
char address[N];
struct contact *next;

} Contact;

/***************************************************************************************************************************/

Contact *head = NULL;
Contact *tail = NULL;

/***************************************************************************************************************************/

void eliminarContactoNombre(){

        Contact *aux = head;
int i = 0;
char nom[N];
int opcion;

imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

printf("Ingrese el nombre del contacto que desea eliminar: ");
scanf("%s", nom);

printf("\n");
imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

while(aux != NULL){
if(strcmp(aux->name, nom) == 0){ //si el nombre del contacto coincide con el nombre ingresado
i++; //el contador suma uno
printf("¿Está seguro de querer eliminar a '%s' de la agenda?\n", nom);
printf("1. Sí\n");
printf("2. No\n");

imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

scanf("%d", &opcion);

switch(opcion) {

case 1:
eliminarContactoNombreLista(nom); //funcion que borra el contacto y ordena la lista para que el anterior apunte al siguiente del nodo eliminado
break;
case 2:
main();
break;
default:
break;
}

if(opcion == 1){
imprimirSeparador(); //imprime una linea y un enter para ordenar el texto
printf("El contacto '%s' ha sido borrado de la agenda\n", nom);
}
break;
}

else{      //en caso de que el nombre del contacto no coincida con el ingresado
aux = aux->next;   //pasa al siguiente contacto
}
}

if(i == 0){ //si no se encontro´ ningun contacto con el nombre ingresado, el contador es igual a 0
printf("No existe ningún contacto con el nombre '%s'\n", nom);
}

}

/***************************************************************************************************************************/

void eliminarContactoNombreLista(char nom[]){

Contact *aux_borrar;
Contact *anterior = NULL;

aux_borrar = head;

while(aux_borrar != NULL && strcmp(aux_borrar->name, nom) != 0){ //
anterior = aux_borrar;
aux_borrar = aux_borrar->next;
}
if(anterior == NULL){
head = head->next;
free(aux_borrar);
}
else{
anterior->next = aux_borrar->next;
free(aux_borrar);
}
}


Espero puedan ayudarme. Muchas gracias.
Saludos. Nahuel.

AlbertoBSD

La funcion eliminar que tienes esta muy simple faltan muchas comprobaciones.

por ejemplo liberas aux_borrar sin comprobar si es NULL.

Ademas si es el ultimo ten en cuenta que ya no hay next

aux_borrar->next;

Es valor es NULL y si realizas operaciones con el head y este es null claramente sera una violacion de segmento.

En mi canal tengo un video donde me toma un buen de tiempo eliminar un nodo.

[youtube=640,360]https://www.youtube.com/watch?v=FqKsZzM0uEU[/youtube]

Saludos
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

Rhessus

Excelente video, Alberto. Con tu ejemplo pude darme cuenta lo que me faltaba.
Muchísimas gracias!