edutecnica
 


Sviluppo top-down e funzioni

Quando il livello di complessità del software conviene dividere il programma in sottoprogrammi più semplici (metodologia top-down). Si definisce quali siano le parti fondamentali di cui si compone il programma (top) per poi procedere allo sviluppo dettagliato di ogni singola parte (down).
Ogni parte che compone il programma, corrisponde ad un modulo che svolge una specifica funzionalità, il programma viene quindi scomposto in moduli funzionalmente indipendenti.
Tutto ciò facilità la manutenzione del software, in oltre alcuni moduli, essendo funzionalmente indipendenti, possono essere riutilizzati, senza bisogno di ulteriori modifiche all'interno di altri programmi.
Nel linguaggio C i sottoprogrammi vengono chiamate funzioni.

Funzioni

Una funzione è un procedimento che riceve dei valori come argomenti in ingresso e restituisce un solo valore come risultato

tipo_di_dato_restituito nome_funzione(elenco_dei_parametri){
istruzioni;
return valore_restituito;
}


Poiché la funzione restituisce un solo valore, occorre specificare , prima del nome che identifica la funzione, il tipo del valore restituito.
Dopo il nome della funzione le parentesi tonde servono per contenere l'elenco degli argomenti passati alla funzione, detti parametri formali.
Il corpo della funzione contiene come ultima istruzione la parola return seguita dal valore o dalla variabile contenente il risultato restituito dalla funzione.
L'istruzione return provoca il ritorno del controllo alla funzione principale o in generale alla funzione chiamante (che può essere anche il main).
Se si vuole invece che la funzione non restituisca alcun valore, bisogna specificare come tipo di dato restituito, il tipo void.
Nelle funzioni di tipo void l'istruzione return non deve essere inserita.


void nome_funzione(elenco_dei_parametri){
istruzioni;
}


L'elenco dei parametri è sostanzialmente una dichiarazione di variabili; i parametri sono separati dalla virgola e per ciascun parametro deve essere indicato il tipo.

tipo nome_funzione(tipo1 nome1,tipo2 nome2,…)

int fun(int x,float y)

La chiamata di una funzione può essere fatta da qualsiasi punto del programma, dopo che la funzione é stata dichiarata e definita: occorre specificare il nome della funzione seguito dall'elenco dei parametri.
E' possibile effettuare una chiamata di una funzione da un qualunque punto del programma, dopo averla dichiarata e definita: occorre specificare il nome della funzione seguita dall'elenco dei parametri (tra parentesi tonde)
Sintassi della chiamata ad una funzione:

nome_funzione(elenco_parametri);

Esempio di funzione che riceve in ingresso due numeri interi e restituisce un intero:

int somma(int a,int b){
int x ;
x=a+b ;
return x ;
}


Esempio di funzione void

void stampasomma(int a,int b){
int sum;
sum=a+b;
cout << sum;
}

La prima deve erssere dichiarata col tipo di dato restituito, la seconda che non deve restituire al programma chiamante nessun dato ma deve solo eseguire una stampa a video, deve essere dichiarata di tipo void.

Il main è a tutti gli effetti una funzione: questo è il motivo per cui si scrive main( ), tuttavia la funzione main ha una caratteristica specifica: è la funzione che viene eseguita per prima all'avvio del programma e dalla quale vengono chiamate tutte le altre funzioni.

L'istruzione return può essere presente anche nel main e in tal caso rappresenta il valore restituito dal programma al sistema operativo.

Variabili locali e variabili globali (regole di visibilità)

In un programma le variabili globali sono dichiarate all'inizio, dopo le direttive d'inclusione(librerie) al di fuori del main .



esse sono chiamate variabili globali in contrapposizione alle variabili locali dichiarate all'inizio di ogni funzione.
Le variabili globali possono essere usate da qualsiasi punto del programma invece quelle locali possono essere usate soltanto all'interno della funzione nella quale sono state dichiarate.
I parametri di una funzione sono a tutti gli effetti delle variabili locali alla funzione a cui si riferiscono: essi sono come variabili implicitamente dichiarate.

L'idea di organizzare programmi in moduli funzionalmente indipendenti porta con se la necessità di definire all'interno della funzione tutte le variabili necessarie al suo funzionamento:in realtà spesso in un programma una funzione può condividere variabili con altre funzioni. In un programma si possono distinguere:
Variabili globali che vengono dichiarate all'inizio del programma e che possono essere usate dal programma principale e da tutte le funzioni. Le variabili locali che vengono dichiarate all'interno della funzione che le utilizza e che non sono visibili alle altre funzioni.
E' da ricordare che anche le variabili dichiarate nel main sono di tipo locale dato che il main è una funzione a sua volta e quindi le variabili dichiarate nel main non sono visibili nelle altre funzioni.
Un programma ben strutturato avrà poche variabili globali e molte variabili locali, per consentire una facile manutenzione e una maggior possibilità di riusare i moduli funzionali in altri programmi.
Alle variabili locali vengono riservate posizioni nella memoria centrale(RAM) solo al momento dell'esecuzione della funzione. Lo spazio viene creato all'inizio e rilasciato al termine della funzione, liberando quindi spazio nella memoria utente: una ragione in più per usare molte variabili locali e molte variabili globali.
Regole di visibilità:ogni ambiente (identificato da una coppia di parentesi graffe) vede:

1)le proprie risorse locali
2)quelle definite all'esterno e prima dell'ambiente stesso

In sostanza una funzione compreso il main può usare tutte le variabili locali e quelle globali che hanno nomi diversi da quelle locali.

Funzioni con parametri

L'operazione con la quale il main (o un'altra funzione chiamante) invia i valori ad una funzione, assegnandoli ai parametri si chiama passaggio di parametri.
Le variabili indicate nell'intestazione della funzione si chiamano parametri formali, le variabili che forniscono i valori ai parametri si chiamano parametri attuali:

float sup(int ray){ //ray parametro formale
float superficie; //variabile locale a sup

superficie=3.14*ray*ray;
return superficie;
}

main ( ){
int R=4;
float AREA;

//invocazione della funzione sup
AREA=sup(R); //R parametro attuale
cout << AREA;
}

Passaggio di parametri

All'operazione sono associate le due liste dei parametri attuali e dei parametri formali, è detta passaggio dei parametri, possono avvenire in due modi diversi.

Passaggio di parametri per valore: quando i valori delle variabili della funzione principale vengono ricopiati nei parametri della funzione; i cambiamenti effettuati sui parametri formali durante l'esecuzione della funzione non influenzano i valori delle variabili nella funzione chiamante.

#include<iostream.h>
void fun(int a,int b){
   a=a+b;
   cout << "fun:" << a<< " " << b << "\n";
} //fine fun
main (){
int x=2,y=3;
   fun (x,y);
   cout<< "main:" << x << " " << y;
}//fine main

#include<iostream.h>
void fun(int a){
   a++;
   cout << "fun:" << a << "\n";
} //fine fun
main (){
int x=2;
   fun (x);
   cout << "main:" << x;
} //fine main


Passaggio di parametri per indirizzo(per referenza): quando i parametri attuali e formali fanno riferimento alla stessa cella di memoria, cioè allo stesso indirizzo di memoria; questo è il caso in cui il programmatore vuole che i cambiamenti di valore ai parametri durante l'esecuzione della funzione, influenzino i valori delle variabili corrispondenti nella funzione chiamante.
Nel linguaggio C il passaggio di parametri avviene indicando nell'intestazione della funzione il tipo e il nome di ciascun parametro formale.
Durante il passaggio dei parametri per indirizzo, la funzione non opera su una copia locale dei dati ma direttamente su i dati originali.
Per attivare questo tipo di comportamento è necessario passare anziché la variabile, direttamente su indirizzo, in modo che la funzione veda la locazione di memoria dove è contenuta la variabile e possa dunque modificarla.

Per indicare il passaggio di un parametro per indirizzo, si deve aggiungere il carattere & subito dopo la dichiarazione del tipo del parametro.

#include<iostream.h>
void fun(int &a,int &b){
   a=a+b;
   cout << "fun:" << a << " " << b << "\n";
} //fine fun
main (){
int x=2,y=3;
   fun (x,y);
   cout << "main:" << x << " " << y;
}

Prototipi di funzione

Le funzioni possono comparire in qualsiasi ordine nel file sorgente; esse però devono essere definite prima di essere utilizzate dal main o da altre funzioni.
L'ordine in cui le funzioni sono definite è quindi importante: infatti la funzione non può richiamare un'altra se quest'ultima non è stata ancora definita.
Per questa ragione e per una migliore organizzazione del programma, è opportuno inserire le funzioni nel codice sorgente attraverso due fasi distinte:

Dichiarazione della funzione per mezzo del suo prototipo.
Definizione(o implementazione) della funzione.

La dichiarazione della funzione che si intende usare nel programma, di norma va imposta in testa al programma subito dopo le direttive di inclusione ed assieme alle variabili globali.
Tramite la dichiarazione, il programmatore si limita ad comunicare al compilatore la sua intenzione di usare una funzione che restituisca un dato di un certo tipo e che utilizza determinati parametri, riservandosi di specificare il codice in seguito, nella fase di definizione.
Questa dichiarazione si chiama prototipo della funzione.
La sintassi per la dichiarazione di un prototipo è:

tipo nomeFunzione(elencoParametri);

La definizione(o implementazione) della funzione, con le istruzioni che la compongono viene normalmente posta dopo la funzione main.

All'inizio del programma le funzioni vengono soltanto dichiarate. Specificandone per ciascuna il tipo restituito, il nome e i parametri richiesti. In questo modo si ottiene una semplice elencazione dei prototipi che facilita la comprensione del programma.

 




edutecnica