• Non ci sono risultati.

Moreno Marzolla

N/A
N/A
Protected

Academic year: 2021

Condividi "Moreno Marzolla"

Copied!
6
0
0

Testo completo

(1)

Funzioni in C++

Concetti avanzati

Moreno Marzolla

moreno.marzolla@pd.infn.it

Moreno Marzolla Fondamenti di Informatica 2

Copyright © 2006 Moreno Marzolla

This work is licensed under the Creative Commons Attribution- Noncommercial-Share Alike 2.5 Italy License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc- sa/2.5/it/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.

Passaggio di vettori Passaggio di vettori

 Abbiamo visto come passare gli eventuali parametri ad una funzione

 Come si fa a passare un vettore (array) come parametro di una funzione?

int somma( int a, int b ) {

int risultato;

risultato = a+b;

return risultato;

}

Sintassi Sintassi



Es: Scrivere una funzione somma_vet() che riceve come parametro un array a[] di 10 interi. La funzione restituisce come risultato intero, che è la somma dei valori di tutti gli elementi del vettore a[]

int somma_vet( int a[] ) {

int i;

int s = 0;

for ( i=0; i<10; i++ ) { s = s+a[i];

}

return s;

}

Nota: non si deve mai

specificare la dimensione

(numero di elementi) di a!

(2)

Moreno Marzolla Fondamenti di Informatica 5

Osservazione Osservazione

 Quando si scrive una funzione che richiede un parametro di tipo array, si mettono parentesi []

dopo il nome del parametro

 Spesso è anche necessario passare la

dimensione dell'array alla funzione, perché la funzione non ha altro modo per richiederne la dimensione.



Nell'esempio precedente assumevamo che l'array passato come parametro avesse SEMPRE 10 elementi

Moreno Marzolla Fondamenti di Informatica 6

Esempio Esempio

#include <iostream>

using namespace std;

int somma_vet( int a[], int dim_a ) {

int i;

int s = 0;

for ( i=0; i<dim_a; i++ ) { s = s+a[i];

}

return s;

}

int main( void ) {

int vet[5] = {1, 2, 3, 4, 5};

cout << “La somma vale “ << somma_vet( vet, 5 ) << endl;

return 0;

}

Questo parametro viene usato per indicare la dimensione (numero di elementi) del vettore a[]

Moreno Marzolla Fondamenti di Informatica 7

Nota Nota

 Attenzione che, a differenza di tutti gli altri parametri, i parametri di tipo array vengono modificati se si tenta di scriverci dentro

 Esempio

#include <iostream>

using namespace std;

void azzera( int a[], int dim_a ) {

int i;

for ( i=0; i<dim_a; i++ ) { a[i] = 0;

} }

int main( void ) {

int vet[5] = {1,2,3,4,5};

azzera( vet, 5 );

// a questo punto tutti gli elementi di vet[] valgono zero return 0;

}

Moreno Marzolla Fondamenti di Informatica 8

Esercizi Esercizi

 Scrivere una funzione prodotto_scalare() con le seguenti caratteristiche:



La funzione accetta tre parametri: un vettore di double a[], un vettore di double b[] (che devono avere la stessa dimensione), e la loro dimensione dim



La funzione restituisce un numero ottenuto facendo il prodotto scalare tra i vettori a[] e b[], ossia il valore calcolato come:

a[0]*b[0] + a[1]*b[1] + ... + a[n-1]*b[n-1]

assumendo che n sia la dimensione di a[] e b[]

(3)

Moreno Marzolla Fondamenti di Informatica 9

Passaggio per valore Passaggio per valore



