Sei sulla pagina 1di 64

Fondamenti di programmazione

Introduzione I linguaggi di programmazione hanno la funzione di fornire ad un computer le istruzioni necessarie ad eseguire determinati compiti e azioni. Un linguaggio di programmazione consta di un insieme di istruzioni ed operazioni, organizzate da regole specifiche e con una sintassi precisa. Le istruzioni possono essere variamente combinate tra di loro cos da far eseguire al computer esattamente le azioni che gli si richiedono. Alcuni linguaggi di programmazione dipendono dallarchitettura del computer e pertanto sono utilizzabili solo con un particolare gruppo di elementi hardware. I linguaggi in questione sono definiti linguaggi di basso livello, come ad esempio il

linguaggio Assembly che si pu appunto utilizzare solo con una particolare tipologia di CPU. I linguaggi indipendenti dalla tipologia di hardware, vengono definiti linguaggi di alto livello, come ad esempio il linguaggio Java. I linguaggi di programmazione datati presentano solitamente una natura procedurale. Al contrario, i linguaggi di programmazione pi recenti presentano, come vedremo, una natura orientata agli oggetti. Mentre i linguaggi pi recenti permettono di suddividere un codice in modo standardizzato, in quelli datati la suddivisione del codice lasciata invece al programmatore.

importante ricordare che i vari linguaggi di programmazione sono degli strumenti e, come tali, ciascuno di essi presenta punti di forza e punti deboli. Scegliere lo strumento pi idoneo alla soluzione di un dato problema un fattore molto importante nella realizzazione di qualsiasi codice di programmazione.

Organizzazione di un programma Un programma nella sua forma pi semplice formato da una lista di istruzioni (statements). Quando il programma viene richiamato, il computer inizia ad eseguire le istruzioni indicate, dalla prima allultima e nellordine in cui sono state scritte. Una volta conclusa lesecuzione delle istruzioni, il computer termina la sua elaborazione. La corretta sintassi di un programma, indicante lordine delle istruzioni e le azioni ad esse collegate, determinata dal linguaggio di programmazione utilizzato.

Le istruzioni (statements) In quasi tutti i linguaggi di programmazione unistruzione una parte di codice isolata da un carattere speciale, definito come fine istruzione (statement terminator). In C e nei linguaggi da questo derivati, come il C++ o il Java, il carattere speciale di fine istruzione rappresentato dal punto e virgola (;). In Basic, e nei linguaggi simili come il Fortran, il Ruby o il Python, il simbolo di fine istruzione costituito dal carattere di nuova riga (in

Basic il numero della nuova riga). Infine, nei linguaggi Prolog e Erland il carattere di fine istruzione il punto (.). Esempio di utilizzo del ; come carattere di fine istruzione: questa una istruzione; questa una altra istruzione;

Le variabili In un programma le istruzioni impostate vengono salvate in memoria, pronte ad essere eseguite. In genere, durante lesecuzione del programma, si generano nuove informazioni, che possono essere dati inseriti dallutente oppure il risultato di calcoli, che devono essere via via memorizzate. Dal momento che le informazioni in questione possono variare nel tempo, esse vengono definite con il termine variabili; questa definizione indica gli elementi di un programma in cui sono immagazzinate le informazioni in questione, quelle cio modificabili nel tempo. Le variabili rappresentano degli elementi fondamentali in qualsiasi linguaggio di programmazione. Esse costituiscono degli elementi

specifici che indicano unarea di immagazzinamento nella memoria di un computer. Le variabili sono dei contenitori che possono racchiudere diverse tipologie di dati, come ad esempio numeri e letterali. Ad esempio una variabile del tipo name potr essere impostata per contenere i valori Mario o Luigi. In informatica una variabile una posizione di memoria, definita da un nome, in cui si possono salvare delle informazioni. In alcuni linguaggi, si pu salvare in una variabile qualsiasi tipo di informazione; in altri invece ad ogni variabile viene assegnata una specifica tipologia di dati dal programma e, pertanto, in ciascuna di

