Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria...

141
Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dell’Informazione Università di Siena Via Roma 56 – 53100 – SIENA Uff. 0577233606 [email protected] http://www.dii.unisi.it/ ~ rigutini/

Transcript of Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria...

Page 1: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Introduzione alla

programmazione

Dott. Ing. Leonardo RigutiniDipartimento Ingegneria dell’InformazioneUniversità di SienaVia Roma 56 – 53100 – SIENAUff. [email protected]://www.dii.unisi.it/~rigutini/

Page 2: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

AlgoritmoAlgoritmo

Page 3: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Che cos’è l’informatica

L’informatica è lo studio sistematico degli L’informatica è lo studio sistematico degli algoritmialgoritmi che descrivono che descrivono e trasformano l’informazione: la loro teoria, analisi, progetto, e trasformano l’informazione: la loro teoria, analisi, progetto, efficienza, realizzazione (ACM efficienza, realizzazione (ACM Association for Computing Association for Computing Machinery)Machinery)

NotaNota: È possibile svolgere un’attività concettualmente di tipo informatico senza l’ausilio del calcolatore, per esempio nel progettare ed applicare regole precise per svolgere operazioni aritmetiche con carta e penna; l’elaboratore, tuttavia, è uno strumento di calcolo potente, che permette la gestione di quantità di informazioni altrimenti intrattabili

Page 4: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Algoritmo

AlgoritmoAlgoritmo: sequenza di istruzioni attraverso le quali un operatore umano è capace di risolvere ogni problema di una data classe; non è direttamente eseguibile dall’elaboratore

ProgrammaProgramma: sequenza di operazioni atte a predisporre l’elaboratore alla soluzione di una determinata classe di problemi

Il programma è la descrizione di un algoritmoalgoritmo in una forma comprensibile all’elaboratore

L’elaboratore è una macchina universalemacchina universale: cambiando il programma residente in memoria, è in grado di risolvere problemi di natura diversa (una classe di problemi per ogni programma)

Page 5: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Algoritmi nella realtà Come abbiamo già detto un algoritmo può essere descritto in

maniera informale come “una sequenza di passi, definiti con una sequenza di passi, definiti con precisione, che portano alla realizzazione di un compitoprecisione, che portano alla realizzazione di un compito”

Es: Le istruzioni di montaggio di un elettrodomestico Il calcolo del MCD (massimo comune divisore) Il prelievo di denaro dal bancomat:

Inserimento tessera Inserimento codice segreto .ecc…

Molte attività umane sono “algoritmi”

Page 6: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Algoritmo

Un algoritmo deve essere: comprensibile

Altrimenti l’esecutore non può capirlo non-ambiguo:

Altrimenti vi potrebbero essere diverse valide interpretazioni dello stesso algoritmo

corretto Ovviamente dovrebbe effettivamente fare quello per cui è

stato pensato efficiente (utile ma non vincolante)

Dovrebbe eseguire il suo compito nel modo più veloce possibile

Page 7: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Codifica di un algoritmo Quindi per risolvere un problema è necessario esprimerlo sotto

forma di algoritmo: Una volta descritto in termini di passi più o meno elementari è

possibile codificare questi passi utilizzando il linguaggio di programmazione prescelto

Ricordiamo anche che per un dato problema possono esistere molteplici algoritmi che lo risolvono e che possono distinguersi per la migliore o peggiore complessità

L’uso di un linguaggio di alto livello permette di utilizzare nomi per le variabili e per le funzioni molto vicini alla loro funzione: tassoInteresse per una variabile che indica il tasso d’interesse, ecc…

Page 8: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Schema dell’algoritmo Solitamente la codifica di un problema in algoritmo avviene

utilizzando i “diagrammi di flusso”, ovvero diagrammi grafici che permettono di visualizzare il “flusso” delle operazioni da compiere per arrivare alla soluzione

Un diagramma di flusso schematizza l’ordine delle operazioni più o meno semplici richieste per risolvere un problema

Ogni operazione di assegnamento è racchiusa in un rettangolo mentre le operazioni di verifica sono visualizzate in rombi

Page 9: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Diagrammi di flusso Esempio di codifica di un banale algoritmo con un diagramma di

flusso:

Rappresentare un grosso programma tramite un unico diagramma di flusso diventa comunque impossibile: Solitamente un algoritmo viene scomposto in unità funzionali distinte

(funzioni, procedure o moduli) Ogni unità dovrebbe essere così semplice da poter essere

facilmente schematizzabile tramite un diagramma di flusso

leggi x e memorizzalo in a

a > 100Fai qualcosa Stampa “errore”false true

Page 10: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggi Il linguaggio utilizzato per descrivere l’algoritmo deve essere

interpretabile dall’esecutore dell’algoritmo: Se abbiamo le istruzioni di montaggio di un elettrodomestico in cinese,

non siamo in grado di seguire i passi necessari a terminare il lavoro (a meno che non si conosca il cinese!!)

In informatica: I calcolatori sono “esecutori di algoritmi” Gli algoritmi sono descritti tramite programmi, cioè sequenze di istruzioni

scritte in un opportuno linguaggio, comprensibile al calcolatore

Compito dell’esperto informatico: Produrre algoritmi per un dato problema Codificarli in programmi (renderli comprensibili al calcolatore)

Page 11: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Precisione

Il calcolatore esegue un programma passo-passo, in modo preciso, veloce e potente, senza deviare dal flusso delle istruzioni anche se esso è palesemente sbagliato: Questo perché il calcolatore è privo di “intelligenza”, non può decidere se

una istruzione è sbagliata, se c’è, la esegue.

Questo richiede quindi che le istruzioni siano puntuali e che l’algoritmo sia chiaro e puntuale: “per fare la torta di mele occorrono 3 Kg di mele, 3 uova e 0,5 Kg di

farina” è sufficientemente precisa “legate l’arrosto e salatelo” non è sufficientemente precisa poiché per

esempio non specifica la quantità di sale da utilizzare

Page 12: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Correttezza

Un algoritmo è corretto se esso perviene alla soluzione del compito per cui è stato sviluppato, senza difettare di alcun passo. Se nell’algoritmo di montaggio di un mobile viene omessa l’istruzione di

stringere una vite, il risultato finale può non essere “corretto” perché il mobile molto probabilmente non starà in piedi (dipende dalla importanza della vite!!)

Sarà necessario individuare l’errore e ripararlo per avere il risultato corretto

Un algoritmo non deve tralasciare nessun passo per giungere alla soluzione, altrimenti il suo risultato potrebbe essere non corretto.

Page 13: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Efficienza

Un algoritmo dovrebbe raggiungere la soluzione nel minor tempominor tempo possibile e/o utilizzando la minima quantità di risorseminima quantità di risorse, compatibilmente con la sua correttezza. efficienza in tempo e spazio (risorse)

Es. Non è efficiente un algoritmo in cui prima viene regolato un dispositivo e

poi, nel passo successivo, tale impostazione viene modificata, se poi deve essere riportata a come era prima

Un buon informatico cercherà di ottimizzareottimizzare un algoritmo il più possibile per cercare di arrivare alla soluzione il più veloce possibile e con l’utilizzo di minor risorse possibili

Page 14: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

Page 15: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

La bontà di un programma viene valutata analizzando due fattori: Quanto è veloce il programma (complessità in tempo) Quante risorse richiede il programma (complessità in spazio)

Solitamente, a meno di richieste esagerate, la complessità spaziale non è un problema, quindi si “guarda” molto più a quanto tempo ci vuole per eseguire un compito

Page 16: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

La complessità temporale di un programma però non è di semplice valutazione

Tempo di esecuzione: dipende dalla potenza della macchina su cui è eseguito dipende dalla dimensione dell’input (molti dati molto più tempo)

La soluzione è stata di assegnare un costo alle operazioni e calcolare quindi la complessità totale come costo complessivo: L’operazione di confronto ha costo uno Tutte le altre hanno costo nullo (non è vero, ma hanno un costo irrisorio

rispetto al confronto)

Page 17: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

Inoltre non è possibile dare una misura puntuale del costo di un algoritmo, poiché molte volte esso dipende dallo spazio dell’input: Si calcola quindi il costo in funzione della dimensione dell’input costo =

f(n) , dove n è la dimensione dei dati su cui andiamo a lavorare

Infine è necessario calcolare il costo nel caso migliore e nel caso peggiore : o(f(n)) per la complessità nel caso migliore (costo minimo) O(f(n)) per la complessità nel caso peggiore

