/* Possibile soluzione al compito del 30 novembre 1999 per coloro che dovevano sostenere 
 * l'esame di FONDAMENTI DI INFORMATICA 2 
 * 
 * ATTENZIONE: dato che questo programma e' stato sviluppato a fini didattici
 * risulta eccessivamente pieno di commenti. NON prendetelo ad esempio. */

#include<stdio.h>
#include<stdlib.h> /* molti di voi si dimenticano di includere stdlib
                    * che pero' e' necessaria per le funzioni di 
                    * allocazione dinamica della memoria !! */

/* definizione struttura dati contenente la lista */

struct elemento{
	char nome[30];      /* non ci sono ipotesi sul numero di elementi
			     * ne faccio sulla lunghezza     */
	long int codice;    /* attenzione! il codice puo' essere troppo
			     * grande per un semplice intero */
	int valid; 
	struct elemento *next;
} *mylist;

struct elemento *mylist=NULL;

/* prototipi delle funzioni */
void inserisci_in_lista(struct elemento);
void libera_lista(struct elemento*);
void marca_elemento(int);
void *Malloc(size_t); 
FILE *Fopen(const char *, const char *);


/*************************************************************************/

int main(int argc, char **argv){

FILE *dati;
struct elemento elemento_tmp; /* struttura temporanea per dati in lettura */
struct elemento *p; /* usato per scorrere la lista */
char c; /* lo uso per leggere il file carattere a carattere */
int ii; /* contatore */

dati=Fopen("tessere.dat","r");

/* prima fase: leggo il file e man mano inserisco gli elementi
 * nella lista */
while(!feof(dati)){
  /* itero finche' non trovo il primo carattere "interessante" */
  c=' ';
  while(c==' ')c=fgetc(dati);
  elemento_tmp.nome[0]=c; /* lo memorizzo */
  ii=1; /* secondo carattere */
  c=' ';
  while(c!=';'){
	  c=fgetc(dati);
	  if(c!=';')elemento_tmp.nome[ii++]=c;
  }
  elemento_tmp.nome[ii]='\0'; /* metto fine stringa */

  /* leggo codice */
  fscanf(dati, "%ld\n", &elemento_tmp.codice);
  /* ora posso inserire nella lista */
  inserisci_in_lista(elemento_tmp);
 }
fclose(dati);
/* seconda fase: chiedo iterativamente un numero, lo cerco
 * nei codici e nel caso lo marco come NON valido */
ii=0;
while(1){
	printf("Inserisci un codice: ");
	scanf("%d",&ii);
	/* se il numero inserito e' nullo allora esco dal
	 * ciclo */
	if(!ii)
		break;
	else 
		marca_elemento(ii);
}
/* terza fase: scrivo il file di output e libero la memoria!!*/
dati=Fopen("rimasti.dat","w");
for(p=mylist;p;p=p->next){
	/* ovviamente scrivo solo quelli non eliminati */
	if(p->valid)
		fprintf(dati,"%s; %ld\n",p->nome,p->codice);
}
fclose(dati);
/* la liberazione della memoria 
 * e' banale usando una funzione ricorsiva */
libera_lista(mylist);

return 0;
}

/*************************************************************************/

void libera_lista(struct elemento *o){
	if(!o)return;
	libera_lista(o->next);
	free(o);
}

/*************************************************************************/

void inserisci_in_lista(struct elemento nuovo){
	
	/* controllo che la lista sia gia' stata inizializzata
	 * nel caso la inizializzo oppure aggiungo semplicemente
	 * l'elemento */
	if(mylist==NULL){
		mylist=Malloc(sizeof(struct elemento));
                /* per semplicita' non cancellero' gli elementi
                 * dalla lista, ma semplicemente utilizzo un flag per
                 * segnalare se sono da scrivere o meno in uscita.
                 * Inizialmente lo sono tutti */
		mylist->valid=1;
		/* prossimo elemento NON esiste */
		mylist->next=NULL;
		/* copio i dati */
		strcpy(mylist->nome,nuovo.nome);
		mylist->codice=nuovo.codice;
	}else{
		struct elemento *p; /* mi serve per scorrere la lista */
		p=mylist;
		/* cerco l'ultimo elemento */
		while(p->next!=NULL)p=p->next;
                /* stesse operazioni del caso precedente */
		p->next=Malloc(sizeof(struct elemento));
		p=p->next;
		p->valid=1;
		p->next=NULL;
		strcpy(p->nome,nuovo.nome);
		p->codice=nuovo.codice;
	}
}

/*************************************************************************/

void marca_elemento(int a){
	struct elemento *p; /* contatore */
	
	/* percorro la lista e marco tutti gli
	 * elementi che hanno il codice dato come non
	 * validi */
	for(p=mylist;p;p=p->next)
		if(p->codice==a)
			p->valid=0;
}

/*************************************************************************/
/* da qui in poi sono semplici funzioni di utilita' gia' viste a lezione */
void *Malloc(size_t size)
{
 void *genericp;
 if((genericp=malloc(size))==NULL)
  {
   perror("Malloc");
   exit(1);
  }
  return genericp;
}

/*************************************************************************/

FILE *Fopen(const char *nome, const char *modo)
{
FILE *tmp;

 if((tmp=fopen(nome, modo))==NULL)
  {
   fprintf(stderr, "Non riesco ad aprire il file %s in maniera %s\n",nome, modo);
   perror("Fopen");
   exit(1);
  }
return tmp;
}