esse potranno essere salvate solo informazioni di un determinato tipo. Anche se nella posizione associata ad una variabile possono essere presenti informazioni, queste in generale non saranno utilizzabili prima dellassegnazione di un nome alla variabile e della specificazione del suo tipo. Il processo che assegna un nome ad una variabile viene definito come creazione, allocazione o dichiarazione di una variabile. In alcuni linguaggi le variabili vengono inizializzate, viene cio assegnato loro il valore iniziale, al momento della loro creazione. Molti linguaggi permettono infatti di inizializzare le variabili nel

momento in cui queste vengono dichiarate; ma tale procedura non sempre obbligatoria. I linguaggi di programmazione come C++ e Java richiedono di specificare il tipo di dati da immagazzinare in una variabile quando questa viene dichiarata. I linguaggi che richiedono questa specificazione (ad es. numero intero, stringa di testo, ecc.) in associazione ad una variabile sono detti fortemente tipizzati. Attenzione: luso di variabili non inizializzate costituisce uno degli errori pi comuni nellutilizzo dei linguaggi fortemente tipizzati, in quanto le informazioni contenute nella porzione di memoria a cui punta la variabile non inizializzata saranno solo bits senza senso

che potrebbero avere effetti negativi sullesecuzione del programma. Una variabile non inizializzata ha pertanto un valore nullo allinterno di un programma e ne pu compromettere la performance. Assegnazione di una variabile Allinterno di un programma possibile trovare una linea di codice simile alla seguente: area = pi * r * r; Si tratta di unistruzione che indica al computer di leggere due aree di memoria che hanno un ID number (ovvero una posizione in memoria) assoluto e che, per convenienza, sono state chiamate r e pi.

Listruzione indica di moltiplicare (*) questi valori fra di loro, salvando poi il risultato delloperazione in una posizione di memoria (area di memoria). In modo analogo, in molti linguaggi di programmazione lassegnazione di una variabile pu avere laspetto seguente: X = X + 1; La linea di codice rappresentata , relativa allassegnazione di una variabile (X), indica alla macchina di compiere la seguente operazione: recupera il valore di X aggiungendo (+) 1 ed assegna il risultato di nuovo ad X.

Pertanto, se il valore di X era 0 prima del raggiungimento della linea di programma in questione, dopo lesecuzione dellistruzione il valore di X sar diventato 1. Molti linguaggi presentano degli operatori specifici per indicare lesecuzione di questa particolare operazione, operatori definiti pertanto come operatori di assegnazione (di una variabile). La stessa assegnazione vista in precedenza (X = X + 1;) potrebbe ad esempio, in presenza delloperatore di assegnazione, essere indicata come: X + = 1.

Tipologie di dati Le tipologie di dati costituiscono un sistema di classificazione atto ad identificare, allinterno di un linguaggio, una delle varie tipologie di dati di uso possibile: numeri interi (integer), numeri a virgola mobile (floating point) o valori Booleani (Boolean Data Type come, per esempio, true e false). Queste tipologie di dati determinano i valori accettabili, le operazioni che possono essere eseguite, il significato dei dati ed il modo in cui i valori possono essere salvati. Un insieme di tipologie di dati forma un cosiddetto sistema di tipi. Un sistema di tipi viene definito fortemente tipizzato qualora imponga delle restrizioni sul modo in cui operazioni, coinvolgenti tipi di dati diversi, possono essere mescolate.

Un sistema di tipi si dice invece debolmente tipizzato quando non impone vincoli particolari allo svolgimento di quelle operazioni che coinvolgono diverse tipologie di dati. Pertanto un linguaggio di programmazione fortemente tipizzato, come Java o C++, stabilisce una serie di limitazioni alla combinazione delle operazioni eseguibili, impedendo la compilazione o linterpretazione di un codice sorgente contenente delle istruzioni che, coinvolgendo tipologie diverse di dati, non possono essere considerate valide. La natura e la forza di queste restrizioni varia molto a seconda del linguaggio di programmazione utilizzato.

Nella tabella a seguire vengono confrontate le stesse istruzioni eseguite da un linguaggio debolmente tipizzato e da uno fortemente tipizzato:
Debolmente tipizzato Pseudocodice a = 2 # a un numero b = 2 # b una frase concatenate(a, b) # restituisce 22 come frase add(a, b) # restituisce 4 come numero Linguaggio Perl; PHP; Rexx; JavaScript Fortemente tipizzato a=2 # a un numero b = 2 # b una frase concatenate(a, b) # Errore di tipo add(a, b) # Errore di tipo concatenate(str(a), b)) # restituisce 22 add(a, int(b)) # restituisce 4 Java; C; C++; Python; C#.

