¡De nada!
Todo el mundo tiene algun patinazo de vez en cuando, servidor incluido
, faltaria mas.
¡Saludos!
			Todo el mundo tiene algun patinazo de vez en cuando, servidor incluido
, faltaria mas.¡Saludos!
Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.
Mostrar Mensajes Menú
, faltaria mas.
 por el!
int (*cmp)(void*,void*) Esta funcion la ha de aportar el usuario del codigo. Es un funcion para poder comparar los valores clave. He aqui algunos ejemplos:
int incmp(void* a,void* b)
{
    return *((int*)a) - *((int*)b;
}
int stringcmp(void* s1, void* s2)
{
    return strcmp((char*)s1,(char*)s2);
}
int fechacmp(void* f1,void* f2)
{
    if(((Fecha*)f1)->año > ((Fecha*)f2)->año)
        return 1; /* la primera fecha es mayor*/
    if(((Fecha*)f1)->año < ((Fecha*)f1)->año)
        return -1; /* la primera fecha es menor*/
    /* ... */
}
struct Tonteria
{
    int x;
    float y;
    char a;
};
#include "ADTlist.h"
#include "ADTlist.c" /* solo si no se va crear un proyecto */
struct Tonteria
{
    int x;
    float y;
    char a;
};
typedef struct Tonteria Tonteria;
int tonteriacmp(void* t1,void* t2);
int intcmp(void* a,void* b);
int main(int argc, char* argv[])
{
    Tonteria unaTonteria;
    ADTList *listaTonta=NULL, *listaInt=NULL;
    int entero=5;
    Tonteria.x = 7;
    ADTListInsert(&listaTonta, &unaTonteria, &unaTonteria.x, sizeof(Tonteria), tonteriacmp);
    ADTListInsert(&listaInt, &entero, &entero, sizeof(int), intcmp);
    return 0;
}
int tonteriacmp(void* t1,void* t2)
{
    return ((Tonteria*)t1)->x - ((Tonteria*)t2)->x;
}
int intcmp(void* a,void* b)
{
    return *((int*)a) - *((int*)b);
}
#ifndef ADT_STACK_H
#define ADT_STACK_H
#include <stdlib.h>
#include <string.h>
#ifndef ADT_STACK_FLAGS
#define ADT_STACK_FLAGS
    #define ADT_STACK_OK                0L
    #define ADT_STACK_NOT_ENOUGH_MEMORY 1L
    #define ADT_STACK_EMPTY_STACK       2L
#endif /* ADT_STACK_FLAGS */
struct ADTStackNode
{
    void *Data; /* guarda la informacion de los datos que maneja la pila */
    struct ADTStackNode *Next; /* apunta al siguiente elemento de la pila */
};
typedef struct ADTStackNode ADTStackNode;
typedef ADTStackNode* pADTStackNode;
typedef pADTStackNode ADTStack;
/* funcion para inicializar un nodo completamente a cero*/
void ADTStackNodeIni(pADTStackNode pNode);
/* Comprueba si top == NULL, equivalentemente, si la pila esta vacia */
int ADTStackIsEmpty(pADTStackNode top);
/* Guarda un valor en la pila. size == sizeof el tipo de dato al que apunta data. */
unsigned long ADTStackPush(pADTStackNode* top,void* data,size_t size);
/* Saca un valor de la pila y lo pone en data. size==sizeof el tipo de dato al que apunta data */
unsigned long ADTStackPop(pADTStackNode* top,void* data,size_t size);
#endif /* ADT_STACK_H */
#include "ADTstack.h"
void ADTStackNodeIni(pADTStackNode pNode)
{
    /* inicializamos a cero la variable */
    memset(pNode,0,sizeof(ADTStackNode));
}
int ADTStackIsEmpty(pADTStackNode top)
{
    return top==NULL;
}
unsigned long ADTStackPush(pADTStackNode* top,void* data,size_t size)
{
    pADTStackNode newNode=NULL; /* puntero al nodo que guardara la nueva informacion */
    /* intentamos asignar un nuevo nodo */
    if(!(newNode = (ADTStackNode *)malloc(sizeof(ADTStackNode))))
        return ADT_STACK_NOT_ENOUGH_MEMORY; /* si no se puede enviamos un aviso */
    /* inicalizamos el nuevo nodo */
    ADTStackNodeIni(newNode);
    /* intentamos asignar memoria para almacenar los datos que haya que introducir en la pila */
    if(!(newNode->Data = malloc(size)))
    {
        /* si no se puede asignar la memoria */
        free(newNode); /* liberamos la memoria anteriormente asignada */
        return ADT_STACK_NOT_ENOUGH_MEMORY; /* y devolvemos un aviso */
    }
    /* copiamos la informacion en el nuevo nodo */
    memcpy(newNode->Data , data , size);
    /* y hacemos que el nuevo nodo sea el superior de la pila */
    newNode->Next = (*top); /* pasando el nodo superior a ser el segundo */
    (*top) = newNode; /* y asignando el puntero superior al nuevo nodo*/
    return ADT_STACK_OK; /* todo correcto */
}
unsigned long ADTStackPop(pADTStackNode* top,void* data,size_t size)
{
    ADTStackNode *aux; /* para saber donde esta el segundo nodo una vez borrado el primero */
    /* no se podra sacar nada de una pila vacia */
    if((*top) == NULL)
        return ADT_STACK_EMPTY_STACK;
    /* apuntamos donde esta el segundo nodo */
    aux = (*top)->Next;
    /* copiamos el valor que sera borrado en data */
    memcpy(data , (*top)->Data , size);
    /* eliminamos la informacion contenida en el primer nodo */
    free((*top)->Data);
    /* liberamos el primer nodo */
    free(*top);
    /* y hacemos que el segundo nodo pase a ser el primero */
    (*top) = aux;
    return ADT_STACK_OK; /* todo correcto */
}
#include <stdio.h>
#include "ADTstack.h"
struct Tonteria
{
    char c;
    int x;
    float y;
};
typedef struct Tonteria Tonteria;
void mostrarTonteria(Tonteria *t);
int main()
{
    ADTStackNode *pilaTonta=NULL;
    Tonteria tontada;
    int i;
    printf("PUSH\n");
    printf("====\n");
    for(i=0 ; i < 10 ; i++)
    {
        tontada.c = rand() % (255 - 32) + 32; /* generamos un caracter imprimible */
        tontada.x = rand() % 100; /* 0 - 99 */
        tontada.y = tontada.x / 10.; /* 0 - 9'9 */
        /* mostramos la informacion */
        mostrarTonteria(&tontada);
        /* y la guardamos en la pila */
        ADTStackPush(&pilaTonta , &tontada , sizeof(Tonteria));
    }
    printf("\n");
    printf("Pulsar intro...");
    getchar();
    printf("\n");
    printf("POP\n");
    printf("===\n");
    while(!ADTStackIsEmpty(pilaTonta))
    {
        /* extraemos el valor superior, que sera almacenado en tontada */
        ADTStackPop(&pilaTonta , &tontada , sizeof(Tonteria));
        /* y lo mostramos para comprobar que los valores se invierten y que la pila funciona */
        mostrarTonteria(&tontada);
    }
    printf("\n");
    printf("Pulsar intro...");
    getchar();
    printf("\n");
    return 0;
}
void mostrarTonteria(Tonteria *t)
{
    printf("[%c , %02d , %3.1f]\n", t->c , t->x , t->y);
}
#ifndef ADT_QUEUE_H
#define ADT_QUEUE_H
#include <stdlib.h>
#include <string.h>
#ifndef ADT_QUEUE_FLAGS
#define ADT_QUEUE_FLAGS
    #define ADT_QUEUE_OK                0L
    #define ADT_QUEUE_NOT_ENOUGH_MEMORY 1L
    #define ADT_QUEUE_EMPTY_QUEUE       2L
#endif /* ADT_QUEUE_FLAGS */
struct ADTQueueNode
{
    void *Data;
    struct ADTQueueNode *First;
    struct ADTQueueNode *Last;
    struct ADTQueueNode *Next;
};
typedef struct ADTQueueNode ADTQueueNode;
typedef ADTQueueNode ADTQueue;
typedef ADTQueueNode* pADTQueueNode;
/* funcion para inicializar un nodo completamente a cero*/
void ADTQueueNodeIni(pADTQueueNode pNode);
/* Comprueba si la cola esta vacia */
int ADTQueueIsEmpty(pADTQueueNode queue);
/* Guarda un valor en la cabeza de la cola. size == sizeof el tipo de dato al que apunta data. */
unsigned long ADTQueueEnqueue(pADTQueueNode *first,pADTQueueNode *last,void* data,size_t size);
/* Saca un valor de la cola de la cola :P y lo pone en data. */
unsigned long ADTQueueDequeue(pADTQueueNode *first,pADTQueueNode *last,void* data,size_t size);
#endif /* ADT_QUEUE_H */
#include "ADTqueue.h"
void ADTQueueNodeIni(pADTQueueNode pNode)
{
    /* ponemos la variable a cero */
    memset(pNode,0,sizeof(ADTQueueNode));
}
int ADTQueueIsEmpty(pADTQueueNode queue)
{
    /* comprobamos si hay datos o no en la cabeza de la cola */
    return queue->First == NULL;
}
unsigned long ADTQueueEnqueue(pADTQueueNode *first,pADTQueueNode *last,void* data,size_t size)
{
    ADTQueueNode *newNode; /* puntero a un nuevo nodo de la cola */
    /* si no podemos asignar memoria para el nuevo nodo */
    if(!(newNode = (ADTQueueNode *) malloc(sizeof(ADTQueueNode))))
        return ADT_QUEUE_NOT_ENOUGH_MEMORY; /* damos el aviso */
    /* inicializamos el nuevo nodo */
    ADTQueueNodeIni(newNode);
    /* si no podemos asignar espacio para que el nuevo nodo contenga datos */
    if(!(newNode->Data = malloc(size)))
    {
        free(newNode); /* eliminamos el espacio que ocupa el nodo */
        return ADT_QUEUE_NOT_ENOUGH_MEMORY; /* y damos el aviso */
    }
    /* copiamos la informacion en el nuevo nodo */
    memcpy(newNode->Data , data , size);
    /* si la lista esta vacia */
    if(!(*first))
        (*first) = newNode; /* la cabeza de la cola apunta al nuevo elemento */
    else /* sino */
        (*last)->Next = newNode; /* añadimos el nuevo elemento al final de la cola */
    (*last) = newNode; /* y el nuevo nodo pasa a ser el ultimo de la cola */
    return ADT_QUEUE_OK;
}
unsigned long ADTQueueDequeue(pADTQueueNode *first,pADTQueueNode *last,void* data,size_t size)
{
    ADTQueueNode* aux; /* puntero para no perder de vista el segundo elemento de la cola */
    /* si la cola esta vacia */
    if(!(*first))
        return ADT_QUEUE_EMPTY_QUEUE; /* avisamos de ello */
    /* guardamos la posicion del segundo elemento */
    aux = (*first)->Next;
    /* recuperamos los datos del primer elemento */
    memcpy(data , (*first)->Data , size);
    /* liberamos la informacion y el espacio del primer elemento */
    free((*first)->Data);
    free(*first);
    /* y hacemos que el segundo elemento pase a la cabeza de la cola */
    (*first) = aux;
    /* si no hay mas elementos */
    if(!(*first))
        (*last) = NULL; /* marcamos el ultimo tambien a NUlL */
    return ADT_QUEUE_OK; /* todo correcto */
}
#include <stdio.h>
#include "ADTqueue.h"
struct Tonteria
{
    char c;
    int x;
    float y;
};
typedef struct Tonteria Tonteria;
void mostrarTonteria(Tonteria *t);
int main()
{
    ADTQueueNode colaTonta;
    Tonteria tontada;
    int i;
    /* inicializamos de forma correcta el nodo inicial */
    ADTQueueNodeIni(&colaTonta);
    printf("ENQUEUE\n");
    printf("=======\n");
    for(i=0 ; i < 10 ; i++)
    {
        tontada.c = rand() % (255 - 32) + 32; /* generamos un caracter imprimible */
        tontada.x = rand() % 100; /* 0 - 99 */
        tontada.y = tontada.x / 10.; /* 0 - 9'9 */
        /* mostramos la informacion */
        mostrarTonteria(&tontada);
        /* y la guardamos en la cola */
        ADTQueueEnqueue(&colaTonta.First , &colaTonta.Last, &tontada , sizeof(Tonteria));
    }
    printf("\n");
    printf("Pulsar intro...");
    getchar();
    printf("\n");
    printf("\n");
    printf("DEQUEUE\n");
    printf("=======\n");
    /* mientras queden elementos en la cola */
    while(!ADTQueueIsEmpty(&colaTonta))
    {
        /* extraemos el valor superior, que sera almacenado en tontada */
        ADTQueueDequeue(&colaTonta.First , &colaTonta.Last, &tontada , sizeof(Tonteria));
        /* y lo mostramos para comprobar que los valores salen en orden y que la cola funciona */
        mostrarTonteria(&tontada);
    }
    printf("\n");
    printf("Pulsar intro...");
    getchar();
    printf("\n");
    return 0;
}
void mostrarTonteria(Tonteria *t)
{
    printf("[%c , %02d , %3.1f]\n", t->c , t->x , t->y);
}
#ifndef ADT_LIST_H
#define ADT_LIST_H
#include <stdlib.h>
#include <string.h>
#include "ADTqueue.h"
#ifndef ADT_LIST_FLAGS
#define ADT_LIST_FLAGS
    #define ADT_LIST_OK                0L
    #define ADT_LIST_NOT_ENOUGH_MEMORY 1L
    #define ADT_LIST_EMPTY_LIST        2L
    #define ADT_LIST_ITEM_NOT_FOUND    4L
#endif /* ADT_LIST_FLAGS */
struct ADTListNode
{
    void *Data;
    struct ADTListNode *Next;
};
typedef struct ADTListNode ADTListNode;
typedef struct ADTListNode ADTList;
typedef struct ADTListNode* pADTListNode;
/* inicializamos la estructura para futuros usos */
void ADTListNodeIni(pADTListNode pNode);
/* comprueba si la lista esta vacia */
int ADTListIsEmpty(pADTListNode List);
/* inserta un nuevo item en la lista */
unsigned long
ADTListInsert(pADTListNode *List, void *data, void *key, size_t size, int (*cmp)(void*,void*));
/* elimina un item de la lista */
unsigned long
ADTListDelete(pADTListNode *List, void *data, void *key, size_t size, int (*cmp)(void*,void*));
/* busqueda de items en la lista */
void* ADTListSearch(pADTListNode *List, void *data, void *key, int (*cmp)(void*,void*));
/* libera la memoria ocupada por la lista y la pasa a una cola, que es mas facil de liberar */
unsigned long ADTListDestroy(pADTListNode *List, size_t dataSize , ADTQueueNode *pQueue);
/* retorna el primer elemento de la lista (facilita la liberacion de la memoria) */
unsigned long
ADTListFirst(pADTListNode *List, void *data, size_t size);
#endif /* ADT_LIST_H */
#include "ADTlist.h"
void ADTListNodeIni(pADTListNode pNode)
{
    /* inicializamos los datos a cero */
    memset(pNode,0,sizeof(ADTListNode));
}
int ADTListIsEmpty(pADTListNode List)
{
    /* ¬¬ */
    return List==NULL;
}
unsigned long
ADTListInsert(pADTListNode *List, void *data, void *key, size_t size, int (*cmp)(void*,void*))
{
    /* punteros para no perdes la pista al nodo anterior y siguiente de la busqueda de la posicion
    del nuevo elemento, y el ultimo puntero sirve para asignar la memoria del nuevo dato */
    ADTListNode *previous,*current,*newNode;
    /* intentamos asignar memoria para el nuevo nodo */
    if(!(newNode = (ADTListNode*) malloc(sizeof(ADTListNode))))
        return ADT_LIST_NOT_ENOUGH_MEMORY; /* si no se puede damos el aviso */
    /* inicializamos el nuevo nodo */
    ADTListNodeIni(newNode);
    /* si no se puede asignar memoria para el nuevo dato */
    if(!(newNode->Data = malloc(size)))
    {
        free(newNode); /* liberamos la memoria del nodo */
        return ADT_LIST_NOT_ENOUGH_MEMORY; /* y avisamos de lo sucedido */
    }
    /* copiamos al nuevo nodo los datos que se quieren guardar */
    memcpy(newNode->Data , data , size);
    /* inicalizamos los punteros auxiliares */
    previous = NULL;
    current = (*List);
    /* mientras no se haya alcalzado el final de la lista y la comparacion del nuevo elemento con
    el actual sea mayor (se insertaran por orden creciente de valores de comparacion) */
    while(current && cmp(key , (char*)(current->Data) + ((char*)key - (char*)data))>0)
    {
        previous = current; /* el puntero actual pasa a ser el anterior */
        current = current->Next; /* el puntero siguiente al actual pasa a ser el actual */
    }
    /* si no hay elemento anterior, no se ha realizado ninguna iteracio, por lo que el nuevo
    elemento debe ser el primero de la lista*/
    if(!previous)
    {
        newNode->Next = (*List);
        (*List) = newNode;
    }
    else /* si existe un nodo anterior */
    {
        /* el nuevo valor tiene que intercalarse entre el anterior y el actual */
        previous->Next = newNode;
        newNode->Next = current;
    }
    return ADT_LIST_OK; /* todo correcto */
}
unsigned long
ADTListDelete(pADTListNode *List, void *data, void *key, size_t size, int (*cmp)(void*,void*))
{
    /* punteros auxiliares para controlar la posicion del nodo que debe ser borrado */
    ADTListNode *previous,*current;
    /* no se puede eliminar nada de una lista vacia */
    if(!(*List))
        return ADT_LIST_EMPTY_LIST;
    /* iniciazliamos los punteros auxiliares */
    previous = NULL;
    current = (*List);
    /* mientras no se haya alcalzado el final de la lista y la comparacion del nuevo elemento con
    el actual sea mayor (los elementos estan insertados por orden creciente) */
    while(current && cmp(key ,(char*)(current->Data) + ((char*)key - (char*)data))>0)
    {
        previous = current; /* anterior = actual */
        current = current->Next; /* el siguiente al actual pasa a ser el nuevo actual */
    }
    /* si se ha alcanzado el final de la lista */
    if(!current)
        return ADT_LIST_ITEM_NOT_FOUND; /* significa que el elemento no existe */
    /* si la comparacion no es igual */
    if(cmp(key ,(char*)(current->Data) + ((char*)key - (char*)data)))
        return ADT_LIST_ITEM_NOT_FOUND; /* el elemento no existe */
    /* copiamos la informacion contenida antes de borrar el nodo */
    memcpy(data , current->Data , size);
    /* si no hay anterior*/
    if(!previous)
        (*List) = (*List)->Next; /* hay que eliminar el primer nodo */
    else /* sino */
        previous->Next = current->Next /* el anterior salta al actual */;
    /* liberamos los datos del nodo y el propio nodo */
    free(current->Data);
    free(current);
    return ADT_LIST_OK; /* todo correcto */
}
void* ADTListSearch(pADTListNode *List, void *data, void *key, int (*cmp)(void*,void*))
{
    /* puntero auxiliar para recorrer la lista */
    ADTListNode *current;
    current = (*List);
    /* mientras no se haya alcalzado el final de la lista y la comparacion del nuevo elemento con
    el actual sea mayor (se insertaran por orden creciente de valores de comparacion) */
    while(current && cmp(key ,(char*)(current->Data) + ((char*)key - (char*)data))>0)
        current = current->Next;
    /* si se ha alcanzado el final de la lista */
    if(!current)
        return NULL; /* no se ha encontrado el elemento y se devuelve NULL */
    /* si el elemento actual es mayor que el buscado, el elemento buscado no existe */
    if(cmp(key ,(char*)(current->Data) + ((char*)key - (char*)data)))
        return NULL;
    /* retornamos un puntero al valor encontrado */
    return current->Data;
}
unsigned long ADTListDestroy(pADTListNode *List, size_t dataSize , ADTQueueNode *pQueue)
{
    unsigned long ret;
    /* lista vacia o final de la lista */
    if(!(*List))
        return ADT_LIST_EMPTY_LIST; /* avisamos */
    /* almacenamos el valor de retorno para ver que ha sucedido al eliminar el resto de nodos */
    ret = ADTListDestroy(&((*List)->Next) , dataSize , pQueue);
    /* los unicos valores que retorna la funcion de forma directa son ADT_LIST_EMMPTY_LIST, que
       indica que se ha llegado al final de la lista, o ADT_LIST_OK, que indica que de momento no
       ha ocurrido ningun error. Ambos valores son indicativos de que no hay errores.
       Si ADTQueueEnqueue retorna ADT_QUEUE_OK, este valor es igual a ADT_LIST_OK por definicion
       El resto de los valores que puede retornar provienen de algun posible error a la hora de
       manipular la cola que almacenara los datos de la lista
    */
    if(ret == ADT_LIST_EMPTY_LIST || ret == ADT_LIST_OK)
    {
        /* en este punto no ha habido ningun error */
        /* intentamos almacenar el siguiente valor en la cola */
        if(!(ret = ADTQueueEnqueue(&(pQueue->First), &(pQueue->Last), (*List)->Data, dataSize)))
        {
            /* se ha podido insertar el valor en la cola */
            /* liberamos la informacion contenida en el nodo actual y el propio nodo */
            free((*List)->Data);
            free((*List));
            return ADT_LIST_OK; /* y avisamos de que todo va bien */
        }
    }
    /* si se llega a este punto, ha habido algun error */
    return ret; /* avisamos del error ocurrido */
}
unsigned long
ADTListFirst(pADTListNode *List, void *data, size_t size)
{
    /* no hay primer elemento en una lista vacia */
    if(!(*List))
        return ADT_LIST_EMPTY_LIST;
    /* copiamos la informacion del primer elemento */
    memcpy(data , (*List)->Data , size);
    return ADT_LIST_OK; /* todo correcto */
}
#include <stdio.h>
#include "ADTlist.h"
struct Tonteria
{
    char c;
    int x;
    float y;
};
typedef struct Tonteria Tonteria;
int intcmp(void *a,void *b);
void mostrarTonteria(Tonteria *t);
int main()
{
    ADTListNode *listaTonta=NULL;
    Tonteria tontada , *pTonto;
    int i;
    printf("INSERCION\n");
    printf("=========\n");
    for(i=0 ; i < 10 ; i++)
    {
        tontada.c = rand() % (255 - 32) + 32; /* generamos un caracter imprimible */
        tontada.x = rand() % 100; /* 0 - 99 */
        tontada.y = tontada.x / 10.; /* 0 - 9'9 */
        /* mostramos la informacion */
        mostrarTonteria(&tontada);
        /* y la guardamos en la lista ordenando los elementos por el valor x */
        ADTListInsert(&listaTonta , &tontada , &tontada.x , sizeof(Tonteria) , intcmp);
    }
    printf("\n");
    getchar();
    printf("BUSQUEDA\n");
    printf("========\n");
    /* aunque no se retorne ningun valor en tontada, es necesario pasar el puntero para que la
    funcion puede calcular el desplazamiento que tiene el campo clave dentro del struct */
    if((pTonto = (Tonteria*) ADTListSearch(&listaTonta , &tontada , &tontada.x , intcmp)))
    {
        printf("%d se encuentra en la lista.\n",pTonto->x);
    }
    else
    {
        printf("%d no se encuentra en la lista.\n",tontada.x);
    }
    tontada.x = 5;
    if((pTonto = (Tonteria*) ADTListSearch(&listaTonta , &tontada , &tontada.x , intcmp)))
    {
        printf("%d se encuentra en la lista.\n",pTonto->x);
    }
    else
    {
        printf("%d no se encuentra en la lista.\n",tontada.x);
    }
    tontada.x = 27;
    if((pTonto = (Tonteria*) ADTListSearch(&listaTonta , &tontada , &tontada.x , intcmp)))
    {
        printf("%d se encuentra en la lista.\n",pTonto->x);
    }
    else
    {
        printf("%d no se encuentra en la lista.\n",tontada.x);
    }
    printf("\n");
    getchar();
    printf("ELIMINAR DATO\n");
    printf("=============\n");
    tontada.x = 27;
    ADTListDelete(&listaTonta , &tontada , &tontada.x , sizeof(Tonteria) , intcmp);
    if((pTonto = (Tonteria*) ADTListSearch(&listaTonta , &tontada , &tontada.x , intcmp)))
    {
        printf("%d se encuentra en la lista.\n",pTonto->x);
    }
    else
    {
        printf("%d no se encuentra en la lista.\n",tontada.x);
    }
    printf("\n");
    getchar();
    printf("VACIADO\n");
    printf("=======\n");
    while(!ADTListIsEmpty(listaTonta))
    {
        ADTListFirst(&listaTonta , &tontada , sizeof(Tonteria));
        ADTListDelete(&listaTonta , &tontada , &tontada.x ,sizeof(Tonteria) , intcmp);
        printf("Eliminado: ");
        mostrarTonteria(&tontada);
    }
    getchar();
    return 0;
}
int intcmp(void *a,void *b)
{
    return *((int*)a) - *((int*)b);
}
void mostrarTonteria(Tonteria *t)
{
    printf("[%c , %02d , %3.1f]\n", t->c , t->x , t->y);
}
#ifndef ADT_BINTREE_H
#define ADT_BINTREE_H
#include <stdlib.h>
#include <string.h>
#include "ADTqueue.h"
#ifndef ADT_BINTREE_FLAGS
#define ADT_BINTREE_FLAGS
    #define ADT_BINTREE_OK                0L
    #define ADT_BINTREE_NOT_ENOUGH_MEMORY 1L
    #define ADT_BINTREE_EMPTY_BINTREE     2L
    #define ADT_BINTREE_ITEM_NOT_FOUND    4L
    #define ADT_BINTREE_DUPLICATED_ITEM   8L
#endif /* ADT_BINTREE_FLAGS */
struct ADTBinTreeNode
{
    void *Data;
    struct ADTBinTreeNode* Left;
    struct ADTBinTreeNode* Right;
};
typedef struct ADTBinTreeNode ADTBinTreeNode;
typedef ADTBinTreeNode ADTBinTree;
typedef ADTBinTreeNode* pADTBinTreeNode;
/* inicializa a cero la estructura para que funcine correctamente cuando sea utilizada */
void ADTBinTreeNodeIni(pADTBinTreeNode pNode);
/* determina si el arbol esta vacio */
int ADTBinTreeIsEmpty(pADTBinTreeNode Root);
/* insterta un nuevo dato en el arbol, eliminando duplicados de forma automatica */
unsigned long
ADTBinTreeInsert(pADTBinTreeNode *Root, void *data, void *key, size_t size, int (*cmp)(void*,void*));
/* elimina un dato del arbol */
unsigned long
ADTBinTreeDelete(pADTBinTreeNode *Root, void *data, void *key, size_t size, int (*cmp)(void*,void*));
/* busca a traves del campo clave key un elemento del arbol, guarda la info en data y devuelve un
puntero al dato encontrado si existe, en caso contrario devuelve NULL */
void* ADTBinTreeSearch(pADTBinTreeNode *Root, void *data, void *key, int (*cmp)(void*,void*));
/* libera la memoria ocupada por el arbol y la pasa a una cola, que es mas facil de liberar */
unsigned long ADTBinTreeDestroy(pADTBinTreeNode *Root, size_t dataSize , ADTQueueNode *pQueue);
/* recorrido en orden del arbol. Los datos se almacenan en la cola *pQueue */
unsigned long ADTBinTreeInOrder(ADTBinTreeNode* Root,size_t dataSize,ADTQueueNode* pQueue);
/* recorrido preorden del arbol. Los datos se almacenan en la cola *pQueue */
unsigned long ADTBinTreePreOrder(ADTBinTreeNode* Root,size_t dataSize,ADTQueueNode* pQueue);
/* recorrido post orden del arbol. Los datos se almacenan en la cola *pQueue */
unsigned long ADTBinTreePostOrder(ADTBinTreeNode* Root,size_t dataSize,ADTQueueNode* pQueue);
/* recorrido por niveles del arbol. Los datos se almacenan en la cola *pQueue */
unsigned long ADTBinTreeLevelOrder(ADTBinTreeNode* Root,size_t dataSize,ADTQueueNode* pQueue);
#endif /* ADT_BINTREE_H */
 */
), para poder seguir el codigo maquina hasta el punto en el que se leen los datos, a partir de ahi deberas investigar sobre donde se almacenan los datos y como se manipulan para obtener el pass correcto. Una vez que tengas claro como se manipulan los datos, lo unico que tienes que hacer es rehacer/deshacer los pasos para poder generar tu propia clave.