/* questo file contiene alcune funzioni C  per la gestione e manipolazione 
   di linked list.  L' implementazione delle function di manipolazione qui
   presentata e' solo una tra molte alternative. Viene fornita solo come 
   esempio, senza pretesa di costituire la migliore soluzione.
   Non tutte  le function sono effettivamente usate nel  programma di prova. */

#define MAXC 40
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct nodo
   {
    char   nome[MAXC];
    struct nodo *successivo;
   } nodo;



nodo *crea_nodo( void )
/* alloca memoria per un nuovo elemento ritornando un puntatore a questo 
   spazio */
/* N.B. la creazione di un nuovo elemento NON lo inserisce nella lista:
 * nessun elemento punta ancora al nuovo e questo non punta a nessuno 
 * (p->successivo punta a  NULL) */
{
    nodo *nuovo_nodo;
    
    nuovo_nodo = malloc(sizeof(nodo) );
    if ( nuovo_nodo == NULL )
	{
	 printf( "crea_nodo: allocazione di memoria fallita  \n");
	 exit(1);
	 }
	 nuovo_nodo->successivo = NULL;
	 return nuovo_nodo;
}



void aggiungi_nodo( nodo *nuovo_nodo , nodo **inizio)
/* questa function aggiunge un elemento del tipo nodo in fondo alla lista 
 * di primo elemento "inizio"  
 * il parametro  inizio deve essere di tipo puntatore a puntatore a nodo
 * per consentire alla function di modificare il parametro.
 */
{
    nodo *nodo_corrente;
    if ( *inizio == NULL)
    {
     *inizio = nuovo_nodo;
     return;
    }
    
    for( nodo_corrente = *inizio   ;   nodo_corrente->successivo != NULL ; 
                            nodo_corrente = nodo_corrente->successivo)
    ;     //  con questo for arriviamo all' ultimo nodo
    nodo_corrente->successivo = nuovo_nodo;
    return;
    
}



void inserisci_dopo(nodo *q, nodo *p)
/* inserisce il  nodo  p dopo il nodo q */
{
    if ( p == NULL || q == NULL || p==q || q->successivo == p )
// per quanto riguarda le ultime due condizioni, sarebbe probabilmente meglio 
// ometterle dalla function in quanto non esaustive delle possibili  situazioni
// non valide in cui si tenti di inserire un elemento gia'  presente nella
// lista 
	{
	printf("inserisci_dopo : inserzione non valida\n");
	return;
	}
	p->successivo = q->successivo;
	q->successivo = p;
        return;
        
}



void elimina(nodo **eliminando, nodo **inizio)
{   
    nodo *p;
    
    if (*eliminando == *inizio)
     {
        if((*inizio)->successivo != NULL)
	    *inizio = (*eliminando)->successivo;
        else
            *inizio=NULL;
     }
    else
     {
	    for(p=*inizio; (p!= NULL) && (p->successivo !=*eliminando);p = p->successivo)
	    if ( p == NULL) {
	        printf("elimina: Errore: non c'e' l' elemento cercato  "
                        "nella  lista \n");
	        return;
             }
	     p->successivo = p->successivo->successivo;
	}
     free(*eliminando);
     *eliminando=NULL;
}



void scrivi_lista(nodo *inizio)
{
    nodo *p;
    int count=0;
    
    if(inizio == NULL) printf("lista vuota\n");
    else {
	  p=inizio;
	  do{count++;
     	     printf("%s\n",p->nome);
	     p= p->successivo;
	     }
	  while(p != NULL);
	  }
     printf("%d elementi\n",count);
     
    return;
}



nodo *trova_nome( char *nome , nodo *inizio)
{
    nodo *p;
    p=inizio;
    
    do{
       if(strcmp(nome,p->nome)==0) return p;
    }while((p=p->successivo) != NULL);
    
    return NULL;
}    




int main(void)
{
    char ans, buffer[80];
    nodo *inizio=NULL;      /*  "inizio" e' il puntatore all' inizio della 
                                 lista  inizializzato a NULL              */

    nodo *p;
    int non_trovato;
    p=inizio;
    while(1)
       {
        printf(" new element ? (y/n) ");
        fgets(buffer,80,stdin);
        sscanf(buffer,"%c",&ans);
	if(ans == 'n') break;
        p=crea_nodo();
        fgets(buffer,80,stdin);
        sscanf(buffer,"%80s",p->nome);
        aggiungi_nodo(p,&inizio);
       }
       
       do{
          scrivi_lista(inizio);
	  printf(" quale vuoi eliminare ? ");
	  scanf("%79s",buffer);
	
         if((p=trova_nome(buffer,inizio)) != NULL)
	    {
	    printf("Trovato ! : %s \n",p->nome);
            non_trovato=0;
	    elimina(&p,&inizio);
            scrivi_lista(inizio);
            }  
         else
	     {
	     printf("Elemento non trovato. Riprova\n");
	     non_trovato=1;
	     }
	} while(non_trovato);
	
    
    return 0;
    
}