Note alla tabella di esempio Allinterno di un programma, con il carattere #, vengono indicati dei commenti di testo alle istruzioni che precedono il simbolo. Tali commenti sono assolutamente indipendenti dalle istruzioni del programma sul quale non hanno alcun effetto. Notare che per rendere possibili le operazioni di concatenazione (concatenate) e di addizione (add) si reso necessario eseguire una trasformazione della variabile a da numero a stringa di testo tramite listruzione str ed una trasformazione della variabile b da stringa di testo a numero tramite listruzione int.

Senza queste trasformazioni il compilatore, o linterprete, non avrebbero permesso la compilazione o lesecuzione della linea di codice. I tipi predefiniti di un linguaggio si dicono tipi primitivi. Il numero di tipi e le loro caratteristiche possono variare a seconda del sistema operativo, dellarchitettura hardware, del linguaggio di programmazione in uso e del compilatore scelto. Un sistema di tipi si dice statico quando i controlli sulla tipologia dei dati vengono fatti al momento della compilazione del programma. Esempi di linguaggi statici sono: ActionScript 3, Ada, C, D, Eiffel, F#, Fortran, Go, Haskell, JADE, Java, ML, Objective-C, Ocaml, Pascal e Scala. Ad eccezione di alcune piccole differenze possono

essere considerati come linguaggi statici anche il C++, il C# ed il Perl (solo per quanto riguarda i tipi primitivi). Un sistema di tipi si dice dinamico quando i controlli sul tipo vengono eseguiti durante lesecuzione del programma. Esempi di linguaggi dinamici sono: APL, Clojure , Erlang, Groovy, JavaScript, Python, Lisp, Lua, MATLAB/GNU Octave, Perl (solo per i tipi definiti dal programmatore), PHP, Prolog, Python, Ruby, Smalltalk e Tcl.

Concludendo, un linguaggio di programmazione si dice di tipo sicuro (type safety) se strutturato in modo da impedire errori relativi alle tipologie di dati. Un linguaggio di questo tipo cercher sempre di impedire quelle operazioni che, secondo il sistema di tipi, sono rite-nute illecite. Il Byte Con la sola possibile eccezione delle variabili Booleane, il byte (8 bit) la pi piccola unit di informazione presente nei moderni linguaggi di programmazione.

Ricordando che il bit pu assumere solo valori 0 o 1, un byte sar una successione di 8 cifre 0 ed 1 variamente combinate; ad esempio: 01001101;10001110;11100011 e cos via. Siccome si tratta di disporre 2 cifre diverse in sequenze di 8, con ripetizione, esistono 28 (vale a dire 256) diversi possibili modi di scrivere un byte.

Byte e variabili Dovendo allocare una variabile in memoria, sia il compilatore che il programmatore devono conoscere quanta memoria sar necessario usare (o allocare) per ogni variabile. Tale quantit di memoria verr allocata in una successione di byte consecutivi nella memoria. Di seguito vengono riportare le principali convenzioni per lallocazione di memoria, per le tipologie di dati pi comuni di una variabile.

Tipo numero I tipi di dati seguenti hanno un nome diverso a seconda del linguaggio di programmazione scelto. La dimensione assoluta espressa in byte ed indipendente dallambiente (cio dal linguaggio). one-byte (8 bit): valori da 0 a 255 (senza segno) o da -128 a +127 (con segno); two-byte (16 bit): valori da 0 a 65535 (senza segno) oppure da 32768 a + 32767 (con segno); four-byte (32 bit): valori da 0 a 4.294.967.295 (senza segno) oppure da 2.147.483.648 a + 2.147.483.647 (con segno);

eight-byte (64 bit): valori da 0 a 18.446.744.073.709.551.615 (senza segno) oppure da -9.223.372.036.854.775.808 a + 9.223.372.036.854.775. 808 (con segno). Tipo carattere Molti linguaggi usano un singolo byte per salvare un singolo carattere di codice. Altri linguaggi, come il Java, ne usano due. Questa tipologia solitamente denominata come variabile char (che labbreviazione di character: carattere).

