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

typedef struct num{

        int n;
        struct num *sig;  //Puntero a la estructura.
}numlist;

void agregar_num(numlist **l); //Agrega numero a la lista.
void MostrarNumeros(numlist *l); //Muestra la lista de números
void BorrarNum(numlist **l); //Borra número de la lista.
int suma_de_numeros(numlist *l);//Suma los números en la lista
int buscar_max(numlist *l);//Busca el valor máximo dentro de la lista.

int main()
{
    int n;
    char opcion;
    numlist *lista=NULL;

    while(1)
    {
        system("cls"); //Limpia pantalla.
        printf("1.- Insertar n%cmeros a la lista\n"
               "2.- Mostrar listado de n%cmeros\n"
               "3.- Borrar N%cmero\n"
               "4.- Sumar los n%cmeros de la lista\n"
               "5.- Buscar el m%cximo de la lista\n"
               "6.- Salir del Programa\n\n\n",163,163,163,163,160);

        while(opcion=getch(), opcion<'1'|| opcion>'6');

        switch(opcion)
        {
            case '1':
                agregar_num(&lista);break;
            case '2':
                MostrarNumeros(lista);break;
            case '3':
                BorrarNum(&lista);break;
            case '4':
                printf("La suma de los n%cmeros de la lista es: %d\n", 163,suma_de_numeros(lista));
                break;
            case '5':
                printf("El m%cximo elemento de la lista es: %d\n", 160,buscar_max(lista));break;
            case '6':
                system("pause");
                return 0;
        }
        printf("\n\n");
        system("pause");
    }

}

void agregar_num(numlist **l)
{
    numlist *rec=NULL, *nodo=NULL;

    nodo=(numlist*)malloc(sizeof(numlist));//Se crea nodo.
    if(!nodo) //Hay memoria suficiente?
    {
        printf("No hay memoria suficiente.\n");
        return;
    }
    nodo->sig=NULL; //Elemento siguiente a la lista se inicializa apuntando a NULL.
    printf("Ingrese valor que desea agregar:\n");
    scanf("%d", &nodo->n); //Se agrega valor a la lista.

    if(!(*l)) //Si no hay lista se crea.
        *l=nodo;
    else{
        rec=*l;
        while(rec->sig)
            rec=rec->sig;
        rec->sig=nodo; //Si había lista, se agrega nodo al final de ésta.
    }
}

void MostrarNumeros(numlist *l)
{
    if(l) //Sólo si hay lista se muestra
    {
        printf("%d\n", l->n);
        MostrarNumeros(l->sig); //Se aprovecha recursividad para mostrar la lista.
    }
}

int suma_de_numeros(numlist *l)
{
    int suma=0; //Variable acumuladora para la suma.
    numlist *rec=NULL; //Variable que se utiliza para recorrer la lista.

    if(!l) //Hay lista?
    {
        printf("No hay lista cargada.\n");
        return 0;
    }
    rec=l; //A rec se le da la dirección de la lista.
    while(rec) //MIentras haya elementos.
    {
        suma+=rec->n; //Se acumula la suma.
        rec=rec->sig;//Se lee cada elemento de la lista
    }
    return suma; //Se retorna la suma.
}

int buscar_max(numlist *l)
{
    int max;
    numlist *rec=NULL; //Se utiliza para recorrer la lista.

    rec=l;
    max=rec->n;;//Se le da el valor inicial de la lista al valor maximo
    while(rec->sig)
    {
        rec=rec->sig; //Se recorre la lista
        if(max<rec->n)// Si hay valor mayor al maximo se redefine el maximo como dicho valor
            max=rec->n;
    }
    return max;//Se retorna el mayor valor dentro de la lista.
}

void BorrarNum(numlist **l)
{
    numlist *rec=NULL, *aux=NULL; //Punteros a la estructura.
    int pos, borrar; //Variables auxiliares.
    if(!*l)//Hay lista?
    {
        printf("No hay n%cmeros para borrar.\n",163);
        return;
    }

    printf("Ingrese n%cmero que desea borrar.\n",163);
    scanf("%d", &borrar); //Se ingresa número a borrar.
    rec=*l;//Se le da a rec la direccion de la lista
    pos=0; //Se inicializa la variable pos con valor 0.
    while(rec)
    {
        if(rec->n==borrar) //Si se encuentra coincidencia se quebra el bucle.
            break;
        rec=rec->sig; //Se recorre lista.
        pos++; //Se le suma 1 a pos, esta variable se usa para detectar la posicion del nodo a borrar.
    }
    if(!rec) //Se habrá encontrado coincidencia?
    {
        printf("No se encontr%c n%cmero para borrar.\n", 162,163);
        return;
    }
    if(!pos)//Si se encontró coincidencia pero se encuentra al inicio de la lista.
    {
        *l=(*l)->sig; //Se modifica la direccion de la lista, apuntando esta a su valor siguiente.
        free(rec); //Se libera la memoria apuntada por rec (valor a borrar)
        return; //Termina la función.
    }

    aux=*l; //Variable auxiliar apunta a la lista.
    borrar=0; //Se recicla ésta variable para usarla de manera auxiliar.
    while(aux)
    {
        //Si se encuentra la posición anterior al nodo a borrar.
        if(borrar==pos-1){
            aux->sig=rec->sig; //aux apunta al valor siguiente del nodo a borrar.
            free(rec); //Se libera memoria del nodo a borrar.
            return;
        }
        borrar++; //Se le suma 1 a borrar.
        aux=aux->sig;//Se recorre la lista.
    }
}