Il limite inferiore (o() ) non ha molto significato

Page 18: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

Es.

Problema:

“Dati n numeri, trovare il più grande”

Algoritmo:

MAXVAL = primo numero

Per ogni numero seguente, se è maggiore di quello in MAXVAL, memorizzalo in MAXVAL

Complessità:

nel caso peggiore, il valore massimo si trova in ultima posizione; in questo caso sono necessari n-1 confronti. Quindi la complessità dell’algoritmo è O(n). Tale funzione (f(n)=n) è detta anche “lineare”, dato che cresce linearmente con n.

Page 19: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

In realtà, l’esempio precedente, avrebbe complessità O(n-1), ma poiché per n >>1 O(n-1)~O(n), viene utilizzato O(n) come valore di complessità

Questo vale per tutte le funzioni f(n) indicanti la complessità di un algoritmo: O(2n+4) , per n>>1 O(n) O(2n2+n+4), per n>>1 O(n2) Ecc..

cioè viene individuata la funzione maggiorante

Page 20: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Complessità

La complessità dà un’idea della “fattibilità” dell’algoritmo. Supponiamo il costo di una operazione pari ad 1 secondo, il tempo necessario per un algoritmo con le varie complessità è il seguente:

Come si vede, un problema con complessità polinomiale diventa molto velocemente “intrattabile”

LogaritmicaO(log(n))

Lineare O(n)

QuadraticaO(n2)

PolinomialeO(2n)

10 3 sec10 sec

1,5 min

17 min

20 4-5 sec20 sec

7 min

291 giorni

30 5 sec30 sec

15 min

191 anni

complessitàn

Page 21: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Esempio: un algoritmo più complicato

Gestione di una biblioteca: Ogni libro si trova su uno scaffale e può essere preso in prestito ed in

seguito restituito.

La biblioteca è dotata di uno schedario ed ogni scheda contiene: Nome,cognome dell’autore (o autori) Titolo Data di pubblicazione Numero scaffale in cui si trova Numero d’ordine della posizione

Le schede sono disposte in ordine alfabetico in base all’autore ed al titolo.

Page 22: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La biblioteca

Algoritmo di ricerca di un libro in biblioteca:1. Ricerca della scheda nello schedario2. Lettura del numero di scaffale e posizione del libro3. Ricerca dello scaffale indicato4. Prelievo del libro e scrittura sulla scheda delle informazioni sul prestito:

data,nome ecc..

Ogni passo può (deve) essere descritto più dettagliatamente: sotto-algoritmo

Passo1:

1.1Lettura della prima scheda dello schedario1.2 Se il nome dell’autore ed il titolo coincidono, ricerca

conclusa1.3 Si ripete il passo 2 fino trovare la scheda cercata o a

terminare le schede1.4 Se non viene trovata la scheda, la ricerca termina in modo

infruttuoso

Page 23: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La biblioteca

Il sotto-algoritmo per il passo 1, è corretto ma non efficiente: Ha una “complessità” lineare con il numero di schede, ossia nel caso peggiore

tutte le schede nello schedario verranno analizzate

E’ possibile definire un altro algoritmo per il passo 1 più efficiente:1.1 Se lo schedario è vuoto ricerca infruttuosa1.2 Lettura scheda centrale1.3 Se è quella cercata, ricerca conclusa con successo1.4 Se il nome dell’autore e/o titolo è precedente, si ripete l’algoritmo sulla prima

metà dello schedario1.5 Se il nome dell’autore e/o titolo è successivo, si ripete l’algoritmo sulla seconda

metà dello schedario

Nel caso peggiore, questo algoritmo analizza log2(n) schede: 16000 schede 16000 schede alg1 = 16000 confronti alg1 = 16000 confronti 16000 schede 16000 schede alg2 = 14 confronti alg2 = 14 confronti

Page 24: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La biblioteca

Nel secondo algoritmo presentato per automatizzare il passo 1, l’algoritmo richiama se stesso su un differente set di dati fino ad una terminazione positiva o negativa

Un algoritmo di questo tipo si dice “ricorsivo”: ovvero il problema viene scomposto in sottoproblemi uguali ma su set di

dati più piccoli, fino ad arrivare o alla soluzione o alla impossibilità di proseguire

condizioni di stop: Il sottoinsieme su cui viene richiamato l’algoritmo è vuoto (1.1) La ricerca è andata a buon fine (1.3)

Vedremo più avanti in dettaglio quali tipi di algoritmi esistono

Page 25: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Livelli di astrazione e

storia dei linguaggi di programmazione

Page 26: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Programmazione di basso livello

Al livello più basso le istruzioni di un computer sono estremamente elementari.

Il processore esegue le istruzioni macchina: Sequenze di bytes i codici delle operazioni e le locazioni in memoria

Le CPU di fornitori diversi (Intel, SUN, Mac) hanno insiemi differenti di istruzioni macchina: Instruction set

Page 27: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggio binario

Scrivere programmi direttamente in linguaggio macchina però risulta essere molto complicato: Sequenze di numeri con poca espressività

Es

- Carica il contenuto della posizione di memoria 40- Carica il valore- Se il primo valore è maggiore del secondo continua con l’istruzione in posizione 240

21 40 16 100 163 240

Page 28: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Assembler

Il primo passo fu di assegnare nomi abbreviati ai comandi: iLoad “carica un numero intero” bipush “inserisci una costante numerica” if_icmpgt “se il numero intero è maggiore”

L’esempio può essere riscritto così:iLoad 40bipush 100if_icmpgt 240

Similmente in seguito furono assegnati dei nomi anche alle locazioni di memoria (variabili):iLoad intRatebipush 100if_icmpgt intError

ASSEMBLER

Page 29: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Assemblatore

Tale metodo di programmazione richiedeva quindi un software che traducesse il codice dal linguaggio ASSEMBLER al linguaggio macchina: ASSEMBLATORE

La nuova forma di programmazione continua ad avere corrispondenza uno-a-uno con il linguaggio macchina Ad ogni istruzione ASSEMBLER corrisponde una istruzione del

Instruction Set

Rimane però molto difficile sviluppare grandi programmi utilizzando istruzioni di così basso livello: If_cmpgt, iLoad, ecc… lavorano su indirizzi in memoria, su registri della

CPU ed anche un semplice confronto tra due variabili richiede una sequenza di alcune istruzioni assembler

Page 30: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggi di alto livello

Furono teorizzati allora linguaggi di programmazione che astraevano dalla architettura del calcolatore (indipendenza dall’ Instruction Set) e permettevano costrutti molto più vicini al “pensiero umano”: “se EXPR allora FAI QUESTO, altrimenti FAI QUEST’ALTRO” “ripeti L1 fino a che NON ACCADE QUESTO”

Questi costrutti permettevano di racchiudere una sequenza di istruzioni macchina in una “descrizione” molto più vicina all’essere umano

Page 31: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La compilazione

Questi linguaggi richiedono l’uso di un compilatore che traduca il codice di alto livello in codice macchina: Ogni linguaggio ha quindi il suo compilatore (o più di uno)

Inoltre, dato che ciò che il compilatore genera è il codice macchina e quest’ultimo è strettamente dipendente dalla macchina (Hardware/SO) su cui gira, la compilazione traduce il codice da un linguaggio astratto in una forma dedicata e strettamente dipendente dalla macchina che si sta adoperando

Page 32: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La compilazione

Quindi: È il compilatore che si occupa di tradurre un dato linguaggio (es. C) nel

codice macchina adatto alla macchina su cui dovrà essere eseguito Se un programma C viene compilato su ambiente Windows, sarà creato

un programma che “girerà” solo su ambienti windows; similarmente, se lo stesso codice viene compilato su Linux, sarà possibile eseguire l’applicazione solo su una macchina Linux

Un linguaggio di programmazione di alto livello deve rispettare RIGOROSE convenzioni affinché sia interpretabile dal compilatore

Page 33: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggi alto livello

If (intRate>100) printf(“Error”) C++

21 40 16 100 163 240

se il tasso di interesse è maggiore di 100 scrivi a video un messaggio di errore

Sviluppo

Compilazione

Page 34: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La compilazione

Il processo di compilazione però “peggiora” le prestazioni rispetto ad un programma scritto direttamente in linguaggio macchina: Il tempo richiesto dal traduttore per generare il codice macchina Il codice oggetto generato dal compilatore tipicamente è meno “ottimizzato”