Il modo di passare parametri che abbiamo usato fino ad ora (con l'esclusione dei vettori) si chiama passaggio di parametri per valore



Significa che ad una funzione viene passato una copia del valore del parametro



Se all'interno della funzione modifico il valore di un parametro, la modifica non avrà alcun effetto al di fuori della funzione

#include <iostream>

using namespace std;

void azzera( int a ) {

a = 0;

}

int main( void ) {

int x = 5;

azzera( x );

cout << x << endl; // stampa 5 return 0;

}

Moreno Marzolla Fondamenti di Informatica 10

Passaggio per riferimento Passaggio per riferimento

 E' anche possibile fare in modo che la modifica del parametro di una funzione si ripercuota sul valore effettivamente passato



Come succede nel caso del passaggio di vettori



In questo caso usiamo il passaggio di parametri per riferimento #include <iostream>

using namespace std;

void azzera( int &a ) {

a = 0;

}

int main( void ) {

int x = 5;

azzera( x );

cout << x << endl; // stampa zero!

return 0;

}

Passaggio per riferimento Passaggio per riferimento

 Per passare un parametro per riferimento (cioè per fare in modo che ogni modifica che la funzione fa a quel parametro venga “vista”

anche al di fuori della funzione) è sufficiente precedere il nome del parametro col simbolo &

Esempio Esempio



Scrivere una funzione scambia() che accetta due parametri a, b di tipo int. La funzione non restituisce alcun risultato, ma scambia tra loro i valori di a e b. In altre parole, la seguente funzione main():

deve stampare “1 5”;

// Dichiarazione di scambia() int main( void )

{

int a=5;

int b=1;

scambia( a, b );

cout << a << “ “ << b << endl;

return 0;

}

(4)

Moreno Marzolla Fondamenti di Informatica 13

Soluzione Soluzione

#include <iostream>

using namespace std;

void scambia( int &a, int &b ) {

int tmp = a;

a = b;

b = tmp;

}

int main( void ) {

int a=5;

int b=1;

scambia( a, b );

cout << a << “ “ << b << endl;

return 0;

}

Moreno Marzolla Fondamenti di Informatica 14

Esercizi per domani / 1 Esercizi per domani / 1

 Scrivere una funzione inverti() che accetta come parametro un vettore di interi a[] e la sua dimensione dim_a; la funzione inverte gli

elementi di a[] (cioè scambia il primo elemento di a con l'ultimo, il secondo col penultimo ecc.)

 Scrivere una funzione main() per testare la inverti() appena realizzata

Moreno Marzolla Fondamenti di Informatica 15

Esercizi per domani / 2 Esercizi per domani / 2

 Scrivere una funzione somma_alternata che accetta come parametro un vettore di interi a[] e la sua dimensione dim_a. La funzione calcola la somma alternata di a[], ossia calcola la quantità:

a[0] - a[1] + a[2] - a[3] + a[4] ...

Moreno Marzolla Fondamenti di Informatica 16

Esercizi per domani / 3 Esercizi per domani / 3



Scrivere una funzione fill() che accetta come parametri un vettore di interi a[], la sua dimensione dim_a e un ulteriore intero x compreso tra 0 e 4 (estremi inclusi). La funzione non

restituisce alcun risultato.



La funzione modifica il vettore a[] come segue. Il primo

elemento di a[] viene posto a x, il secondo a x+1 e così via. Ogni volta che il valore assegnato ad un elemento di a raggiunge 4, l'elemento successivo ricomincia da zero



Esempio: se dim_a=10, x=3, allora dopo la chiamata fill( a, dim_a, x ) il vettore deve contenere questi valori

{ 3, 4, 0, 1, 2, 3, 4, 0, 1, 2 };



Esempio: se dim_a=10, x=4, allora dopo la chiamata fill( a, dim_a, x ) il vettore deve contenere questi valori

{ 4, 0, 1, 2, 3, 4, 0, 1, 2, 3 };

(5)

Moreno Marzolla Fondamenti di Informatica 17

Cenni alle funzioni ricorsive Cenni alle funzioni ricorsive

 Ovviamente è possibile che una funzione f(), al suo interno, richiami un'altra funzione g()

int g( int x ) {

return x+1;

}

int f( int x, int y ) {

return g(x) + g(y);

}

// domanda: cosa calcola f( 3, 4 )?

Moreno Marzolla Fondamenti di Informatica 18

Funzioni ricorsive Funzioni ricorsive

 E' anche possibile per una funzione f() richiamare se' stessa

 Esempio: come si calcola il fattoriale di un numero non negativo n?



fattoriale( 0 ) = 1



se n>0, fattoriale( n ) = n * fattoriale( n-1 )

 Tutto questo si può direttamente implementare in C++

Esempio fattoriale Esempio fattoriale

#include <iostream>

using namespace std;

int fattoriale( int n ) {

if ( n == 0 ) { return 1;

} else {

return n * fattoriale( n-1 );

} }

int main( void ) {

cout << fattoriale( 3 ) << endl; // stampa 3*2*1 = 6 cout << fattoriale( 4 ) << endl; // stampa 4*3*2*1 = 24 return 0;

}

Osservazione Osservazione

 Perché la ricorsione funziona?



E' sempre necessario definire almeno un caso base, ossia un caso in cui il valore della funzione è

univocamente determinato senza invocare nuovamente la funzione stessa



nel caso del fattoriale, 0! = 1, per definizione



Ogni volta che la funzione invoca se stessa, è

necessario che lo faccia passando dei parametri che si

“avvicinino” al caso base



il calcolo del fattoriale di n richiede il calcolo del fattoriale di

n-1, che a sua volta richiede il fattoriale di n-2 finché

inevitabilmente si arriva a calcolare il fattoriale di 0, e qui la

ricorsione si ferma

(6)

Moreno Marzolla Fondamenti di Informatica 21

Calcolo del Massimo Comune Divisore Calcolo del Massimo Comune Divisore

 Definiamo la funzione MCD( a, b ) che calcola il massimo comune divisore tra due interi non negativi a e b



Se a=b, allora MCD( a, b ) = a (oppure b, tanto sono uguali!)



Se a>b, allora MCD( a, b ) = MCD( a-b, b )



Se b>a, allora MCD( a, b ) = MCD( a, b-a )

Moreno Marzolla Fondamenti di Informatica 22

Soluzione Soluzione

#include <iostream>

using namespace std;

int MCD( int a, int b ) {

if ( a == b ) { return a;

} else {

if ( a > b ) {

return MCD( a-b, b );

} else {

return MCD( a, b-a );

} } }

int main( void ) {

cout << MCD( 3, 4 ) << endl; // stampa 1 cout << MCD( 12, 4 ) << endl; // stampa 4 cout << MCD( 18, 12 ) << endl; // stampa 6 return 0;

}

Moreno Marzolla Fondamenti di Informatica 23

Esercizio per domani Esercizio per domani

 Scrivere una funzione ricorsiva che calcola il prodotto tra due interi non negativi a e b come segue:



Se a=1, prodotto( a, b ) = b



Se a>1, prodotto( a, b ) = b + prodotto( a-1, b );

 Come modifichereste la funzione perché si

comporti correttamente anche se a=0?

Riferimenti

Documenti correlati

 Gli indirizzi Internet sono rappresentati, a livello più basso, come numeri di 32 bit, suddivisi in una serie di 4 numeri di 8 bit.

 “Prendi il contenuto della cella sulla colonna A, stessa riga (1), sommaci 1 e inserisci il risultato nella cella corrente”.  Se copio la cella B1 in D4, il contenuto di D4

To view a copy of this license, visit http://creativecommons.org/licenses/by-nc- sa/2.5/it/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San

cin &gt;&gt; n; // chiede all'utente di inserire n cin &gt;&gt; m; // chiede all'utente di inserire m cout &lt;&lt; massimo( n, m ) &lt;&lt; endl;.

 I diagrammi delle classi mostrano anche gli attributi e le operazioni di una classe, e le restrizioni che si applicano al modo con cui gli oggetti sono collegati tra loro.

relazioni commerciali attraverso tecnologie di trasferimento elettronico di fondi e dati. Moreno Marzolla Tecnologie

Rete privata, basata sulle tecnologie WEB, che ospita le applicazioni Internet su una rete locale E' sostanzialmente una versione “chiusa” di Internet, messa in piedi per agevolare

Le prestazioni di alcuni server degradano pauro- samente all'aumentare del numero di accessi Vi sono tipi di pagine (pagine dinamiche) che vengono gestite meno efficientemente da