Sei sulla pagina 1di 33

FIL:

Astrazione Funzionale

Michele Nappi, Ph.D


Dipartimento di Matematica e Informatica
Università degli Studi di Salerno

mnappi@unisa.it
biplab.unisa.it
biplab unisa it
089-963334
Divide et impera

– Costruire un programma a partire da piccoli


pezzi o componenti

– Ciascun pezzo è meglio gestibile rispetto al


programma iniziale

11/24/2014 Michele Nappi 2


Le funzioni in C
– Modularizzano un programma: I programmi sono
scritti combinando funzioni definite dall’utente con
funzioni di libreria
• Le
L librerie
lib i standard
d d del
d l C hanno
h una gran varierà
i à di
funzioni
• Facilitano il lavoro del programmatore – evitano di
reinventare la ruota
• Permettono di estendere il set di operatori del C

11/24/2014 Michele Nappi 3


Lee funzioni
u o in C (co
(cont.)
t.)
• Vantaggi

– Divide
Di id et impera
i
• Sviluppo facile del programma

– Riusabilità del software


• Uso di funzioni esistenti come building blocks per nuovi programmi
• Astrazione – si nascondono i dettagli interni (funzioni di libreria)

– Si evita la ripetizione del codice

11/24/2014 Michele Nappi 4


Astrazione Funzionale
• C
Creazione
i di unità
ità di programma

– Nome assegnato ad un gruppo di istruzioni che in sequenza


logica implementano un
un’operazione
operazione non presente in LP
• Unità di programma

– Funzione
– Procedura

11/24/2014 Michele Nappi 5


Astrazione Funzionale (cont.)
( t)

• Funzione
– Astrazione della nozione di operatore su un TD primitivo o
definito dall’utente. Può essere attivata durante la
valutazione di una qualsiasi espressione
• Procedura
– Astrazione della nozione di istruzione su un TD primitivo
o definito dall’utente. Una procedura è di fatto
un’istruzione complessa è può essere attivata ovunque può
essere usata un’istruzione
un istruzione

11/24/2014 Michele Nappi 6


Astrazione Funzionale (cont.)
( t)

• F i
Funzione e Procedura
P d sono analoghe
l h dal
d l punto
t di vista
i t sintattico
i t tti e per ciò
iò che
h concerne le
l regole
l che
h governano la
l loro
l
valutazione

– Scopo di una Procedure è di modificare il contenuto di


l
locazioni
i i di memoria
i
– Scopo di una Funzione è restituire un valore all’interno
d ll’
dell’espressione
i dove
d è stata
t t invocata
i t

11/24/2014 Michele Nappi 7


Astrazione Funzionale (cont.)
( t)

• Di hi
Dichiarazione
i della
d ll funzione
f i (o
( procedura)
d )

– Il nome
– I parametri formali
– Il corpo, costituito da dichiarazioni locali e da una sequenza
di istruzioni
– Un tipo per il risultato

11/24/2014 Michele Nappi 8


Astrazione Funzionale (cont.)
( t)

Ti
Tipo del
d l risultato
i l N
Nome d
della
ll Funzione
F i

Parametri formali

1. int esempio(int i)
2
2. {
3. int k;
4
4. k i+5
k=i+5;
5. return(k%dim);
6. } Corpo della funzione

11/24/2014 Michele Nappi 9


Binding
• La dichiarazione di una variabile è definita binding (legame)

– All’
All’atto
tt della
d ll dichiarazione
di hi i il binding
bi di associa
i all TD tutte
t tt le
l
informazioni necessarie per il suo utilizzo
– Il ciclo di vita di queste informazioni legate alle variabile
nella dichiarazione è equivalente al tempo di attivazione del
programma (funzione o procedura) in cui compare la
dichiarazione

11/24/2014 Michele Nappi 10


Binding (
(cont.)
t)

1.
1 iint esempio(int
i (i i) • Il ciclo d vita di k
l di
2. { inizierà ogni volta che
3. int k; esempio sarà invocato e
terminerà nel momento
4. k=i+5; in cui la funzione
5. return(k%dim); restituisce il valore (step
6. } 5).
)
• I valori che k assume
durante le varie
chiamate sono
indipendenti tra di loro
11/24/2014 Michele Nappi 11
Binding (
(cont.)
t)

• Tutte le occorrenze del nome di un binding sono dette essere nell’ambito del binding
• Il binding di un nome x è visibile in punto del programma se un’occorrenza di x in quel punto ricadrebbe nell’ambito del
binding medesimo