rispetto a quello generato direttamente dall’essere umano

In realtà: Anche considerando il tempo di traduzione del compilatore, il tempo

necessario allo sviluppo del programma rimane comunque decisamente inferiore a quello necessario a sviluppare direttamente in codice oggetto

Il codice generato dal compilatore è sì difficile che sia “ottimizzato”, ma comunque la perdita di prestazione risulta essere accettabile: Oggi inoltre tutti i compilatori hanno la possibilità di ottimizzare il codice E comunque non è detto che un essere umano riuscirebbe a generare

codice ottimizzato per programmi molto complicati come quelli che si possono scrivere utilizzando linguaggi di alto livello

Page 35: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Un po’ di storia dei linguaggi di alto livello A seguito di queste teorie nacquero i primi linguaggi di alto livello:

FORTRAN (FORmula TRANslator): il primo linguaggio di alto livello sviluppato per descrivere formule matematiche

COBOL (Common Business Oriented Language): il primo linguaggio orientato alle applicazioni gestionali

Per molto tempo questi due linguaggi rimasero i linguaggi più diffusi fino a quando non fu studiata una categoria di linguaggi più rigorosamente basati su uno studio dei principi della programmazione: Il capostipite di questa famiglia fu ALGOL60 (ALGOrithmic Language)

che pur non essendo mai stato utilizzato nella pratica, è famoso per questo motivo.

Page 36: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Un po’ di storia dei linguaggi di alto livello Dopo l’ALGOL60, furono sviluppati molti nuovi linguaggi di

programmazione “orientati” ad una programmazione generale : PASCAL, oggi molto diffuso per la didattica C ,tra i più potenti linguaggi di programmazione, divenuto molto

popolare grazie al fatto che il sistema Unix fu interamente sviluppato utilizzando questo linguaggi di programmazione

ADA, Basic, Perl, Phyton, ecc….

Anche questi però ad un certo punto furono superati da un nuovo paradigma: la programmazione ad oggetti C++, C# e Java derivati dal C Eiffel e Delphi derivati dal Pascal VisualBasic ecc…

Page 37: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Programmazione Procedurale

Page 38: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggio procedurale La programmazione “classica” segue il paradigma di

programmazione procedurale o imperativo

Cosa significa: Il problema è scomposto in molti sottoproblemi che possono essere

risolti in maniera semi-indipendente per poi essere aggregati per ottenere il risultato finale

Ogni sotto-problema viene assegnato ad un sottoprogramma che si occupa di eseguire le operazioni per restituire il risultato (o effettuare il compito per cui è stato creato)

L’applicazione stessa è vista come un sottoproblema: Assemblare i sotto-problemi individuati in maniera da ottenere il

risultato

Page 39: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggio procedurale Quindi seguendo questa idea, il programma è costituito da diverse

funzioni (procedure o subroutines) ognuna disegnata per uno scopo

Il corpo del programma è esso stesso una funzione, con la particolarità però di avere una forma (prototipo) standard: la funzione main()

Quando un programma procedurale è compilato ed avviato, ciò che viene lanciato è la procedura main: Tutto ciò che deve essere eseguito dal programma deve essere

implementato nella procedura main, ricorrendo a tutte le chiamate di funzione e dati necessari

Page 40: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Linguaggio procedurale

int main(int,int)

funzione1

funzione2

funzioneM

Dato A

Dato B

Dato N

avvio dell’applicazione

……

Page 41: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Variabili e tipi di dato

Page 42: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Variabili

Una variabile rappresenta un’area di memoria riservata dal compilatore per memorizzare dati

Quest’area di memoria è riferita tramite un nome univoco: Questo nome permette di accedere alla memoria per leggere/scrivere

informazioni In fase di programmazione, quando viene definita ed utilizzata la

variabile non ha un valore, ma rappresenta tutti i valori che ciò che essa rappresenta potrà assumere

Il valore è assegnato a run-time

Page 43: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Nomi di variabili

Ogni variabile (e funzione che vedremo in seguito) è riferita tramite un nome

Un nome in un linguaggio di programmazione è inteso come una etichetta che rispetta alcune regole fissate dal linguaggio stesso: Deve essere costituita da un singolo token. Etichette formate da più

parole separate non sono accettate (il compilatore non può sapere che le due parole vanno interpretate insieme!!)

Non può essere una delle parole riservate del linguaggio (if, else, while, return ecc…)

Deve contenere solo caratteri alfa-numerici più il carattere ‘_’: questa condizione implica la prima poiché il carattere spazio ‘ ‘ non è permesso

Non può comunque iniziare con un carattere numerico

Page 44: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione di variabili

Dichiarare una variabile significa avvertire il compilatore che riservi un’area di memoria perché in futuro essa verrà utilizzata con quel nome: Processo di allocazione della memoria

Ogni variabile, prima di essere utilizzata, deve essere dichiarata: In caso contrario il compilatore genera un errore, non trovando la

corrispondenza del nome con un area di memoria nella tabella simboli

Quando una variabile viene dichiarata, deve perciò essere specificato sia il nome della variabile, sia il tipo di dato che tale variabile potrà assumere: Se una variabile viene dichiarata di tipo T, necessariamente essa potrà

memorizzare valori di tipo T

Page 45: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Tipi di dato

I tipi di dato si distinguono in tipi semplici e tipi strutturati: tipi di dato semplici – sono tipi di dato a cui può essere associato un

singolo valore (numerico o stringa) ed un riferimento alla variabile è un riferimento al contenuto

tipi di dato strutturati – sono tipi di dato composti da più “campi”, da cioè uno o più altri tipi di dato a loro volta semplici o strutturati

Ogni linguaggio di programmazione mette a disposizione una serie di tipi di dati predefiniti: Tipi di dato semplici bool, int, char, double, ecc… Tipi di dato strutturati array

Page 46: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Tipi semplici predefiniti Tutti i linguaggi di programmazione mettono a disposizione un

numero di tipi di dato semplice “built-in”:

bool Valori logici: true e false

char

Interi su 8 bit utilizzati per rappresentare numeri e caratteri (ASCII): signed/unsigned

intInteri su 16 bit: signed/unsigned

longInteri su 32 bit: signed/unsigned

floatNumeri in virgola mobile a 32 bit

double

Numeri in virgola mobile a 64 bit

Page 47: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Operatori

Per questi tipi di dato semplici sono forniti dal linguaggio anche gli operatori: Assegnamento (=) Addizione (+) Sottrazione (–) Moltiplicazione (*) Divisione (/) Modulo (%) , ritorna il resto della divisione. Es. 5%3 = 2 Uguaglianza (==) e disuguaglianza (!=), ritornano vero o falso Minore o maggiore (<, <=, >, >=) , ritornano vero o falso

Page 48: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Il tipo char

Il tipo char è un tipo semplice particolare: Il nome deriva dall’abbreviazione di “character” ed infatti è utilizzato per

rappresentare l’insieme finito dei caratteri (la tabella ASCII)

Ogni carattere ha un codice numerico compreso tra 0 e 127 (7 bit), più un “extended set” compreso tra 128 e 255 (8° bit)

Page 49: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Il tipo char e le sequenze di escape Alcuni codici sono riservati per i caratteri di controllo e solitamente

sono indicati utilizzando il carattere “\” come carattere di escape: Molte volte è necessario utilizzare particolari sequenze di caratteri per

rappresentare caratteri che altrimenti non sarebbe possibile visualizzare Es:

Le stringhe sono sequenze di caratteri delimitate da “. Se vogliamo inserire un carattere “ all’interno di una stringa dobbiamo utilizzare la sequenza di escape \” per informare il compilatore che “ non delimita la fine della stringa

Di solito le sequenze di escape sono utilizzate per i caratteri di controllo: “new line” \n, “tab” \t, ecc….

Page 50: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Caratteri di controllo

escape

ASCII

codice

Descrizione

0NULL

Carattere nullo

… … … …

\b 8 BSBack Space

\t 9 HTHorizontal Tab

\n 10 LF Line Feed… … … …

\r 13 CRCarriage Return

… … … …

La rappresentazione dei caratteri tramite un codice numerico permette un ordinamento tra gli stessi caratteri e quindi la possibilità di operazioni

Page 51: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Valori esadecimali

È inoltre possibile assegnare valori in base 16 utilizzando la convenzione:

0xNNNN

dove NNNN è il numero in base 16

Es

int y=0x0A; assegna 10 alla variabile y

