Código C:
Ver originaltypedef struct ElementoLista{
Amigo dato;
struct Persona *sig; // <<--- AQUI!!!
}Persona;
En este punto,
Persona no ha sido declarado, luego el compilador no sabe tratarlo. La solución es esta:
Código C++:
Ver originaltypedef struct ElementoLista{
Amigo dato;
struct ElementoLista *sig;
}Persona;
Más cosas:
Código C:
Ver originalLista *lista;
if ((lista
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){
Lista no es lo mismo que
Persona. Ese malloc está mal invocado:
Código C:
Ver originalLista *lista;
if ((lista
= (Lista
*) malloc (sizeof (Lista
))) == NULL
){
Seguimos:
Código C:
Ver originalvoid mostrarDatos(Lista *l){
Persona *aux;
int i=1;
if ((aux
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){ return -1; // <<--- AQUI!!!
}
Si la función es void, es decir, no retorna nada... ¿por qué pones "return -1"?.
Por otro lado, si seguimos revisando esa función nos encontramos con lo siguiente:
Código C:
Ver originalif ((aux
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){ return -1;
}
aux=l->inicio;
Es decir, reservas memoria para
aux y seguidamente haces una asignación en
aux, por lo que pierdes la reserva que acabas de hacer. Si
aux lo usas para iterar sobre la lista no hace falta que hagas ninguna reserva, ya que su única función es apuntar a posiciones de memoria de
l, posiciones de memoria que dicho sea de paso ya existen.
Por otro lado se supone que el último elemento de una lista enlazada ha de ser un puntero nulo. Por este motivo no es necesario usar la variable
i. Simplemente basta con iterar hasta que
aux sea
NULL. Algo así:
Código C:
Ver originalvoid mostrarDatos(Lista *l){
Persona *aux = l->inicio;
while (aux){
mostrarAmigo(aux->dato);
aux=aux->sig;
}
}
Nota: Estos dos últimos prolemas se repitne en otras funciones, como
estaAmigo.
Revisando, ya puestos,
estaAmigo tenemos:
Código C:
Ver originalint estaAmigo(Lista *l,Amigo p){
int i=1;
Persona *aux;
if ((aux
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){ return -1;
}
if(l->cantidad==0){
return 0;
}else {
aux=l->inicio;
while (i<=l->cantidad){
// ...
Que aplicando los cambios anteriores queda así (una forma de hacerlo):
Código C:
Ver originalint estaAmigo(Lista *l,Amigo p){
int existe = 0;
for(Persona *aux=l->inicio; aux && !existe; aux=aux->sig)
{
existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
existe &= (strcmpi(aux->dato.email,p.email)==0);
existe &= (strcmpi(aux->dato.celular,p.celular)==0);
existe &= (aux->dato.fecNac.anio==p.fecNac.anio);
existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
}
return existe;
}
Entre otras cosas, la función
estaAmigo se entiende que debería devolver 0 o 1, ya que el elemento o está o no está... no tiene sentido que retornes -1 o cosas raras.
Más detalles:
Código C:
Ver originalint insEnListaVacia (Lista *l,Amigo p){
Persona *aux;
if ((aux
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){ return -1;
}
aux->dato=p;
aux->sig=NULL;
l->inicio=aux;
l->fin=aux;
l->cantidad++;
}
int insInicioLista (Lista *l,Amigo p){
Persona *aux;
if ((aux
= (Persona
*) malloc (sizeof (Persona
))) == NULL
){ return -1;
}
aux->dato=p;
aux->sig=l->inicio;
l->inicio=aux;
l->cantidad++;
}
¿Por qué dos funciones individuales que hacen prácticamente lo mismo? ¿Por qué si tienen como valor de retorno un
int no hay ningún
return si todo ha ido bien? Realmente las dos funciones hacen exactamente lo mismo aunque no lo parezca. La más genérica es la segunda (si la lista está vacía, entonces
l->inicio va a ser
NULL:
Código C:
Ver original// Nota que a la función le da igual que haya o no elementos en la lista.
int insertarInicio(Lista*l, Amigo p)
{
int toReturn = 0; // 0 = error
Persona
*aux
= (Persona
*) malloc (sizeof (Persona
))); if ((aux != NULL)
{
aux->dato=p;
aux->sig=l->inicio;
l->inicio=aux;
l->cantidad++;
// Por si acaso la lista está vacía
if( !l->fin ) l->fin = aux;
toReturn = 1; // 1 = ok
}
return toReturn;
}
Y bueno, referente a esta función:
Código C:
Ver originalvoid inicializacion (Lista *l){
l->fin=NULL;
l->inicio=NULL;
l->cantidad=0;
}
Decirte que sobra si pasas a crear la lista con
calloc en vez de con
malloc.
calloc setea todos los valores de la memoria reservada a cero, lo cual es ideal para incializar estructuras con punteros y cadenas. También puedes usar
memset para inicializar una región de memoria cualquiera. La ventaja de cualquiera de estas dos alternativas es que si, por ejemplo, modificas la estructura para añadir o quitar elementos las funciones se adaptarán al nuevo tamaño sin tener que tocar código:
Código C:
Ver originalint main(){
Lista *lista;
if ((lista
= (Lista
*) calloc (1,sizeof(Lista
))) == NULL
){ return -1;
}
// Ahora esto sobra
//inicializacion(lista);
Y bueno, para rematar comentarte que hay que tener especial cuidado con la memoria dinámica... cada
malloc /
calloc ha de tener su correspondiente
free para liberar la memoria correspondiente y en tu código las llamadas a
free brillan por su ausencia.
Un saludo.