11/24/2014 Michele Nappi 12


Binding (
(cont.)
t)

• Nome globale
11. iint esempio(int
i (i i)
– Visibile a tutte le
funzioni (o procedure) 2. {
• Nome locale 3. int k;
– Visibile solo nella 4. k=i+5;
funzione in cui è stato 5. return(k%dim);
dichiarato
6. }
• dim→globale
• i,k→locale
ik l l

11/24/2014 Michele Nappi 13


Legami tra parametri
• Il legame tra parametri si realizza durante la chiamata di
una funzione
• I parametri formali
– int exp(int base,
base int espon);
• base ed espon sono parametri formali
• Un pparametro fformale indica che un valore deve essere p
passato alla funzione e corrisponde
p ad una
variabile locale alla funzione

• I pparametri attuali
for (x = 1; x <= 10; x++)
printf(“%d “, exp(2, x));
• 2 e x sono parametri attuali
• Un parametro attuale è il valore effettivamente passato alla funzione. Questo valore viene assegnato al
corrispondente
p parametro
p formale all’atto della chiamata della ffunzione

11/24/2014 Michele Nappi 14


Classificazione Legami
• Legame per valore

– Si crea una copia della variabile trasmessa e non si altera il


valore originale al termine dell’esecuzione
– La variabile è quindi gestita in modo locale
• Legame per riferimento

– Si trasmette l’indirizzo della variabile


– Ogni modifica ha effetto sulla variabile stessa

11/24/2014 Michele Nappi 15


Definire
e e una
u a funzione
u o e
tipo-del-valore-restituito
ti d l l tit it nome_funzione
f i ( lista-parametri
li t t i)
{
dichiarazioni e istruzioni
}

– Nome
Nome-funzione
funzione : qualsiasi identificatore valido
– Tipo-del-valore-restituito: tipo del risultato
• void – la funzione non restituisce nulla
– Lista-parametri : lista separata da virgole, dichiara il tipo e il numero dei parametri
• void
id – la
l funzione
f i non riceve
i nulla
ll

11/24/2014 Michele Nappi 16


1/*
2 Trovare il massimo tra tre interi */
3#include <stdio.h>
4
5int massimo( int, int, int ); /* prototipo di funzione */
6
7int main()
8{
9 i
int a, b,
b c;
10
11 printf( “Inserisci tre interi: " );
12 scanf( "%d%d%d", &a, &b, &c );
13 printf( “Il
Il massimo è: %d\n"
%d\n , massimo( a,
a b,
b c ) );/*Chiamata*/
14
15 return 0;
16 }
17
18 /* definizione della funzione massimo */
19 int massimo( int x, int y, int z )
20 {
21 int max = x;
22
23 if ( y > max )
24 max = y;
25
26 if ( z > max )
27 max = z;
28
29 return max;
30 }
Inserisci tre interi: 22 85 17
Il massimo è: 85
Esempio:
p IL Fattoriale
/*Questo programmma effettua il calcolo del fattoriale*/

#include <stdio.h>
#include <math.h>

/*prototipi*/
int scegli_opzione(void);
scegli opzione(void);
int leggi_intero(void);
int fattoriale (int);
int stampa_fattoriale(int, int);

/*inizio main*/
int main(void)
{
int opzione,
p , fact,, intero,, temp=1;
p ;
do
{
opzione=scegli_opzione();
switch(opzione){
case 0:
0 temp=0;
t 0 break;
b k
case 1: intero=leggi_intero(); fact=fattoriale(intero); stampa_fattoriale(fact, intero); break;
}
}while(temp);
return 0;
}/*fine main*/
11/24/2014 Michele Nappi 18
Esempio: IL Fattoriale (cont.)
int scegli_opzione(void) #include <stdio.h>
{ /*prototipi*/
/* t ti i*/
int flag; int scegli_opzione(void);
char risposta; int leggi_intero(void);
int fattoriale (int);
do int stampa_fattoriale(int, int);
{ /*inizio main*/
printf("Questo programma calcola il fattoriale di un int main(void)
numero\n"); {
int opzione, fact, intero, temp=1;
printf("Che opzione scegli? (F)Fattoriale or (U)Uscita\n"); do
scanf("%s", &risposta); {
switch (risposta){ opzione=scegli_opzione();
switch(opzione)
case 'F':flag=1; break; {
case 'U':flag=0;
U :flag=0; break; case 0:
0 temp=0;
t 0 break;
b k
default: printf("Hai Sbagliato! Riprova\n"); flag=-1; case 1: intero=leggi_intero();
fact=fattoriale(intero);
break; stampa_fattoriale(fact, intero); break;
} }
}while(temp);
}while(flag==-1); return 0;
return (flag); }/*fine main*/
}

11/24/2014 Michele Nappi 19


Esempio: IL Fattoriale (cont.)
#include <stdio.h>
int leggi_intero(void)
{ /*prototipi*/
int scegli_opzione(void);
scegli opzione(void);
d bl numero, vint,
double i t vreal;
l int leggi_intero(void);
do int fattoriale (int);
{ int stampa_fattoriale(int, int);
printf("Inserisci un intero >=0\n"); /*inizio main*/
scanf("%lf",
f("%lf" &&numero); ) int main(void)
{
vreal=modf(numero,&vint); int opzione, fact, intero, temp=1;
if (numero>=0&&vreal==0) do
break; {
opzione=scegli_opzione();
else switch(opzione)
printf("Hai Sbagliato! Riprova\n"); {
}while(1); case 0: temp=0; break;
case 1: intero=leggi_intero();
intero=leggi intero();
return((int)vint); fact=fattoriale(intero);
} stampa_fattoriale(fact, intero); break;
}
}while(temp);
return
t 0;
0
}/*fine main*/

11/24/2014 Michele Nappi 20


Esempio: IL Fattoriale (cont.)
#include <stdio.h>
int fattoriale(int n)
/*prototipi*/
{ int scegli_opzione(void);
scegli opzione(void);
int temp; int leggi_intero(void);
int fattoriale (int);
if(n==0) int stampa_fattoriale(int, int);
return ((1);
); /*inizio main*/
int main(void)
else {
for(temp=1;n>=1;n--) int opzione, fact, intero, temp=1;
temp=temp*n; do
{
return(temp);
t (t ) opzione=scegli_opzione();
} switch(opzione)
{
case 0: temp=0; break;
case 1: intero=leggi_intero();
intero=leggi intero();
fact=fattoriale(intero);
int stampa_fattoriale (int fact, int intero) stampa_fattoriale(fact, intero); break;
{ }
printf("Il
p ( fattoriale di %d è %d : \n",intero,
, , fact);
); }while(temp);
return
t 0;
0
return 0; }/*fine main*/
}

11/24/2014 Michele Nappi 21


Visibilità delle variabili
• Ogni variabile è ‘locale’ alla funzione in cui è dichiarata

• Funzioni diverse possono dichiarare variabili distinte con lo stesso nome

• Visibilità ed allocazione:

– Allocazione e deallocazione automatica

11/24/2014 Michele Nappi 22


Risolvere problemi con la
decomposizione top
top--down

• Decomposizione top-down

– Analizzare il problema scomponendolo in sottoproblemi


– Ripetere la decomposizione in maniera gerarchica fino ad
arrivare a sottoproblemi di dimensione gestibile
– Risolvere ciascun sottoproblema progettando una funzione
specifica

11/24/2014 Michele Nappi 23


Risolvere problemi con la
decomposizione top
top--down (cont.)

• Vantaggi

– Programmi concettualmente ordinati e meglio documentati


– Modularità: ciascun sottoproblema può essere risolto in
maniera indipendente
– Manutenibilità: è più facile intervenire su parti del
programmi in maniera circoscritta

11/24/2014 Michele Nappi 24


U esempio:
Un i lal congettura
tt di Goldbach
G ldb h

“Ogni numero pari maggiore di 2 è somma di due numeri


primi” (Goldbach)

4 = 2+2
6 = 3+3
8 = 3+5
10 = 5+5
12 = 5+7
14 = 7+7
16 = 3+13
........
11/24/2014 Michele Nappi 25
LIVELLO 1 (funzione main)
a) stampare una intestazione
b) per tutti i valori K pari dell’intervallo
specificato stampare una linea del tipo:
K=i+j
con i e j numeri primi (se possibile)
c) se è stato coperto l’intero intervallo
stampare
t “G ldb h ha
“Goldbach h ragione”
i ”
altrimenti stampare “Goldbach si sbaglia”