Page 52: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Definizione di nuovi tipi semplici Oltre ai tipi di dato semplici predefiniti, è possibile definirne di nuovi

: Ridefinizione typedef : il nuovo tipo di dato è solamente un alias di

uno già esistente. Per esempio, l’istruzione C typedef int T1;

definisce un tipo di dato T1 che altro non è che un altro nome per un intero (int)

Enumerazione enum : il nuovo tipo di dato può assumere solamente uno dei valori (numerici o meno) contenuti in una lista di enumerazione. Per esempio, l’istruzione C

enum{“A”,”B”,”C”} D1; definisce una variabile D1 che può assumere solamente i valori “A”,”B”, o “C”. In questo esempio il tipo di dato è enum{….} ; per avere un tipo di dato T1 è necessario utilizzare il costrutto typedef:

typedef enum{“A”,”B”,”C”} T1; tipo di dato T1T1 D1; crea una variabile D1 di tipo T1

Page 53: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Tipi strutturati predefiniti I linguaggi di programmazione forniscono anche dei tipi strutturati

predefiniti: array questo tipo di dato corrisponde ad una sequenza di celle

consecutive di memoria di lunghezza fissata (e fornita al momento della dichiarazione della variabile di quel tipo). Tutte le celle devono necessariamente contenere lo stesso tipo di dato. Per esempio, in C, l’istruzione “int list[20];” dichiara la variabile list come una sequenza di 20 interi

I recenti linguaggi di programmazione forniscono altri dati strutturati predefiniti per esempio: date, record, ecc…

Page 54: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Creazione di nuovi tipi strutturati Oltre ai tipi “built-in” è possibile create nuovi tipi di dato strutturati

tramite appositi costrutti del linguaggio: Es. in C (o C++)

struct {int giorno;int mese;int anno;

} D1;

L’esempio mostra una situazione tipica in cui è preferibile utilizzare un dato strutturato: La data infatti può essere vista come una tripla di interi, ma gestire tre

variabili intere separate per tutto il programma può essere contro-intuitivo per il programmatore. Risulta migliore, come si può immaginare, creare un dato D1 come aggregazione dei tre interi. Anche in questo esempio per definire un tipo di dato T1 si può utilizzare la funzione typedef

Page 55: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione ed inizializzazione Una volta dichiarata, la variabile può essere utilizzata nel

programma: La dichiarazione crea una istanza di quel tipo di dato con il suo relativo

nome (normalmente si parla di variabile istanziata) Notare che la dichiarazione non inizializza la variabile ad un valore, ma

semplicemente riserva uno spazio in memoria per quella variabile: un successivo accesso alla variabile non inizializzata, può restituire un valore non valido

L’inizializzazione di una variabile è fatta con un istruzione di assegnamento: Può essere fatta al momento della dichiarazione Può essere fatta in un secondo momento

Page 56: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Cast Se memorizziamo un dato in una variabile di tipo diverso, è

solitamente avviene un’operazione di “casting”, ovvero il compilatore traduce automaticamente il dato nella forma richiesta dal tipo della variabile: int double ( 54 54,00) – non si ha perdita di precisione double int (54,23451 54) – si perde la parte decimale signed char unsigned char (-1 255) – vengono utilizzati tutti i 28

valori positivi generabili con 8 bit.

Infatti:

signed char [-27,27-1], di cui 1xxxxxxx sono i valori negativi

[-128,-1] [10000001 , 11111111]

se non consideriamo il segno,

10000001 129 e 11111111 255

quindi -1 255 nel passaggio da signed ad unsigned (e viceversa)

Page 57: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Cast Il cast avviene in maniera implicita se è previsto dal linguaggio di

programmazione (int char, double int, ecc…) altrimenti è necessario farlo in maniera esplicita definendo un’operatore di casting

Per i tipi di dato semplici predefiniti il casting è quasi sempre fornito dal linguaggio di programmazione stesso

Page 58: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione delle costanti Una dichiarazione di costante associa permanentemente un valore ad un

identificatore

La dichiarazione di una costante è praticamente la dichiarazione con assegnamento di una variabile con l’aggiunta della parola riservata const davanti, a specificare il fatto che quella cella di memoria conterrà il valore assegnato senza possibilità di modifica

ES:const int numAlunni = 25; numALunni conterrà 25 per tutto il

suo ciclo di vita

const char nome[16]=“leonardo” nome conterrà “leonardo” senza possibilità di modifiche

const date data = {5,10,2005} data conterrà 5/10/2005

Page 59: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni e controllo del flusso

Page 60: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni

Le istruzioni sono frasi proprie del linguaggio di programmazione delimitate dal simbolo “;” Es. read(x); è una istruzione – senza il simbolo terminatore, il

compilatore non capirebbe dove termina l’istruzione

Molte volte è necessario che sequenze di istruzioni vengano eseguite sequenzialmente: Corpo del programma, corpo di una funzione, corpo di un ciclo

Una lista di istruzioni è delimitata dai simboli “{“ e “}”: “{“ inizia una lista di istruzioni “}” termina la lista

E’ possibile innestare più liste di comandi

Page 61: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Struttura di un semplice programma Un programma è organizzato in maniera sequenziale

(non è più tanto vero)

La prima parte è l’intestazione, ovvero una etichetta seguita da una coppia di parentesi tonde () Il significato di queste parentesi sarà spiegato in seguito

A seguire inizia una lista di istruzioni, delimitate quindi da { e }

Ma che tipo di istruzioni prevede un linguaggio?

Page 62: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione di assegnamento

Questa istruzione fondamentale viene utilizzata per assegnare a una variabile il valore di una espressione: Consiste nel simbolo = preceduto dal nome della variabile a cui deve essere

assegnato il valore Alla destra del simbolo = viene specificate l’espressione che genera il risultato da

assegnare alla variabile

L’espressione può essere costituita da un valore costante (numero) , identificatori di altre variabili, espressioni aritmetico/logiche di combinazioni di valori e variabili e funzioni: x =23; w=‘a’; y =z; alfa = x + y; r3=(alfa * 43 –xgg)*(delta-32ijj); x = x + 1;

Page 63: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione di assegnamento

L’esecuzione di una istruzione di assegnamento comporta la valutazione della espressione a destra del simbolo = e la sostituzione del valore nella cella di memoria individuata dal nome della variabile a sinistra del simbolo =

Si noti che un valore cotante può essre un numero ma anche un carattere: Nell’esempio w=‘a’, assegna il carattere ‘a’ alla variabile w

Page 64: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Controllo del flusso

Il flusso delle istruzioni può cambiare a seconda della valutazione di una espressione: Può essere necessario per esempio effettuare una lista di operazioni L1

se una condizione è vera, una lista L2 altrimenti Oppure può essere necessario ripetere una lista di istruzioni fino a che

non è verificata una condizione

Le istruzioni che permettono queste scelte sono dette di controllo del flusso e come si evince dai due esempi qui sopra sono divise in due gruppi: Istruzioni condizionali Istruzioni iterative

Page 65: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione condizionale

Consente di valutare una espressione e di eseguire due sequenze distinte di operazioni a seconda del risultato ritornato dalla espressione

Sintassi:if (E1) {L1} else {L2}

Se E1 è vera verrà eseguita la lista di istruzioni L1, altrimenti sarà eseguita la lista L2 Il cosiddetto “ramo else” non è obbligatorio e può essere omesso nel caso in

cui non vi sia alcuna lista L2

Se L1 e L2 sono composta da un’unica istruzione anche le parentesi graffe possono essere omesse: Es.

if (E1) I1; else I2;

Page 66: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Castello di if

Se è necessario verificare più espressioni in maniera innescata, è necessario fare attenzione a quale if fa riferimento ogni else

if (E1) {

if (E2) {

L2;

} else {

if (E3) {

L3;

}

} chiude l’else di E2

} else {

L1;

} chiude l’else di E1

Page 67: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione iterativa while

Consente di ripetere la lista di istruzioni (iterare) più volte fino a che non risulta vera una condizione

Sintassi:

while (E1) {L1}

L’espressione E1 viene valutata e se è vera, viene eseguito il corpo del ciclo. Terminato il corpo, viene di nuovo valutata E1, e se continua ad essere vera, il corpo è di nuovo eseguito. Questo è ripetuto fino a che la valutazione di E1 non ritorna false

È possibile utilizzare all’interno del ciclo while l’istruzione break che interrompe incondizionatamente il ciclo, come se la condizione E1 fosse verificata

