edutecnica

Concetto di funzione

     

Se nella realizzazione di un programma il codice diventa molto lungo o in più parti vengono ripetute sequenze di istruzioni uguali, è conveniente raggruppare segmenti di codice in moduli autonomi identificati da un nome.
Questi moduli, detti funzioni, possono essere eseguiti in ogni punto del programma in cui sono richiesti scrivendo semplicemente il loro nome.
L'organizzazione di un programma in funzioni comporta anche il vantaggio di poterlo suddividere in parti che possono essere modificate in maniera indipendente l’una dall’altra.

Definizione,dichiarazione e chiamata

     


Definizione:



tipo nome(tipo1 par1….,tipoN, parN){
Corpo..
}


Dichiarazione prototipo



tipo nome (tipo1 par1,…,tipoN parN);

par1,…,parN sono i parametri formali della funzione.

Chiamata



nome(esp1,…,espN);

esp1,…,espN sono dei valori(di variabili,costanti o espressioni) e rappresentano gli argomenti attuali della funzione.
Devono essere di tipo compatibile con quelli dei corrispondenti parametri formali.

Istruzione return

     

Il corpo di una funzione puo contenere una o più istruzioni return.

Sintassi



return espressione;

l’istruzione return termina l’esecuzione della funzione e associa al suo nome il valore di espressione. Se la funzione non restituisce un valore(funzioni void) return espressione non è presente.

Definizione di funzione

     


/* Funzione che calcola il massimo comune divisore MCD tra due numeri interi positivi*/
int Mcd(int a,int b){
  int resto;
  while(b!=0){
    resto=a%b;
    a=b
    b=resto;
    }
 return a
}   


Prototipo di funzione

     


Le funzioni devono essere anteposte al blocco di istruzioni della funzione main().
Se vogliamo collocare il codice delle funzioni dopo il blocco del main() dobbiamo preventivamente dichiararle attraverso un loro prototipo, costituito dal tipo, dal nome e dalla segnatura della funzione anteposto al blocco main().

/* Programma che chiama la funzione Mcd()per il calcolo del M.C.D. */

#include <iostream>
Using namespace std;
int Mcd(int a, int b);// prototipo
int main(){
int num1,num2;
cout<< "inserisci una coppia di numeri:";
cin>>num1>>num2;
cout <<"il M.C.D. tra"
<< num1<<" e " << num2
<< " vale:"
<< Mcd(num1,num2)// chiamata
<< endl;
}


Parametri e variabili locali

     

Un parametro formale è una variabile locale della funzione cui viene assegnato il valore del corrispondente argomento attuale al momento della chiamata. Le variabili locali di una funzione sono visibili solo nella funzione in cui sono dichiarate ed esistono soltanto durante la sua esecuzione. Al termine della funzione la memoria occupata delle variabili locali viene restituita al sistema.

Chiamata della funzione Mcd()

     

La chiamata di funzione Mcd (num1,num2) viene eseguita nel modo seguente:
1 I valori degli argomenti attuali, num1 e num2, vengono assegnati, rispettivamente, ai parametri formali a e b;
2 La funzione viene eseguita. I valori delle variabili locali a e b (i parametri formali) e della variabile resto sono modificati dalle istruzioni contenute nel corpo della funzione. Le modifiche dei parametri formali non si riflettono sui valori degli argomenti attuali, num1 e num2;
3 Il valore dell’ espressione che appare nell’istruzione return (il valore di a) viene associato al nome della funzione e ne rappresenta il valore di ritorno.

Funzioni void (procedure)

     

È possibile scrivere funzioni prive (void) di valore di ritorno.
Queste funzioni equivalgono a quelle che in altri linguaggi di programmazione sono conosciute come procedure.
Diversamente, dalle altre funzioni, non possono essere impiegate in espressioni ne possono contenere istruzioni return seguite da valori.

Esempio:



void Stampa (int a, int b) {
cout<<a<<’\t’<<b<<endl;
}


Funzioni ricorsive

     

Una funzione può chiamare qualsiasi altra funzione, compresa se stessa. In questi casi si parla di funzione ricorsiva.
Questa possibilità consente di semplificare la scrittura di programmi in cui risulta naturale formulare il problema da risolvere in maniera ricorsiva. Un esempio classico è il calcolo del fattoriale di un numero, definito come: n!=n·(n-1)! con 0!=1 .

Esempio di funzione ricorsiva

//Calcolo del fattoriale di un numero
Unsigned long Fatt (unsigned long n) {
if (n<2) return 1;
return n * Fatt (n-1);
}

Funzioni di libreria

     

Una libreria è un file che contiene un insieme di funzione precompilate. Il C++ possiede una libreria standard, disponibile in tutte le implementazioni standard del linguaggio e contenente le medesime funzioni. Assieme al file di libreria deve essere fornito almeno uno di intestazione (header file) contenente le dichiarazioni delle funzioni impiegate, e indicare al linker il nome de file di libreria.

Alcune funzioni della libreria standard

     