Variabili intere Gli interi senza segno (unsigned integer) possono salvare solo numeri positivi e zero (lintervallo di valori che si possono salvare dipende dalle dimensioni della memoria utilizzata). Gli interi con segno (signed integer) salvano sia numeri positivi che negativi, in un intervallo quasi simmetrico centrato sullo zero. La maggior parte dei linguaggi fortemente tipizzati possiede diversi tipi di interi. Il linguaggio Java ad esempio presenta i tipi rappresentati nella tabella seguente:

Nome byte short int long char

Byte 1 2 4 8 2 -128 -32768

Minimo 127 32767

Massimo

-2147483648 -9223372036854775808 0

2147483647 9223372036854775807 65535

Anche se il linguaggio Java in genere non usa i tipi interi senza segno, dispone comunque del tipo char corrispondente ad un tipo intero senza segno di 2 byte. Molti linguaggi di programmazione trattano i caratteri come interi; ad esempio in C, A non la lettera maiuscola A ma il numero 65 e lespressione numerica C-A significa 6 7 - 6 5 e porta, ovviamente, al risultato 2. Quando si legge un input o si scrive un output il valore della variabile di tipi carattere viene convertito nel corrispondente carattere di testo.

Interi letterali Consideriamo la seguente istruzione: int numeroDiMesi = 12; Nellistruzione il programma dichiara una variabile di tipo intero denominata numeroDiMesi e la inizializza con il valore 12. 12 un esempio di intero letterale. La regola esatta per la definizione di un intero letterale varia da linguaggio a linguaggio. Le diverse definizioni seguono comunque uno schema comune:

un intero letterale inizia con un segno specifico (+ o -, anche se di solito il carattere + opzionale), seguito da una successione di cifre; il punto decimale non ammesso (il punto decimale il carattere utilizzato per distinguere gli interi letterali dai numeri a virgola mobile letterali). Operazioni su interi La semplice operazione 1 + 1 costituisce un primo esempio basilare di unespressione intera: unespressione che restituisce come risultato un intero. In questo esempio compaiono due operandi (i due interi

letterali) ed una operazione indicata dal carattere pi (+) che rappresenta un operatore. Il processo che esegue il calcolo definito valutazione dellespressione e la risposta al processo si dice risultato, o valore, dellespressione. Tutti i linguaggi di programmazione che supportano i numeri interi comprendono almeno quattro operazioni (cio quattro operatori): la somma, la sottrazione, la moltiplicazione e la divisione. Delle quattro operazioni standard quella che pu causare maggiori problemi la divisione.

Il risultato restituito per la divisione 3 : 2 dipende dal linguaggio di programmazione. In linguaggi come Java, C o C++, qualora i due operandi, dividendo e divisore, siano interi, il risultato viene espresso come intero: pertanto 3 : 2 avr come risultato 1. In altri linguaggi, tra cui il Pascal, in cui esistono operatori diversi per i numeri a virgola mobile e per gli interi, il risultato della stessa divisione sar restituito come 1.5.

Precedenza nelle svolgimento delle operazioni In tutti i linguaggi che supportano le espressioni intere, esiste un ordine di precedenza nella valutazione degli operatori. La moltiplicazione e la divisione sono sempre valutate prima delladdizione e della sottrazione, a meno che non siano presenti delle parentesi che, con lo stesso significato delle espressioni matematiche, modificano le regole di precedenza. Le regole di precedenza nello svolgimento delle operazioni, e quindi lordine esatto di valutazione degli operatori, dipendono dal numero di operatori definiti nel linguaggio utilizzato.

Come gi detto esistono operatori con uguale precedenza, e cio addizione e sottrazione e, rispettivamente, moltiplicazione e divisione. Di conseguenza in ogni linguaggio di programmazione esiste una regola associativa, che indica lordine per lo svolgimento degli operatori di pari precedenza. Cos, ad esempio, per laddizione, la maggior parte dei linguaggi di programmazione applica la regola della lettura da sinistra a destra, che determina questo specifico ordine di valutazione degli operatori. Quindi lespressione 1 + 2 + 3 equivarr alla (1 + 2) + 3.