11/24/2014 Michele Nappi 26


LIVELLO 1 (funzione main)

LIVELLO 2 (funzione stampa_linea)

a) calcolare la scomposizione relativa alla


linea K-esima
b) se la scomposizione è possibile stampare
una linea del tipo:
K=i+j
segnalando il successo
altrimenti segnalare il fallimento

11/24/2014 Michele Nappi 27


LIVELLO 1 (funzione main)

LIVELLO 2 (stampa
(stampa_linea)
linea)

LIVELLO 3 (funzione scomponi)

dato K, per tutti i valori i compresi fra 1 e K/2

se i è primo e K-i è primo


restituisci
tit i i i
altrimenti
restituisci 0

11/24/2014 Michele Nappi 28


LIVELLO 1 (funzione main)

LIVELLO 2 (stampa_linea)

LIVELLO 3 ((funzione scomponi)


p )

LIVELLO 4 (funzione primo)


dato i
a) se i è 2 restituisci 1 (vero)
b) se i è pari restituisci 0 (falso)
2
c) per tutti i valori j dispari fra 3 e √i
se i%j==0
j restituisci 0
d) restituisci 1
11/24/2014 Michele Nappi 29
#include
c ude <stdio.h>
std o.
LIVELLO 1 (funzione
(f i main)
i ) #include <math.h>
#define INIZIO 22
a)) stampare
p una intestazione #define FINE 144
b) per tutti i valori K pari dell’intervallo int stampa_linea (int );
specificato stampare una linea del int scomponi (int );
tipo: K=i+j int primo (int );