Header file <cmath>

 fabs(x) valore assoluto di x (reale);
 ceil (x) approssima x a un intero per eccesso;
 floor(x) approssima x a un intero per difetto;
 sqrt(x) radice quadrata di x;
 pow(x,y) eleva x alla potenza di y;
 exp(x) eleva e alla potenza di x;
 log(x) logaritmo naturale di x;
 log10(x) logaritmo in base 10 di x;
 sin(x) e asin(x) seno e arcoseno di x;
 cos(x) e acos (x) coseno e arcoseno di x;
 tan(x) e atan(x) tangente e arcotangente di x;

header file <cstdlib>

 abs(n) valore assoluto di n (intero);
 rand() numero pseudocasuale compreso tra 0 e la costante RAND_MAX (solitamente 32767);
 srand(n) inizializza il punto di partenza per la sequenza generata dalla funzione rand ();
 system(s) interpreta la stringa s come un comando del sistema operativo.

Esempio:

int maxrand=10; //n sarà un numero casuale compreso tra 0 e maxrand-1
n=rand()% maxrand;

Visibilità (scope) e durata (lifetime)

     

Visibilità:è la porzione di programma in cui un identificatore può essere referenziato per nome. Durata: è il periodo di tempo in cui un "oggetto" del programma occupa memoria. Può essere globale (se la durata coincide con quella di esecuzione del programma) o locale (quando la durata è limitata a quella di esecuzione di un blocco). Le funzioni hanno sempre durata globale.

Visibilità di una variabile

     

Visibilità a livello di file : la variabile può essere impiegata in tutte le espressioni del file sorgente dov'è dichiarata.
Visibilità locale : la variabile può essere usata solo all'interno del blocco che contiene la sua dichiarazione.
In caso di blocco nidificati, la dichiarazione di una variabile omonima "nasconde" quella dichiarata nel blocco superiore.

Esempio di visibilità

// visibilità a livello file
const double pi=3.14159;
int x; //variabile x globale
/* x,k e r hanno visibilità locale. All'interno di Funz() la x globale è nascosta dalla x locale */
int Funz(double x, int k) {
    double r;
    r=pi*x/k;
   . . .
}

Specificatore static

     

Lo specificatore static consente di modificare la visibilità o la durata di un "oggetto" del programma. Se è applicato a una variabile globale o a una funzione ne restringe la visibilià all'unità di traduzione in cui sono dichiarate. Se è applicato a variabili locali ne trasforma il periodo di vita in globale. Una variabile locale static viene inizializzata solo la prima volta che è eseguito il blocco in cui è dichiarata.

Esempio di variabile static

#include <iostream>
using namespace std;
usigned long Fibonacci();
int main() {
   for(int i=0; i<5; i++)
   cout<<Fibonacci()<<’\t’;
}

unsigned long Fibonacci() {
   static unsigned long f1=0; //var. globale
   static unsigned long f2=1;
   unsigned long f;
   f=f1+f2;
   f1=f2;
   f2=f;
   return f;
}

L’uscita prodotta sarà:

1   2  3   5   8

Dichiarazione e definizione

     

In un programma variabili e funzioni possono essere dichiarati molte volte, ma la loro definizione deve essere una sola. Se compaiono più dichiarazioni di una stessa variabile o funzione, esse devono essere identiche. Ogni definizione è, implicitamente, anche una dichiarazione.

Lo specificatore extern

     

Lo specificatore extern consente di rendere visibili variabili globali definite in altre unità di traduzione. L'uso di extern per le funzioni è opzionale.

Esempio

Primo file

int x = 5; //definizione di x
//definizione di Quadrato
int Quadrato(int y){
return y * y;
}

Secondo file

#include<iostream>
using namespace std;
//dichiarazioni di x e Quadrato
extern int x; //rende visibile la x
int Quadrato(int);
int main(){
  cout<<Quadrato(x)<<endl;
}

Il valore visualizzato sarà 25.

Programmazione modulare

     

Programmi di grosse dimensioni possono essere suddivisi in più file, ovvero è possibile creare una struttura modulare.

Esempio : programma su un solo file

double Sum(double x, double y) {return x + y;}
double Diff(double x, double y) {return x - y;}
int main(){
...
switch(operazione){
  case 1: Sum(x, y); break;
  case 2: Diff(x, y); break;
  }
  ...
}

Scrivendo lo stesso programma su più file ogni file sarà compilato separatamente. Il linker ha il compito di associare le dichiarazioni di variabili e funzioni presenti in un file con le corrispondenti definizioni presenti negli altri file.

Lo stesso programma su più file

//file main.cpp
#include "funz.h"
main(){
  ...
  switch(operatore){
  case 1: Sum(x, y); break;
  case 2: Diff(x, y); break;
  }
  ...
}

//file funz.h
double Sum(double, double);
double Diff(double, double);

//file funz.cpp
double Sum(double x, double y) {return x + y;}
double Diff(double x, double y) {return x - y;}