Operatori di assegnazione Quasi tutti i linguaggi presentano lo stesso operatore di assegnazione rappresentato dal simbolo uguale (=). Loperatore di assegnazione permette di assegnare il valore che si trova alla sua destra alla posizione di memoria rappresentata dalla variabile che si trova alla sua sinistra. Loperatore di assegnazione in quasi tutti i linguaggi ha la precedenza pi bassa. Pertanto viene eseguito per ultimo e presenta, come regola associativa, la direzione da destra a sinistra. Cos, ad esempio: a = b = c equivalente a: a=(b=c)

Variabili Booleane Le variabili booleane usano un singolo bit e quindi sono in grado di salvare due soli valori. Possiamo pensare a questi valori come acceso e spento, 1 e 0. Generalmente questi valori vengono detti true e false. Le variabili Booleane trovano impiego nel gestire specifiche informazioni basate su una domanda a due sole risposte possibili che, nel caso in questione, corrispondono ai valori true e false. Le variabili e le espressioni Booleane, vale a dire quelle espressioni che restituiscono un valore Booleano, costituiscono uno dei mattoni fondamentali della programmazione.

Booleani letterali Alcuni linguaggi di programmazione non presentano n variabili n letterali Booleani, ma solamente espressioni. Per quei linguaggi che presentano dei letterali, questultimi possono restituire esclusivamente i due valori true e false. Espressioni Booleane Allinterno di un programma, la maggior parte delle espressioni Booleane non contiene variabili o letterali di tipo Booleano. Ad esempio frequente trovare espressioni di questo tipo: a>5

in cui > loperatore Booleano di confronto che prende le variabili a destra e a sinistra per valutarle e quindi confrontarle. Nellesempio considerato lespressione sar vera (true) nel caso in cui a contenga un valore maggiore di 5, nel caso contrario sar falsa (false). La maggior parte dei linguaggi di programmazione presenta gli operatori di confronto (o operatori relazionali) indicati nella tabella seguente.

Descrizione maggiore di maggiore o uguale a minore di minore o uguale a uguale a non uguale a

Java; C; C++ > >= < <= == !=

Fortran GT GE LT LE EQ NE

Attenzione: espressioni del tipo 7 > a > 5 sono prive di validit in quasi tutti i linguaggi. Se ad esempio a ha il valore 5 allora 7 > a restituir un valore true e sar 7 > a true > 5 Lespressione true > 5, tuttavia priva di significato in quanto i Booleani non possono essere confrontati con gli interi.

Operatori logici Il problema di come scrivere lespressione 7 > a > 5 in un linguaggio di programmazione, in modo che non diventi priva di significato, si risolve spezzando lespressione stessa in altre due: 7>a e a>5 Affinch lespressione completa risulti true bisogner che entrambe le espressioni da essa ottenute siano vere. Per scomporre unespressione i linguaggi di programmazione impiegano gli operatori logici and, or e not. loperatore and prende una coppia di operandi di tipo Booleano e restituisce true solamente se entrambi gli operandi sono true.

loperatore or prende due operandi di tipo Booleano e restituisce true solamente se almeno uno dei due operandi true. loperatore not prende un operando e restituisce true qualora loperando risulti false e viceversa. Gli operatori logici hanno sempre una precedenza pi bassa rispetto agli operatori di confronto. Quindi lespressione 7 > a > 5 si potr scrivere come 7 > a and a > 5 che equivale a (7 > a) and (a > 5)

Strutture di controllo Fino ad ora abbiamo visto dei programmi molto semplici e di natura sequenziale che ovviamente non sono allaltezza di qualsiasi problema. Consideriamo il problema seguente: scrivere un programma che calcoli il numero di secondi presenti in un anno. Il primo fattore da considerare che il numero di giorni in un anno non rappresenta una costante e pertanto sar necessario compilare un programma che usi un numero diverso di giorni a seconda che lanno sia bisestile o meno. Si pu risolvere il problema con diversi approcci.

Il pi semplice consiste nello scrivere una parte di codice, da eseguire solo nel caso in cui una certa condizione risulti vera: se lanno di cui vogliamo calcolare i secondi bisestile allora sar costituito da 366 giorni e, in caso contrario, da 365. Listruzione If Ci che stato sin qui considerato rende possibile solo la scrittura di semplici righe di codice da eseguire linearmente, come ad esempio: int giorniInAnno = 365; Ci che necessario introdurre a questo punto unespressione per stabilire la seguente condizione:

