prof. Nunzio Brugaletta Programmazione e linguaggio C

EnneBi - Programmazione
Avanti Indietro Inizio


4.8 Un esempio pratico: elaborazioni statistiche

A questo punto si sono acquisite tutte le informazioni che servono per codificare il programma delle elaborazioni statistiche di temperature. Al solito le righe significative sono accompagnate da commenti numerici utilizzati per le osservazioni successive:

/*
  Temperatura media, escursione termica e scostamento medio
  di una serie di temperature rilevate in una località
  Le temperature sono state rilevate ogni 2 ore
*/

#include <stdio.h>
#define RILEVAZ 12	/*1*/

void rilevaTemp(int *t);	/*2*/
void aggiorna(int *t,int *st,int *tmn,int *tmx);	/*2*/
float scostMed(int *t,float mt);	/*2*/

main(){
  int temp[RILEVAZ],tempMax,tempMin,escur;
  float medTemp,medSco;
  int sommaTemp;

  /* Acquisizione temperature rilevate */

  rilevaTemp(temp);	/*3*/

  /* Calcolo media e ricerca massimo e minimo */

  sommaTemp = tempMin = tempMax = temp[0];
  aggiorna(temp,&sommaTemp,&tempMin,&tempMax);	/*4*/ 
  medTemp = (float) sommaTemp/RILEVAZ;	/*5*/
 
  /* Calcolo escursione termica */

  escur = tempMax-tempMin; 

  /* Scostamento medio */ 

  medSco = scostMed(temp,medTemp);	/*6*/

  /* Comunicazione risultati */

  printf("\nMedia temperature rilevate -> %2.2f",medTemp);
  printf("\nEscursione termica ---------> %d",escur); 
  printf("\nScostamento medio ----------> %2.2f",medSco); 
}

/* Lettura temperature */

void rilevaTemp(int *t){	/*7*/
  int i; 
  printf("\nAcquisizione temperature rilevate\n"); 
  for (i=0;i<RILEVAZ;i++){	/*8*/ 
    printf("Temperatura ore %d ",i*2); 
    scanf("%d",&t[i]); 
  } 
     
/* Aggiornamento Somma temperature, temp massima e minima */

void aggiorna(int *t,int *st,int *tmn,int *tmx){	/*9*/
  int i; 
  for (i=1;i<RILEVAZ;i++){ 
    *st += t[i]; 
    t[i]<*tmn ? *tmn=t[i] : (t[i]>*tmx ? *tmx=t[i] : 0);	/*10*/ 
  } 
}
    
/* Calcolo scostamento medio */

float scostMed(int *t,float mt){	/*11*/
  float somScost,scost,media; 
  int i; 
  somScost = 0; 
  for (i=0;i<RILEVAZ;i++){ 
    scost = t[i]>mt ? t[i]-mt : mt-t[i]; 
    somScost += scost; 
  } 
  media = somScost/RILEVAZ; 
  return media;	/*12*/ 
}

Nella riga 1 si dichiara una costante. Tale dichiarazione essendo esterna rispetto a tutte le funzioni ha visibilità globale: tutte le funzioni possono utilizzarla. Le variabili globali, se ci sono, devono essere dichiarate in questa posizione in modo da essere disponibili per tutte le funzioni.

Nelle 2 sono dichiarati i prototipi delle funzioni utilizzate. A questo punto quello che importa è il tipo di parametro. I nomi dei parametri, potendo mancare, sono aggiunti qui per chiarezza.

Nella riga 3 viene effettuata una chiamata alla funzione rilevaTemp passando il parametro temp. Si tratta in pratica di un puntatore al vettore, infatti per quanto osservato precedentemente, il nome di un vettore rappresenta il puntatore al primo elemento del vettore stesso. In questo modo la main fa conoscere a rilevaTemp la posizione in memoria del vettore temp.

Nella 4 viene effettuata una chiamata alla funzione aggiorna. Tale funzione ha il compito di aggiornare i valori contenuti in sommaTemp, tempMin e tempMax (che quindi per la funzione rappresentano degli output). Il vettore temp per la funzione è un input (non viene effettuata da aggiorna alcuna modifica sul vettore), basterebbe quindi un passaggio per valore del parametro solo che un vettore, per quanto osservato precedentemente, è sempre passato per indirizzo: possono essere passati per valore solo i singoli elementi di un vettore essendo questi delle variabili come tutte le altre.

Nella riga 5 si effettua una divisione fra interi, se si vuole conservare anche la parte decimale si deve effettuare un casting.

Nella riga 6 viene effettuata una chiamata alla funzione scostMed, solo che in questo caso a differenze delle precedenti chiamate alle altre funzioni (righe 3 e 4), volendo utilizzare il valore ritornato dalla funzione, tale valore è assegnato ad una variabile.

Nella riga 7 viene definita la funzione rilevaTemp che restituisce un valore indefinito (void). La funzione prepara il puntatore t per conservare l’indirizzo che gli viene passato dal chiamante: main passa alla funzione il puntatore temp, la funzione conserva tale puntatore in t che è locale, così come la variabile intera i definita nella riga successiva. Quando la funzione termina scompaiono sia t che i solo che t era un riferimento a temp e, quindi, le modifiche effettuate a t nella funzione, praticamente erano modifiche effettuate a temp. La variabile i invece, al termine della funzione, scompare senza lasciare alcuna traccia della sua esistenza.

La condizione di controllo del ciclo della riga 8 è espressa come i<RILEVAZ perché gli elementi del vettore sono in numero di RILEVAZ e quindi le posizioni utilizzabili vanno da 0 a RILEVAZ-1.

Per quanto riguarda la definizione della funzione della riga 9 valgono considerazioni analoghe alla definizione della funzione della riga 7 per quanto riguarda il vettore. Per gli altri parametri vengono preparati, dalla funzione, dei puntatori per poter permettere alla stessa la modifica dei valori contenuti.

Nella riga 10 è codificata utilizzando l’operatore ? una doppia condizione nidificata. Se la prima condizione è vera (t[i]<*tmn) viene effettuata l’assegnazione specificata. Se risulta falsa viene testata una nuova condizione (t[i]>*tmx). Anche qui se tale condizione è vera viene effettuata una assegnazione, se è falsa non c’è alcuna elaborazione: viene assegnato il valore 0 che, non essendoci alcuna variabile pronta per riceverlo, viene trascurato. Il valore deve essere espresso poiché l’operatore ? deve restituire sempre un valore.

Nella riga 11 viene definita una funzione che ritorna un valore di tipo float. Altrove questi sono gli unici sottoprogrammi che vengono chiamati funzioni, laddove i precedenti due (che in C sono funzioni che restituiscono un valore di tipo void) verrebbero chiamati procedure. Anche in questo caso nelle due righe successive sono dichiarate delle variabili locali.

Nella riga 12 viene ritornato al chiamante il valore atteso. La variabile media è dichiarata di tipo float in concordanza con il tipo di ritorno della funzione. La variabile è locale e quindi cessa la sua esistenza al cessare della funzione, ma in questo modo si rende noto al chiamante il valore contenuto in essa.



Avanti Indietro Inizio

http://ennebi.solira.org ennebi@solira.org