/* Risoluzione compito d'esame del 26-4-99, Fondamenti di Informatica */
/* CCL Ambiente e Territorio */

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

typedef struct {
	char nome[13],
	     cognome[21],
	     indirizzo[21],
	     civico[10],
	     cap[6],
	     citta[21],
	     provincia[3],
	     telcasa[11],
	     tellavoro[11],
	     cellulare[12],
	     fax[11],
	     email[26];
} scheda;

struct el {
	scheda info;
	struct el *next;
};

typedef struct el elista;


/* prototipi */
void LeggiNomeFile(char *);
scheda LeggiScheda(void);
FILE *ApriFile(char *, char *);
void CostruisciRubrica(char *);
void ScriviScheda(scheda);
void StampaRubrica(char *);
void AggiornaRubrica(char *, scheda);
char LeggiLettera(void);
void Accoda(elista **, elista **, scheda);
void StampaLista(elista *);
elista *CostruisciLista(char *, char);
int main(void);

void LeggiNomeFile(char *nome)
{
	printf("Inserire nome del file: ");
	gets(nome);
	return;
}

scheda LeggiScheda(void)
{
	scheda s;
	printf("Inserimento di una scheda\n");
	printf("Nome [invio per terminare]: ");
	if(*gets(s.nome)==0)
		return s;
	printf("Cognome                   : ");
	gets(s.cognome);
	printf("Indirizzo                 : ");
	gets(s.indirizzo);
	printf("Num. civico               : ");
	gets(s.civico);
	printf("CAP                       : ");
	gets(s.cap);
	printf("Citta`                    : ");
	gets(s.citta);
	printf("Sigla prov. (2 lettere)   : ");
	gets(s.provincia);
	printf("Telefono (casa)           : ");
	gets(s.telcasa);
	printf("Telefono (lavoro)         : ");
	gets(s.tellavoro);
	printf("Cellulare                 : ");
	gets(s.cellulare);
	printf("FAX                       : ");
	gets(s.fax);
	printf("E-MAIL                    : ");
	gets(s.email);
	
	return s;
}


FILE *ApriFile(char *nome, char *modo)
{
	FILE *f;
	f=fopen(nome, modo);
	if(f==NULL) {
		fprintf(stderr, "Impossibile aprire file %s in modalita` %s. Programma terminato.\n", nome, modo);
		exit(1);
	}
	return f;
}


void CostruisciRubrica(char *nomefile)
{
	FILE *f;
	scheda s;
	f=ApriFile(nomefile,"wb");
	s=LeggiScheda();
	/* assume che quando l'utente vuole terminare l'immissione 
	   di schede egli digita invio alla richiesta del nome */
	while(s.nome[0]!='\0') {
		fwrite(&s, sizeof(scheda), 1, f);
		s=LeggiScheda();
	}
	fclose(f);
	return;
}


void ScriviScheda(scheda s)
{
	printf("Nome             : %s\n",s.nome);
	printf("Cognome          : %s\n",s.cognome);
	printf("Indirizzo        : %s\n",s.indirizzo);
	printf("Num. civico      : %s\n",s.civico);
	printf("CAP              : %s\n",s.cap);
	printf("Citta`           : %s\n",s.citta);
	printf("Sigla prov.      : %s\n",s.provincia);
	printf("Telefono (casa)  : %s\n",s.telcasa);
	printf("Telefono (lavoro): %s\n",s.tellavoro);
	printf("Cellulare        : %s\n",s.cellulare);
	printf("FAX              : %s\n",s.fax);
	printf("E-MAIL           : %s\n",s.email);
	printf("--\n");
	return;
}


void StampaRubrica(char *nomefile)
{
	FILE *f;
	scheda s;
	printf("\nSTAMPA RUBRICA\n");
	f=ApriFile(nomefile,"rb");
	while(fread(&s,sizeof(scheda),1,f)==1) 
		ScriviScheda(s);
	fclose(f);
	printf("FINE RUBRICA\n");
	return;
}


void AggiornaRubrica(char *filein, scheda nuova)
/* funzione richiesta al punto 1.2 */
{
	FILE *fin, *fout;
	char fileout[24];
	scheda vecchia;
	int presente=0;
	
	strcpy(fileout,"new");
	strcat(fileout,filein);
	fin=ApriFile(filein,"rb");
	fout=ApriFile(fileout, "wb");
	while(fread(&vecchia,sizeof(scheda),1,fin)==1)
		if((strcmp(nuova.nome,vecchia.nome)==0)&&(strcmp(nuova.cognome,vecchia.cognome)==0)) {
			presente=1;
			fwrite(&nuova, sizeof(scheda), 1, fout);
		} else
			fwrite(&vecchia, sizeof(scheda), 1, fout);
	fclose(fin);
	if(!presente)
			fwrite(&nuova, sizeof(scheda), 1, fout);		
	fclose(fout);
	remove(filein);
	rename(fileout,filein);
	return;
}


char LeggiLettera(void)
{
	char ch;
	printf("Inserire iniziale cognomi per costruzione lista: ");
	ch=getchar();
	getchar();
	return ch;
}


void Accoda(elista **ppinizio, elista **ppcoda, scheda s)
{
	elista *nuovo;
	
	nuovo=malloc(sizeof(elista));
	nuovo->info=s; /* le struct possono essere assegnate */
	nuovo->next=NULL;
	if(*ppinizio==NULL)
		*ppinizio=nuovo;
	else
		(*ppcoda)->next=nuovo;
	*ppcoda=nuovo;
	return;
}


void StampaLista(elista *pprimo)
{
	printf("\nSTAMPA LISTA\n");
	while(pprimo!=NULL) {
		ScriviScheda(pprimo->info);
		pprimo=pprimo->next;
	}
	printf("FINE LISTA\n");
	return;
}

elista *CostruisciLista(char *nomefile, char iniziale)
/* funzione richiesta al punto 1.3 */
{
	elista *pinizio, *pcoda;
	FILE *f;
	scheda s;
	
	f=ApriFile(nomefile, "rb");
	pinizio=NULL;
	while(fread(&s,sizeof(scheda),1,f)==1)
		if(*s.cognome==iniziale)
			Accoda(&pinizio,&pcoda,s);
	fclose(f);
	return pinizio;
}


main(void)
{
	char nomefile[21], lettera;
	scheda nuova;
	elista *ptesta;
	
	LeggiNomeFile(nomefile);
	CostruisciRubrica(nomefile);
	StampaRubrica(nomefile);
	nuova=LeggiScheda();
	AggiornaRubrica(nomefile,nuova);
	StampaRubrica(nomefile);
	lettera=LeggiLettera();
	ptesta=CostruisciLista(nomefile,lettera);
	StampaLista(ptesta);
	return 0;
}