se lanno bisestile, allora bisogner assegnare alla variabile giorniInAnno il valore 366. Si pu raggiungere tale obiettivo utilizzando listruzione If. La struttura dellistruzione If comune a quasi tutti i linguaggi e consta di tre parti: 1. una parola chiave che indica al computer lutilizzo di unistruzione If; tale parola chiave pu variare da linguaggio a linguaggio; 2. un espressione Booleana 3. unistruzione o un blocco di istruzioni. Il modo in cui il computer risolve listruzione If il seguente:

Valuta lespressione Booleana Se lespressione viene valutata false viene saltata tutta la terza parte. Se invece lespressione viene valutata come true, allora la terza parte viene eseguita. Si pu quindi risolvere il problema tramite la definizione di una variabile Booleana eBisestile nel seguente codice: int giorniInAnno = 365; if (eBisestile){ giorniInAnno = 366; }

Le parentesi tonde vengono utilizzate per delimitare lespressione Booleana, mentre le parentesi graffe racchiudono le istruzioni da eseguire, nel caso in cui la variabile venga verificata. Variazioni dellistruzione if Un modo alternativo per impostare la variabile il seguente: int giorniInAnno; if (eBisestile) { giorniInAnno = 366; }

if (not eBisestile) { giorniInAnno = 365; } La forma di cui sopra per meno lineare rispetto alla precedente e richiede una doppia valutazione della variabile Booleana. Molti linguaggi di programmazione presentano unestensione dellistruzione If, tramite la clausola else, espressa generalmente nel modo seguente:

int giorniInAnno; if (eBisestile) { giorniInAnno = 366; } else { giorniInAnno = 365; } In questo modo qualora in cui lespressione Booleana restituisca true, verr eseguito il blocco di codice definito dallIf; nel caso invece che lespressione Booleana restituisca false, allora verr eseguito il blocco di codice alternativo, associato alla clausola else.

Cicli Un ciclo una struttura del programma che esegue una parte di codice zero o pi volte. Ogni ciclo formato da diverse parti: 1. Un blocco di codice, racchiuso tra parentesi graffe, contenente le istruzioni da eseguire. 2. Una espressione Booleana che rappresenta la condizione alla base dellesecuzione del codice. Ogni volta che il computer esegue il blocco di codice del ciclo, compiendo uniterazione, la condizione viene valutata.

Il computer, di conseguenza, continuer ad iterare listruzione racchiusa tra le parentesi graffe fintanto che lespressione sar valutata come true. Un ciclo presenta laspetto seguente: int counter = 1; int sum = 0; while (counter < 10) { sum + = counter; print sum; counter + = 1; }

La parola chiave while indica in molti linguaggi listruzione del ciclo, mentre le parentesi tonde contengono lespressione Booleana e quelle graffe il blocco di codice. Nel nostro esempio il blocco di codice verr eseguito 9 volte, finch la variabile counter non raggiunge il valore 10. E importante notare che la variabile stata inizializzata ad 1 e pertanto incrementer il suo valore di 1 ad ogni iterazione o giro (loop) del programma.

Pre-condizione e post-condizione Lesempio visto in precedenza corrisponde ad un ciclo in cui la condizione viene controllata prima dellesecuzione del blocco di codice: questo tipo di ciclo viene definito ciclo con precondizione. In questo caso le istruzioni del blocco non verranno eseguite nel caso in cui la condizione risulti falsa nel momento in cui raggiungiamo il ciclo. In alcuni linguaggi, come in Java o in C, esistono dei cicli, denominati do-while, che sono sostanzialmente identici al ciclo appena visto tranne che per il fatto che usano una post-condizione e cio unespressione Booleana che viene valutata dopo lesecuzione delliterazione.

I cicli con una post-condizione garantiscono almeno unesecuzione, o giro, del programma. Di seguito viene riportato un esempio di ciclo con post-condizione. int counter = 1; int sum = 0; do { sum + = counter; print sum; counter + = 1; } while (counter < 10)

