520 likes | 674 Views
Funzioni e Procedure. Marco D. Santambrogio – marco.santambrogio@polimi.it Ver. aggiornata al 21 Marzo 2014. Info di servizio 1. Vi siete dimostrati volenterosi, quindi teniamo la divisione proposta da voi Questa mattina è arrivato l ’ ultimo gruppo per lo scambio!. Info di servizio 1.
E N D
Funzioni e Procedure Marco D. Santambrogio – marco.santambrogio@polimi.it Ver. aggiornata al 21 Marzo 2014
Info di servizio 1 • Vi siete dimostrati volenterosi, quindi teniamo la divisione proposta da voi • Questa mattina è arrivato l’ultimo gruppo per lo scambio!
Info di servizio 2 • Il lab di lunedì 24 Marzo inizierà alle 3pm invece che alle 3.30pm FALSO!Rimane alle 3.30pm
Info di servizio 3 • Mercoledì 3 Aprile, avete lezione prima di IEIM (10.15am) • Vorrei verificare la possibilità, solo per il 3 Aprile di iniziare alle 9.30am e finire alle 11am
Info di servizio 4 • Nuova pagina dei tool! • Caricati dei video su • Come installare la VM • Come usare Code::Blocks • Come scrivere il primo programma http://home.deib.polimi.it/santambr/dida/ieim/2014/tools/video.htm
Info di servizio 5 • Progetti alternativi di Informatica • Ven 7am – 9am • Quando il Ven non fosse possibile (ponti, scioperi, etc.): Gio 8.30am – 10am • Calendario online sul sito del corso
Info di servizio 6 • Il NECST lab organizza visite ad altri centri di ricerca • Avvicinarsi a/conoscere nuove realtà di ricerca • Networking • Centro di Super-computing Svizzero • http://www.cscs.ch • Data candidata: 22 Aprile 2014 • Se interessati, scrivere a me :)
Obiettivi • Funzioni • Scope dellevariabili
La calcolatrice? Meglio! Umh….
La calcolatrice! • Problema • Si scriva un programma in C che, dati due numeri, permette all’utente di calcolarne la somma, sottrazione, moltiplicazione, e la divisione tra essi • L’utente, per ogni coppia di numeri inseriti, potrà eseguire una e una sola operazione
Prima osservazione: i dati! • Definizione dei dati su cui devo lavorare • Quanti dati mi servono? • Di che tipo devono essere? • Come gestisco l’operazione?
Ragioniamo sul fIusso • Inserire i dati (numeri e operazione) • Verificare che l’inserimento dei dati sia corretto • Sulla base dell’operazione selezionata, eseguire la funzione richiesta • Mostrare il risultato • Questo NON e’ un algoritmo!!!! • Non e’“non ambiguo” • I passi non sono atomici
Primo compito per casa Scrivere l’algoritmo che risolve il problema in esame!
Una prima soluzione Problema con i char
Una 1ma sol corretta ;) E qui cosa succede?
Osservazioni • Quando abbiamo ragionato sul flusso, abbiamo detto: • Sulla base dell’operazione selezionata, eseguire la funzione richiesta • Quali sono le funzioni che potremmo definire? • somma, sottrazione, divisione e moltiplicazione • In C, queste vengo chiamate anche sottoprogrammi
Sottoprogrammi • Un sottoprogramma è: • un insieme di istruzioni dotato di nome • descritto (definito) una sola volta • attivabile (richiamabile o invocabile) all’interno del programma o di un altro sottoprogramma • Alcuni sottoprogrammi sono già definiti • si pensi alla scanf e alla printf • dietro a questi nomi vi sono una serie di istruzioni in grado di, rispettivamente, intercettare la pressione dei tasti e di visualizzare un carattere sullo schermo • chi richiama queste funzioni non si preoccupa di come sono fatte, basta sapere solo cosa fanno (visione black box)
Sottoprogrammi: motivazioni • Astrazione e leggibilità: • enucleano parti di codice, nascondendo dettagli algoritmici e di codifica • il nome di programma si presenta come “un’operazione elementare” • Strutturazione e scomposizione funzionale del programma: • consentono una stesura del programma che riflette un’analisi funzionale del problema • Collaudo: • verifica di correttezza della soluzione facilitata dal poter verificare la correttezza prima dei singoli sottoprogrammi e poi dell’intero programma visto come insieme di chiamate che si scambiano informazioni • Compattezza ed efficienza del codice: • si evita di ripetere sequenze di istruzioni in più parti del programma • Modificabilità: • una sola modifica vale per tutte le attivazioni del sottoprogramma • Riuso: • sottoprogrammi non troppo specifici possono essere raccolti in librerie utilizzabili da programmi diversi
Funzioni e procedure • I sottoprogrammi si differenziano per la logica di definizione per l’uso e per la modalità di chiamata e possono essere • di tipo funzionale • di tipo procedurale • Sottoprogrammi di tipo funzionale (funzioni) possono essere considerati una astrazione di valore • l’invocazione della funzione associa al nome della funzione il valore del risultato calcolato dal sottoprogramma • Sottoprogrammi di tipo procedurale (procedure) possono essere considerati una astrazione di operazioni • l’invocazione della procedura è associata all’esecuzione delle istruzioni del sottoprogramma che realizzano l’operazione specificata dal sottoprogramma • Ad esempio: leggi(A,B); /* procedura*/ risultato = somma(A,B); /* funzione*/
Funzioni e procedure in C • In C esistono solo le funzioni • Le procedure sono particolari funzioni che non restituiscono nulla (VOID) • Quindi parleremo solo di funzioni intendendo sia le funzioni che le procedure • Definire una funzione secondo il linguaggio C implica: • dichiarazione del prototipo della funzione (nella sezione dichiarativa) • definizione della funzione • invocazione o chiamata della funzione (nel codice che necessita della funzioni)
Dichiarazione del prototipo • Il prototipo definisce: • il nome della funzione • il tipo (funzione, procedura) • il tipo dei parametri in ingresso e in uscita • Chi utilizzerà la funzione dovrà rispettare la sintassi definita nel prototipo • Prototipo funzione <tipo_ris> <nome_funz> (<lista tipi dei parametri>); • Prototipo procedura (void è una parola chiave del C che indica assenza di tipo) void <nome_funz> (<lista tipi dei parametri>);
Definizione del sottoprogramma • La definizione del sottoprogramma va messa dopo il main. Ha la stessa struttura del main (anche il main, come sappiamo è una funzione): • Una parte dichiarativa • Una parte esecutiva <tipo> <nome> (tipo par_for1, tipo par_for2 ...) { parte dichiarativa locale parte esecutiva } • <tipo> <nome> (tipo par_for1, tipo par_for2 ...) è la testata della funzione • par_for1, par_for2 sono i nomi dei parametri formali della funzione, il cui tipo deve corrispondere in modo ordinato ai tipi elencati nella dichiarazione del prototipo
Parametri formali • Parametri Formali: • Rappresentano un riferimento simbolico (identificatori) a oggetti utilizzati all’interno della funzione • Sono utilizzati dalla funzione come se fossero variabili dichiarate localmente • Il valore iniziale di parametri formali viene definito all’atto della chiamata della funzione tramite i parametri attuali (passaggio di parametri) Le funzioni in C sono funzioni in senso matematico, il tipo del valore di ritorno definisce il Codominio mentre i valori possibili dei parametri in ingresso corrispondono al Dominio
Istruzione return • Parola chiave C utilizzata solo nelle funzioni • Sintassi return <espressione> • È l’ultima istruzione di una funzione e indica: • il punto in cui il controllo torna al chiamante • il valore restituito • In una funzione • deve esserci almeno un’istruzione di return • possono esserci più istruzioni di return ma in alternativa • la funzione può restituire un solo valore
Chimante/Chiamato • All’atto della chiamata, il controllo dell’esecuzione passa dal chiamante al chiamato • Il codice del chiamato viene eseguito • Al termine dell’esecuzione il controllo ritorna al chiamante, all’istruzione successiva a quella della chiamata codice chiamante Inizio programma Istruzione 1 Istruzione 2 Chiama funzione Istruzione 3 Passaggio del controllo Ritorno del controllo funzione chiamata Istruzione 1 Istruzione 2 Istruzione 3 Istruzione 4 return
Invocazione o chiamata • Nel corpo del main o di un’altra funzione indica il punto in cui va eseguita la parte del codice presente nella definizione di funzione • Invocazione di funzione • come operando in una espressione <espressione> = <… nomefunzione(par_att1 …)…>; • Invocazione di procedura • come un’istruzione nomeprocedura(par_att1, …); • In entrambi i casi: • par_att1,… sono i parametri attuali che devono corrispondere per ordine e per tipo ai parametri formali • I parametri attuali possono essere variabili, costanti o espressioni definite nell’ambiente chiamante, i cui valori all’atto della chiamata vengono copiati nei parametri formali
Passaggio dei parametri • Il passaggio dei parametri consiste nell’associare, all’atto delle chiamata di un sottoprogramma, ai parametri formali i parametri attuali • Se il prototipo di una funzione è float circonferenza (float raggio); • Invocare questa funzione significa eseguire l’istruzione c = circonferenza(5.0); • In questo modo la variabile raggio (il parametro formale) assumerà per quella particolare invocazione il valore 5 (il parametro attuale). • Lo scambio di informazioni con passaggio dei parametri tra chiamante e chiamato può avvenire in due modi: • Passaggio per valore • Passaggio per indirizzo
Passaggio per VALORE • All’atto della chiamata il valore del parametro attuale viene copiato nelle celle di memoria del corrispondente parametro formale. • Il parametro formale e il parametro attuale si riferiscono a due diverse celle di memoria • Il sottoprogramma in esecuzione lavora nel suo ambiente e quindi sui parametri formali • I parametri attuali non vengono modificati
Pausa… Pausa per 10’
La calcolatrice con le funzioni - prototipi I prototipi Le chiamate
Esempio: passaggio per valore } /* nel main */ float valore1, valore2; float risultato; risultato=somma(valore1,valore2); Ambiente della funzione somma risultato d1, d2 Quando la funzione termina il valore di risultato in smma viene copiato in risultato nel main Quando invoco la funzione in d1 e d2 vengono copiati i valori di valore1 e valore 2 risultato valore1, valore2 Ambiente della funzione main
Visibilità • Visibilità di un identificatore: • indicazione della parte del programma in cui tale identificatore può essere usato • Ambiente globale del programma • insieme di identificatori (tipi, costanti, variabili) definiti nella parte dichiarativa globale • regole di visibilità: visibili a tutte le funzioni del programma • Ambiente locale di una funzione • insieme di identificatori definiti nella parte dichiarativa locale e degli identificatori definiti nella testata (parametri formali) • Regole di visibilità: visibili alla funzione e ai blocchi in essa contenuti • Ambiente di blocco • insieme di identificatori definiti nella parte dichiarativa locale del blocco • regole di visibilità: visibili al blocco e ai blocchi in esso contenuti
Esempi int x; f() { int y; y=1; } int x; g(int y, char z) { int k; int l; … } f(int x) { int x; } • La visibilità di y si estende dal punto di dichiarazione fino alla fine del blocco di appartenenza • y e z locali alla funzione g,con visibilità nel blocco racchiuso da parentesi graffe • k e l hanno la stessa visibilità • Errata! Si tenta di definire due volte la variabile locale x nello stesso blocco
Mascheramento (shadowing) • Un nome ridefinito all’interno di un blocco nasconde il significato precedente di quel nome • Tale significato è ripristinato all’uscita del blocco più interno • In caso di omonimia di identificatori in ambienti diversi è visibile quello dell’ambiente più “vicino”
Visibilità Livello globale g1,g2,g3 a,b main a,c blocco1 f1 a,d blocco2 d blocco3 char g1, g2, g3; main() { int a, b; … {/*blcco1*/ double a,c; } … } void f1(){ … {/*blocco2*/ char a,d; } … {/*blocco3*/ float d … } }
Torniamo alla calcolatrice Verifichiamo gli ingressi?
Selezione multipla • Operazione e’uguale in tutti i casi • Non posso evitare di ripetere operazione ==
Lo switch • Lo switch ci permette una alternativa al come selezionare la prossima istruzione da eseguire • Lo switch valuta una espressione, quindi cerca di confrontare un valore con diversi possibili cases switch ( expression ){ case value1: statement-list1 case value2: statement-list2 case value3 : statement-list3 case... }
Lo switch • Ciascun case contiene un valore (value) e una lista di istruzioni (statement) • Il flusso di controllo si traferisce attraverso tutte le istruzioni, partendo dal primo case che “corrisponde” switch ( expression ){ case value1: statement-list1 case value2: statement-list2 case value3 : statement-list3 case... }
Perche’??? Flusso
Zoom Flusso