Page 68: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni derivate: strutture di controllo Teorema di Bohem-Jacopini: “Le istruzioni di controllo viste finora “if

… else …” e “while” sono equivalenti alle strutture di controllo del linguaggio assemblatore basate sulla diretta e condizionale manipolazione del registro contatore di programma: tramite esse è possibile esprimere ogni qualsiasi altra struttura di controllo di ogni qualsiasi altro linguaggio di programmazione”

Questo teorema ci dice che sebbene sia possibile “pensare” a molte altre possibili strutture di controllo di alto livello, per ognuna di esse si può sempre trovare una forma equivalente in termini di “if…else…” o di ciclo “while”: La specifica di nuove strutture di controllo rimane comunque utile per

fornire ai programmatori strumenti più vicini ai casi concreti

Page 69: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni condizionali derivate: else if

Quando sono necessarie valutazioni di più espressioni su di una variabile è possibile utilizzare il costrutto else if:

if (E1) {L1

} else if (E2) {L2

} ….else if (En-1) {

Ln-1}else {

Ln}

In alcuni linguaggi “else if” è stato condensato in un comando unico “elseif”

Page 70: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni condizionali derivate: switch…case Molti linguaggi per evitare enormi castelli di if, mettono a disposizione un

costrutto derivato: switch … case

Sintassi:switch (E1) {

case A:

LA;break;

case B:

Lb;break;

….default:

Ldefault;}

Page 71: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni condizionali derivate: switch…case L’istruzione switch-case, valuta l’espressione E1 e suppone che siano

possibili vari casi Per ognuno dei casi viene fornita una lista di istruzioni, seguita dal comando

break Nel caso si verifichi una condizione non specificata da alcun case , viene fornita

una scelta di default

Il comando break non è obbligatorio, serve solamente per evitare che nel caso A, il programma prosegua effettuando anche le istruzioni relative al caso B, caso C, e così via fino al caso di default. Se all’interno di un particolare algoritmo è richiesto un tale comportamento, il comando break può essere rimosso

NB: il costrutto switch-case lavora solamente su valori numerici La valutazione di E1 deve ritornare quindi un valore numerico

Page 72: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni iterative derivate: for

Consente di ripetere la lista di istruzioni (iterare) un numero prefissato di volte

Sintassi:for (START; EXPR; STEP) {L1;}START è la condizione iniziale da cui partire; EXPR è la espressione che viene valutata ad ogni iterazione per decidere se interrompere o meno il ciclo; STEP è la modifica che viene effettuata ad ogni passo

Es.for (i=0;i<N;i++) {L1;}per i che va da 0 a N, con passo 1, fai L1. Questo ciclo esegue N volte la lista di istruzioni L1.

Page 73: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzioni iterative derivate: for

L’istruzione for è in realtà un modo diverso per scrivere la forma while. Essa può essere infatti sostituita con:

i=0;while (i<N) {

L1;

i=i+1;}

dove N è conosciuto.

Oramai comunque è diventata una forma di istruzione “standard” in tutti i linguaggi di programmazione.

Page 74: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione iterative derivate: do…while Così come l’istruzione for può essere vista come un caso particolare

del più generale ciclo while, così molte altre istruzioni condizionali sono state proposte nei vari linguaggi di programmazione

do … while

do {L1;} while (E1) – ripete la lista di istruzioni fino a che E1 non è verificata; a quel punto esce dal ciclo

La differenza importante dal ciclo while è il punto in cui E1 viene valutata:

- nel ciclo while viene valutata prima di eseguire L1, - nel ciclo do-while è valuata dopo aver eseguito almeno

una volta il corpo del ciclo

Page 75: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione iterative derivate: goto Molti linguaggi hanno mantenuto tra le proprie strutture di

controllo “istruzioni di salto” direttamente ispirate alle istruzioni macchina dei processori: Istruzione goto

Sintassi:goto LABEL;…LABEL: L1L’istruzione goto permette di saltare l’esecuzione del programma alla linea di codice individuata dalla etichetta LABEL.

Sono molto poco utilizzate ed anzi i teorici della programmazione sostengono che “se siamo costretti ad utilizzare un istruzione goto, abbiamo sicuramente sbagliato qualcosa nell’impostare l’algoritmo”

Page 76: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Funzioni e procedure

Page 77: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Sottoprogrammi Nella creazione di un programma può accadere che problemi simili

appaiano in mole parti diverse

La soluzione più ovvia è quella di replicare il codice in ogni parte dove è necessario, ma questa soluzione non è certamente la più “friendly”: Se il codice ha un errore, infatti, esso sarà replicato in tutte le parti in cui

quel codice è stato copiato Se quella parte di codice viene aggiornata, sarà necessario aggiornare

tutte le parti in cui è stato copiato

Molto poco flessibile e manutenibile: uso di sottoprogrammi

Page 78: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Sottoprogrammi Sottoprogrammi: parti di codice separate dal flusso principale del

programma che possono essere richiamate dove necessario senza replicare il codice ogni volta

Un sottoprogramma deve essere innanzitutto definito, cioè deve essere dichiarato da qualche parte ciò che esso esegue, su cosa lo esegue e cosa restituisce (se restituisce qualcosa)

Una volta definito, esso deve essere implementato, cioè scritto il corpo del sottoprogramma, con le variabili e le istruzioni che permettono di eseguire il compito per cui è stato progettato

Infine, una volta dichiarato e implementato, esso può essere richiamato ogni qualvolta è richiesta una operazione di quel tipo

Page 79: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Funzioni e procedure

Ma cosa sono di preciso i sottoprogrammi?

Ogni sottoprogramma è un blocco più o meno lungo di codice che riceve in ingresso alcuni parametri (anche nessuno) e può restituire un valore: I parametri che riceve in ingresso sono i valori che il chiamante passa

alla procedura: sono quindi variabili in cui a run-time vengono memorizzati i valori attuali dei parametri

Il sottoprogramma utilizza questi parametri per eseguire il suo compito ed “eventualmente” restituisce a sua volta al chiamante un valore

Page 80: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Funzioni e procedure

Formalmente due tipologie di sottoprogrammi sono state individuate: Le funzioni, che in analogia con le funzioni matematiche, ricevono

alcuni valori in ingresso e restituiscono un valore in uscita Le procedure, che ricevuti alcuni dati in ingresso, eseguono un compito

che non può concettualmente essere associato ad una funzione (es. stampa, aggiornamento ecc…)

Diciamo subito che la distinzione è abbastanza formale e che chiamare entrambi funzioni o procedure non comporta alcun problema Le procedure, in efetti possono essere assimilate a funzioni che non

restituiscono alcun valore, ma eseguono semplicemente un compito

Page 81: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Funzioni e procedure

I parametri che la funzione utilizza per “ricevere dati dall’esterno” sono variabili locali: Ovvero esistono localmente alla funzione Come tali devono avere un tipo ed un nome (univoco all’interno della

funzione)

Anche il valore di ritorno della funzione è un dato di un certo tipo, quindi nella descrizione della funzione sarà necessario specificare che tipo di dato essa ritorna

Page 82: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Le funzioni

Una funzione è una parte di programma individuato da una etichetta che riceve in ingresso dei parametri e ritorna un risultato, terminando sempre il suo compito I parametri d’ingresso sono chiamati semplicemente parametri della

funzione Il valore di uscita è detto valore di ritorno della funzione

Come accennato in precedenza una funzione deve essere prima definita, ovvero deve venire specificato la struttura della funzione stessa: il nome univoco della funzione i parametri che riceve in ingresso il tipo di dato che essa restituisce

Page 83: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione di funzione Prima di implementare una funzione è necessario dichiarare la

sua “interfaccia” con l’esterno, il modo cioè con cui essa è invocata ed il tipo di risultato che ritorna: La dichiarazione di una funzione specifica il prototipo della funzione

Es:

double potenza( int x, int y) è una funzione che riceve due parametri di tipo int (x e y) e restituisce un double

Come la dichiarazione di una variabile non inizializzava la variabile, così la dichiarazione di una funzione non realizza la funzione: In questo modo per ora è stato dichiarata solamente la interfaccia

della funzione

Page 84: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione di funzione La dichiarazione di una funzione (prototipo) è utile per far capire

al compilatore che la funzione esiste e che forma ha: La funzione poi, potrebbe essere implementata in qualsiasi altro file

