/* Possibile soluzione al compito del 22 febbraio 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 dal
* punto di vista dei commenti!!! */
/* L'esercizio proposto era la lettura di un file del tipo:
* turbo C # 0001
* delphi # 231A
* nedit # 0001
* emacs # 0001
* kataweb script di connessione # 0001
* netscape # 231A
* turbo C++ (3.0) # 231A
* mozilla (beta) # 0013
* il programma doveva leggerlo e produrre in uscita un altro file del tipo:
* 0001: turbo C , nedit , emacs , kataweb script di connessione
* 231A: delphi , netscape , turbo C++ (3.0)
* 0013: mozilla (beta)
* */
#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 LEN_COD 4
#define BUFFER_LEN 1024
/* dichiarazione struttura dati base, e' richiesta una
* multilista: utilizzo due tipi di nodi differenti */
struct software {
char *titolo;
struct software *next;
};
struct cd {
char codice[LEN_COD+1];
struct software *link;
struct cd *next;
} *cd_list;
/* prototipi delle funzioni */
void libera_cd(struct cd *);
void libera_sw(struct software *p);
void *Malloc(size_t);
FILE *Fopen(const char *, const char *);
int main(int argc, char **argv){
FILE *file_handler; /* contiene i dati in ingresso */
char *buffer; /* buffer per leggere dal file */
int riga=0; /* tiene traccia della riga che
* sto leggendo */
int ii; /* semplice contatore */
char codice_tmp[LEN_COD+1];
char *titolo_tmp; /* variabili temporanee */
struct cd *pcd; /* mi servono per scorrere la lista di cd */
struct software *psw;
/* fase di inizializzazione variabili */
cd_list=NULL;
/* apro primo file */
file_handler=Fopen("package.dat","r");
/* alloco un buffer per leggere riga per riga
* si noti che non sono state fatte ipotesi sulla lunghezza massima
* dei titoli del software. Le faccio ora */
buffer=Malloc(BUFFER_LEN);
/* ciclo di lettura dei file e loro
* inserzione in struttura dati */
while(!feof(file_handler)){
++riga;
fgets(buffer, BUFFER_LEN, file_handler);
/* controllo che ci siano i dati */
if(strlen(buffer)<=LEN_COD){
break;
}
/* conto i caratteri necessari per il
* titolo del software */
ii=0;
while(buffer[ii]!='#') ++ii;
/* alloco lo spazio necessario */
titolo_tmp=Malloc(ii+1);
/* copio i dati e termino la stringa*/
memcpy(titolo_tmp,buffer,ii);
titolo_tmp[ii]='\0';
/* cerco il primo carattere del codice */
++ii;
while(buffer[ii]==' ')++ii;
/* copio e termino */
memcpy(codice_tmp,&buffer[ii],LEN_COD);
codice_tmp[LEN_COD]='\0';
/* lo inserisco in lista. Non e' previsto alcun
* tipo di ordinamento */
/* devo controllare che la lista esista,
* nel caso creo e inserisco */
if(cd_list==NULL){
cd_list=Malloc(sizeof(struct cd));
memcpy(cd_list->codice,codice_tmp,LEN_COD);
cd_list->next=NULL;
cd_list->link=Malloc(sizeof(struct software));
cd_list->link->titolo=titolo_tmp;
}
else{
pcd=cd_list;
/* scorro la lista di CD fino a che non trovo lo stesso codice
* E fino a che ho elementi */
while((strcmp(codice_tmp,pcd->codice))&&(pcd->next))
pcd=pcd->next;
if(!strcmp(codice_tmp,pcd->codice)){
/* devo scorrere la lista fino al penultimo elemento */
psw=pcd->link;
while(psw->next)psw=psw->next;
psw->next=Malloc(sizeof(struct software));
psw=psw->next;
psw->next=NULL;
psw->titolo=titolo_tmp;
}
else{
/* alloco un nuovo cd */
pcd->next=Malloc(sizeof(struct cd));
pcd=pcd->next;
memcpy(pcd->codice,codice_tmp,LEN_COD);
pcd->next=NULL;
pcd->link=Malloc(sizeof(struct software));
pcd->link->titolo=titolo_tmp;
}
}
}
/* libero le variabili temporanee
* e chiudo il file */
free(buffer);
fclose(file_handler);
/* apro il file in scrittura */
file_handler=Fopen("cd.dat","w");
/* stampo i dati come richisto */
pcd=cd_list;
while(pcd){
fprintf(file_handler,"%s:",pcd->codice);
psw=pcd->link;
while(psw){
fprintf(file_handler," %s",psw->titolo);
psw=psw->next;
if(psw)
fprintf(file_handler,",");
}
fprintf(file_handler,"\n");
pcd=pcd->next;
}
fclose(file_handler);
/* libero la memoria sfruttando la ricorsione */
libera_cd(cd_list);
return 0;
}
void libera_cd(struct cd *p){
if(!p)
return;
libera_sw(p->link);
libera_cd(p->next);
free(p);
}
void libera_sw(struct software *p){
if(!p)
return;
libera_sw(p->next);
free(p);
}
/*************************************************************************/
/* 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;
}