Sotto-programmi Data la complessit di alcuni software, non certo singolare trovare degli errori al loro interno (i cosiddetti bug). Uno dei modi pi idonei per risolvere un eventuale problema e minimizzare gli errori di compilazione consiste nello scomporre il problema in vari problemi meno complessi e quindi pi facilmente risolvibili. Il principio in questione alla base del concetto di sottoprogramma. Invece di compilare un unico e complesso programma che risolva il problema, si realizzano diversi piccoli programmi, ciascuno preposto alla risoluzione di una piccola parte del problema originale. I sottoprogrammi assumono nomi diversi a seconda del linguaggio di programmazione di riferimento:

Subroutine FORTRAN, Visual Basic, Perl Procedure (procedura) Pascal Function (funzione) Pascal, C, C++, Java, JavaScript, Python Super Espressione GML, GMPL Metodo un termine generico che indica in alcuni linguaggi di programmazione una funzione, una procedura, o una subroutine.

Visibilit Nella realizzazione dei primi programmi il numero di dati da elaborare era limitato ed era relativamente ristretta anche larea di memoria a disposizione del programma stesso. Tutti i dati, pertanto, erano racchiusi in una sola area di memoria e vi si poteva accedere da qualsiasi punto del programma. Levoluzione dei computer e dei software ha reso sempre pi facile leventualit che parti diverse di un programma entrino in conflitto tra di loro per i dati necessari e, allo stesso tempo, diventato sempre meno semplice stabilire quale parte di un programma utilizzi correttamente i dati.

Si cercato di risolvere tali problemi aggiungendo ai linguaggi di programmazione delle funzionalit specifiche che permettono ad un blocco di programma di controllare laccesso ai propri dati in modo che questi non siano visibili agli altri blocchi. Con il termine visibilit (scope) ci si riferisce alla visibilit di una variabile o di un metodo di un blocco di programma, da parte di un altro blocco del programma stesso. Anche se limportanza ed il significato della visibilit variano da linguaggio a linguaggio esistono tuttavia due idee generali condivise da quasi tutti i linguaggi di programmazione: la visibilit globale e la visibilit locale.

Visibilit locale Le variabili ed i metodi che hanno visibilit locale sono accessibili solo allinterno del blocco di codice che li definisce oppure nei blocchi in esso contenuti. Questo crea una sorta di modello di inclusione della visibilit. Visibilit globale Alcune variabili o metodi hanno una visibilit globale, devono cio essere disponibili allintero programma: perci tutte le variabili definite allinizio di un programma saranno a disposizione dellintero

programma; inoltre le variabili allinizio di una funzione (metodo) saranno a disposizione dellintera funzione. Duplicazione dei nomi delle variabili In un programma bisogna prestare particolare attenzione alleventuale riutilizzo dei nomi delle variabili. E infatti possibile sovrascrivere una variabile locale, definita appena sopra il blocco corrente, dichiarando una variabile dello stesso tipo e con lo stesso nome allinterno del blocco corrente. La nuova variabile con una visibilit locale potr essere usata allinterno del blocco corrente ma, dal momento che laltra variabile

stata temporaneamente sovrascritta, il nuovo valore della variabile nasconder qualsiasi valore della variabile esterna. Ad esempio: int a = 25; int b = 30; { a = 25, b = 30 a * = 2; # ora a = 50, b = 30 # a questo punto, a = 25; b= 30

b /= 2; int a = b*b; }

# ora a = 50, b=15 # ora a = 225, b=15 # qui (fuori dal blocco delimitato dalle parentesi graffe) abbiamo a = 225, b = 30

Come si vede le due variabili sono manipolate allinterno del blocco nel quale, creando la nuova versione di a, tutte le informazioni precedenti sono state nascoste. Uscendo dal blocco per si possono recuperare tutte le informazioni, comprese le eventuali modifiche. Anche con unottima comprensione della visibilit delle variabili sempre buona norma dichiarare le variabili che servono ad un blocco

allinizio dello stesso oppure ad un livello pi alto nella struttura gerarchica del programma: ci affinch tali variabili si possano referenziare facilmente e non ci sia ambiguit nel punto del programma in cui la nuova variabile stata definita.

FINE LEZIONE