con i e j numeri primi (se possibile)


int main(void)
c) se è stato coperto l’intero intervallo
{
stampare “Goldbach ha ragione”
int k;
altrimenti stampare
printf("Ogni numero pari maggiore di 2 ”);
“Goldbach
Goldbach si sbaglia
sbaglia” printf(“e' somma di due primi?\n");
for (k = INIZIO; k <= FINE; k+=2)
if (!stampa_linea(k)) break;
if (k > FINE)
printf("E' vero! Goldbach ha ragione\n ");
else printf(”No! Goldbach si sbaglia\n");
}
11/24/2014 Michele Nappi 30
/*
* Function: stampa_linea
LIVELLO 2 (funzione stampa
stampa_linea)
linea) * Usage: stampa_linea(linea)
* -----------------------------------------
a) calcolare la scomposizione relativa * Ritorna 0 e non stampa nulla se linea non può
alla linea K-esima * essere scomposta; stampa la scomposizione di
* linea e restituisce 1 se ciò e' possibile.
b) se la scomposizione è possibile
*/
stampare una linea del tipo: i t stampa_linea
int t li (i t linea)
(int li )
K=i+j {
segnalando il successo int scomp;
altrimenti
lt i ti segnalare
l il fallimento
f lli t scomp = scomponi(linea);
if (scomp == 0) return (0);
printf(“%d = %d + %d\n", linea, scomp,
linea - scomp);
return (1);
}

11/24/2014 Michele Nappi 31


/*
* Function: scomponi
* Usage: scomponi(linea)
LIVELLO 3 (funzione scomponi) * --------------------------------------------------
* Scompone linea in 'i' e 'linea-i' entrambi numeri
dato K, per tutti i valori i compresi * primi
i i e restituisce
tit i i Se
i. S la
l scomposizione
i i non e''
* possibile, ritorna 0.
fra 1 e K/2
*/

se i è primo e K-i è primo int scomponi (int linea)


{
restituisci i
int i = 3;
altrimenti if (linea == 4) return 2;
restituisci 0 while (i <=linea/2) {
if (primo(i) && primo(linea-i)) return i;
i += 2;
}
return 0;
}
11/24/2014 Michele Nappi 32
/*
* Function: primo

LIVELLO 4 (funzione primo) * Usage:


U primo(numero)
i ( )
* ----------------------------------------------------
* Ritorna 1 se numero e' primo,
* 0 altrimenti.
dato i */
a) se i è 2 restituisci 1 (vero)
int primo (int numero)
b)) se i è p
pari restituisci 0 ((falso)) {
2
c) per tutti i valori j dispari fra 3 e √i int j;
if (numero == 2) return 1;
se i%j==0 restituisci 0
if (! numero % 2) return 0;
d) restituisci
tit i i 1 for (j = 3; j <=sqrt(numero); j += 2)
if (!(numero%j)) return 0;
return 1;
}

11/24/2014 Michele Nappi 33

Potrebbero piacerti anche