/* ATTENZIONE richiede util.c e util.h */
#include<stdio.h>
#include<stdlib.h>
#include"util.h"
#define MAX_MAT 52
#define MAX_FILE 13
#define MAX_VOTO 31
struct esame{
int voto;
char materia[MAX_MAT];
struct esame *prossimo;
struct esame *precedente;
};
int main(int argc, char **argv)
{
FILE *mystream;
char miofile[MAX_FILE];
struct esame *tmp;
struct esame *lista_esami;
char votochar[3];
int numchars;
/* prototipi */
void add_lista_in_ordine(struct esame*, struct esame **);
void stampa_lista(struct esame*);
void calcola_e_stampa_media(struct esame*);
void libera_lista(struct esame*);
for(;;) /* itero */
{
/* chiedo un nome di file e continuo finche' non riesco
* ad aprirlo */
printf("Inserire il nome del file: ");
gets(miofile); /* operazione potenzialmente pericolosa */
if((mystream=fopen(miofile,"r"))==NULL)
{
printf("Attenzione: non è possibile aprire il file %s!\n",miofile);
continue;
}
lista_esami=NULL;
while(!feof(mystream))
{
/* alloco un puntatore temporeaneo che serve per contenere i
* dati via via che sono letti */
tmp=Malloc(sizeof(struct esame));
tmp->prossimo=tmp->precedente=NULL;
/* leggo la materia ed esco se non esiste */
numchars=fscanf(mystream,"%[^\n]\n",tmp->materia);
if(!numchars)break;
/* creo la stringa che contiene il voto letto
e' un modo chiaro anche se poco efficiente */
votochar[0]=fgetc(mystream);
votochar[1]=fgetc(mystream);
votochar[2]='\0'; /*questo andrebbe fuori dal ciclo*/
fgetc(mystream);
tmp->voto=atoi(votochar);
add_lista_in_ordine(tmp, &lista_esami);
}
/* elimino il nodo fasullo */
free(tmp);
tmp=lista_esami->prossimo;
free(lista_esami);
lista_esami=tmp;
lista_esami->precedente=NULL;
/* ora la lista e' a posto */
stampa_lista(lista_esami);
calcola_e_stampa_media(lista_esami);
libera_lista(lista_esami);
}
return 0;
}
void stampa_lista(struct esame *jj){
for(;jj;jj=jj->prossimo)
printf("Materia: %s, voto: %d\n",jj->materia,jj->voto);
}
void calcola_e_stampa_media(struct esame *jj){
int somma=0, num_esami=0;
for(;jj->prossimo->prossimo->prossimo;jj=jj->prossimo);
for(;jj;jj=jj->precedente){
somma+=jj->voto;
++num_esami;
}
printf("Media %2.2f\n", ((float)somma)/num_esami);
}
void add_lista_in_ordine(struct esame *nuovo, struct esame **mylist){
struct esame *count, *ii;
/* se la lista e' vuota la creo, inserisco un nodo
* di testa che contiene dati non validi e metto
* nuovo come secondo elemento */
if (*mylist==NULL){
*mylist=Malloc(sizeof(struct esame));
(*mylist)->voto=MAX_VOTO+1;
(*mylist)->prossimo=nuovo;
(*mylist)->precedente=NULL;
return;
}
/* scorro la lista per determinare dove
* inserire nuovo */
ii=count=*mylist;
while(count&&(count->voto>nuovo->voto)){
ii=count;
count=count->prossimo;
}
/* il trucco della testa fasulla
* permette di ridursi a due casi */
nuovo->precedente=ii;
if(ii->prossimo!=NULL){
ii->prossimo->precedente=nuovo;
nuovo->prossimo=ii->prossimo;
}
ii->prossimo=nuovo;
}
void libera_lista(struct esame *nodo){
if(nodo==NULL)return;
libera_lista(nodo->prossimo);
free(nodo);
}