del progetto e compilata “dopo” il file principale, ma l’importante è che nel file principale sia riportato il prototipo della funzione che viene utilizzata altrimenti il compilatore non può continuare

Questo metodo permette di scomporre il progetto in più file in cui implementare le varie procedure, organizzandole in maniera più intelligente: E’ importante che quando una funzione viene utilizzata in qualche file,

sia specificato in quel file il prototipo di quella funzione Il linker si occupa di “collegare” il corpo della funzione nei punti in cui

la funzione è chiamata

Page 85: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione di funzione

La sintassi comune di una dichiarazione di funzione è la seguente:

[tipo_di_dato] [nome_della_funzione] ([lista di parametri])

Dove

[lista di parametri] = lista di dichiarazioni di variabili visibili dall’interno e dall’esterno della funzione

Es.

double potenza( int x, int y);

Questa riga di codice dice che da qualche parte esiste una funzione potenza che riceve in ingresso due interi, esegue qualcosa e ritorna un double.

Page 86: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Dichiarazione di funzione Se una funzione (o procedura) non ritorna alcun valore, si utilizza

un tipo di dato apposito void :

void stampa(String file);

È possibile infine avere funzioni che non richiedono parametri, poiché quello che devono fare è indifferente da valori esterni:

void stampa();

In molti linguaggi (C++) è possibile specificare valori di default ai parametri della funzione: Valori che se non forniti alla funzione

Page 87: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Valori di default Se un parametro normalmente assume un certo valore (=K) e solo

poche volte varia, è possibile inserire il valore K come valore di default: se quel parametro non è fornito, la funzione utilizza il valore di default

double potenza( int x, int y);

Ad esempio:

double ris = potenza(4,2) 16

NB: se un parametro ha un valore di default, allora tutti i parametri seguenti devono avere un valore di default, altrimenti durante la chiamata con valore di default il compilatore non sa più a quale parametro fare riferimento:

double potenza( int x=2, int y); se chiamiamo int r=potenza(4); il compilatore non sa se associare 4 ad x o a y.

Page 88: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Implementazione della funzione La funzione deve comunque essere implementata (cioè realizzata)

da qualche parte nel progetto: La definizione del prototipo infatti non specifica cosa deve fare la

funzione

L’implementazione di una funzione avviene dichiarando il prototipo della funzione stessa ed iniziando immediatamente dopo un blocco di istruzioni:double potenza( int x, int y) {

Lista di istruzioni;}

Il blocco nell’esempio qui sopra è delimitato dalle parentesi graffe, come avviene nel C, C++ e JAVA.

Page 89: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Implementazione della funzione All’interno del corpo di una funzione, possono essere dichiarate

nuove variabili, utilizzando anche nomi di variabili utilizzati in altre funzioni: Ogni variabile interna ad una funzione ha infatti una visibilità limitata a

quella funzione ed una volta usciti dalla funzione le variabili vengono deallocate

Le varibili allocate all’interno di una funzione sono chiamate variabili locali, per distinguerle dalle variabili globali che sono variabili dichiarate fuori da ogni altra funzione, compresa la principale e sono quindi visibili sempre ed ovunque: Se all’interno di una funzione viene utilizzato un nome di variabile

globale, ogni riferimento a quel nome viene reindirizzato alla variabile locale

Page 90: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione return Quando la funzione deve ritornare un valore è necessario al suo

interno contenga una istruzione di ritorno valore che termina la funzione e restituisce un dato conforma al prototipo:

il valore viene restituito tramite l’istruzione return

Sintassi:

return [VALORE o VARIABILE];

Il tipo di valore restituito deve coincidere con il tipo di valore specificato nella dichiarazione della funzione, altrimenti il compilatore ritorna errore.

Page 91: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione return Il valore di ritorno può essere una valore costante oppure il

contenuto di una variabile: Nel secondo caso la variabile dovrà essere dello stesso tipo del dato

da ritornare

ES

double potenza( int x, int y) {

double ris=1;

for (int i=0;i<y;i++) {

ris=ris*x;

}

return ris;

ris=0;

}

Page 92: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione return Quando la funzione non deve ritornare alcun valore l’istruzione

return non è richiesta: è però possibile inserirlo senza specificare il dato ritornato:

void stampa(String file) {

L1;

return;

}

Page 93: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Istruzione return L’istruzione return può essere utilizzata anche per interrompere

l’esecuzione della funzione senza attendere la fine della lista di istruzioni: ad esempio può accadere che se una condizione è verificata, la

funzione ritorna un valore X, altrimenti esegue altre operazioni e ritorna un valore Y

In questo caso avremo due istruzioni return, ma eseguite in maniera esclusiva (o l’una o l’altra)

ES.

double potenza( int x, int y) {

if (y==0) {

return 1;

}

double r=(calcola la potenza xy);

return r;

}

Page 94: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Chiamate alle funzioni Una volta dichiarata ed implementata, una funzione può essere richiamata

laddove è necessario

la chiamata di una funzione è semplicemente il nome della funzione seguito dai parametri da passare: Es.

double r=potenza( 2, 4)

in questo caso r assume il valore ritornato dalla funzione potenza con i parametri x=2 e y=4

È possibile passare anche variabili invece che valori numerici costanti: Es.

int a=2;int b=4;double r=potenza(a,b);

Page 95: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Chiamate alle funzioni Il prototipo deve necessariamente essere rispettato:

double potenza( int x, int y) double potenza( 2, 3)

se viene omesso qualche parametro, il compilatore dà errore: il compilatore cerca una funzione con prototipo diverso e non la trova

Page 96: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri

Page 97: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri

Cosa succede quando si passa una variabile come parametro ad una funzione? Ossia, se all’interno della funzione modifico il valore di quel parametro, il valore della variabile originaria viene modificato ?

La risposta è: dipende !!

Esistono due modi per il passaggio dei parametri: Per valore Per riferimento

Page 98: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri per valore

Quando è richiesto che i valori delle variabili non siano modificati dal corpo della funzione, quello che avviene è che il valore della variabile viene copiato nella variabile-parametro della funzione. In questo modo: ogni modifica alla variabile locale non si riflette sulla variabile esterna ogni modifica fatta alle variabili locali, però, va persa all’uscita dalla

funzione e solo il risultato ritornato è visibile dall’esterno della funzione

Questo metodo di passaggio dei parametri va sotto il nome di passaggio per copia o per valore

Page 99: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri per riferimento Quando invece è richiesto che le variabili interne alla funzione siano

non una copia di quelle esterne, ma la stessa cosa, si parla di passaggio per riferimento: In questo caso, la variabile locale assume il riferimento in memoria alla

variabile esterna Quindi ogni modifica ad essa è una modifica alla cella di memoria

originale e permane anche alla chiusura dalla funzione

Normalmente questa situazione è richiesta quando si ha un sottoprogramma che deve effettuare delle operazioni su un dato e non ritorna alcun valore: ES. aggiornamento del fatturato totale, ecc…

in questo caso il fatturato totale, una volta aggiornato deve rimanere tale, quindi è necessario operare l’aggiornamento sulla variabile originale e non su una copia del valore

Page 100: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri

Notiamo che il passaggio per valore richiede la copia della variabile nella nuova variabile locale, mentre il riferimento ha un costo costante, viene copiato comunque un indirizzo di memoria Se stiamo passando dati strutturati particolarmente complessi, array di

grandi dimensioni, ecc… il passaggio per valore può essere molto più lento del passaggio per riferimento

E’ anche vero però che il passaggio per valore è molto più safety rispetto all’altro, dato che qualsiasi modifica, anche quella non voluta ed erronea non si riflette sul dato originario

Page 101: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri

Il metodo utilizzato per il passaggio dei parametri cambia da linguaggio a linguaggio:

Il C e C++ utilizzano il passaggio per valore, ma forniscono dei tipi di dato che permettono di realizzare il passaggio per riferimento (puntatori e riferimenti)

Il JAVA utilizza il passaggio per riferimento. Il passaggio per valore può comunque essere effettuato costruendo ogni volta una copia del parametro e passare quella alla funzione.

Page 102: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Funzioni e procedure

La differenza sul metodo di passaggio dei parametri stabilisce la principale differenza tra una funzione ed una procedura: Funzione: lo scopo principale è quello di utilizzare alcuni valori in

ingresso per produrre un valore di uscita, senza modificare null’altro passaggio per valore

