/* ATTENZIONE: questo programma NON riesco a testarlo! (La ragione per
* chiunque abbia seguito le lezioni e' ovvia). Quindi prendetelo con le
* molle */
/* Possibile soluzione al compito del 31 gennaio 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>
/* dichiarazione struttura dati base (come da testo) */
struct dipendente {
char nome[20];
char codice_qualifica[3];
int stipendio; /* e' chiaro che NON e' portabile */
};
/* non conoscendo a priori il numero di codici qualifica
* la soluzione piu' pulita per memorizzare il tutto e' una
* lista allocata dinamicamente, a seguire la sua dichiarazione: */
struct stipendi{
char codice_qualifica[3];
long stipendio_totale;
int numero_dipendenti;
struct stipendi *next;
} *mylist;
/* prototipi delle funzioni */
void inserisci_in_lista(struct dipendente);
void libera_lista(struct stipendi*);
void *Malloc(size_t);
FILE *Fopen(const char *, const char *);
int main(int argc, char **argv){
FILE *dati;
struct dipendente dato_in_lettura;
struct stipendi *p;
size_t num;
dati=Fopen("dip.dat","r+b");
/* la lista ora e' vuota, non necessariamente il puntatore
* al primo elemento sara' NULL, e' quindi opportuno inizializzarlo*/
mylist=NULL;
/* ciclo di lettura file e inserimento dati in lista */
while(!feof(dati)){
/* leggo un singolo valore */
num=fread(&dato_in_lettura, sizeof(struct dipendente), 1, dati);
/* questo e' solo un test di correttezza se l'if
* si verifica probabilmente il file in ingresso e' sbagliato */
if(num!=1) break;
fprintf(stderr, "%s - %c%c%c - %d\n",dato_in_lettura.nome,dato_in_lettura.codice_qualifica[0],
dato_in_lettura.codice_qualifica[1],dato_in_lettura.codice_qualifica[2],
dato_in_lettura.stipendio);
inserisci_in_lista(dato_in_lettura);
}
fclose(dati);
/* ciclo di scrittura dati elaborati, il programma non
* specificava il tipo di file, per semplicita' lo facciamo
* ASCII */
dati=Fopen("qual.dat","w+b");
for(p=mylist;p->next;p=p->next){
/* KLUDGE */
fprintf(dati,"codice: %c%c%c numero dipendenti: %d totale emolumenti: %ld\n",
p->codice_qualifica[0],p->codice_qualifica[1],p->codice_qualifica[2],
p->numero_dipendenti,
p->stipendio_totale);
}
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 dipendente 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 dipendente));
/* inizializzo semplicemente i valori e torno */
mylist->next=NULL;
memcpy(mylist->codice_qualifica,nuovo.codice_qualifica,3);
mylist->stipendio_totale=nuovo.stipendio;
mylist->numero_dipendenti=1;
return;
}else{
struct stipendi *p; /* mi serve per scorrere la lista */
p=mylist;
/* ciclo fino a che uno degli elementi contiene lo stesso codice o
* fino alla fine della lista */
while((!strncmp(p->codice_qualifica,nuovo.codice_qualifica,3))||(p->next!=NULL))p=p->next;
if(!p->next){
/* sono arrivato alla fine della lista:
* stesse operazioni del caso precedente */
p->next=Malloc(sizeof(struct stipendi));
p=p->next;
p->next=NULL;
memcpy(p->codice_qualifica,nuovo.codice_qualifica,3);
p->stipendio_totale=nuovo.stipendio;
p->numero_dipendenti=1;
return;
}
/* ho trovato un elemento della lista con lo stesso
* codice dipendente, non mi serve aggiungere altro,
* aggiorno semplicemente i dati */
p->stipendio_totale+=nuovo.stipendio;
++p->numero_dipendenti;
}
return;
}
void libera_lista(struct stipendi *p){
if(p->next)libera_lista(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;
}