/* Possibile soluzione al compito del 22 febbraio 2000 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 dal
 * punto di vista dei commenti!!! */

#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 !! */
#include<string.h>

#define MAXANAGR 40


/* dichiarazione struttura dati base, una lista e' la cosa piu' semplice da
 * implementare */

struct elementi {
	char nome[MAXANAGR]; /* ipotesi ragionevole */
	unsigned long codice; /* 4 byte in turboC */
	struct elementi *prossimo; 
} *mylist;

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


int main(int argc, char **argv){
	
	FILE *dati;
	struct elementi dato_in_lettura, *p;
	int ris;
	
	/* inizializzo la testa della lista, non conterra' dati utili ma
	 * e' solo per comodita' */
	mylist=Malloc(sizeof(struct elementi));
        mylist->codice=0; /* per evitare problemi con 
			   *  l'ordinamento (0 sara'
			   *  comunque il codice + basso */
	mylist->prossimo=NULL;

	/* lettura primo file */
	dati=Fopen("primo22.dat","r");
	/* ciclo di lettura file e inserimento dati in lista */
	while(!feof(dati)){
		/* leggo un singolo valore */
		ris=fscanf(dati,"%ld;%[^\n]",&dato_in_lettura.codice, &dato_in_lettura.nome);
		if((!ris)||(ris==EOF))break;
                inserisci_in_lista(dato_in_lettura);
	}
	fclose(dati);

	/* lettura secondo file */
	dati=Fopen("secondo22.dat","r");
	/* ciclo di lettura file e inserimento dati in lista */
	while(!feof(dati)){
		/* leggo un singolo valore */
		ris=fscanf(dati,"%ld;%[^\n]",&dato_in_lettura.codice, &dato_in_lettura.nome);
		if((!ris)||(ris==EOF))break;
                inserisci_in_lista(dato_in_lettura);
	}
	fclose(dati);

	dati=Fopen("risultato22.dat","w");
	/* stampiamo i dati (attenzione si deve tralasciare la testa */
	for(p=mylist->prossimo;p;p=p->prossimo)
		fprintf(dati,"%ld;%s\n",p->codice,p->nome);
	fclose(dati);


 /* non  necessario  e non  richiesto  dal  compito,  ma io  valuto  sempre
  * positivamente il fatto che si  liberi la memoria allocata dinamicamente
  * prima di uscire dal programma (e comunque e' banale farlo)*/
	libera_lista(mylist);

	return 0;
}


/*************************************************************************/
/*           permette l'inserimento nella lista dei codici               
 * nota: era piu' efficiente il passaggio di un puntatore invece che di
 * una struttura per intero */

void inserisci_in_lista(struct elementi nuovo){
	/* notare che la testa della lista gia' esiste */
	struct elementi *p; /*contatore*/
	struct elementi *i; /*punto di inserimento*/
	struct elementi *a;

	/* l'inserimento andra' comunque fatto,
	 * alloco il nuovo nodo e ci copio i dati*/

	a=Malloc(sizeof(struct elementi));
	a->codice=nuovo.codice;
	memcpy(a->nome,nuovo.nome,MAXANAGR);

	/* li memorizzo in ordine da quello con codice piu'
	 * basso a quello con codice piu' alto */

	/* esce o a fine lista o quando incontro un valore piu' alto */
	/* for(i=p=mylist;(p)&&(p->codice<nuovo.codice);p=p->prossimo)i=p;*/
	i=punto_di_inserzione(mylist,nuovo.codice);

	/* inserisco il nodo */
	a->prossimo=i->prossimo; /* anche NULL eventualmente */
	i->prossimo=a;

	return;
}

void libera_lista(struct elementi *p){
	if(p->prossimo)libera_lista(p->prossimo);
	free(p);
}


/*************************************************************************/
/* scorre la lista e restituisce il punto in cui inserire il dato        */
struct elementi *punto_di_inserzione(struct elementi *start, long int valore){
	if(!start->prossimo)return start; /* sicuramente inserisco qui se sono in fondo */
	if(start->prossimo->codice>valore)return start;
	return punto_di_inserzione(start->prossimo,valore);
}

/*************************************************************************/
/* 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;
}