Procedura: lo scopo principale è quello di operare delle operazioni sui parametri in ingresso che abbiano una semantica tale da poterle racchiudere in un corpo unico passaggio per riferimento

Comunque la differenza è solamente formale: In C++ o in JAVA non esistono metodi per dichiarare una funzione

piuttosto che una procedura. In realtà il primo prevede solamente funzioni, il secondo procedure.

Page 103: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri per valore

Programma chiamante

Funzionechiamata

Spazio di memoria del chiamato

par1

Spazio di memoria del chiamante

int acopia

chiamata di funzione

valore di ritorno

modifica locale

Page 104: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Passaggio di parametri per riferimento

Programma chiamante

Funzionechiamata

Spazio di memoria del chiamato

par1

Spazio di memoria del chiamante

int ariferimento

chiamata di funzione

valore di ritorno

modifica

modifica locale

Page 105: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La funzione main

Page 106: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Il corpo del programma

Adesso che abbiamo acquisito il concetto di funzione è possibile descrivere la struttura completa di un programma (procedurale)

Un programma procedurale è composto da: Dichiarazioni di variabili Dichiarazioni di funzioni (prototipi) Implementazioni delle funzioni (anche su più file) Corpo del programma

Ma cosa s’intende per “corpo del programma” ? Il corpo del programma è a sua volta una funzione globale particolare

che utilizzando tutte le altre funzioni ed i dati a disposizione, assembla il tutto per eseguire il compito ell’algoritmo

Page 107: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La funzione main

In definitiva, un programma non è altro che una funzione dal prototipo particolare e fissato:

int main(int argc,char[] argv)

Questa funzione accetta due parametri in ingresso e restituisce un valore intero in uscita: I due parametri in ingresso permettono di leggere eventuali parametri

passati da linea di comando all’applicazione

Es. il comando copy in windows accetta due parametri

copy file_a file_b argc=2, argv=[file_a,file_b] Il valore di ritorno permette di stabilire se l’esecuzione del programma è

andata a buon fine o meno. Solitamente un programma ritorna 0 se esce correttamente, 1 se vi sono stati errori

C e C++

Page 108: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Variabili globali e locali

La dichiarazione di una variabile normalmente può avvenire in qualsiasi punto del programma, sempre però prima che la variabile sia utilizzata per la prima volta

