Ver Mensaje Individual
  #2 (permalink)  
Antiguo 22/07/2016, 02:37
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Archivos y Listas enlazadas simples en C

Código C:
Ver original
  1. typedef struct ElementoLista{
  2.   Amigo  dato;
  3.   struct Persona *sig; // <<--- AQUI!!!
  4. }Persona;

En este punto, Persona no ha sido declarado, luego el compilador no sabe tratarlo. La solución es esta:

Código C++:
Ver original
  1. typedef struct ElementoLista{
  2.   Amigo  dato;
  3.   struct ElementoLista *sig;
  4. }Persona;

Más cosas:

Código C:
Ver original
  1. Lista *lista;
  2. if ((lista = (Persona *) malloc (sizeof (Persona))) == NULL){

Lista no es lo mismo que Persona. Ese malloc está mal invocado:

Código C:
Ver original
  1. Lista *lista;
  2. if ((lista = (Lista*) malloc (sizeof (Lista ))) == NULL){

Seguimos:

Código C:
Ver original
  1. void mostrarDatos(Lista *l){
  2.   Persona *aux;
  3.   int i=1;
  4.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  5.         return -1; // <<--- AQUI!!!
  6.   }

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 original
  1. if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  2.       return -1;
  3. }
  4. 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 original
  1. void mostrarDatos(Lista *l){
  2.   Persona *aux = l->inicio;
  3.   while (aux){
  4.     mostrarAmigo(aux->dato);
  5.     aux=aux->sig;
  6.   }
  7. }

Nota: Estos dos últimos prolemas se repitne en otras funciones, como estaAmigo.

Revisando, ya puestos, estaAmigo tenemos:

Código C:
Ver original
  1. int estaAmigo(Lista *l,Amigo p){
  2.   int i=1;
  3.   Persona *aux;
  4.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  5.         return -1;
  6.   }
  7.   if(l->cantidad==0){
  8.     return 0;
  9.   }else {
  10.     aux=l->inicio;
  11.     while (i<=l->cantidad){
  12.     // ...

Que aplicando los cambios anteriores queda así (una forma de hacerlo):

Código C:
Ver original
  1. int estaAmigo(Lista *l,Amigo p){
  2.   int existe = 0;
  3.   for(Persona *aux=l->inicio; aux && !existe; aux=aux->sig)
  4.   {
  5.     existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
  6.     existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
  7.     existe &= (strcmpi(aux->dato.email,p.email)==0);
  8.     existe &= (strcmpi(aux->dato.celular,p.celular)==0);
  9.     existe &= (aux->dato.fecNac.anio==p.fecNac.anio);
  10.     existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
  11.     existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
  12.   }
  13.  
  14.   return existe;
  15. }

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 original
  1. int insEnListaVacia (Lista *l,Amigo p){
  2.   Persona *aux;
  3.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  4.         return -1;
  5.   }
  6.   aux->dato=p;
  7.   aux->sig=NULL;
  8.   l->inicio=aux;
  9.   l->fin=aux;
  10.   l->cantidad++;
  11. }
  12.  
  13.  
  14. int insInicioLista (Lista *l,Amigo p){
  15.   Persona *aux;
  16.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  17.         return -1;
  18.   }
  19.   aux->dato=p;
  20.   aux->sig=l->inicio;
  21.   l->inicio=aux;
  22.   l->cantidad++;
  23. }

¿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
  1. // Nota que a la función le da igual que haya o no elementos en la lista.
  2. int insertarInicio(Lista*l, Amigo p)
  3. {
  4.   int toReturn = 0; // 0 = error
  5.  
  6.   Persona *aux = (Persona *) malloc (sizeof (Persona)));
  7.   if ((aux != NULL)
  8.   {
  9.     aux->dato=p;
  10.     aux->sig=l->inicio;
  11.     l->inicio=aux;
  12.     l->cantidad++;
  13.  
  14.     // Por si acaso la lista está vacía
  15.     if( !l->fin ) l->fin = aux;
  16.  
  17.     toReturn = 1; // 1 = ok
  18.   }
  19.  
  20.   return toReturn;
  21. }

Y bueno, referente a esta función:

Código C:
Ver original
  1. void inicializacion (Lista *l){
  2.   l->fin=NULL;
  3.   l->inicio=NULL;
  4.   l->cantidad=0;
  5. }

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 original
  1. int main(){
  2.   Lista *lista;
  3.   if ((lista = (Lista *) calloc (1,sizeof(Lista))) == NULL){
  4.         return -1;
  5.   }
  6.  
  7.   // Ahora esto sobra
  8.   //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.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.