Introduzione. per astrarre delle operazioni complesse

Documenti analoghi
Funzioni e Procedure in C. Funzioni e Procedure in C

Funzioni e procedure

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

int main(){ int numero; /* numero di cui voglio calcolare il fattoriale */ int fatt; /* memorizzo il fattoriale di numero */ int somma=0;

Strutture di controllo

Il passaggio parametri per indirizzo

Array k-dimensionali

LABORATORIO di INFORMATICA

FUNZIONI E PROCEDURE IN C. Docente: Giorgio Giacinto AA 2009/2010. dall utente, sia predefiniti, il C consente di creare funzioni e procedure

Funzioni, Stack e Visibilità delle Variabili in C

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

Concetto di Funzione e Procedura METODI in Java

Funzioni, Stack e Visibilità delle Variabili in C

METODI in Java. Prof.Angela Bonifati. Metodi e Sottoprogrammi

Definizione di metodi in Java

Funzioni in C. Funzioni. Strategie di programmazione. Funzioni in C. Come riusare il codice? (2/3) Come riusare il codice? (1/3)

Il linguaggio C. Prof. E. Occhiuto INFORMATICA 242AA a.a. 2010/11 pag. 1

Variabili e Funzioni. Informatica 1 / 19

Strategie di programmazione

Laboratorio di Informatica I

Do...While() Break Continue Concetto di Funzione e Procedura METODI in Java

Introduzione al linguaggio C Funzioni

Le Funzioni in C. Fondamenti di Informatica Anno Accademico 2010/2011. Corso di Laurea in Ingegneria Civile Politecnico di Bari Sede di Foggia

PROGRAMMAZIONE: I sottoprogrammi

Dati due punti sul piano calcolare la loro distanza

Laboratorio di informatica Ingegneria meccanica

Elementi DI INFORMATICA. Linguaggio C

ESECUZIONE DI PROGRAMMI C SU MACCHINE REALI. Docente: Giorgio Giacinto AA 2009/2010

ESECUZIONE DI PROGRAMMI C SU MACCHINE REALI. Docente: Giorgio Giacinto AA 2008/2009. formalizzazione degli algoritmi in linguaggio C

Lezione 6 Introduzione al C++ Mauro Piccolo

C funzioni à scope di variabili

Struttura dei programmi C

Linguaggio C - sezione dichiarativa: costanti e variabili

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - Programma

Dove vengono definiti? il concetto di sottoprogramma

Esercizio 1: funzione con valore di ritorno di tipo puntatore

Definizione di classi. Walter Didimo

Struttura di un. Struttura dei programmi C

La Programmazione. Cos è la programmazione? Concetti preliminari

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

uguale livello gerarchico non vi sono funzioni più importanti di altre main main

Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

Passare argomenti al programma

Linguaggio C: le funzioni. Introduzione e sintassi

Lezione 8 Struct e qsort

Introduzione al linguaggio C Puntatori

Programmazione Procedurale in Linguaggio C++

OOP in C++ ha membro (dati membro) e funzioni membro In Java i dati membro sono chiamati attributi e le funzioni membro metodi

Il linguaggio C. Puntatori e dintorni

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

Variabili e input/ Alessandra Giordani Lunedì 18 marzo

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

Cosa serve per cominciare?

Informatica (A-K) 12. Linguaggio C -3

Esercizi. La funzione swapint() primo tentativo

Esercizio 1: parole nel testo

Passaggio dei parametri

Corso sul linguaggio Java

Linguaggio C: le funzioni. Introduzione e sintassi

INPUT/OUTPUT L'immissione dei dati di un programma e l uscita dei suoi risultati avvengono attraverso operazioni di lettura e scrittura.

Funzioni in C. Informatica Generale - Funzioni in C Versione 1.0, aa p.1/25

C++ funzioni Alberto Ferrari. Alberto Ferrari Programmazione di applicazioni SW

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Lezione 6 Struct e qsort

Esercitazione 11. Liste semplici

#include <stdio.h> main() { - 1 -

Puntatori. Obiettivi: Richiamare quanto noto sui puntatori dal modulo A Presentare l analogia tra puntatori e vettori e l aritmetica dei puntatori

Compendio sottoinsieme del C++ a comune col C. (Libreria standard, Input/Output, Costanti, Dichiarazioni e typedef, Memoria Dinamica)

Funzioni. Unità 1. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Il linguaggio C Funzioni e procedure

LB5 FUNZIONI cap. 7 del testo

Puntatori. Obiettivi: Richiamare quanto noto sui puntatori dal modulo A Presentare l analogia tra puntatori e vettori e l aritmetica dei puntatori

Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di

FUNZIONI. attribuire un nome ad un insieme di istruzioni parametrizzare l esecuzione del codice

Ambienti di Programmazione per il Software di Base

Laboratorio Progettazione Web Le funzioni in PHP. Angelica Lo Duca IIT-CNR 2012/2013

STRUTTURA DI UN PROGRAMMA!

Programmazione M.A. Alberti. Comunicazione digitale AA 2009/ Classi in Java 1. Le classi in Java. Oggetti. Classi. Classi. Visibilità dei dati

Perché il linguaggio C?

Il linguaggio C. Notate che...

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

Le direttive del Preprocessore

Linguaggi di Programmazione

Capitolo 10 - Strutture

Introduzione alla programmazione. Alice Pavarani

Lezione 8. Sottoprogrammi

Costanti e Variabili

INPUT/OUTPUT INPUT/OUTPUT

FUNZIONI FUNZIONI COME COMPONENTI SW

Passaggio dei parametri Per valore Il valore viene copiato dall environment esterno all environment della funzione o procedura Cambiamenti dei paramet

Passaggio dei parametri. Passaggio dei parametri

I/O da tastiera + Alessandra Giordani Lunedì 2 maggio

Laboratorio di Programmazione e Calcolo

DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE. Puntatori. Marco D. Santambrogio Ver. aggiornata al 20 Aprile 2016

Transcript:

Introduzione Perché i sottoprogrammi? per riutilizzare codice già scritto se si devono ripetere tante volte le stesse operazioni in punti diversi di un programma, è meglio fattorizzare il codice da ripetere in un sottoprogramma, e richiamare il sottoprogramma più volte per astrarre delle operazioni complesse se si incapsula del codice complesso in un sottoprogramma, il programma globale può essere strutturato in macro-operazioni un codice ben strutturato in sottoprogrammi è più facile da correggere, modificare, mantenere per estendere le operazioni del linguaggio per definire nuove operazioni su tipi predefiniti, e per definire le operazioni sui tipi definiti dall'utente Approfondiamo quest ultimo aspetto Abbiamo visto come definire nuovi tipi in C mediante la dichiarazione typedef Con una dichiarazione typedef noi definiamo il dominio dei valori di un nuovo tipo, ma tipo = valori + operazioni, ci manca ancora di definire le operazioni usiamo i sottoprogrammi per arricchire il C con nuove operazioni, definite dall'utente 1

Un esempio Supponiamo di avere le seguenti dichiarazioni #define MaxNumFatture 10000; #define MaxNumCosti 10000; typedef char String[20]; typedef struct { String Destinatario; int Importo; Data DataEmissione; DescrizioneFatture; typedef struct { String Destinatario; int Importo; Data DataSpesa; DescrizioneCosti; typedef struct { int NumFatture; DescrizioneFatture Sequenza[MaxNumFatture]; ElencoFatture; typedef struct { int NumCosti; DescrizioneCosti Sequenza[MaxNumCosti]; ElencoCosti;... ElencoFatture archiviofatture; ElencoCosti archiviocosti; int risultatodigestione; 2

Esempio (cont.) Ci piacerebbe realizzare operazioni come calcola la somma di tutte le fatture dell'archivio oppure calcola la somma di tutti i costi sostenuti per esempio per scrivere il guadagno netto è pari al fatturato totale meno le spese sostenute ci piacerebbe avere: risultatodigestione = FatturatoTotale(archivioFatture) SommaCosti(archivioCosti); Al momento, però, noi al massimo sappiamo scrivere una cosa del tipo: fatturato = 0; for(i = 0; i < ArchivioFatture.NumFatture; i++){ fatturato = fatturato + ArchivioFatture.Sequenza[i].Importo; costi= 0; for(i = 0; i<archiviocosti.numcosti; i++){ costi = costi + ArchivioCosti.Sequenza[i].Importo; risultatodigestione = fatturato costi; Il meccanismo che viene usato per astrarre questo codice in una operazione a parte è quello dei sottoprogrammi Un sottoprogramma è un pezzo di codice che risolve un sottoproblema specifico un sottoprogramma realizza un sottoalgoritmo, cioè risolve un sottoproblema del problema principale Un sottoprogramma è opportunamente incapsulato ed isolato dal resto del codice mediante una apposita dichiarazione 3

Struttura di un programma C: versione completa Un programma C è fatto di: direttive #include, #define,... parte dichiarativa globale main La parte dichiarativa globale contiene: dichiarazione di elementi condivisi tra il main e i sottoprogrammi costanti, variabili, ecc. definizioni di sottoprogrammi in realtà il main è un sottoprogramma speciale tra tutti i sottoprogrammi Il main e gli altri sottoprogrammi possono usare: gli elementi dichiarati nella parte dichiarativa globale gli elementi dichiarati nella loro propria parte dichiarativa Per esempio, se nella parte dichiarativa globale si mette la dichiarazione int var_g; la variabile var_g può essere usata da tutti i sottoprogrammi, incluso il main 4

Le funzioni Matematicamente, una funzione è un oggetto che ha: un dominio un codominio Una funzione, a fronte di valori nel suo dominio, ritorna un valore nel codominio fino ad ora le operazioni che abbiamo considerato sono tutte delle funzioni (per esempio +, -, *, ecc.) a fronte dei valori 3 e 5, la funzione + restituisce il valore 8 Di fatto una funzione ha: dei valori in ingresso un valore in uscita I valori in ingresso alla funzione + sono gli addendi, ed il valore in uscita è il risultato della somma Avvertenza: spesso in C si usa il termine funzione come sinonimo di sottoprogramma, ma non è un uso preciso del termine una funzione è un genere particolare di sottoprogramma, ne vedremo un altro più avanti Definizione di una funzione: testata (header) tra parentesi graffe: parte dichiarativa (detta parte dichiarativa locale) contiene dichiarazioni di costanti, variabili, locali parte esecutiva (detta corpo della funzione) contiene una sequenza di istruzioni 5

Testata e corpo di una funzione La testata di una funzione si compone, nell'ordine, di: tipo del risultato identificatore del sottoprogramma cioè il suo nome lista dei parametri (detti parametri formali) a cui la funzione viene applicata Ogni dichiarazione di parametro è fatta di un identificatore di tipo seguito dall'identificatore (cioè dal nome) del parametro Alcune osservazioni: il tipo del risultato è il codominio della funzione i parametri formali sono il dominio della funzione il tipo del risultato può essere qualunque (predefinito o definito dall'utente), tranne che di tipo array può però essere di tipo puntatore a qualsiasi tipo Esempi di testate (non di definizioni complete) int FatturatoTotale (ElencoFatture par) boolean Precede (StringaCaratteri par1, StringaCaratteri par2) boolean Esiste (int par1, SequenzaInteri par2) /* Stabilisce se il primo parametro, di tipo intero, * appartiene all'insieme di interi contenuti nel * secondo parametro: una sequenza di interi */ MatriceReali10Per10 *MatriceInversa (MatriceReali10Per10 *par) La definizione di una funzione è completata da dichiarazioni locali costanti, variabili, esattamente come era per il main le variabili dichiarate all'interno di una funzione sono dette variabili locali corpo della funzione costruito secondo le stesse regole della parte esecutiva del main in più può contenere una (o più) istruzioni di return 6

istruzione return ed esempi di funzioni Sintassi dell'istruzione di return: return espressione il valore di espressione è il risultato della funzione ci può essere più di una istruzione return nel corpo di una funzione quando, durante l'esecuzione del corpo di una funzione, si incontra l'istruzione di return, l'esecuzione della funzione termina e viene restituito il valore dell'espressione Esempio: funzione che calcola il valore totale degli importi di un elenco di fatture int FatturatoTotale (ElencoFatture par){ int i; int totale = 0; for(i = 0; i < par.numfatture; i++){ totale = totale + par.sequenza[i].importo; return totale; Altro esempio: funzione che calcola la radice quadrata intera di un numero intero int RadiceIntera (int par) { int cont; cont = 0; while (cont*cont <= par){ cont = cont + 1; return (cont 1); 7

Chiamata delle funzioni Dopo che è stata definita, una funzione può essere chiamata (o invocata) ogni invocazione di una funzione restituisce un valore, che dipende dai valori dei parametri della funzione al momento dell'invocazione ci sono 2 attori in gioco: chi chiama la funzione (il chiamante), e la funzione chiamata (il chiamato) chi chiama la funzione è il main, oppure un altro sottoprogramma Sintassi di chiamata: IdentificatoreFunzione ( lista dei parametri attuali ) Esempi: FatturatoTotale(archivioFatture) Radice(num) Radice(13) Parametri attuali: valore attribuito ai parametri della funzione al momento della chiamata contrapposti ai parametri formali, che sono i nomi (le scatole vuote ) dichiarati nella testata della funzione per esempio il valore di num e 13 sono parametri attuali per il parametro formale par della funzione Radice Quando per esempio invoco Radice(13), il valore 13 viene messo dentro al parametro par è di fatto un assegnamento 8

Parametri attuali e formali La corrispondenza tra parametri formali e parametri attuali è posizionale: il primo parametro attuale nella chiamata viene assegnato al primo parametro formale nella dichiarazione il secondo parametro attuale va nel secondo parametro formale... Il numero di parametri attuali deve essere uguale al numero di parametri formali altrimenti viene segnalato un errore in fase di compilazione Un parametro attuale è una espressione, che può a sua volta includere una chiamata di funzione Il tipo dei parametri attuali (cioè dell'espressione corrispondente) deve essere compatibile con il tipo dei parametri formali sono possibili le conversioni implicite di tipo In diversi momenti dell'esecuzione di un programma ci possono essere diverse invocazioni della stessa funzione con diversi parametri attuali Esempi di invocazioni: x = sin(y) cos(pigreco alfa); x = cos(atan(y) beta); x = sin(alfa); y = cos(alfa) sin(beta); z = sin(pigreco) + sin(gamma); risultatodigestione = FatturatoTotale(archivioFatture) - SommaCosti(archivioCosti); det1 = Determinante(matrice1); det2 = Determinante(MatriceInversa(matrice2)); totaleassoluto = Sommatoria(lista1) + Sommatoria(lista2); elencoordinato = Ordinamento(elenco); ordinatialfabeticamente = Precede(nome1, nome2); 9

Prototipo delle funzioni Una funzione può essere chiamata solo se è definita o se è dichiarata Attenzione: definita dichiarata Definizione testata { dichiarazioni locali corpo Dichiarazione (detta prototipo) testata; Esempi di prototipi di funzione: int FatturatoTotale (ElencoFatture par); int RadiceIntera (int par); Punto PuntoMedio(Segmento seg); La dichiarazione di una funzione può andare in una qualunque parte dichiarativa tra quelle viste: parte dichiarativa globale parte dichiarativa locale di una funzione parte dichiarativa del main Dichiarare una funzione è utile quando una chiamata della funzione precede la sua definizione nel file da compilare, oppure quando si una una funzione definita in un file separato (per esempio le funzioni di libreria) Dichiarare le funzioni aiuta il compilatore ed è buono stile di programmazione Per riassumere, una parte dichiarativa (globale, locale ad un sottoprogramma, oppure locale al main) può contenere (in ordine sparso): dichiarazioni di costanti dichiarazioni di tipo dichiarazioni di variabili prototipi delle funzioni 10

Esecuzione di funzioni e passaggio parametri Cominciamo con un esempio: /* Programma Contabilità */ /* Parte direttiva */ #include <stdio.h> #define MaxNumFatture 1000 /* Parte dichiarativa globale */ typedef char String [30]; typedef struct { String Indirizzo; int ammontare; Data DataFattura; DescrizioneFatture; typedef struct { int NumFatture; DescrizioneFatture Sequenza[MaxNumFatture]; ElencoFatture; main() { ElencoFatture archiviofatture1, archiviofatture2; int fatt1, fatt2, fatt; /* Prototipo della funzione FatturatoTotale */ int FatturatoTotale(ElencoFatture par);... fatt1 = FatturatoTotale(archivioFatture1); fatt2 = FatturatoTotale(archivioFatture2); fatt = fatt1 + fatt2;... /* Fine del main del programma Contabilità */ int FatturatoTotale (ElencoFatture par) { int totale, i;... return totale; 11

Esecuzione (cont.) E' come se ci fossero 2 esecutori, uno per il main, ed uno per la funzione FatturatoTotale Ogni esecutore ha un insieme di variabili locali (detto ambiente di esecuzione) ambiente di esecuzione per il main: archiviofatture1 e archiviofatture2, di tipo ElencoFatture fatt1, fatt2, fatt3, di tipo int ambiente di esecuzione per FatturatoTotale: par, di tipo ElencoFatture totale ed i, entrambe di tipo int una variabile anonima (che non può essere referenziata in nessun modo) in cui viene memorizzato il valore ritornato dalla chiamata archiviofatture1 archiviofatture2 fatt1 fatt2 par totale i valore da ritornare fatt3 esecutore del main esecutore di FatturatoTotale 12

Esecuzione (cont.) archiviofatture1 par archiviofatture2 fatt1 fatt2 totale i valore da ritornare fatt3 Effetto dell'esecuzione di: fatt1 = FatturatoTotale(archivioFatture1); l'esecutore del main vede che a destra di = c'è un'invocazione alla FatturatoTotale con parametro attuale archiviofatture1 viene creato l'esecutore per la funzione FatturatoTotale, con il suo ambiente di esecuzione avviene il passaggio dei parametri il valore del parametro attuale viene copiato nel corrispondente parametro formale viene ceduto il controllo alla macchina asservita l'esecuzione dell'esecutore del main viene sospesa viene eseguito il corpo della funzione fino a return la variabile anonima contiene il valore da ritornare viene restituito il controllo all'esecutore del main l'esecutore del main preleva il valore della variabile anonima questo valore diventa il valore dell espressione: FatturatoTotale(ArchivioFatture1) il valore viene assegnato alla variabile fatt1 13

Le procedure Non tutte le operazioni interessanti sono descrivibili astrattamente da funzioni matematiche a volte si vuole: effettuare qualche azione cambiare valore di variabili Per esempio: stampare un elenco di fatture non c è alcun valore da calcolare va fatto in modo parametrico (diversi elenchi in diversi momenti) inserire una nuova fattura in un archivio di fatture preesistente aggiornamento di variabile, non calcolo di valore ordinare un array di interi ar effetto: permutare i valori presenti in ar NON calcolare un valore di tipo array di interi modificare le coordinate di un vertice di una linea spezzata Per queste operazioni si usa diverso tipo di sottoprogramma: sottoprogramma procedurale o procedura Sintatticamente, una procedura si distingue da una funzione dal tipo del risultato: una procedura ha come tipo del risultato il tipo void Il tipo void è un tipo predefinito fittizio, non possiede alcun valore né operazione il tipo void è usabile anche come tipo per parametri formali di sottoprogrammi senza parametri La chiamata di una procedura è un istruzione che non produce alcun valore: IdentificatoreProcedura( lista dei parametri attuali ); è quindi un'istruzione singola, a parte, non può essere inserita in un'espressione si noti il ';' di chiusura: questa è una istruzione completa 14

Esempio di procedura Operazione InserisciFattura: /*Programma Contabilità */ #include<stdio.h> #define MaxNumFatture 1000... typedef struct { String Indirizzo; int ammontare; Data DataFattura; DescrizioneFatture; typedef struct { int NumFatture; DescrizioneFatture Sequenza[MaxNumFatture]; ElencoFatture; ElencoFatture archfatture; /* variabile condivisa */ main() { Data dataodierna; DescrizioneFatture fattura1, fattura2; void InserisciFattura(DescrizioneFatture fatt); boolean Precede(Data d1, Data d2);... /* Qui va la sequenza di istruzioni (non mostrata) * che leggono i dati di una fattura in fattura1 */ InserisciFattura(fattura1);... /* Qui va la sequenza di istruzioni (non mostrata) * che leggono i dati di una fattura in fattura2 */ if (Precede(fattura2.DataFattura, dataodierna)) InserisciFattura(fattura2);... void InserisciFattura(DescrizioneFatture fatt){ if (archfatture.numfatture == MaxNumFatture){ printf("l'archivio è pieno.\n"); else { archfatture.sequenza[archfatture.numfatture] = fatt; archfatture.numfatture = archfatture.numfatture + 1; 15

Esecuzione dell'esempio archiviofatture Ambiente globale dataodierna... fattura1 fattura2 fatt Ambiente locale di InserisciFattura Ambiente di main del programma Contabilità oltre all'ambiente del main e a quello della procedura c è l'ambiente globale del programma contiene la variabile archiviofatture di tipo ElencoFatture L'esecutore della procedura InserisciFattura accede all ambiente globale modificandolo La variabile archiviofatture è per la procedura una variabile globale Al della sua esecuzione, l'esecutore di InserisciFattura cede il controllo all'esecutore principale senza restituire alcun risultato l' effetto desiderato è la modifica della variabile globale Osservazione: le varie procedure e funzioni (main compreso) non possono accedere agli ambienti locali altrui la comunicazione avviene o passandosi parametri e risultati o attraverso l ambiente globale/comune 16