In particolare, la variabile può essere dichiarata “fuori” da qualsiasi funzione oppure all’interno di una funzione (o procedura : Nel primo caso, ”ambito globale”, la variabile esiste in ogni parte del

programma (con le debite eccezioni) , a partire dal momento in cui il compilatore legge la riga di dichiarazione e la istanzia

Nel secondo caso, “ambito locale”, invece, la variabile esiste solamente all’interno della funzione in cui è stata dichiarata e sarà “deallocata” all’uscita della funzione stessa

Page 109: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Visibilità di variabili (scope)

Ma cosa accade se una variabile locale ha lo stesso nome di una variabile globale? Quando la funzione è chiamata, con quel nome a quale variabile ci riferiamo, quella globale o quella locale?

Risposta: la variabile più “vicina”, è quella a cui viene fatto riferimento con il nome (“nesting rule”) Il campo di visibilità di una variabile (scope) è sempre quello ultimo in cui

la variabile è stata dichiarata, anche se due variabili portano lo stesso nome

Quindi durante l’esecuzione di tutta la procedura, ogni riferimento alla variabile A sarà risolto con un riferimento alla variabile A locale alla procedura. Tale riferimento cessa non appena la procedura e lo scope relativo ad essa terminano

Page 110: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Lo spazio di memoria globale

Per tutto quello che si è detto, anche le variabili dichiarate nella funzione principale sono variabili locali alla funzione main: Un programma allora è composto da più spazi di memoria distinti, di cui

solamente uno, lo spazio di memoria globale è condiviso in tutto il progetto

Lo spazio di memoria globale è composto dalle variabili dichiarate fuori da ogni funzione, compresa la funzione principale (il main())

Page 111: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

fn

Schema di un programma procedurale

int main(int,int) f2

f1

Spazio di memoria delle funzioni

Spazio di memoria del main

Spazio di memoria globale

Chiamate di funzione

Accessi alla memoria globale

Page 112: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Le funzioni nella CPU

Page 113: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Cambio di contesto

Ma cosa succede a basso livello quando viene chiamata una funzione ?

La chiamata di una funzione genera un cambio di contesto (context switch) nella CPU: Lo stato attuale della CPU deve essere salvato da qualche parte affinchè

una volta eseguita la procedura sia possibile riprendere correttamente l’esecuzione delle istruzioni

Anche i registri devono essere salvati dato che le istruzioni della procedura non devono assolutamente modificare i valori “eterni” alla procedura stessa

Lo stato del processo viene allora salvato sullo stack di sistema

Page 114: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Lo stack Una parte di memoria centrale viene gestita come stack di

sistema (pila)

Alla chiamata di una procedura: il contesto attuale viene inserito in cima allo stack:

operazione push Prepara la CPU ad eseguire la nuova procedura:

Setta l’istruzione da eseguire, il registro dati e quello indirizzi con i parametri passati alla procedura

La procedura esegue le istruzioni Quando la procedura termina, il contesto in cima allo stack viene

ripristinato: Operazione pop

Lo stack memorizza le chiamate a procedura e le richiama in ordine inverso di memorizzazione

Page 115: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Stack – 1

Alla chiamata della funzione f, il contesto della funzione in esecuzione attualmente viene memorizzato in cima allo stack

main()

f1

f2 f4

CPU

stack

f3

main()

f1

f2

f3

stack

funzione in esecuzione

push

Page 116: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Stack – 2

Quando poi la funzione termina, viene ripristinato l’ultimo contesto inserito nello stack, la funzione f(t-1):

main()

f1

f2

stack

CPUff3

Funzioni chiamate e terminate

funzione in esecuzione

pop

Page 117: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Stack – 3

Quando anche la funzione f(t-1) termina, viene ripristinato il contesto di f(t-2), e così via…

f3

main()

f1

f2

stack

CPU

f

Funzioni chiamate e terminate

funzione in esecuzione

pop

Page 118: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Stack – 4

L’ultimo contesto nello stack sarà quello relativo alla funzione main(). Quando questo termina, l’applicazione termina.

f3

main() f1

f2

stack

CPU

f

Funzioni chiamate e terminate

funzione in esecuzione

pop

empty

Page 119: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La ricorsione

Page 120: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La ricorsione

Si parla di ricorsione quando all’interno di una funzione P, viene richiamata P stessa, normalmente su un diverso set di dati

La chiamata ricorsiva può essere sia esplicita che implicita: Esplicita – la funzione P è richiamata esplicitamente all’interno del corpo

di P stesso Implicita – la funzione P è richiamata attraverso la chiamata ad un’altra

funzione Q che contiene la chiamata a P

A prima vista la cosa può apparire sorprendente dato che una funzione (o procedura) è dedita a risolvere un sottoproblema: La ricorsione è come dire che per risolvere il sottoproblema P è

necessario risolvere il sottoproblema P stesso !!

Page 121: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

La ricorsione

In realtà la programmazione ricorsiva a profonde radici concettuali derivanti dal fatto che “per molti problemi la soluzione per un caso generico può essere ricavata sulla base della soluzione di un caso più semplice dello stesso problema”: L’ordinamento di un array, il calcolo del fattoriale, ecc… sono tipici

problemi di questo tipo

Page 122: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. somma come ricorsione La ricorsione è nascosta in moltissime forme del ragionamento

umano. Per esempio la somma tra due numeri può essere vista come ricorsione dell’operatore successore():successore(x)=numero successivo ad x

Algoritmo ricorsivo per l’addizionex+0 = x;x+y = x+successore(y-1) = successore(x+y-1)

1+3 = successore(1+2) = successore(sucessore(1+1)) = = successore(successore(successore(1+0))) = = successore(successore(successore(1))) = = successore(successore(2)) = successore(3) = 4

Page 123: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 1 – Pesate Problema:

date un gruppo di palline di forma identica e tutte di peso identico tranne una di peso maggiore delle altre, trovare la pallina più pesante utilizzando una bilancia ed il minor numero di pesate (supponiamo di avere un numero di palline multiplo di 3)

Algoritmo:1. Dividi il gruppo in tre gruppi di egual numero di palline e pesa due di questi

gruppi

2. Se i due gruppi hanno lo stesso peso scartarli entrambi, altrimenti scartare il gruppo non pesato e quello sulla bilancia con il peso minore (la pallina cercata si troverà nel gruppo con peso maggiore)

3. Dividi il gruppo rimasto in tre sottogruppi e ripeti il procedimento finché i sottogruppi non contengano una sola palline: in tal caso l’ultima pesata indica quale delle tre palline rimaste è quella cercata

Page 124: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 1 – Pesate Notiamo come l’ultimo punto sia la ripetizione dell’algoritmo su

un set ridotto di dati fino a che non ci troviamo di fronte ad un caso notevole, di cui possiamo dare una immediata soluzione: tre gruppi di una pallina ciascuno

Per avere una visione più informatica dell’algoritmo:1. Se il gruppo di palline consiste di una sola pallina, la pallina è la

soluzione cercata, altrimenti …

2. Dividi il gruppo di palline in tre sottogruppi e poni due sottogruppi sulla bilancia

3. Se i due gruppi hanno peso uguale scartarli entrambi, altrimenti scartare il gruppo non pesato e quello di peso minore

4. Applica l’algoritmo pesate al sottogruppo individuato

Page 125: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 2 – Successione di Fibonacci

La successione di numeri di Fibonacci fu definita dal matematico come modello di crescita dei conigli in allevamento:

f0=0

f1=1

fn=fn-1 + fn-2 , per n> 1

Es. calcolando f per i primi 6 numeri:

f0=0

f1=1

f2=f1+f0=1+0=1

f3=f2+f1=1+1=2

f4=f3+f2=2+1=3

f5=f4+f3=3+2=5…

Page 126: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 3 – Fattoriale

Il fattoriale di un numero è la produttoria di tutti i numeri fino al numero stesso, escluso lo 0: 5! = 5 x 4 x 3 x 2 x 1 = 120

Il fattoriale può essere espresso in forma ricorsiva:

0! = 1

n! = n x (n-1)!

Infatti: 5!=5 x (4 x 3 x 2 x 1) = 5 x 4!

Anche il fattoriale è un tipico esempio di algoritmo ricorsivo

Page 127: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 4 – ricerca in un vettore

Un esempio tipico di algoritmo di ricerca dati in un vettore ordinato è il seguente: Se il vettore è composto da un solo elemento, confronta l’elemento con

D e se è uguale ritorna D altrimenti ritorna “non trovato” Seleziona l’elemento centrale P del vettore Confronta il dato D da cercare con l’elemento centrale P Se D<P, ripeti l’algoritmo sulla prima metà del vettore, altrimenti ripetilo

sulla seconda

Page 128: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Es. 5 – Sommatoria

La sommatoria di una sequenza di n numeri può essere vista come la somma numero n-esimo alla sommatoria dei rimanenti (n-1) numeri:

La sommatoria comunque può essere risolta semplicemente con un ciclo, risparmiando così il carico aggiuntivo della ricorsione

0

0

1

1 1

0ii

n n

i n ii i

a

a a a

=

-

= =

=

= +

¥ ¥

Page 129: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Caso generale

Si può generalizzare il concetto di ricorsione. Affinché un algoritmo sia scrivibile in forma ricorsiva, è necessario che: l’algoritmo abbia una soluzione banale, f(0)=0 l’algoritmo al passo n possa essere espresso come funzione del valore

al passo (n-1)

La condizione banale è necessarie per evitare una ricorsione infinita: Se infatti non esiste una condizione in cui siamo in grado di dare la

soluzione, le iterazioni non terminano mai In questo caso, solitamente si verifica un errore di stack overflow,

ovvero pila piena

Page 130: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Ricorsione e stack

La ricorsione viene realizzata mantenendo nello stack la sequenza delle chiamate alla procedura che non possono essere risolte fino al caso banale

Una volta trovata la soluzione banale questa viene passata a ritroso a tutte le istanze dell’algoritmo sospese nello stack fino alla istanza finale che restituisce il risultato finale

Page 131: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Successione di Fibonacci

Scriviamo l’algoritmo ricorsivo per la successione di Fibonacci:

int fibonacci(int n) {

int ris=0;

if (n==0) return 0;

else if (n==1) return 1;

else ris = fibonacci(n-1) + fibonacci(n-2);

}

Page 132: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Fattoriale e sommatoria

Scriviamo l’algoritmo ricorsivo per il calcolo del fattoriale:int fatt(int n) {

int ris=0;if (n==0) return 1;else ris = n * fatt(n-1);return ris;

}

Scriviamo l’algoritmo ricorsivo per la sommatoria:int sum(int a[]) {

int ris=0;if (vuota(a)==true) return 0;else ris = testa(a) + coda(a);return ris;

}

Page 133: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Fattoriale – 1

y=fatt(5)

fatt(5)

fatt(4)

fatt(3) fatt(1)

CPU

stack

fatt(2)

fatt(5)

fatt(4)

fatt(3)

fatt(2)

stack

funzione in esecuzione

push

Page 134: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Fattoriale – 2

fatt(5)

fatt(4)

fatt(3)

stack

CPUfatt(1)=1fatt(2)

Funzioni chiamate e terminate

funzione in esecuzione

pop

y=fatt(5)

Page 135: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Fattoriale – 3

fatt(2)=2

fatt(5) fatt(4)=24

fatt(3)=6

stack

CPU

fatt(1)=1

Funzioni chiamate e terminate

funzione in esecuzione

pop

empty

y=fatt(5)

Page 136: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Programmazione ad oggetti

Page 137: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Paradigma ad oggetti

Come detto, i linguaggi di programmazione procedurali sono stati quasi tutti sostituiti dalle rispettive versioni ad oggetti (tranne nei casi in cui la programmazione ad oggetti non è “consigliata”, ad esempio programmazione di basso livello, S.O., programmazione PLC ecc…)

Ma cos’è questo diverso tipo di programmazione? In cosa differisce dalla programmazione “classica”?

Page 138: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Object Oriented Programming (OOP) La maggior parte dei programmi utili non manipola soltanto numeri e

stringhe, ma gestisce dati più complessi e più aderenti alla realtà: Conti bancari, informazioni sugli impiegati, forme grafiche…

L’idea della programmazione ad oggetti è di rappresentare questi dati così come sono anche nel linguaggio di programmazione: gli oggetti o classi

La programmazione ad oggetti estende al massimo l’idea di dato strutturato presente nella programmazione classica: una classe (o oggetto) è un tipo di dato strutturato a cui sono associate

variabili e funzioni

Page 139: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Object Oriented Programming (OOP) Il programmatore individua degli oggetti nella applicazione che deve

progettare: Conto corrente, client e server, documento, ecc…

Ogni oggetto ha delle proprietà e delle capacità (o funzioni)

L’applicazione è poi costruita facendo interagire correttamente gli oggetti esistenti nell’ “ambiente” che si va a progettare

Ma la funzione main() che fine ha fatto ? Se non si usano più le procedure/funzioni globali, come si rende eseguibile un programma? Cioè qual è il corpo principale dell’applicazione?

Due filosofie differenti per rispondere a queste domande: il C++ ed il JAVA

Page 140: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Object Oriented Programming(OOP) Il C++ ha mantenuto comunque una certa compatibilità con i

linguaggi procedurali: in C++ è ancora possibile infatti definire funzioni globali, variabili globali e

quindi la funzione main() rimane una funzione definita globalmente e “cercata” dal compilatore per rendere eseguibile un programma

Il JAVA ha seguito un altro approccio: In JAVA non esistono funzioni globali, cioè esterne da qualsiasi oggetto,

ma ogni funzione o variabile deve appartenere ad un oggetto (o meglio classe): è possibile però definire una funzione main() per ogni classe e “rendere eseguibile” la classe stessa

In compilazione, vengono creati degli oggetti eseguibili (non un unico programma). La scelta di cosa far partire viene fatta dall’utente selezionando l’oggetto eseguibile desiderato.

Page 141: Introduzione alla programmazione Dott. Ing. Leonardo Rigutini Dipartimento Ingegneria dellInformazione Università di Siena Via Roma 56 – 53100 – SIENA.

Object Oriented Programming(OOP) Es di oggetti JAVA

Normalmente quello che accade in JAVA è che viene creato un oggetto che rappresenta l’applicazione e che contiene la funzione main(): Eseguire l’applicazione significa lanciare il main() di tale oggetto

ObjectA:-datoY-funzione1-funzione2-main()

ObjectB:-datoX-funzione1-funzione2-funzione3-main()