Questo esercizio presenta molti aspetti interessanti: da una parte la lettura di dati da diversi strumenti con identificatori arbitrari, dall'altra il fatto che, dopo essere stati letti ed analizzati i dati dei singoli strumenti, bisogna stamparli dopo averli messi in ordine di codice.
Dovendo fare operazioni cosí diverse, proponiamo una soluzione in cui i dati vengono organizzati nella struttura:
struct strumento {
int codice;
double media;
int misure;
};
Perchè questa struttura, oltre ai dati richiesti (codice e media)
contenga anche il numero di misure sarà chiaro in seguito.
In problemi di ordinamento di diversi dati rispetto ad un campo (nel nostro caso dovremmo ordinare le coppie codice-media in ordine di codice), se i dati sono immagazzinati in una struttura, basta avere in mente come si fa una funzione ordina generica, del tipo costruito in laboratorio, ed adattarla al caso specifico:
void ordina( struct strumento * vettore, int N) {
int i, j;
struct strumento temp;
for (i=0; i<N-1; i++) {
for (j=i+1; j<N; j++) {
if ( vettore[i].codice > vettore[j].codice ) {
temp = vettore[j];
vettore[j]=vettore[i];
vettore[i]=temp;
}
}
}
}
Usando l'operatore di assegnazione tra strutture si automatizza la scambio
delle variabili ausiliarie per l'ordinamento.
Con questi due mattoni possiamo iniziare a descrivere l'algoritmo usato per risolvere l'esercizio. Notiamo che, siccome non sappiamo il numero di righe del file di ingresso, non è possibile direttamente immagazzinare in memoria tutti i dati per poi analizzarli successivamente, ma bisogna procedere in modo tale da mantenere sempre aggiornata la lista degli strumenti con le loro medie.
Il programma seguente segue il flusso:
#include <stdio.h>
#define MAX_STRUMENTI 100
int main() {
/* Dichiarazione del vettore di strumenti. */
struct strumento strumenti[MAX_STRUMENTI];
int Nstrumenti=0;
int i, codice;
double lettura;
FILE* f;
/* Apertura del file di ingresso. */
f=fopen("rilevazioni.dat","r");
/* Ciclo di lettura del file. */
while ( fscanf(f,"%d %lf",&codice,&lettura)!=EOF) {
/* si confronta il codice letto con quello
degli strumenti già incontrati. */
for (i=0; i<Nstrumenti; i++) {
if ( codice==strumenti[i].codice ) {
/* Se lo strumento viene trovato, la media viene aggiornata.
Osservare la formula: non c'è bisogno di immagazzinare
i dati e fare la media successivamente.
*/
strumenti[i].misure++;
strumenti[i].media=
(1-1./strumenti[i].misure)*strumenti[i].media
+lettura/strumenti[i].misure;
/* ...ed è inutile continuare il ciclo.
in questo modo usciamo dal ciclo con i pari alla
posizione dello strumento nel vettore. */
break;
}
}
/* Se lo strumento non è stato trovato, all'uscita
del ciclo i vale Nstrumenti, allora inseriamo di dati del
nuovo strumento ed incrementiali il numero degli strumenti
conosciuti */
if (i==Nstrumenti) {
strumenti[Nstrumenti].codice=codice;
strumenti[Nstrumenti].media =lettura;
strumenti[Nstrumenti].misure=1;
Nstrumenti++;
}
}
/* Chiusura del file di ingresso. */
fclose(f);
/* Ordinamento del vettore di strumenti. */
ordina(strumenti,Nstrumenti);
/* Apertura del file di uscita. */
f=fopen("output.dat","w");
/* Stampa dei dati. */
for ( i=0; i<Nstrumenti; i++)
fprintf(f,"%d %lf\n",strumenti[i].codice,strumenti[i].media);
/* Chiusura del file di uscita e termine del programma. */
fclose(f);
return 0;
}