Funzioni e sviluppo top

Transcript

Funzioni e sviluppo top
Funzioni e sviluppo top - down
• costruire programmi modificando programmi
esistenti
• funzioni di libreria
• sviluppo top-down e diagrammi di struttura
• funzioni senza argomenti
• funzioni con argomenti
1
Costruire programmi modificando
programmi esistenti
è spesso possibile riutilizzare parti di codice preesistenti
nella costruzione di nuovi programmi
Esempio:
• calcolare l’area e la circonferenza di un cerchio
• calcolare il peso di un insieme di rondelle
2
Area e circonferenza di un cerchio
Problema:
dato il raggio di un cerchio, calcolarne l’area e la
circonferenza
Analisi:
l’input del problema è il raggio del cerchio;
ci sono due output: area e circonferenza;
il raggio può essere un numero reale, quindi utilizzo
variabili di tipo double;
mi occorrono le relazioni geometriche tra raggio e
area di un cerchio e tra raggio e circonferenza
3
Analisi - richieste sui dati
Costanti del problema
PI = 3.14159
Dati in input
double radius
/* raggio del cerchio
*/
Dati in output
double area
/* area del cerchio
*/
double circum /* circonferenzza del cerchio */
Formule utilizzate
radius 2
area = !
circumference = 2!
radius
4
Progettazione
Algoritmo iniziale
1. prendi il raggio
2. calcola l’area
3. calcola la circonferenza
4. visualizza area e circonferenza
Raffinamenti dell’algoritmo
Raffinamento del passo 2
2.1 assegna PI * radius * radius ad area
Raffinamento del passo 3
3.1 assegna 2 * PI * radius a circum
5
Fase di implementazione
nelle fasi di analisi e progettazione ho prodotto la
seguente documentazione:
• descrizione delle richieste sui dati (fase di analisi)
• algoritmo che risolve il problema (fase di progettazione)
utilizzo queste informazioni come punto di partenza per
la produzione del codice:
• trasformo le richieste sui dati in definizioni di costanti
e dichiarazioni di variabili
• utilizzo i passi dell’algoritmo e i raffinamenti come
commenti
• scrivo il codice C corrispondente sotto ogni
(sotto)passo non raffinato
6
/*
* Calcola area e circonferenza di un cerchio
*/
#include <stdio.h>
#define PI 3.14159
int
main(void)
{
double radius;
/* input - raggio del cerchio
double area;
/* output - area del cerchio
double circum;
/* output - circonferenza del
cerchio
/* prendi il raggio */
*/
*/
*/
/* calcola l’area */
/* assegna PI * radius * radius ad area */
/* calcola la circonferenza */
/* assegna 2 * PI * radius a circum */
/* visualizza area e circonferenza */
return (0);
}
7
/*
* Calcola area e circonferenza di un cerchio
*/
#include <stdio.h>
#define PI 3.14159
int
main(void)
{
double radius;
double area;
double circum;
/* input - raggio del cerchio
/* output - area del cerchio
/* output - circonferenza del
cerchio
*/
*/
*/
/* prendi il raggio */
printf("Inserisci il raggio> ");
scanf("%lf", &radius);
/* calcola l’area */
area = PI * radius * radius;
8
/* calcola la circonferenza */
circum = 2 * PI * radius;
/* visualizza area e circonferenza */
printf("Area = %.4f\n", area);
printf("Circonferenza = %.4f\n", circum);
return (0);
}
9
Test
utilizzare un raggio per il quale sia semplice calcolare
a mano l’area e la circonferenza
Inserisci il raggio> 5.0
Area = 78.5397
Circonferenza = 31.4159
10
Calcolare il peso totale di un
insieme di rondelle
esempio di utilizzo della soluzione di un problema per
risolvere un problema più complesso
Problema
Un’azienda produttrice di rondelle deve stimare i costi
di spedizione.
Scrivere un programma che calcola il peso di una
quantità specificata di rondelle.
11
Analisi
Per calcolare il peso di una rondella devo conoscere
l’area, lo spessore e la densità del materiale utilizzato;
spessore e densità sono dati di input;
l’area del bordo della rondella si calcola a partire da
due dati forniti in input: il diametro interno e il diametro
esterno;
utilizzo come dati intermedi il raggio interno ed esterno,
l’area del bordo della rondella e il peso di una singola
rondella.
Per fornire in output il peso complessivo dovrò conoscere
la quantità di rondelle.
12
Analisi - richieste sui dati
Costanti del problema
PI = 3.14159
Dati in input
double hole_diameter
double edge_diameter
double thickness
double density
double quantity
Dati in output
double weight
/* diametro del buco
/* diametro esterno
/* spessore della rondella
/* densita’ del materiale
/* numero di rondelle
*/
*/
*/
*/
*/
/* peso totale
*/
13
Analisi - richieste sui dati
Variabili del programma
double hole_radius
/* raggio del buco
double edge_radius /* raggio esterno
double rim_area
/* area del bordo
doble unit_weight
/* peso di 1 rondella
*/
*/
*/
*/
Formule utilizzate
raggio 2
area del cerchio = !
raggio del cerchio = diametro /2
area del bordo = area cerchio esterno - area cerchio interno
peso unitario = area del bordo spessore densità
14
Progettazione
Algoritmo iniziale
1. prendi diametro interno, diametro esterno e spessore
di una rondella
2. prendi densità del materiale e quantità di rondelle
3. calcola l’area del bordo della rondella
4. calcola il peso di una rondella
5. calcola il peso totale
6. visualizza il peso totale
15
Progettazione
Raffinamento passo3
3.1 calcola hole_radius e edge_radius
3.2 rim_area è PI * edge_radius * edge_radius PI * hole_radius * hole_radius
Raffinamento passo 4
4.1 unit_weight è rim_area * thickness * density
16
/*
* Calcola il peso di una quantita’ specificata di rondelle.
*/
#include <stdio.h>
#define PI 3.14159
int
main(void)
{
double
double
double
double
double
double
double
double
double
double
hole_diameter;
edge_diameter;
thickness;
density;
quantity;
weight;
hole_radius;
edge_radius;
rim_area;
unit_weight;
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
input - diametro del buco
input - diametro esterno
input - spessore della rondella
input - densita’ del materiale
input - numero di rondelle
output - peso totale
raggio del buco
raggio esterno
area del bordo
peso di una rondella
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
17
/* Prendi diametro interno, diametro esterno e spessore
di una rondella.*/
printf("Inner diameter in centimeters> ");
scanf("%lf", &hole_diameter);
printf("Outer diameter in centimeters> ");
scanf("%lf", &edge_diameter);
printf("Thickness in centimeters> ");
scanf("%lf", &thickness);
/* Prendi densita’ del materiale e quantita’ di rondelle. */
printf("Material density in grams per cubic centimeter> ");
scanf("%lf", &density);
printf("Quantity in batch> ");
scanf("%lf", &quantity);
/* Calcola l’area del bordo della rondella */
hole_radius = hole_diameter / 2.0;
edge_radius = edge_diameter / 2.0;
rim_area = PI * edge_radius * edge_radius PI * hole_radius * hole_radius;
18
/* Calcola il peso di una rondella. */
unit_weight = rim_area * thickness * density;
/* Calcola il peso totale. */
weight = unit_weight * quantity;
/* Visualizza il peso totale. */
printf("\nThe expected weight of the batch is %.2f", weight);
printf(" grams.\n");
return (0);
}
19
Test
• utilizzare dati per i quali è sempice verificare la
correttezza del risultato (es. diametro interno = 2
e diametro esterno = 4 forniscono un’area del
bordo = 3!)
• prima verificare il calcolo del peso unitario
(quantità = 1)
• verificare quindi il calcolo del peso totale
(quantità = 1000)
20
Esempio di test
Inner diameter in centimeters> 2
Outer diameter in centimeters> 4
Thickness in centimeters> 1
Material density in grams per cubic centimeter> 1
Quantity in batch> 1000
The expected weight of the batch is 9424.78 grams.
21
Esercizio
Le rondelle vengono ricavate da lastre di materiale
di forma rettangolare e di spessore uniforme.
Scrivere un programma che calcola
• la quantità di materiale (in cm 2 ) necessaria per
fabbricare una data quantità di rondelle;
• il peso del materiale di scarto.
22
Funzioni predefinite
Riutilizzo di codice
obiettivo: produrre codice senza errori
riutilizzo di parti di codice già scritte e testate
il C fornisce librerie di funzioni predefinite che
permettono, ad esempio, di effettuare calcoli
matematici
23
Esempio: radice quadrata
chiamata a
funzione
y = sqrt(x);
nome della
funzione
parametro
La chiamata a funzione attiva il codice della funzione
sqrt, passando il contenuto della variabile x come
argomento.
Al termine dell’esecuzione della funzione, il risultato della
funzione è sostituito al posto della chiamata.
24
Esempio
y = sqrt(x);
x
16.0
y
??
x
16.0
y
4.0
1. x contiene 16.0, quindi sqrt calcola 16.0, che
è 4.0
2. il risultato della funzione, 4.0, viene assegnato a y
25
Black box
Una funzione può essere vista come una “scatola nera”:
fornendogli uno o più valori in input, questa ritorna
automaticamente un valore in output
y = sqrt(x);
16.0
calcolo della
radice quadrata
il risultato
è 4.0
26
Esempio
z = 5.7 + sqrt(w);
w
9.0
z
??
w
9.0
z
8.7
1. w contiene 9.0, quindi sqrt calcola 9.0, che è 3.0
2. i valori 5.7 e 3.0 vengono sommati
2. il risultato della della somma, 8.7, viene assegnato a z
27
/*
* Performs three square root computations
*/
#include <stdio.h> /* definitions of printf, scanf */
#include <math.h> /* definition of sqrt */
int
main(void)
{
double first, second,
first_sqrt,
second_sqrt,
sum_sqrt;
/*
/*
/*
/*
input - two data values
output - square root of first
output - square root of second
output - square root of sum
/* Get first number and display its square root. */
printf("Enter the first number> ");
scanf("%lf", &first);
first_sqrt = sqrt(first);
printf("The square root of the first number is %.2f\n",
first_sqrt);
28
*/
*/
*/
*/
/* Get second number and display its square root. */
printf("Enter the second number> ");
scanf("%lf", &second);
second_sqrt = sqrt(second);
printf("The square root of the second number is %.2f\n",
second_sqrt);
/* Display the square root of the sum of the two numbers. */
sum_sqrt = sqrt(first + second);
printf("The square root of the sum is %.2f\n",
sum_sqrt);
return (0);
}
29
Test
Enter the first number> 9.0
The square root of the first number is 3.00
Enter the second number> 16.0
The square root of the second number is 4.00
The square root of the sum is 5.00
Note
• il programma effettua tre chiamate alla funzione
sqrt;nell’ultima chiamata, l’argomento della funzione
è un’espressione.
• ogni istruzione è una chiamata a una funzione di libreria;
ho utilizzato le funzioni predefinite del C come blocchi
per la costruzione del programma
30
Funzioni di libreria
abs(x)
ritorna il valore assoluto dell’argomento
(di tipo int)
standard header file: <stdlib.h>
argomento: int
risultato: int
Es: abs(-5) è 5
abs(2) è 2
31
Funzioni di libreria
Se una funzione di libreria viene chiamata con un
argomento di tipo diverso da quello richiesto, l’argomento
viene convertito nel tipo richiesto prima di essere usato.
La conversione da double a int provoca una perdita
di informazione.
Es: abs(-4.36)
è 4
Per calcolare il valore assoluto di numeri reali bisogna
utilizzare la funzione fabs
32
Funzioni di libreria
fabs(x)
ritorna il valore assoluto dell’argomento
(di tipo double)
standard header file: <math.h>
argomento: double
risultato: double
Es: fabs(-5.348) è
fabs(203)
è
5.348
203.0
33
Funzioni di libreria in <math.h>
cos(x)
sin(x)
tan(x)
coseno dell’angolo x
seno dell’angolo x
tangente dell’angolo x
argomento: double (in radianti)
risultato: double
Es: cos(0.0)
è 1.0
34
Funzioni di libreria in <math.h>
exp(x)
log(x)
log10(x)
sqrt(x)
e x (e = 2.718...)
logaritmo naturale di x (per x > 0.0)
logaritmo in base 10 di x (per x > 0.0)
radice quadrata di x (per x " 0.0)
argomento: double
risultato: double
Es: log10(100.0)
è 2.0
35
Funzioni di libreria in <math.h>
pow(x,y)
ritorna x y
se x è negativo, y deve essere intero (non deve avere
cifre decimali)
argomenti: double
risultato: double
Es.: pow(9.0, 0.5)
pow(4.0, -1.0)
pow(-2.0, 2.0)
pow(-2.0, 3.0)
è 3.0
è 0.25
è 4.0
è -8.0
36
Funzioni di libreria in <math.h>
ceil(x)
floor(x)
il più piccolo valore intero (senza
decimali) non minore di x
il più grande valore intero (senza
decimali) non maggiore di x
argomento: double
risultato: double
Es.: floor(45.23)
ceil(45.23)
ceil(-45.23)
è
è
è
45.0
46.0
-45.0
37
Esempio
Calcolare le radici dell’equazione
ax 2 + bx + c = 0
quando il discriminante è positivo
root 1 =
root 2 =
- b + b 2 - 4ac
2a
- b - b 2 - 4ac
2a
38
/* Compute two roots, root_1 and root_2,
for disc > 0.0 */
disc = pow(b, 2) - 4 * a * c;
root_1 = (-b + sqrt(disc)) / (2 * a);
root_2 = (-b - sqrt(disc)) / (2 * a);
39
Funzione definite dall’utente
Supponiamo di aver definito le funzioni
find_area(r)
ritorna l’area di un cerchio
di raggio r
find_circum(r) ritorna la circonferenza di un
cerchio di raggio r
queste funzioni possono essere utilizzate direttamente
nei programmi per il calcolo di area e circonferenza e
per il calcolo del peso delle rondelle, rendendo tali
programmi più chiari e leggibili
40
...
rim_area = PI * edge_radius * edge_radius PI * hole_radius * hole_radius;
...
può essere sostituita da
...
rim_area = find_area(edge_radius) find_area(hole_radius);
...
41
Sviluppo top - down
metodo per la soluzione di problemi:
• il problema viene suddiviso in sottoproblemi
• ogni sottoproblema viene risolto
• le soluzioni ai sottoproblemi vengono combinate
per ottenere la soluzione al problema iniziale
Diagramma della struttura
strumento di documentazione che evidenzia le
relazioni tra il problema e i sottoproblemi
42
Esempio: disegnare semplici figure
Problema:
disegnare sullo schermo figure del tipo seguente:
***
*
/ \
/
***
/ \
\
/
\
------|
|
/
|
|
-------
*
\
/
\
------/ \
/
\
/
\
43
Analisi:
La casa è formata da un triangolo senza base sopra
ad un rettangolo.
La figura stilizzata è costituita da un cerchio, un triangolo
e un triangolo senza base.
Entrambe le figure possono essere disegnate a partire
dalle seguenti componenti:
• un cerchio
• una linea orizzontale
• due linee parallele
• due linee che si intersecano
44
Progettazione (figura stilizzata):
Algoritmo iniziale
1. disegna un cerchio
2. disegna un triangolo
3. disegna due linee che si intersecano
Raffinamento del passo 2
2.1 disegna due linee che si intersecano
2.2 disegna una linea orizzontale
45
Diagramma della struttura
disegna una
figura
problema
originario
sottoproblemi
1° livello
sottoproblemi
2° livello
disegna un
cerchio
disegna un
triangolo
disegna linee
intersecanti
disegna linee
intersecanti
disegna linea
orizzontale
46
Nota
i sottoproblemi appaiono sia nell’algoritmo che
nel diagramma di struttura;
• l’algoritmo specifica l’ordine in cui vengono
eseguiti i sottoproblemi;
• il diagramma di struttura specifica le relazioni
tra problema originario e sottoproblemi
47
Funzioni senza argomenti
• prototipo di funzione
• definizione di funzione
• disposizione delle funzioni nel programma
• ordine di esecuzione delle funzioni e del main
• vantaggi derivati dall’uso di funzioni
• visualizzazione di istruzioni per l’utente
48
Funzioni senza argomenti
Le funzioni definite dall’utente permettono di
implementare facilmente gli algoritmi sviluppati
con metodo top-down:
per ogni sottoproblema, viene definita una funzione
che lo implementa.
Il tipo più semplice di funzione non ha argomenti
e non ritorna valori.
49
/*
* Draws a stick figure
*/
#include <stdio.h>
/* function prototypes
*/
void draw_circle(void);
/* Draws a circle
*/
void draw_intersect(void);
/* Draws intersecting lines */
void draw_base(void);
/* Draws a base line
*/
void draw_triangle(void);
/* Draws a triangle
*/
50
int
main(void)
{
/* Draw a circle.
draw_circle();
/* Draw a triangle.
draw_triangle();
*/
*/
/* Draw intersecting lines.
draw_intersect();
*/
return (0);
}
51
Istruzione di chiamata a funzione
(funzioni senza argomenti e valore di ritorno)
Sintassi
fname();
Esempi
draw_circle();
Viene invocata la funzione fname.
Quando fname ha terminato l’esecuzione, l’esecuzione
procede con l’istruzione che segue la chiamata a fname.
Le parentesi dopo fname indicano che si tratta di una
funzione che non richiede argomenti.
52
Prototipi di funzione
Come gli altri identificatori, una funzione deve essere
dichiarata prima dell’uso.
Una funzione può essere dichiarata inserendo un
prototipo di funzione prima della funzione main.
Il prototipo comunica al compilatore:
• il tipo di dato della funzione
• il nome della funzione
• informazioni sugli argomenti della funzione
53
Prototipo di funzione
(funzione senza argomenti)
sintassi
ftype fname(void);
esempi
void draw_circle(void);
L’identificatore fname è il nome della funzione.
ftype specifica il tipo di dato del risultato della funzione.
ftype è void se la funzione non ritorna un valore.
La lista di argomenti (void) indica che la funzione non
ha argomenti.
Il prototipo di funzione deve apparire prima della prima
chiamata alla funzione.
54
Definizione di funzione
• il prototipo specifica gli argomenti della funzione e il
valore ritornato;
• le operazioni effettuate dalla funzione sono specificate
nella definizione della funzione
/*
* Draws a circle
*/
void
draw_circle(void)
{
printf(“ *** \n”);
printf(“*
*\n”);
printf(“ *** \n”);
}
55
Definizione di funzione
• l’intestazione della funzione è simile al prototipo
(viene omesso il ; finale)
• il corpo della funzione contiene le operazioni effettuate
dalla funzione
• l’istruzione return è omessa perchè la funzione
non ritorna un risultato
L’istruzione di chiamata a funzione
draw_circle();
causa l’esecuzione delle 3 printf; il controllo ritorna alla
funzione main dopo che il cerchio è stato visualizzato.
56
Definizione di funzione
(funzione senza argomenti)
sintassi
ftype
fname(void)
{
local_declarations
executable statements
}
esempio
/*
* Displays a block letter H
*/
void
print_h(void)
{
printf(“** **\n”);
printf(“** **\n”);
printf(“******\n”);
printf(“** **\n”);
printf(“** **\n”);
}
57
Definizione di funzione
(funzione senza argomenti)
Viene definita la funzione fname.
Nell’intestazione della funzione, ftype specifica il tipo
del risultato della funzione.
Le parentesi graffe racchiudono il corpo della funzione.
Gli identificatori dichiarati nelle local declarations sono
definiti solo durante l’esecuzione della funzione e possono
essere usati solo all’interno della funzione.
Gli executable statements descrivono le operazioni
effettuate dalla funzione.
58
il sottoproblema disegna un triangolo è ulteriormente
scomposto in due sottoproblemi: disegna linee intersecanti
e disegna linea orizzontale.
Lo sviluppo top-down viene utilizzato per implementare
la funzione che disegna il triangolo:
/*
* Draws a triangle
*/
void
draw_triangle(void)
{
draw_intersect();
draw_base();
}
59
/* Draws a stick figure */
#include <stdio.h>
/* Function prototypes */
void draw_circle(void);
/* Draws a circle
void draw_intersect(void);
/* Draws intersecting lines */
void draw_base(void);
/* Draws a base line
*/
void draw_triangle(void);
/* Draws a triangle
*/
*/
int
main(void)
{
/* Draw a circle.
draw_circle();
*/
/* Draw a triangle.
draw_triangle();
*/
60
/* Draw intersecting lines.
draw_intersect();
*/
return (0);
}
/*
* Draws a circle
*/
void
draw_circle(void)
{
printf(" ***
\n");
printf(" *
* \n");
printf(" *** \n");
}
61
/*
* Draws intersecting lines
*/
void
draw_intersect(void)
{
printf(" / \\ \n"); /* Use 2 \'s to print 1 */
printf(" /
\\ \n");
printf("/
\\\n");
}
/*
* Draws a base line
*/
void
draw_base(void)
{
printf("-------\n");
}
62
/*
* Draws a triangle
*/
void
draw_triangle(void)
{
draw_intersect();
draw_base();
}
63
Disposizione delle funzioni all’interno del programma
• i prototipi precedono la funzione main (appaiono dopo
le direttive #include e #define)
• le definizioni si trovano dopo la funzione main
• l’ordine relativo delle definizioni di funzioni non influisce
sul loro ordine di esecuzione; l’ordine di esecuzione è
determinato dall’ordine in cui vengono effettuate le
chiamate
Uso dei commenti
ogni definizione di funzione è preceduta da un commento
che descrive lo scopo della funzione.
64
Ordine di esecuzione delle funzioni
e del main
• i prototipi forniscono al compilatore informazioni sulle
funzioni utilizzate
• ogni chiamata a funzione viene tradotta in un
trasferimento del controllo al codice della funzione
• al termine del corpo di ogni funzione, il compilatore
aggiunge un’istruzione in linguaggio macchina che
trasferisce il controllo all’istruzione che segue la
chiamata alla funzione
65
Ordine di esecuzione delle funzioni
e del main
funzione main
draw_circle();
draw_triangle();
draw_intersect();
void
draw_circle(void)
{
printf(“ *** \n”);
printf(“*
*\n”);
printf(“ *** \n”);
ritorna al chiamante
}
66
Vantaggi derivati dall’uso di
funzioni
• astrazione procedurale
il main è una sequenza di chiamate a procedura (una
per ogni passo principale dell’algoritmo);
ogni funzione viene implementata separatamente
• riutilizzo di codice
una funzione può essere eseguita più volte all’interno
di un programma (es. draw_intersect);
dopo aver scritto e testato una funzione, posso riciclarla
in altri programmi
67
Visualizzare istruzioni per l’utente
le funzioni senza parametri possono essere usate per
separare la visualizzazione di istruzioni per l’utente
dal corpo del main.
Es. programma che calcola area e circonferenza
void instruct(void)
{
printf(“Questo programma calcola area\n”);
printf(“e circonferenza di un cerchio.\n\n”);
printf(“Per usare il programma, inserire\n”);
prinft(“il raggio del cerchio dopo il prompt.\n”);
}
68
dichiarare prima del main il prototipo della funzione
void instruct(void);
inserire la chiamata a funzione
instruct();
come prima istruzione eseguibile nel corpo del
main
69
Funzioni con argomenti di input
• funzioni void con argomenti di input
• funzioni con argomenti di input e un singolo risultato
• funzioni con argomenti multipli
• corrispondenza tra argomenti attuali e parametri formali
• area dati della funzione
• driver per testare funzioni
70
Funzioni con argomenti di input
gli argomenti di una funzione sono utilizzati per
trasportare informazioni dal chiamante all’interno della
funzione e viceversa.
• argomenti di input
argomenti usati per passare informazioni dal chiamante
alla funzione
• argomenti di output
argomenti usati per ritornare risultati al chiamante
71
Funzioni con argomenti di input
L’utilizzo degli argomenti rende le funzioni più versatili:
una funzione può manipolare dati diversi ad ogni
chiamata
Es.
rim_area = find_area(edge_radius) find_area(hole_radius);
72
funzioni di tipo void con argomenti
di input
Es. funzione che stampa un numero reale all’interno di
una cornice
/*
* Displays a real number in a box.
*/
void
print_rboxed(double rnum)
{
printf("***********\n");
printf("*
*\n");
printf("* %7.2f *\n", rnum);
printf("*
*\n");
printf("***********\n");
}
73
print_rboxed(135.68);
chiama print_rboxed
con rnum = 135.68
void
print_rboxed(double rnum)
{
printf("***********\n");
printf("*
*\n");
printf("* %7.2f *\n", rnum);
printf("*
*\n");
printf("***********\n");
}
74
Effetto della chiamata
Quando si effettua la chiamata print_rboxed(135.68)
il valore del argomento attuale (135.68) viene passato
alla funzione e sostituito al parametro formale (rnum).
La funzione print_rboxed visualizza sullo schermo
il seguente messaggio:
***********
*
*
* 135.68 *
*
*
***********
75
Parametri attuali e formali
• argomento attuale
espressione inserita tra le parentesi di una chiamata
a funzione
• parametro formale
identificatore che rappresenta il corrispondente
argomento attuale nella definizione della funzione
76
Funzioni con argomenti di input e
un singolo risultato
le funzioni che ritornano un risultato possono essere
chiamate all’interno di espressioni, come le funzioni
di libreria
i
n
p
u
t
.
.
funzione
risultato
77
Esempio: circonferenza del cerchio
/*
* Computes the circumference of a circle with radius r.
* Pre: r is defined and is > 0.
*
PI is a constant macro representing an
*
approximation of pi.
*/
double
find_circum(double r)
{
return (2.0 * PI * r);
}
78
Esempio: area del cerchio
/*
* Computes the area of a circle with radius r.
* Pre: r is defined and is > 0.
*
PI is a constant macro representing an
*
approximation of pi.
*
Library math.h is included.
*/
double
find_area(double r)
{
return (PI * pow(r, 2));
}
79
#define PI 3.14159
radius = 10.0;
circum = find_circum(radius);
ritorna il
risultato
62.8318
chiama find_circum
con r = 10.0
double
find_circum(double r)
{
return (2.0 * PI * r);
}
80
Definizione di funzione
(con argomenti in input e singolo risultato)
sintassi
function interface comment
ftype
fname (formal parameter declaration list)
{
local variable declarations
executable statements
}
81
Definizione di funzione
(con argomenti in input e singolo risultato)
esempio
/*
* Finds the cube of its argument.
* Pre: n is defined.
*/
int
cube(int n)
{
return(n * n * n);
}
82
Definizione di funzione
(con argomenti in input e singolo risultato)
L’intestazione della funzione specifica il nome della
funzione, fname, e il tipo del risultato ritornato dalla
funzione, ftype.
L’intestazione indica inoltre i nomi e i tipi dei parametri
formali nella formal parameter declaration list.
Note:
• l’intestazione NON termina con il punto e virgola
• utilizzare void nella formal parameter declaration list
per indicare che la funzione non ha argomenti
83
Definizione di funzione
(con argomenti in input e singolo risultato)
Le parentesi graffe racchiudono il corpo della funzione.
Il tipo delle variabili aggiuntive necessarie nella funzione
è dichiarato nelle local variable declarations.
Gli executable statements specificano le operazioni
effettuate sui dati e sulle variabili locali per ottenere il
risultato.
L’esecuzione dell’istruzione return ritorna il controllo
al chiamante.
La funzione ritorna come risultato il valore dell’espressione
che segue la parola return.
84
Stile: function interface comment
Il commento che precede l’intestazione della funzione
contiene tutte le informazioni necessarie all’uso della
funzione:
• descrizione dello scopo della funzione
• precondizione
condizione che viene assunta vera al momento della
chiamata
• postcondizione
condizione che sarà vera al termine dell’esecuzione
della funzione
85
Funzioni con argomenti multipli
/*
* Multiplies its first argument by the power of
* 10 specified by its second argument.
* Pre : x and n are defined and
* math.h is included.
*/
double
scale(double x, int n)
{
double scale_factor;
/* local variable */
scale_factor = pow(10, n);
return (x * scale_factor);
}
86
Funzione scale
scale(2.5, 2)
restituisce il valore 250.0 (che è 2.5
102 )
scale(2.5, -2)
restituisce il valore 0.025 (che è 2.5 10-2 )
La variabile locale scale_factor è definita solo
all’interno della funzione scale.
Come si fa a testare il corretto funzionamento di
una funzione?
87
/*
* Tests function scale.
*/
#include <math.h>
/* Function prototype */
double scale(double x, int n);
int
main(void)
{
double num_1;
int num_2;
/* Get values for num_1 and num_2 */
printf("Enter a real number> ");
scanf("%lf", &num_1);
printf("Enter an integer> ");
scanf("%d", &num_2);
88
/* Call scale and display result. */
printf("Result of call to function scale is %f\n",
scale(num_1, num_2));
return (0);
}
flusso dell’informazione
double
scale(double x, int n)
{
double scale_factor;
/* local variable 10 to power n */
scale_factor = pow(10, n);
return (x * scale_factor);
}
89
Corrispondenza tra argomenti
attuali e parametri formali
• il numero di argomenti attuali usati in una chiamata a
funzione deve essere uguale al numero di parametri
formali elencati nel prototipo della funzione
• l’ ordine degli argomenti determina la corrispondenza
tra le due liste. Il primo argomento attuale corrisponde
al primo parametro formale; il secondo argomento attuale
corrisponde al secondo parametro formale e così via
• ogni argomento attuale deve essere di un tipo che può
essere assegnato al corrispondente parametro formale
senza perdita di informazione
90
Area dati della funzione
Ogni volta che viene eseguita una chiamata a funzione,
viene allocata un’area di memoria per memorizzare i
dati della funzione:
• parametri formali
• variabili locali
Quando la funzione termina, l’area dati viene persa;
viene ricreata (con valori indefiniti) quando la funzione
viene chiamata di nuovo.
91
Area dati della funzione scale
Area dati
del main
num_1
2.5
num_2
-2
Area dati
della funzione scale
x
2.5
n
-2
scale_factor
??
92
Area dati della funzione scale
La variabile locale scale_factor può essere utilizzata
solo all’interno della funzione scale.
Le variabili num_1 e num_2, dichiarate nella funzione
main, possono essere utilizzate solo all’interno del main.
Per renderle utilizzabili a un’altra funzione, occorre
passarle come parametri.
93
Driver
Ogni funzione è un modulo di programma indipendente,
quindi può essere testato separatamente dal programma
che la usa.
Un driver è un piccolo programma scritto per testare
una funzione:
• definisce gli argomenti della funzione
• chiama la funzione
• ne visualizza i risultati
94
Prototipo di funzione
funzione senza parametri e valore di ritorno
void star_line(void);
funzione con parametri e valore di ritorno
double partition(double x, int n);
Chiamata a funzione
funzione senza parametri e valore di ritorno
star_line();
funzione con parametri e valore di ritorno
money = partition(funds, num_kids) + bonus;
95
Definizione di funzione
funzione senza parametri e valore di ritorno
void
star_line(void)
{
printf(“*\n*\n*\n*\n);
}
funzione con parametri e valore di ritorno
/*
* Pre: x and n are defined, x >= 0, n > 0
* Post: result is x / n
double
partition(double x, int n)
{
return (x / n);
}
96