Sei sulla pagina 1di 483

e e

i d i d

u o r

u o r
i t o r

i t o r
g

g
l i e l i e

A. Chianese, V. Moscato, A. Picariello ALLA SCOPERTA DEI FONDAMENTI DELLINFORMATICA


Questo testo uno strumento didattico utile per la comprensione
dei principali metodi ed algoritmi di Analisi Numerica e delle
problematiche connesse alluso di un elaboratore nella risoluzione
di un problema di matematica applicata. Gli argomenti trattati
riguardano: lanalisi degli errori, la risoluzione di sistemi lineari
e di equazioni non lineari, linterpolazione e lo smoothing di dati,
lapprossimazione di integrali e la risoluzione numerica di equazioni
differenziali e il sistema interattivo MATLAB. Il testo corredato
di numerosi esempi ottenuti implementando gli algoritmi esposti
in ambiente MATLAB.

Alessandra D'Alessio docente di Calcolo Numerico presso la Facolt di


Ingegneria dellUniversit di Napoli.
ANGELO CHIANESE
VINCENZO MOSCATO
ANTONIO PICARIELLO

Alla scoperta dei fondamenti


dellinformatica
Un viaggio nel mondo dei BIT

COD. U

35,00

e e
i d i d
u o r

u o r
i t o r

i t o r
g

g
l i e l i e
MANUALI
Angelo Chianese, Vincenzo Moscato, Antonio Picariello

Alla scoperta dei fondamenti


dellinformatica
Un viaggio nel mondo dei BIT

Liguori Editore
Questa opera protetta dalla Legge sul diritto dautore
(Legge n. 633/1941: http://www.giustizia.it/cassazione/leggi/l633_41.html).
Tutti i diritti, in particolare quelli relativi alla traduzione, alla citazione, alla riproduzione
in qualsiasi forma, alluso delle illustrazioni, delle tabelle e del materiale software a corredo,
alla trasmissione radiofonica o televisiva, alla registrazione analogica o digitale,
alla pubblicazione e diffusione attraverso la rete Internet sono riservati, anche nel caso
di utilizzo parziale.
La riproduzione di questa opera, anche se parziale o in copia digitale, ammessa
solo ed esclusivamente nei limiti stabiliti dalla Legge ed soggetta allautorizzazione scritta
dellEditore.
La violazione delle norme comporta le sanzioni previste dalla legge.
Il regolamento per luso dei contenuti e dei servizi presenti sul sito della Casa Editrice Liguori
disponibile al seguente indirizzo: http://www.liguori.it/politiche_contatti/default.asp?c=legal
Lutilizzo in questa pubblicazione di denominazioni generiche, nomi commerciali e marchi
registrati, anche se non specificamente identificati, non implica che tali denominazioni
o marchi non siano protetti dalle relative leggi o regolamenti.

Liguori Editore - I 80123 Napoli


http://www.liguori.it/

2008 by Liguori Editore, S.r.l.


Tutti i diritti sono riservati
Prima edizione italiana Marzo 2008

Chianese, Angelo :
Alla scoperta dei fondamenti dellinformatica. Un viaggio nel mondo dei BIT/
Angelo Chianese, Vincenzo Moscato, Antonio Picariello
Napoli : Liguori, 2008
ISBN-13 978 - 88 - 207 - 4305 - 5

1. Programmazione strutturata 2. Linguaggio C, MATLAB I. Titolo

Aggiornamenti:
16 15 14 13 12 11 10 09 08 10 9 8 7 6 5 4 3 2 1 0
Indice

PREFAZIONE

CAPITOLO PRIMO

1. LINFORMAZIONE E LE SUE RAPPRESENTAZIONI ....1


1.1. Linformatica ed il mondo moderno.......................................................1
1.1.1. Una definizione di Informatica..............................................................2
1.1.2. La rappresentazione dellinformazione .................................................2

1.2. La rappresentazione digitale ...................................................................5


1.2.1. I numeri in binario.................................................................................6
1.2.2. La rappresentazione dei numeri relativi ..............................................15
1.2.3. La rappresentazione dei numeri reali...................................................20

1.3. Gli operatori booleani ............................................................................26

1.4. La convergenza digitale .........................................................................27


1.4.1. La codifica delle informazioni testuali ................................................31
1.4.2. La codifica delle immagini..................................................................35
1.4.3. Immagini in movimento o video .........................................................40
1.4.4. La codifica del suono ..........................................................................42

1.5. Dati e metadati .......................................................................................43

CAPITOLO SECONDO

2. IL MODELLO DI ESECUTORE......................................45
VI

2.1. Processi e processori ..............................................................................45

2.2. Modello di Von Neumann......................................................................46


2.2.1. Le memorie .........................................................................................48
2.2.2. La CPU................................................................................................51
2.2.3. I bus.....................................................................................................53
2.2.4. Il clock.................................................................................................55

2.3. Firmware, software e middleware ........................................................57

2.4. Evoluzione del modello di Von Neumann ............................................61

2.5. Il modello astratto di esecutore .............................................................63

2.6. I microprocessori....................................................................................67

2.7. Un modello di processore.......................................................................74


2.7.1. La programmazione in linguaggio assemblativo.................................79

CAPITOLO TERZO

3. ALGORITMI E PROGRAMMI.........................................97
3.1. Informatica come studio di algoritmi ...................................................97
3.1.1. La soluzione dei problemi ...................................................................97
3.1.2. La calcolabilit degli algoritmi............................................................99
3.1.3. La trattabilit degli algoritmi.............................................................103

3.2. La descrizione degli algoritmi .............................................................105


3.2.1. Sequenza statica e dinamica di algoritmi ..........................................107

3.3. I linguaggi di programmazione...........................................................110

3.4. I metalinguaggi.....................................................................................111

3.5. La programmazione strutturata .........................................................113


3.5.1. La progettazione dei programmi di piccole dimensioni ....................117
3.5.2. La documentazione dei programmi ...................................................121

CAPITOLO QUARTO

4. LA STRUTTURA DEI PROGRAMMI ...........................123


Indice VII

4.1. Le frasi di un linguaggio di programmazione....................................123


4.1.1. Le dichiarazioni.................................................................................123
4.1.2. Le frasi di commento.........................................................................124
4.1.3. Listruzione di calcolo ed assegnazione ............................................124
4.1.4. I costrutti di controllo ........................................................................125

4.2. La potenza espressiva ..........................................................................130

4.3. La modularit.......................................................................................135
4.3.1. La parametrizzazione del codice .......................................................137
4.3.2. Le funzioni ........................................................................................140
4.3.3. La visibilit........................................................................................142
4.3.4. L'allocazione dinamica ......................................................................146
4.3.5. La ricorsione......................................................................................149
4.3.6. Gli effetti collaterali ..........................................................................149
4.3.7. Il riuso dei sottoprogrammi ...............................................................151
4.3.8. L'information hiding..........................................................................151

CAPITOLO QUINTO

5. I DATI ...........................................................................153
5.1. Informazione e dato .............................................................................153

5.2. La classificazione dei tipi .....................................................................156

5.3. I tipi atomici..........................................................................................157


5.3.1. Il tipo booleano..................................................................................157
5.3.2. Il tipo carattere ..................................................................................159
5.3.3. Il tipo intero.......................................................................................160
5.3.4. Il tipo reale ........................................................................................161
5.3.5. Il tipo per enumerazione....................................................................163
5.3.6. Il tipo subrange..................................................................................163

5.4. I tipi strutturati ....................................................................................164


5.4.1. Gli array.............................................................................................166
5.4.2. Il tipo stringa di caratteri ...................................................................169
5.4.3. Il record .............................................................................................171

5.5. I puntatori.............................................................................................172

5.6. I file........................................................................................................174
5.6.1. I file sequenziali ................................................................................174
5.6.2. I file di caratteri o textfile..................................................................177
5.6.3. La connessione e sconnessione dei file .............................................179
VIII

5.6.4. I file ad accesso diretto (RANDOM).................................................181

5.7. Lastrazione sui dati.............................................................................181


5.7.1. Il tipo pila ..........................................................................................182
5.7.2. Il tipo coda.........................................................................................182
5.7.3. Il tipo tabella......................................................................................183

CAPITOLO SESTO

6. IL LINGUAGGIO C.......................................................185
6.1. Introduzione .........................................................................................185

6.2. Le caratteristiche generali del linguaggio C ......................................185


6.2.1. Il vocabolario del linguaggio.............................................................186
6.2.2. Separatori ed identificatori ................................................................186
6.2.3. I simboli speciali ...............................................................................187
6.2.4. Parole chiavi......................................................................................188
6.2.5. I delimitatori......................................................................................188
6.2.6. Le frasi di commento.........................................................................188
6.2.7. Le costanti .........................................................................................189
6.2.8. Le stringhe.........................................................................................191

6.3. Il programma e la gestione dei tipi in C .............................................191


6.3.1. Lintestazione di una funzione ..........................................................194
6.3.2. Il blocco di una funzione ...................................................................194
6.3.3. I tipi semplici.....................................................................................195
6.3.4. Dichiarazione di variabili ..................................................................196
6.3.5. Alias di tipi ........................................................................................198
6.3.6. Il tipo enumerativo ............................................................................198
6.3.7. I tipi derivati ......................................................................................198
6.3.8. Il tipo array ........................................................................................198
6.3.9. Il tipo struct .......................................................................................199
6.3.10. Il tipo unione.................................................................................200
6.3.11. I campi ..........................................................................................200
6.3.12. Stringhe di caratteri ......................................................................201
6.3.13. I Puntatori .....................................................................................201

6.4. Gli operatori del linguaggio.................................................................202


6.4.1. Operatori Aritmetici ..........................................................................202
6.4.2. Operatori Relazionali ........................................................................202
6.4.3. Operatori Logici ................................................................................202
6.4.4. Operatori di incremento e decremento ..............................................202
6.4.5. Operatori sui puntatori.......................................................................203
6.4.6. Operatori logici bit oriented ..............................................................204
Indice IX

6.5. La specifica dellalgoritmo in C ..........................................................204


6.5.1. Istruzioni di assegnazione..................................................................204
6.5.2. Richiamo di funzioni .........................................................................205
6.5.3. Costrutti selettivi ...............................................................................206
If-else ..........................................................................................................206
Switch-case .................................................................................................208
6.5.4. Costrutti Iterativi ...............................................................................209
Il ciclo while ...............................................................................................209
Il ciclo do-while ..........................................................................................210
Il ciclo for....................................................................................................211

6.6. Le librerie di funzioni ..........................................................................212


6.6.1. La gestione dellI/O...........................................................................213
Apertura file................................................................................................213
Lettura da file..............................................................................................214
Scrittura su file............................................................................................215
La gestione delle stringhe ...........................................................................216
Funzioni per il calcolo matematico .............................................................217

6.7. Gli algoritmi di base in C.....................................................................218


6.7.1. Lo scambio di valore .........................................................................218
6.7.2. Inserimento in un vettore...................................................................220
6.7.3. Eliminazione in un vettore.................................................................222
6.7.4. Eliminazione di una colonna da una matrice.....................................224
6.7.5. Eliminazione di una riga da una matrice ...........................................226
6.7.6. Ricerca sequenziale ...........................................................................228
6.7.7. Ricerca binaria...................................................................................230
6.7.8. La ricerca del valore massimo in un vettore......................................233
6.7.9. La posizione del valore minimo in un vettore ...................................235
6.7.10. Ordinamento di un vettore col metodo della selezione.................237

6.8. Esempi di programmi completi in C...................................................239


6.8.1. Gestione di un array ..........................................................................240
6.8.2. Gestione di un archivio......................................................................244

CAPITOLO SETTIMO

7. IL LINGUAGGIO DELLAMBIENTE MATLAB ............249


7.1. Caratteristiche del linguaggio .............................................................249
7.1.1. Il vocabolario del linguaggio.............................................................250
7.1.2. I separatori.........................................................................................251
7.1.3. Gli identificatori e le parole chiavi ....................................................251
7.1.4. I simboli speciali ...............................................................................252
Operatori Aritmetici....................................................................................252
X

Operatori Relazionali ..................................................................................253


Operatori Logici..........................................................................................253
I delimitatori ...............................................................................................253
7.1.5. Le frasi di commento.........................................................................253
7.1.6. Le costanti numeriche .......................................................................254
7.1.7. Le costanti stringhe di caratteri .........................................................254

7.2. La struttura del programma ...............................................................255


7.2.1. La dichiarazione e gestione dei tipi ...................................................255
Tipi Semplici: il tipo intero.........................................................................255
Tipi Semplici: il tipo reale ..........................................................................256
Tipi Semplici: il tipo char ...........................................................................256
Tipi Semplici: il tipo booleano....................................................................256
Tipi Strutturati: il tipo array ........................................................................256
Tipi Strutturati: il tipo record ......................................................................258
Tipi Strutturati: il tipo intervallo.................................................................259
Tipi Strutturati: il tipo file...........................................................................260
7.2.2. La dichiarazione di funzione .............................................................260
7.2.3. La specifica dellalgoritmo................................................................261
7.2.4. Assegnazione.....................................................................................261
7.2.5. Richiamo di funzione ........................................................................262
Funzioni predefinite ....................................................................................263
Funzioni per lI/O .......................................................................................263
Lettura da file di INPUT .............................................................................264
Scrittura su file di OUTPUT .......................................................................264
7.2.6. Gli enunciati di selezione ..................................................................265
Il costrutto IF-ELSE....................................................................................265
Il costrutto switch-case ...............................................................................266
7.2.7. Le strutture iterativa ..........................................................................268
Il while ........................................................................................................268
Il for ............................................................................................................269

7.3. Gli algoritmi di base in MATLAB ......................................................270


7.3.1. Lo scambio di valore .........................................................................270
7.3.2. Linserimento in un vettore ..............................................................272
7.3.3. Leliminazione in un vettore .............................................................273
7.3.4. Leliminazione di una colonna da una matrice..................................275
7.3.5. Leliminazione di una riga da una matrice ........................................276
7.3.6. La ricerca sequenziale .......................................................................277
7.3.7. La ricerca binaria...............................................................................280
7.3.8. Il valore massimo in un vettore .........................................................283
7.3.9. La posizione del valore minimo di un vettore ...................................285
7.3.10. Minimo e massimo in una matrice................................................286
7.3.11. Ordinamento di un vettore col metodo della selezione.................288
7.3.12. Ordinamento di un vettore col metodo del gorgogliamento .........290

7.4. Esercizi completi...................................................................................293


Indice XI

CAPITOLO OTTAVO

8. LA TRADUZIONE DEI PROGRAMMI..........................299


8.1. Introduzione .........................................................................................299

8.2. Il processo di traduzione......................................................................300


8.2.1. La compilazione ................................................................................301
8.2.2. Il collegamento ..................................................................................305
8.2.3. Il caricamento ....................................................................................307
8.2.4. Gli interpreti ......................................................................................308

8.3. La verifica della correttezza dei programmi......................................309

8.4. Gli ambienti integrati...........................................................................313


8.4.1. Lambiente DEV-C++.......................................................................313
8.4.2. Lambiente MATLAB.......................................................................319

CAPITOLO NONO

9. LA PROGRAMMAZIONE ORIENTATA AGLI OGGETTI


331
9.1. I limiti del paradigma procedurale.....................................................331

9.2. Introduzione al paradigma object oriented .......................................332


9.2.1. La nascita della programmazione ad oggetti .....................................335

9.3. I fondamenti della programmazione ad oggetti.................................336


9.3.1. Oggetti e classi ..................................................................................336
9.3.2. Oggetti software e classi come implementazioni di tipi di dato astratto
339
9.3.3. Il meccanismo dellereditariet .........................................................344
9.3.4. Polimorfismo e binding dinamico .....................................................346
9.3.5. Note di progetto.................................................................................348

CAPITOLO DECIMO

10. INTRODUZIONE AI SISTEMI OPERATIVI...............349


XII

10.1. Introduzione .........................................................................................349

10.2. Caratteristiche di un Sistema Operativo............................................352


10.2.1. Levoluzione storica dei Sistemi Operativi...................................354
10.2.2. Alcuni esempi di Sistemi Operativi ..............................................356
DOS ............................................................................................................357
UNIX e LINUX ..........................................................................................357
OS/2 ............................................................................................................357
WINDOWS.................................................................................................357
Mac OS .......................................................................................................358

10.3. Larchitettura dei Sistemi Operativi ..................................................358


10.3.1. La gestione dei processi................................................................360
10.3.2. La gestione della memoria............................................................363
10.3.3. Il file system .................................................................................364
10.3.4. Linterprete dei comandi: la shell .................................................365

CAPITOLO UNDICESIMO

11. LE RETI DI COMUNICAZIONE ................................367


11.1. I sistemi di comunicazione...................................................................367
11.1.1. Codici e codifica...........................................................................368
11.1.2. Il problema degli errori.................................................................369
11.1.3. La trasmissione dellinformazione................................................370
11.1.4. I mezzi trasmissivi ........................................................................371

11.2. Le reti di calcolatori .............................................................................373


11.2.1. Tipologie di reti di calcolatori ......................................................375
11.2.2. Cenni allInternetworking.............................................................382
11.2.3. Aspetti software delle reti di calcolatori .......................................382
11.2.4. Il modello Internet.....................................................................386
11.2.5. La struttura di una rete TCP/IP .....................................................387
11.2.6. Le applicazioni di una rete TCP/IP...............................................390

CAPITOLO DODICESIMO

12. IL MONDO DI INTERNET.........................................393


12.1. Introduzione .........................................................................................393
12.1.1. Una ragnatela di connessioni ........................................................395
12.1.2. Internet ed il modello di comunicazione.......................................397
Indice XIII

12.1.3. La storia di Internet.......................................................................398

12.2. Il World Wide Web..............................................................................401


12.2.1. Nuovi standard per il Web............................................................404
12.2.2. I browser.......................................................................................405
12.2.3. La ricerca dellinformazione ed i motori di ricerca ......................405
Indici di rete ................................................................................................406
Motori di ricerca .........................................................................................406
12.2.4. I Portali .........................................................................................408

12.3. Internet ed il mondo del business........................................................409


12.3.1. Le-commerce...............................................................................410
12.3.2. Le-banking ..................................................................................410
12.3.3. Le-trading....................................................................................411
12.3.4. Le-procurement ...........................................................................411
12.3.5. Internet e la Pubblica Amministrazione: le-governement ...........412
12.3.6. Internet ed il mondo della formazione: le-learning .....................413

CAPITOLO TREDICESIMO

13. BASI DI DATI E SISTEMI INFORMATIVI.................417


13.1. Sistemi Informativi e Sistemi Informatici ..........................................417
13.1.1. Sistemi Informativi aziendali: levoluzione storica ......................419

13.2. Analisi e progettazione di un Sistemi Informativo ............................420


13.2.1. Le basi di dati ...............................................................................422
13.2.2. I Data Base Management Systems................................................422
13.2.3. Levoluzione dei DBMS...............................................................425
13.2.4. Le funzionalit di un DBMS.........................................................426
13.2.5. Ricerche in un database: introduzione al linguaggio SQL............427

APPENDICE A

14. VADEMECUM DEI PRINCIPALI TERMINI USATI IN


INFORMATICA....................................................................429
14.1. Fasce di Computer ...............................................................................429

14.2. Componenti Interni di un Computer..................................................430

14.3. I dispositivi di input e output ..............................................................433


XIV

APPENDICE B

15. ESERCIZI DI PROGRAMMAZIONE.........................437


15.1. Premessa ...............................................................................................437

15.2. Esercizi sulle variabili non strutturate ...............................................438

15.3. Esercizi sui vettori ................................................................................439

15.4. Esercizi sulle matrici ............................................................................442

15.5. Esercizi sui record ................................................................................447

15.6. Esercizi sulle stringhe ..........................................................................449

15.7. Esercizi sui file ......................................................................................453

INDICE DEI TERMINI ................................. 455

GLI AUTORI ............................................... 461


a Ilaria, Miriam e Susanna
a Marco
e a Vinni

e a chi non esiste,


ed bello pensare che c
Prefazione

Il titolo Alla scoperta dei fondamenti dellinformatica non stato scelto


con facilit. Per condividerlo gli autori hanno discusso a lungo e tra i tanti titoli sui
quali hanno litigato, lo hanno preferito perch sottolinea i diversi obiettivi che si
erano prefissi quando hanno iniziato la loro avventura di docenti in corsi di base
dellinformatica.
Negli ultimi anni il mondo dellinformatica ha vissuto frenetici
cambiamenti indotti dalle innovazioni tecnologiche imposte dalle esigenze di una
societ che ha scoperto nella conoscenza, e nella sua gestione, una primaria
occasione di competizione in un mercato sempre pi globalizzato. Non un caso
che molte delle tecnologie che hanno caratterizzato momenti della nostra vita sono
diventate rapidamente vecchie, inutilizzabili, o come si dice obsolete. Tanti
possono essere gli esempi di oggetti tecnologici che hanno mostrato una vita
brevissima se confrontata con la storia delluomo o con altri aspetti della societ.
Da archeologi appassionati della materia che proviamo ad insegnare abbiamo
selezionato quei concetti di base che vivono senza rischiare di arrugginire con il
tempo che passa. Non sappiamo se ci siamo riusciti, ma le nostre diverse
esperienze di insegnamento ci hanno fatto convergere su un testo che crediamo
possa rispondere alle aspettative. A dimostrazione di tale tesi nel libro sono
presenti sia il linguaggio C che quello di MATLAB per ribadire uno dei
fondamenti dellinformatica, la tesi di Church, che viene spesso dimenticata per
dare spazio ad esigenze di mercato o a mode: saper progettare un programma di
gran lunga pi appassionante del saper codificare un algoritmo in un linguaggio di
programmazione.
Il titolo vuole sottolineare anche il desiderio di insegnare senza annoiare,
coinvolgendo il lettore in un viaggio alla scoperta di un una materia di cui molti
parlano dilungandosi solitamente su temi secondari, specifici, o semplicemente
tecnologici. Il libro non un tradizionale testo di fondamenti di informatica, n uno
di preparazione al conseguimento del patentino europeo. Ha la pretesa di volersi
rivolgere a tutte le persone curiose di capire cosa si nasconde dietro un sipario fatto
di tanta tecnologia, ma soprattutto di tanto lavoro di persone, gli informatici, capaci
di trasformare idee in soluzioni, esigenze in applicazioni, realt in immaginario
della realt. E cerca di farlo camminando su un filo sottile teso tra due esigenze
difficili da coniugare: la precisione scientifica importante per insegnare e il
raccontare con lintenzione di appassionare. Abbiamo cos scoperto che un viaggio
nella storia dellinformatica poteva essere il collante giusto. E il libro si presenta al
XVIII

suo lettore proprio come un viaggio attraverso le tappe pi significative di un


cammino recente: dalla introduzione del codice binario, allaffermazione del
modello architetturale di Von Neumann, alla introduzione dei linguaggi di
programmazione, per terminare con le diffuse applicazioni tra cui i Sistemi
Operativi ed Internet. Il libro si presta ad essere letto in modi diversi a seconda
degli obiettivi didattici. Ad esempio per i corsi di Fondamenti di Informatici per
lIngegneria Informatica si consigliano i capitoli I, II, III, IV, V, VI, VIII e X;
mentre per i corsi di Elementi di Informatica per i non informatici si consigliano i
capitoli XII, II (senza microprocessori), I, X, VIII, VII, XIII (per i corsi di
ingegneria gestionale).
Come autori abbiamo una grande consapevolezza sorretta dai cambiamenti
intervenuti nella filiera di produzione del mondo delleditoria. I libri non sono pi
blocchi granitici difficili da modificare. Oggi possono seguire non solo le
esperienze degli autori, ma soprattutto dei lettori che con le loro indicazioni
possono contribuire a miglioramenti e adeguamenti. Non un caso che il materiale
da cui siamo partiti, stato per diversi anni sperimentato in corsi universitari.
Anche il presente libro sar sottoposto a continue revisioni per le quali ci
auguriamo che forte sia il coinvolgimento costruttivo principalmente dei nostri
studenti. Ai quali va sin da ora il nostro ringraziamento.
A tal fine ci preme sottolineare che la trattazione degli argomenti in un libro per la
didattica frutto dellesperienza che gli autori hanno maturato grazie al confronto
con il mondo circostante.
Come non ringraziare chi prima stato nostro maestro e chi poi ha
collaborato con noi; ma anche tutti i colleghi con i quali abbiamo discusso e con i
quali continuiamo a condividere la passione per linformatica. Il nostro primo
pensiero va al professore Bruno Fadini che oggi non pi tra noi: ci fa piacere
ricordarne la grande passione per la ricerca e la didattica che ci ha contagiato
rendendo il nostro lavoro appassionante. Un particolare ringraziamento ci sembra
giusto rivolgerlo a Nello Cimitile che per primo ci ha insegnato i principi della
programmazione strutturata: il sogno di alcuni di noi poter scrivere un libro con
lui spiegando il mondo dellinformatica con il semplice concetto di tipo. Infine un
ringraziamento tutto particolare va al professore Nino Mazzeo per il grande lavoro
che sta attualmente facendo per affermare il ruolo positivo dellinformatica: ci
aspettiamo da lui che le discussioni di questo ultimo periodo continuino con la
stessa partecipazione e piacere reciproco. I collaboratori da ringraziare sono tanti
per la loro presenza costante alle attivit del gruppo di ricerca sui sistemi
informativi multimediali, ma una citazione specifica va ad Antonio dAcierno e
Antonio Penta.
Non abbiamo bisogno di ringraziare lamico e maestro Lucio Sansone:
ormai parte di noi e con noi procede sul lungo cammino della didattica e della
ricerca.
Infine intendiamo dedicare anche il presente libro a tutti i docenti e
ricercatori universitari che come noi vivono nellUniversit credendo che la
didattica e la ricerca sono importanti per lo sviluppo di una societ pi giusta. E gli
autori hanno scritto il libro principalmente perch amano il proprio lavoro di
docenti e ricercatori.
va2
Capitolo primo

Linformazione e le sue rappresentazioni

1.1. Linformatica ed il mondo moderno


Lattuale societ moderna sempre pi dipendente dallinformatica. In molti
aspetti della vita quotidiana possibile avvertire la presenza di elaboratori
elettronici, il pi delle volte nascosti allinterno di altre macchine.
Le plurifunzionalit (agende, giochi, messaggi multimediali, etc) offerte dai
moderni telefoni cellulari, da sole, basterebbero a testimoniare la diffusione del
suddetto fenomeno, favorita anche dallavvento di Internet che ha abbattuto ogni
tipo di barriera e distanza sociale, culturale e tecnologica, rendendo possibile a tutti
laccesso a informazioni e servizi distribuiti in diverse parti del globo terrestre.
I moderni elaboratori, attraverso linsieme delle applicazioni software
(sistema operativo pi programmi) in esso contenute, mettono a disposizione
dellutente finale una vasta gamma di funzionalit in grado di adattarsi e rispondere
alle sue pi disparate esigenze del mondo del lavoro, intrattenimento o altro.
Grazie poi alla presenza delle interfacce grafiche, sempre pi user-friendly (facili
da usare per i suoi utilizzatori o utenti), di cui sono dotati i recenti sistemi operativi
e le applicazioni moderne, lutilizzo degli elaboratori stessi diventato sempre pi
semplice, accattivante ed intuitivo, suscitando un notevole interesse soprattutto
nelle generazioni pi giovani. Gi dalle scuole elementari i ragazzi iniziano ad
utilizzare il computer per giocare ai videogiochi, navigare su Internet, ascoltare
canzoni, scrivere documenti, vedere film, leggere la posta elettronica e cos via.
Molte delle attivit del mondo contemporaneo hanno risentito della
preponderante invasione degli elaboratori. Ad esempio sia nelle aziende che negli
uffici pubblici tutto il flusso (workflow) dei documenti (produzione, trasferimento,
archiviazione) avviene oramai mediante lutilizzo di elaboratori in un formato
immateriale detto digitale; nei pi moderni studi medici e aziende ospedaliere, la
gestione dei pazienti avviene attraverso cartelle cliniche digitali; nelle industrie
la maggior parte dei processi logistici, amministrativi e di produzione sono
automatizzati grazie alluso di elaboratori; nel settore dei trasporti aereo e
ferroviario risulta da anni possibile prenotare ed acquistare biglietti on-line;
analogamente in settori paralleli stanno sempre pi aumentando le aziende, i
negozi e gli enti che, attraverso siti Internet, consentono lacquisto di merci e
servizi (e-commerce); nel settore televisivo e dello spettacolo, grazie
allinformatica, che si stanno diffondendo sempre nuovi e pi sofisticati servizi
interattivi; parte del settore dellintrattenimento (sport, giochi, musica) stato, poi,
2 Capitolo primo

di fatto completamente rivoluzionato dagli elaboratori (videogiochi, software


musicali, moviole in campo); infine anche le pi moderne conquiste dellumanit
(viaggi spaziali, scoperte nel campo medico e scientifico, etc.) sono state in parte
rese possibili grazie allinformatica.
1.1.1. Una definizione di Informatica
La diffusa presenza degli elaboratori elettronici in tantissime e diversissime realt
sociali, ha determinato nella quotidianit la spontanea associazione tra il termine
Informatica e lutilizzo delle macchine informatiche.
In realt linformatica un campo di studio molto giovane. I primi elaboratori
risalgono infatti solo al 1946, ed allora, essa non era considerata una disciplina
separata dallelettronica e dalla matematica.
Nel corso degli anni, con lincremento delle capacit di calcolo (o
computazionale) degli elaboratori (anche detti per tali motivi computer), ci si
rese conto che il compito di programmare queste macchine era estremamente
difficile e richiedeva teorie e pratiche diverse da quelle dei campi esistenti.
Linformatica, ovvero la scienza della risoluzione dei problemi con laiuto degli
elaboratori, divenne quindi una disciplina autonoma.
Linformatica una disciplina complessa che abbraccia campi molto diversi
tra loro, in cui lelaboratore elettronico solo lo strumento mediante il quale si
possono attuare le tante applicazioni per esso pensate. Non a caso il termine
informatica deriva dalle parole informazione e automatica per sottolinearne
caratteristiche e finalit. Infatti linformatica soprattutto la scienza della gestione
e della elaborazione della informazione, e ci, spiega perch essa penetrata in
tutte le attivit umane rappresentando nei paesi pi evoluti linfrastruttura
fondamentale per lo sviluppo culturale ed economico della societ.
In tale ottica lelaboratore assolve al compito di gestire e memorizzare le
informazioni o dati, mentre lesperto informatico progetta le applicazioni
necessarie ad organizzare e quindi gestire le informazioni sia mediante luso di
macchine (tra le quali lo stesso elaboratore), sia facendo ricorso a sole risorse
umane, o infine a soluzioni miste in cui macchine ed uomini provvedono alla
attuazione dei processi individuati.
1.1.2. La rappresentazione dellinformazione
Affinch uninformazione venga correttamente memorizzata e gestita da un
elaboratore risulta fondamentale rappresentarla in una forma che sia ad esso
comprensibile. Risulta pertanto importante definire i concetti di informazione e
rappresentazione.
Spesso, si attribuisce al termine informazione un senso molto generico: esso
deriva da informare, ossia dare forma e fa riferimento ad un concetto astratto,
quanto mai vasto e differenziato, che pu, in linea del tutto generale, coincidere
con qualunque notizia o racconto. In termini molto semplici si pu dire che
l'informazione qualcosa che viene comunicato in una qualsiasi forma scritta o
orale.
Nella Teoria dell'Informazione l'informazione viene associata al concetto di
messaggio, anche se esso ha il solo compito di rappresentarla e trasportarla. In tal
caso, risulta evidente che, affinch un messaggio possa essere interpretato, mittente
Linformazione e le sue rappresentazioni 3

e destinatario debbano aver concordato un insieme di regole con le quali scrivere, e


in seguito leggere, il messaggio stesso. Inoltre perch esista informazione, il
messaggio deve contribuire ad eliminare incertezza: infatti, se una sorgente di
messaggi inviasse ripetutamente un solo simbolo, la quantit di informazione
ricevuta a destinazione sarebbe nulla. Infine i messaggi possono aumentare le
conoscenze se linformazione ricevuta si aggiunge a quelle preesistenti nel senso
che, dopo aver ricevuto un messaggio, si sa di pi rispetto alle situazioni
precedenti.
Come gi anticipato, perch persone o macchine possano utilizzare
uninformazione hanno bisogno che essa sia appropriatamente rappresentata. A
tale proposito, la storia delluomo ricca di esempi che testimoniano limportanza
della rappresentazione efficace delle informazioni: basti pensare che se non fosse
esistita la scrittura non avremmo un resoconto oggettivo degli avvenimenti
delluomo dalla sua nascita fino ad oggi. Del resto scrivere, leggere ed elaborare
informazioni implica che chi lo fa abbia preliminarmente concordato un codice,
ossia una serie di regole e convenzioni da seguire; e il mondo che ci circonda
ricco di esempi in campi anche molto diversi tra loro.
In generale esistono due modalit di rappresentazione. Nella prima, le
propriet del fenomeno rappresentato sono omomorfe alla forma della
rappresentazione. Essa viene detta analogica proprio perch la rappresentazione
varia in analogia con la grandezza reale: si pensi ad un termometro tradizionale, nel
quale la dilatazione del mercurio messa in relazione con la variazione rilevata di
temperatura. Nella rappresentazione analogica una grandezza rappresentata in
modo continuo e la gran parte delle grandezze fisiche della realt sono di tipo
continuo.
La seconda modalit di rappresentazione invece discreta, nel senso che si
utilizza un insieme finito di rappresentazioni distinte che vengono messe in
relazione con alcuni elementi delluniverso rappresentato. Una tale
rappresentazione unapprossimazione di quella analogica: infatti, se ad esempio
si prova a descrivere il colore del mare, ci si accorge che non si hanno nel
linguaggio naturale tanti termini quanti ne servirebbero per descrivere le infinite
sfumature percepite dai nostri occhi. La scelta del livello di approssimazione
dipende dalluso della rappresentazione discreta in quanto in molte applicazioni
reali non sempre hanno importanza tutti gli infiniti valori che linformazione reale
pu assumere. noto, ad esempio, a tutti che in una proiezione cinematografica
locchio umano percepisce il movimento per effetto della sovrapposizione
successiva di 24 fotogrammi in un secondo: non servirebbe a molto aggiungere
altre istantanee. In tale caso si sfrutta un limite dellutilizzatore della informazione
rappresentata per estrarre da un insieme infinito di valori un suo opportuno
sottoinsieme.
Noti ora i concetti di informazione e rappresentazione, ritornando al caso
degli elaboratori elettronici, in maniera pi dettagliata possibile affermare che
uninformazione per essere correttamente elaborata deve essere codificata in una
rappresentazione comprensibile allelaboratore stesso, e, a tale proposito, risultano
fondamentali i concetti di codifica e codice riportati di seguito.
La codifica linsieme di convenzioni e di regole da adottare per trasformare
uninformazione in una sua rappresentazione e viceversa. Si noti che la stessa
informazione pu essere codificata in modi diversi (rappresentazioni diverse) a
4 Capitolo primo

seconda del contesto: le rappresentazioni araba o romana dei numeri ne sono un


esempio (i simboli 1 e I costituiscono due codifiche diverse della stessa
informazione numerica).
Un codice un sistema di simboli che permette la rappresentazione
dellinformazione ed definito dai seguenti elementi:
- i simboli che sono gli elementi atomici della rappresentazione;
- lalfabeto che rappresenta linsieme dei simboli possibili: con cardinalit
(n) del codice si indica il numero di elementi dellalfabeto;
- le parole codice o stringhe che rappresentano sequenze possibili
(ammissibili) di simboli: per lunghezza (l) delle stringhe si intende poi il
numero di simboli dellalfabeto da cui ciascuna parola codice risulta
composta;
- il linguaggio che definisce le regole per costruire parole codici che
abbiano significato per lutilizzatore del codice.
La scrittura lesempio pi noto di codifica nella quale trovare facilmente un
esempio dei concetti indicati.
Siano allora V = {v1, v2, ..., vm } linsieme degli m valori diversi di una data
informazione e A = {s1, s2, ..., sn } un alfabeto composto da n simboli distinti. Si
considerino diverse lunghezze delle parole codice:
- con l = 1 si hanno tante parole codice diverse (n1) quanti sono i simboli
dellalfabeto;
- con l = 2 si hanno tante parole codice diverse quante sono le combinazioni
con ripetizione degli n simboli nelle due posizioni, ossia n2;
- con l = 3 si hanno n3 parole codice diverse.
In generale il numero di parole codice differenti uguale a nl. Ad esempio,
fissato lalfabeto A = {-,.} del codice Morse con n=2, si hanno le diverse
rappresentazioni riportate in tabella 1.

nl l=1 l=2 l=3 l=4


- -- --- ----
2 . -. --. ---.
.- -.- --.-
4 .. -.. --..
.-- -.--
.-. -.-.
..- -..-
8 -
.---
.--.
.-.-
.-..
..--
..-.
...-
16 .
Tabella 1 Esempi di codici Morse a lunghezza differente

Se la codifica deve mettere in corrispondenza biunivoca i valori


dellinformazione con le parole codice, ossia ad ogni vi deve corrispondere una ed
una sola sequenza s1i s2j ...sni , allora la lunghezza l deve essere scelta in modo che:
nl > m
Linformazione e le sue rappresentazioni 5

Si noti che nel caso di nl > m non tutte le configurazioni possibili (parole
codice) vengono utilizzate per la rappresentazione, come lesempio nella tabella 2
mostra nei primi due casi.

Informazione Suoi Valori Sue rappresentazioni


Giorni settimana luned, marted, mercoled, --- , --. , -.- , -.. , .-- ,
gioved, venerd, sabato, .-. , ..-
domenica
Colori semaforo rosso, giallo, verde -- , -., .-
Risposta si, no -,.

Tabella 2 Esempi di rappresentazione di informazioni diverse con codici a


lunghezza differente

Infine la codifica pu essere a lunghezza fissa o variabile. Nel primo caso


tutte le parole codice hanno sempre la stessa lunghezza fissata da particolari
esigenze applicative. La scrittura un caso, di contro, di codifica a lunghezza
variabile come possibile verificare in un qualsiasi vocabolario. I calcolatori
adottano codifiche a lunghezza fissata e definita.

1.2. La rappresentazione digitale


La scrittura alfabetica e le cifre della numerazione araba sono alcuni esempi tra le
numerose forme di quella che stata precedentemente definita rappresentazione
discreta.
Ai fini informatici assume particolare interesse la rappresentazione binaria
digitale basata su un alfabeto costituito da due soli simboli distinti, che assumono
convenzionalmente la forma di 0 e 1. Tali due simboli rappresentano le unit
minime di rappresentazione e memorizzazione digitale e vengono denominate bit
da binary digit.
Solitamente si indica con digitale la rappresentazione basata sui bit, anche se
essa teoricamente sottintende una rappresentazione con qualsiasi tipo di cifre.
Inoltre la diffusione dellinformatica nella societ ha comportato unestensione del
significato del termine ed oggi, nella sua accezione pi ampia, digitale assume il
significato di informazione codificata in contrapposizione con analogico che
invece descrive la realt nelle sue infinite forme e variet.
La rappresentazione digitale, sebbene implica ladozione di parole codici pi
lunghe per rappresentare una determinata quantit di informazioni, semplifica la
memorizzazione delle informazioni e rende i sistemi digitali meno soggetti ai
disturbi elettrici rispetto ai sistemi analogici.
Non a caso la rappresentazione delle informazioni allinterno dellelaboratore
si basa sullalfabeto binario {0,1} in quanto i supporti di memorizzazione delle
informazioni, i registri di memoria, vengono realizzati con componenti elementari
semplici detti flip-flop, che operano in due soli stati possibili.
In generale esistono tanti fenomeni diversi che possono essere facilmente
associati ad un bit:
- la presenza o assenza di tensione elettrica in un circuito elettrico;
6 Capitolo primo

- le polarit positiva e negativa di un magnete o di un supporto con


caratteristiche magnetiche tipo nastri e dischi;
- la presenza o lassenza di un buco su un supporto ottico come quello dei
cd-rom;
- lapertura o chiusura di una conduttura;
- la condizione di acceso o di spento di un interruttore.

Figura 1 Esempio di rappresentazione digitale di un segnale di tensione

La rappresentazione digitale anche pi affidabile (probabilit di errore


bassa), in quanto disturbi provenienti dallambiente o interferenze (rumore) indotte
da altri componenti difficilmente possono far variare lo stato di un componente che
memorizza i bit. Infatti adottando due soli stati si pu scegliere una separazione
massima tra le corrispondenti grandezze indicative dello zero e delluno, per cui il
rumore pur sommandosi non produce significative alterazioni.
La trasformazione delle grandezze analogiche nella loro rappresentazione
digitale ha tra i tanti vantaggi quello della fedelt della riproduzione e quello della
trasmissione dellinformazione a diversi tipi di dispositivi elettronici.
Alcune informazioni nascono gi in formato digitale grazie a strumenti che
operano direttamente con tale rappresentazione: tra essi il calcolatore elettronico
con le sue tante applicazioni, ma anche le moderne macchine fotografiche digitali ,
i telefoni cellulari, i registratori di suoni e video.
Per elaborare con un calcolatore delle grandezze reali di tipo continuo,
bisogna utilizzare la loro rappresentazione digitale con una approssimazione che
dipende dal processo di trasformazione in grandezze a valori discreti e dalla
precisione della rappresentazione digitale dei numeri.
1.2.1. I numeri in binario
Come gi anticipato, laritmetica usata dai calcolatori diversa da quella
comunemente utilizzata dalle persone ed utilizza il sistema binario poich pi
adatto ad essere maneggiato da circuiti elettronici.
facile osservare che il codice binario utilizza un alfabeto A = {0,1} con n=2.
Le informazioni numeriche vengono quindi rappresentate mediante stringhe di bit
di lunghezza l che producono 2l configurazioni (parole codice) diverse.
Viceversa se si devono rappresentare K informazioni diverse occorrono log2K
bit per associare ad esse codici diversi.
La precisione con cui i numeri possono essere espressi finita e
predeterminata, poich questi devono essere memorizzati con parole codice di
lunghezza fissata. Per ragioni legate alla costruzione dei moderni calcolatori,
d'uso fare riferimento a stringhe con l uguale ad 8 che vengono dette byte.
Sequenze di bit pi lunghe di un byte sono invece denominate word, la loro
lunghezza dipende dalle caratteristiche del sistema, ma sempre un multiplo del
Linformazione e le sue rappresentazioni 7

byte: 16, 32, 64 o 128 bit. Poich i calcolatori trattano con molti bit/byte sono state
introdotte le unit di misura binarie riportate in tabella 3.

Sigla Nome Numero byte Numero bit


B Byte 1 8
KB KiloByte 210=1024 8.192
MB MegaByte 220=1.048.576 8.388.608
GB GigaByte 230=1.073.741.824 8.589.934.592
TB TeraByte 240=1.099.511.627.776 8.796.093.022.208

Tabella 3 Unit di misura binarie

Con otto bit si rappresentano solo 28 (256) valori diversi. Nel caso in cui un
solo byte non fosse sufficiente per rappresentare i K valori dellinformazione,
allora si individua il numero b di byte tale che:

2 (b*8) > K

In altri termini, allinterno dei moderni calcolatori, la codifica a lunghezza


fissa ed adotta parole codice con una lunghezza che ha valori multipli di 8.

Numero di byte b Numero di bit (b*8) 2 (b*8) Configurazioni


1 8 28 256
2 16 216 65.536
3 24 224 16.777.216
4 32 232 4.294.967.296

Tabella 4 Valori di informazione rappresentabili al variare del numero di byte

Ladozione di stringhe a lunghezza finita e definita implica che i numeri


gestiti siano a precisione finita, ossia siano quelli rappresentati con un numero
finito di cifre, o pi semplicemente definiti allinterno di un prefissato intervallo di
estremi [min,max] determinati.
Nel mondo reale esistono esempi di sistemi di numerazione basati su numeri a
precisione finita come i sistemi di misura dei gradi degli angoli ([0, 360]) e del
tempo ([0, 60] per minuti e secondi e [0, 24] per le ore). In tali sistemi di
numerazione si introduce il concetto di periodicit, per cui valori non compresi
nellintervallo di definizione vengono fatti ricadere in esso. In generale, nei sistemi
di calcolo con numeri a precisione finita, le operazioni possono causare errori
quando il risultato prodotto non appartiene allinsieme dei valori rappresentabili. Si
dice condizione di underflow quella che si verifica quando il risultato
delloperazione minore del pi piccolo valore rappresentabile (min). Si chiama
overflow la condizione opposta, ossia quella che si verifica quando il risultato
delloperazione maggiore del pi grande valore rappresentabile (max). Infine il
risultato delloperazione non appartiene allinsieme quando non compreso
nellinsieme dei valori rappresentabili, pur non essendo n troppo grande n troppo
piccolo.
8 Capitolo primo

La tabella seguente mostra alcuni casi di overflow, di underflow e di non


appartenenza allinsieme di definizione per una calcolatrice decimale dotata di sole
tre cifre, con intervallo di definizione formato da numeri interi compresi
nellintervallo [-999,+999].

Operazione Condizione
200 +100 risultato rappresentabile
730 + 510 Overflow
-500-720 Underflow
2:3 risultato non rappresentabile

Tabella 5 Esempi di operazioni che generano risultati rappresentabili e non

Anche lalgebra dei numeri a precisione finita diversa da quella


convenzionale poich alcune delle propriet:
- propriet associativa: a + (b - c) = (a + b) c
- propriet distributiva: a (b - c) = a b a c
non sempre vengono rispettate in base allordine con cui le operazioni
vengono eseguite, come i casi seguenti mostrano usando la stessa calcolatrice di tre
cifre.

a b C a + (b - c) condizione (a + b) c Condizione
100 900 600 100 + ok (100 + 900) - 600 Overflow
(900 - 600)
a b C a (b - c) condizione abac Condizione
200 90 88 200 Ok 200 90 200 88 Overflow
(90 88)

Tabella 6 Applicazione delle propriet associativa e distributiva per algebre a


precisione finita

Lalgebra dei numeri a precisione finita deve essere gestita applicando i noti
criteri di periodicit e tenendo in considerazione le condizioni di errore indicate.
Per la periodicit i valori esterni allintervallo di definizione vengono ricondotti ad
esso prendendo il resto della divisione dei valori per il periodo.

intervallo periodo valore divisione resto


[0,360] 360 1200 1200 : 360 120
[0,60] 60 61 61 : 60 1
[0,60] 60 55 60 : 55 55
Tabella 7 Sistemi periodici

Le operazioni in sistemi periodici possono essere effettuate utilizzando la


sveglia della figura seguente che associa alle tacche i valori definiti
nellintervallo fissato. Per comodit di disegno si ristretto lintervallo di
definizione a [-7, 8]. La sveglia pu essere assimilata ad una calcolatrice che fa
somme e sottrazioni: basta posizionare la lancetta sul valore del primo operando,
spostarla di un numero di posizioni uguale al secondo operando in senso orario per
Linformazione e le sue rappresentazioni 9

la somma e in senso antiorario per la sottrazione, quindi leggere come risultato la


sua posizione finale. Si nota che, muovendo le lancette in senso orario, al valore
pi grande fa seguito quello pi piccolo; viceversa quello pi piccolo preceduto
da quello pi grande. Se a 6 si somma 8 si ottiene come risultato -2 e non 14.

Figura 2 Calcolatrice per un sistema di numerazione finita

Il sistema binario ha una importanza capitale in informatica in quanto


consente di rappresentare numeri mediante la combinazione di due soli simboli,
ovvero di codificare i numeri direttamente in bit, secondo la notazione interna dei
circuiti numerici. Inoltre allinterno dei calcolatori viene adottata unalgebra dei
numeri a precisione finita con un intervallo di definizione che dipende dal numero
di byte associato alla rappresentazione.
Poich le considerazioni che seguono non dipendono da tale intervallo, si
adotter una rappresentazione dei numeri che adotta un solo byte, solo per
semplicit degli esempi. La tabella seguente riporta alcuni numeri rappresentati in
binario.

1 0 1 0 0 1 0 1 165
0 0 0 0 0 0 0 1 1
1 1 1 1 1 1 1 1 255
0 0 0 0 0 0 0 0 0
Peso Peso Peso Peso Peso Peso Peso Peso
7 6 5 4 3 2 1 0
Tabella 8 Numeri in binario

Nel byte il bit pi a destra quello meno significativo (posizione o peso 0,


detto anche LSB da Least Significant Bit) mentre quello pi a sinistra quello pi
significativo (posizione o peso 7, detto anche MSB da Most Significant Bit).
Poich un byte pu rappresentare 28 valori diversi, si possono, ad esempio con
8 bit gestire i seguenti intervalli di numeri interi:
- [0, 255] (in binario [00000000,11111111])
- [-127, 128] (in binario [11111111,01111111])
10 Capitolo primo

entrambi costituiti da 256 numeri.


Un sistema di numerazione pu essere visto come un insieme di simboli
(cifre) e regole che assegnano ad ogni sequenza di cifre uno ed un solo valore
numerico.
I sistemi di numerazione vengono di solito classificati in sistemi posizionali e
non posizionali. Nei primi (un esempio il sistema decimale) ogni cifra della
sequenza ha unimportanza variabile a seconda della relativa posizione (nel sistema
decimale la prima cifra a destra indica lunit, la seconda le centinaia, etc), nei
secondi (un esempio dato dal sistema romano), di contro, ogni cifra esprime una
quantit non dipendente dalla posizione (nel sistema romano il simbolo L
esprime la quantit 50 indipendentemente dalla posizione).
possibile osservare che una data stringa di bit pu essere interpretata come
una qualsiasi sequenza di cifre in un sistema di numerazione posizionale che
associa alle cifre c un diverso peso in base alla posizione i occupata nella stringa
che compone il numero, dove il peso dipende dalla base b di numerazione:

ci bi + ci - 1 bi - 1 + ci - 2 bi - 2 + + c2 b2 + c1 b1 + c0 b0 + c-1 b-1
+ c-2 b-2 +

Nel caso dei numeri interi scompaiono le potenze negative della base e la
formula diventa:

ci bi + ci - 1 bi - 1 + ci - 2 bi - 2 + + c2 b2 + c1 b1 + c0 b0

Un sistema di numerazione posizionale quindi definito dalla base (o radice)


utilizzata per la rappresentazione. In un sistema posizionale in base b servono b
simboli per rappresentare i diversi valori delle cifre compresi tra 0 e (b-1).

Base Denominazione Valori delle cifre


10 Decimale 0123456789
2 Binaria 01
8 Ottale 01234567
16 Esadecimale 0123456789ABCDEF

Tabella 9 Sistemi posizionali

Poich basi diverse fanno uso delle stesse prime cifre, si rende necessario
distinguere le rappresentazioni dei numeri con un pedice indicante la base dopo
aver racchiuso la stringa tra parentesi.

(101111)2 = (142)5 = (47)10


Inoltre, poich nel sistema decimale la prima cifra a destra indica le unit, la
seconda indica le decine, la terza le centinaia, la quarta le migliaia, e cos di seguito
secondo le potenze del dieci, solo in esso possibile leggere i numeri come
tremilacentouno, unmilioneetrenta. Negli altri sistemi di numerazione devono
essere scandite le cifre, da quella di peso maggiore fino a quella di minor peso, con
indicazione della base (ad esempio unoquattrodue in base cinque). In tutte le
Linformazione e le sue rappresentazioni 11

basi gli zeri a sinistra possono essere omessi, cos come quelli a destra se il numero
dotato di virgola.
Nel passaggio da una base allaltra alcune propriet dei numeri si perdono: ad
esempio un risultato di una divisione pu essere periodico nella base dieci ma non
detto che lo sia in unaltra base, cos come la propriet di un numero di essere
divisibile per cinque ha senso solo se la base maggiore di cinque.
La introdotta interpretazione del numero secondo il sistema di numerazione
posizionale pesato consente di convertire nella base 10 il valore rappresentato in
una qualsiasi base b, calcolando la sommatoria dei prodotti delle cifre per i pesi:

l 1
Valore ci b i (1)
i 0
Ad esempio:

(101111)2 = 1 25+ 0 24+ 1 23+ 1 22+ 1 21+ 1 20= 32 + 8 + 4 + 2 +1 =

(142)5 = 1 52 + 4 51 + 2 50 = 25 +20 +2 =

(47)10 = 4 101 + 7 100

L'impiego nella base 2 di un minor numero simboli rispetto al sistema


decimale (2 contro 10) implica che lo stesso numero abbia una parola-codice pi
lunga in notazione binaria che non in quella decimale. Poich per rappresentare le
dieci cifre ci vogliono log210 bit ( 3,3 bit), solitamente la stringa di cifre in bit
approssimativamente tre volte pi lunga di quella decimale come lesempio
seguente mostra:

(1001101)2 = 1 26 + 0 25 + 0 24 + 1 23 + 1 22 + 0 21 + 1 20 =

= 64 + 0 + 0 + 8 + 4 + 0 + 1 =

= (77)10

In informatica, per evitare di dover trattare con stringhe di bit troppo lunghe,
sono stati introdotti il sistema ottale ed esadecimale. La tabella seguente mostra la
corrispondenza tra le cifre usate in tali rappresentazioni e i bit che le rappresentano.
Le numerazioni ottale ed esadecimale sono interessanti perch la
trasformazione di rappresentazioni di valori tra esse si e la base 2 (e viceversa)
immediata. Infatti la trasformazione di un valore da binario in ottale molto
semplice dato che una cifra del sistema ottale rappresentabile esattamente con tre
bit del sistema binario il cui valore uguale proprio alla cifra rappresentata.
La conversione avviene raggruppando le cifre binarie in gruppi di tre a partire
dalla posizione di peso minore. La conversione opposta ugualmente semplice:
ogni cifra ottale viene esplosa esattamente nelle tre cifre binarie che la
rappresentano.
12 Capitolo primo

Ottale Binario Esadecimale Binario


0 000 0 0000
1 001 1 0001
2 010 2 0010
3 011 3 0011
4 100 4 0100
5 101 5 0101
6 110 6 0110
7 111 7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111
Tabella 10 Rappresentazione cifre nei sistemi Ottale ed Esadecimale

La rappresentazione esadecimale ancora pi compatta: il processo di


conversione equivalente a quello binario-ottale ma le cifre binarie devono essere
raggruppate in gruppi di quattro.

Figura 3 Conversione tra Binario ed Ottale e Binario ed Esadecimale

Dagli esempi precedenti si visto che per convertire un valore da una


qualsiasi base b di numerazione al corrispondente valore nel sistema decimale, si
deve calcolare la somma delle potenze della base b assegnata.
Il procedimento inverso, cio quello da applicare per convertire un valore
decimale in un altro sistema di numerazione, viene mostrato per la conversione in
binario ma pu essere applicato per analogia con qualsiasi altra base di
numerazione.
Per convertire un numero decimale in binario si procede separando la parte
intera da quella decimale e applicando due procedimenti (algoritmi) diversi. Dato
un valore d decimale, lo si pu rappresentare come:

d = ci bi + ci-1 bi-1 + + c2 b2 + c1 b1 + c0 b0 + c-1 b-1 + c-2 b-2


+
Linformazione e le sue rappresentazioni 13

e scomporlo in parte intera e frazionaria. Nel caso di b=2:

dpi = ci 2i + ci-1 2i-1 ++ c2 22 + c1 21 + c0 20


dpf = c-1 b-1 + c-2 b-2 +

con: d = dpi + dpf

se si divide la parte intera per 2:

dpi /2 = ci 2i-1 + ci-1 2i-2 ++ c2 21 + c1 20 + c0 2-1

si ottiene:

dpi1= ci 2i-1 + ci-1 2i-2 ++ c2 21 + c1 20

con c0 resto della divisione.


Se ora si divide la parte intera ottenuta precedentemente dpi1 ancora per la base 2:
dpi1 /2 = ci 2i-2 + ci-1 2i-3 ++ c2 20 + c1 2-1

si ottiene:

dpi2 = ci 2i-2 + ci-1 2i-3 ++ c2 20

con c1 resto della divisione.


Si comprende allora che il procedimento deve essere ripetuto fino a quando si
ottiene un quoziente uguale a 0. Linsieme dei resti delle diverse divisioni
comporranno la stringa in binario del numero d, in particolare: il resto della prima
divisione corrisponde alla cifra binaria del bit meno significativo, quello
dellultima il bit pi significativo come lesempio che segue mostra.
ALGORITMO
1) dividere la parte intera del numero d
per la base b
2) scrivere il resto della divisione
3) se il quoziente maggiore di zero,
usare tale risultato al posto del numero
d di partenza e continuare dal punto 1)
4) se il quoziente zero, scrivere tutte le
cifre ottenute come resto in sequenza
inversa

Esempio 1 Algoritmo per la conversione della parte intera di un numero in base b nel
corrispondente decimale
14 Capitolo primo

Si noti che lalgoritmo nellesempio 1 consente di convertire un numero intero


in base dieci in una qualunque base b. Nel caso di b =2 si ottiene la conversione in
binario del numero assegnato.
Per la conversione della parte frazionaria si procede al contrario moltiplicando
per 2:

dpf 2 = c-1 b0 + c-2 b-1 +


dpf1 = c-2 b-1 +

per spostare c-1 a sinistra della virgola che diventa parte intera.

Anche in questo si continua a moltiplicare per 2 solo la parte frazionaria fino a


quando non si verifica una delle seguenti condizioni:
- la parte frazionaria dpfi-esima non si annulla;
- la parte frazionaria dpfi-esima si ripete con periodicit;
- ci si accontenta di una rappresentazione approssimata con un numero di
bit inferiore a quello che andrebbero calcolati per raggiungere una delle
condizioni precedenti. Si noti che solo la prima condizione garantisce una
conversione senza approssimazione.

ALGORITMO
1) moltiplicare la parte frazionaria
del numero d per la base b
2) scrivere la parte intera del
prodotto
3) se la nuova parte frazionaria del
prodotto diversa da zero o non
si ripete periodicamente, oppure
si non sono state determinate le
cifre binarie prefissate, usare
tale risultato al posto del
numero d di partenza e
continuare dal punto 1)
4) se la nuova parte frazionaria
verifica una delle tre condizioni
di terminazione, scrivere tutte le
cifre ottenute come parte intera
nellordine in cui sono state
calcolate

Esempio 2 Algoritmo per la conversione della parte frazionaria di un valore in base b


nel corrispondente decimale

Si noti che lalgoritmo consente di convertire un numero frazionario in base


dieci in una qualunque base b. Nel caso di b =2 si ottiene la conversione in binario
del numero assegnato.
Linformazione e le sue rappresentazioni 15

Ladozione della notazione posizionale pesata senza altra convenzione


(posizione della virgola o indicazione di un eventuale segno) consente di
interpretare una sequenza di bit come rappresentazione di un numero naturale. Su
tali numeri si applicano gli algoritmi di somma e sottrazione, prodotto e divisione
in modo del tutto analogo ai numeri in base 10, l'unica differenza risiede nella poca
pratica che si ha con essi.
Come nel decimale si definiscono la tavola delladdizione e la tabellina del
prodotto per le cifre binarie.

Tabella 11 Tabelle di somma e prodotto per le cifre binarie

Di seguito sono riportati alcuni esempi di operazioni: si noti che nella somma
si deve tener conto del riporto (che si propaga a sinistra cos come nellaritmetica
decimale) mentre nella sottrazione, in presenza delloperazione 0 1, si deve
attivare il prestito dalle cifre pi a sinistra (come nellaritmetica decimale).

Esempio 3 Esempi di somma, sottrazione e prodotto fra numeri binari

La rappresentazione finora presentata, che fa uso dellequazione (1) per la


codifica da binario a decimale e dellalgoritmo nellesempio 1 per la codifica da
decimale a binario, viene anche detta in binario puro. Essa rende possibile
rappresentare tutti i numeri interi positivi appartenenti allintervallo [0, 2l 1] con l
ad indicare i bit a disposizione.
1.2.2. La rappresentazione dei numeri relativi
Per i numeri relativi, ovvero tutti i numeri interi, positivi e negativi, incluso lo
zero, si utilizzano invece altre tipologie di rappresentazioni. A tale proposito,
nellevoluzione dellaritmetica binaria, sono state definite rappresentazioni diverse
16 Capitolo primo

(segno e modulo, complemento a uno, complemento a due, eccesso 2l - 1) per


cercare di realizzazione circuiti elettronici capaci di effettuare le operazioni
aritmetiche allinterno di un calcolatore in modo ottimizzato e allo stesso tempo
semplice.
Poich il segno assume due soli valori (+ oppure ), allora lo si pu
codificare con un singolo bit utilizzando il bit pi significativo per indicarlo: ad
esempio, 0 per indicare un valore positivo ed 1 per indicarne uno negativo.
Con l bit, l 1 di essi vengono attribuiti alla rappresentazione del valore assoluto
del numero, e il bit pi a sinistra (MSB) alla rappresentazione del segno.

Figura 4 Rappresentazione per segno e modulo

La rappresentazione, detta per segno e modulo, consente di codificare tutti i


numeri relativi appartenenti allintervallo:

[-2l -1
+ 1, 2l -1
- 1]

con 2l - 1 valori positivi e altrettanti negativi: per un totale di 2l valori diversi.


Per l =8 sono rappresentabili tutti i numeri relativi appartenenti allintervallo [-
127,127]. Si noti che, poich sono presenti due configurazioni dello zero, lo 0
positivo (00000000) e lo 0 negativo (10000000), le operazioni di somma e
sottrazione devono essere corrette nellattraversamento dello zero. Ma il motivo che
ha portato alla ricerca di una rappresentazione diversa per i numeri negativi, che la
rappresentazione per segno e modulo richiede un algoritmo complesso per effettuare somma e
sottrazione in presenza delle diverse combinazioni dei segni degli operandi.
Con la rappresentazione in complemento a due, somma e sottrazione si
possono effettuare con lo stesso algoritmo, e quindi si possono affidare allo stesso
circuito elettronico. In complemento a 2 le configurazioni che hanno il bit pi
significativo uguale a zero, cio quelle comprese nellintervallo [0, 2l - 1- 1],
rappresentano se stesse (numeri positivi), mentre le configurazioni col bit pi
significativo uguale a uno, cio quelle rientranti nellintervallo [2l - 1,2l - 1],
rappresentano i numeri negativi che si ottengono traslando a sinistra lintervallo di
2l, cio lintervallo [-2l - 1,-1].

Figura 5: Rappresentazione per complemento a 2


Linformazione e le sue rappresentazioni 17

Nella rappresentazione per complemento a 2, i valori rappresentati sono


compresi nellintervallo:

[-2l -1, 2l -1 - 1]

sono sempre 2 l :

- [0,2l -1] per i valori positivi


- [-2l - 1,-1] per i valori negativi.

lintervallo non simmetrico:

- 2l - 1 valore assoluto del minimo


- 2l -1 valore del massimo

ed esiste una sola rappresentazione dello zero.


Con 8 bit, ad esempio, si rappresentano i numeri naturali nellintervallo [0, 28-
1], cio [0, 255], oppure i numeri relativi nellintervallo [-27, 27-1], cio [-128,
127]. Con 16 bit (2 byte) si rappresentano i numeri naturali nellintervallo [0,216-1],
cio [0,65535], oppure i numeri relativi nellintervallo [-215, 215-1], cio [-32768,
32767].
Il complemento a due x di un valore negativo x si calcola sottraendo il valore
assoluto di x a 2l:

x = 2l |x|

Se si definisce il complemento alla base b di una cifra c come:

c = b -1 - c

allora il complemento a 2 si ottiene complementando alla base tutte le cifre


del valore assoluto del numero x e sommando poi 1 al valore ottenuto, come
lesempio 4 mostra nel caso di l = 8. Si noti che il complemento alla cifra nel caso
di b=10 si ottiene sottraendo la cifra c a 9, mentre nel caso di b=2 equivale alla
sostituzione dello zero con luno e delluno con lo zero.

Esempio 4 Calcolo del complemento a 2 di un numero x negativo


18 Capitolo primo

Viceversa, se si ha una sequenza di l bit che rappresenta un numero intero con


segno, con i numeri negativi rappresentati in complemento a 2, allora, per ottenere
il numero rappresentato, si procede nel seguente modo.
- Si esamina il bit di segno.
- Se esso zero, il numero rappresentato non negativo e lo si calcola con
la normale conversione binario-decimale.
- Se invece il bit di segno uno, allora si tratta di un numero negativo, per
cui, per ottenerne il valore assoluto, si applica lo stesso procedimento
visto in precedenza complementando tutti i bit e sommando 1 al risultato.
Unaltra interpretazione del complemento a 2 riporta che il bit di segno, quello
pi significativo nella stringa di bit, contribuisca con peso negativo alla
determinazione del valore nel sistema di numerazione posizionale pesato; in altri
termini, con l bit, con la prima posizione che parte da zero, si ha che il peso della
cifra pi significativa cl-1 -2l - 1:

cl - 1 (-2l -1
) + cl - 2 (2l -2
) + + c1 21 + c0 20

come lesempio che segue dimostra (sempre con l = 8).

Esempio 5 Interpretazione del complemento a 2

Il complemento a uno (x) del numero x si differenzia dal complemento a 2


(x) dello stesso numero per una unit:

x = x - 1

Dalla definizione si comprende che il complemento a 1 di un numero, detto


anche complemento diminuito o complemento alla base, si ottiene semplicemente
complementando tutte le cifre del numero.
Il complemento a 1 stato usato in alcuni calcolatori, ma stato abbandonato
perch alla semplicit di determinazione dei numeri negativi (nel caso di base 2
basta sostituire ad ogni uno lo zero ed ad ogni zero luno) accompagna una doppia
rappresentazione dello zero che complica le operazioni di somma e sottrazione. Va
notato che tale rappresentazione simmetrica come quella per segno e modulo: con
l bit lintervallo rappresentato [-(2l - 1-1), 2 l - 1-1].
Nella rappresentazione per eccesso 2l -1 i numeri negativi si determinano
come somma di se stessi con 2l -1 dove l il numero di bit utilizzati. Si noti che il
sistema identico al complemento a due con il bit di segno invertito. In pratica i
numeri compresi in [-2l - 1, 2l - 1-1] sono mappati tra [0, 2 l -1].
Linformazione e le sue rappresentazioni 19

Figura 6: Rappresentazione per eccessi

In tale rappresentazione, il numero binario che rappresenta 2l -1 sar associato


allo zero, mentre i valori minori di 2l - 1 ai numeri negativi e quelli maggiori a
quelli positivi. Nel caso di n = 8 i numeri appartenenti a [128, 127] sono mappati
nellintervallo [0, 255] (con i numeri da 0 a 127 considerati negativi, il valore 128
corrisponde allo 0 e quelli maggiori di 128 sono positivi).

Tabella 12 Esempi di codifica di numeri negativi nelle varie rappresentazioni

Le rappresentazioni in complemento a due ed eccesso 2l -1 sono le pi


efficienti per svolgere operazioni in aritmetica binaria poich permettono di trattare
la sottrazione tra numeri come una somma tra numeri di segno opposto:
(X - Y) = (X + (-Y))
Si noti che tale propriet ha validit solo nel caso di rappresentazioni finite dei
numeri come lesempio 6 dimostra. cos possibile costruire dei circuiti che fanno
solo addizioni.

Esempio 6 Operazioni in complementi a 2


20 Capitolo primo

1.2.3. La rappresentazione dei numeri reali


I numeri reali vengono rappresentati in binario attraverso la seguente notazione
scientifica:

con m numero frazionario detto mantissa, la base b numero naturale prefissato


ed e numero intero chiamato esponente o caratteristica. L'esponente determina
lampiezza dell'intervallo di valori preso in considerazione, mentre il numero di
cifre della mantissa determina la precisione del numero (ossia con quante cifre
significative sar rappresentato). Tale notazione scientifica viene adottata per
diversi motivi:
- la sua indipendenza dalla posizione della virgola;
- la possibilit di trascurare tutti gli zeri che precedono la prima cifra
significativa con la normalizzazione della mantissa;
- la possibilit di rappresentare con poche cifre numeri molto grandi oppure
estremamente piccoli;
- la dipendenza del valore rappresentato dalla mantissa e dallesponente se si
adottano specifiche convenzioni per la base e la mantissa.
La rappresentazione in binario dei numeri reali si caratterizza rispetto alla notazione
scientifica per alcune particolarit nel modo di rappresentare e utilizzare i numeri, dovute
all'uso di rappresentazioni finite e definite sia per l'esponente che per la mantissa. I due
fattori limitano quindi sia l'intervallo dell'insieme dei numeri reali che possibile
rappresentare, che il grado di precisione che essi avranno. Infatti in un intervallo reale
comunque piccolo esistono infiniti valori (i numeri reali formano un continuo).
I valori rappresentabili in binario appartengono invece ad un sottoinsieme che contiene
un numero finito di valori reali ognuno dei quali rappresenta un intervallo del continuo. In
altri termini, diviso l'insieme dei numeri reali in intervalli di fissata dimensione, si ha, come
la figura mostra, che ogni x appartenente all'intervallo [Xi, Xi+1[ viene sostituito con Xi.

Figura 7 Finitezza della rappresentazione numeri reali


Linformazione e le sue rappresentazioni 21

La sostituzione di un numero reale x con il valore X rappresentante l'intervallo


a cui x appartiene, pone notevoli problemi di approssimazione in tutti i calcoli che
usano valori del tipo reale.
Per valutare gli effetti delle approssimazioni e gli errori che ne possono
derivare, nata la disciplina chiamata calcolo numerico, che si pone come
obiettivo la ricerca di algoritmi appropriati per la soluzione di problemi matematici
che fanno largo uso dei numeri reali. Difatti un qualsiasi calcolo numerico sarebbe
privo di senso, qualora non si avesse un'idea del tipo e dell'entit degli errori che si
possono commettere.
In concreto i numeri reali rappresentabili in binario godono della seguente
propriet:

x X
Xi 1 Xi

dove rappresenta l'errore che si commette sostituendo x con X, dove:


- X = Xi se si approssima per difetto;
- X = Xi+1 se si approssima per eccesso.
Il valore dipende dalla rappresentazione finita (numero finito di cifre)
utilizzata per i numeri reali. Ad esempio disponendo di una calcolatrice con una
aritmetica a quattro cifre decimali che applica le note regole di arrotondamento
sull'ultima cifra, si ha:

NUMERO ARROTONDAMENTO ERRORE


0,00347 0,0035 3*10-5 = 0.3 *10-4
0,000348 0,0003 48*10-6 = 0.48*10-4
0,00987 0,0099 3*10-5 = 0.3 *10-4
0,000987 0,0010 13*10-6 = 0.13*10-4
Tabella 13 Errori di arrotondamento

con un errore massimo sull'ultima cifra di 0.5 (0.5 * 10-4) per le classiche
regole dell'arrotondamento. In generale se -m il peso della cifra meno
significativa, l'errore massimo che si commette :

1 m
10
2

Linsieme R anche costituito da infiniti valori ( definito dallintervallo ]-


, [). I numeri reali rappresentabili sono invece definiti in un insieme limitato con
estremi predefiniti [-minreal, maxreal]. Si definiscono:
- loverflow come la condizione che si verifica quando i valori o sono pi
piccoli di minreal o pi grandi di maxreal;
- lunderflow come la condizione che si verifica quando un valore, per
effetto delle approssimazioni, viene confuso con lo zero.
Si noti che la rappresentazione in virgola mobile, fissata la base, consente di
esprimere lo stesso valore con infinite coppie (mantissa, esponente), ad esempio:
48 103 uguale a 4800 100, ma anche a 4,8 102
22 Capitolo primo

allora possibile scegliere, tra le infinite coppie quella che preserva il


maggior numero di cifre significative con la normalizzazione della mantissa. Per
esempio, per i numeri minori di uno quando la cifra pi a sinistra uno zero, si
traslano (shift) verso sinistra le cifre diverse da zero (significative) decrementando
l'esponente di tante cifre quante sono le posizioni scalate: in questo modo si ottiene
unaltra coppia distinta, ma avente il medesimo valore del precedente (ad esempio
0,0025 *100 equivalente 2,5000 * 10-3). La mantissa scalata in questo modo
prende il nome di mantissa normalizzata e il numero in virgola mobile, il nome di
numero normalizzato. In generale la forma normalizzata della mantissa obbliga che
la sua prima cifra sia diversa da zero e che la sua parte intera sia in generale un
numero minore dalla base.
Ad esempio disponendo di una calcolatrice con le seguenti caratteristiche:
- rappresentazione con b = 10,
- cinque cifre per la mantissa considerata minore di 10,
- due cifre per l'esponente,
- rappresentazione normalizzata con la prima cifra diversa da zero.
si hanno le seguenti rappresentazioni normalizzate:

Numero Valore
0,384 3,8400 10-1
1345 1,3450 103
64350 6,4350 104
333 3,3300 102
0,0048 4,8000 10-3
0,0000001 1,0000 10-8

Tabella 14 Rappresentazioni Normalizzate

e la condizione di overflow quando:

x >9,9999 1099

e di underflow quando:

x < 1,0000 10-99

Osservando la modalit di rappresentazione in virgola mobile, si pu notare


che gli intervalli [Xi, Xi+1] non hanno tutti la stessa ampiezza a causa della finitezza
del numero di cifre della mantissa: man mano che ci si avvicina alla condizione di
overflow gli intervalli si fanno sempre pi ampi, mentre intorno alla condizione di
underflow non solo si addensano ma diventano sempre pi piccoli. Con la
calcolatrice precedente facile osservare il fenomeno confrontando gli intervalli
[1.0000 10-99, 1.0001 10-99] e [9.9998 1099, 9.9999 1099].
Con la rappresentazione in virgola mobile le operazioni non solo si
complicano ma possono generare errori di approssimazione. Ad esempio la somma
e la sottrazione richiedono l'allineamento degli esponenti:
100 100 + 100 10-2 = 100 100 + 1 100 = 101 100
Linformazione e le sue rappresentazioni 23

mentre per il prodotto e la divisione servono operazioni separate sulle


mantisse e sugli esponenti:

100 100 * 100 10-2 = (100 * 100) 10(0-2) = 10000 10-2

L'allineamento degli esponenti produce come effetto indesiderato quello di far


scomparire alcune cifre rappresentative del numero. Ad esempio la somma dei
numeri seguenti:

1,9099 101 + 5,9009 104

con la calcolatrice considerata prima, diventa:

0,0001 104 + 5,9009 104

con il troncamento delle cifre 9099 del numero con esponente pi piccolo.
Le operazioni che richiedono maggiore attenzione sono l'addizione e la
sottrazione. Infatti, la causa principale degli errori di calcolo numerico risiede nella
sottrazione di numeri di valore quasi uguale; in tal caso le cifre pi significative si
eliminano fra loro e la differenza risultante perde un certo numero di cifre
significative o anche tutte (fenomeno detto cancellazione). Altra causa di errori la
divisione per valori molto piccoli, poich il risultato pu facilmente superare il
valore di overflow: deve essere pertanto evitata non solo la divisione per lo zero
ma anche per valori ad esso prossimi.
Il grande vantaggio della rappresentazione in virgola mobile che, se si
conviene che le mantisse siano trasformate in valori minori di 10 con operazioni
interne, un numero reale pu essere rappresentato nella memoria di un calcolatore
con un numero intero indicativo della parte decimale della mantissa e con un altro
numero intero per l'esponente.
Per esempio il numero 0,1230 10-9 viene rappresentato con la coppia di
numeri interi (1230,-9) e gestito con operazioni interne che ne costruiscono
l'effettivo valore.
Nel caso binario la rappresentazione in virgola mobile normalizzata assume la
forma:

Nel 1980, i principali costruttori di elaboratori elettronici, producevano


calcolatori che utilizzavano i numeri float, ognuno con un proprio formato
numerico e con proprie convenzioni di calcolo. Nel 1985 divenne operativo lo
Standard 754 IEEE per i numeri in virgola mobile, e i maggiori costruttori
24 Capitolo primo

adottarono questo standard per i loro processori matematici. Lo standard 754


definisce principalmente tre formati numerici a virgola mobile:
- singola precisione o precisione semplice (32 bit),
- doppia precisione 64 bit),
- precisione estesa (80 bit).

Consideriamo i formati a 32 e 64 bit, che utilizzano la base 2 e la notazione in


eccesso per lesponente.

Figura 8 Formati a singola e doppia precisione

Nella stringa di bit, si succedono nellordine da sinistra (MSB) a destra


(LSB):
- un bit per il segno del numero complessivo, (zero per positivo ed uno per
negativo);
- otto bit nel caso della singola precisione (11 per la doppia precisione) per
l'esponente rappresentato per eccesso cos da non doverne indicare il
segno;
- 23 bit nel caso della singola precisione (52 per la doppia) per la mantissa.
La mantissa normalizzata per cui comincia sempre con un 1 seguito da
una virgola binaria, e poi a seguire il resto delle cifre. Lo standard prevede
lassenza sia del primo bit che del bit della virgola perch sono sempre
presenti: linsieme delluno implicito, della virgola implicita e delle cifre
esplicite prende il nome di significante.

Argomento Precisione singola Precisione doppia


32 Bit 64 bit
Bit del segno 1 1
Bit per lesponente 8 11
Bit per la mantissa 23 52
Cifre decimali mantissa Circa 7 (23/3.3) Circa 15 (52/3.3)
Esponente (rappresentazione) Base 2 ad eccesso 127 base 2 ad eccesso 1023
Esponente (valori) [-126, 127] [-1022, 1023]

Tabella 15 Caratteristiche formati singola e doppia precisione


Linformazione e le sue rappresentazioni 25

Lesempio di seguito riepiloga alcuni dei procedimenti illustrati per la


rappresentazione di numeri da binario a decimale e viceversa.

Problema Soluzione
Si vuole convertire il Poich la rappresentazione binaria pura consente la
numero 16 in binario codifica di numeri interi postivi allora 16
utilizzando una codificabile attraverso questa rappresentazione.
rappresentazione binaria Utilizzando 8 bit lintervallo di rappresentazione
pura su 8 bit. linsieme dei numeri interi postivi compresi in [0,28-
1], ovvero in [0,255]. Poich 16 racchiuso in tale
intervallo possibile passare alla sua codifica.
Utilizzando lalgoritmo dellesempio (1) si ha:
16:2 -> q1=8, r1=0
8:2 -> q2=4, r2=0
4:2 -> q3=4, r3=0
2:2 -> q4=1, r4=0
1:2 -> q5=0, r5=1
Considerando la successione dei resti invertita
[r5,r4,,r1] e inserendo gli zeri a sinistra del bit pi
siginificativo, si ha che il numero in binario
corrispondente : 00010000.
Si vuole convertire il Poich la rappresentazione per complementi a 2
numero -12 in binario consente la codifica di numeri relativi allora -12
utilizzando una codificabile attraverso questa rappresentazione.
rappresentazione per Utilizzando 5 bit lintervallo di rappresentazione
complementi a 2 su 5 bit linsieme dei numeri interi compresi in [-25-1,25-1-1],
ovvero in [-16,15]. Poich -12 racchiuso in tale
intervallo possibile passare alla sua codifica.
Poich -12 negativo per ottenere il corrispettivo in
binario si codifica il suo modulo su 5 bit, si
complimentano le cifre ottenute e si aggiunge 1.
Utilizzando lalgoritmo dellesempio (1) si ha:
12:2 -> q1=6, r1=0
6:2 -> q2=3, r2=0
3:2 -> q3=1, r3=1
1:2 -> q4=0, r4=1
Considerando la successione dei resti invertita
[r4,,r1] e inserendo gli zeri a sinistra del bit pi
siginificativo, si ha che il numero in binario
corrispondente 01100.
Complementando le cifre ottenute si ha 10011, infine
aggiungendo 1 al numero complementato si ha:
10100
Si vuole convertire il Poich la rappresentazione per complementi a 2
numero -10 in binario consente la codifica di numeri relativi allora -10
utilizzando una codificabile attraverso questa rappresentazione..
rappresentazione per Utilizzando 4 bit lintervallo di rappresentazione
complementi a 2 su 4 bit. linsieme dei numeri interi compresi in [-24-1,24-1-1],
26 Capitolo primo

ovvero in [-8,7]. Poich -10 non racchiuso in tale


intervallo la sua codifica non possibile.
Si vuole convertire il Innanzitutto si esamina il primo bit. Poich esso
numero 111000 da pari ad 1, il numero negativo e quindi, per
complementi a 2 in determinarne il modulo, si complementano ad 1 tutti i
decimale. bit e si somma 1 al risultato. Il complemento
000111, mentre sommando a tale numero 1, si ottiene
001000, il cui corrispettivo in decimale 0*25 + 0*24
+ 1*23+ 0*22 + 0*22 + 0*20 = 8.
Il numero decimale corrispondente quindi -8.
Lo stesso risultato poteva essere ottenuto, in via
alternativa, aggiungendo a -2l-1, ovvero a -25 = -32, la
codifica in decimale di 11000, ovvero 1*24 + 1*23+
0*22 + 0*22 + 0*20 = 24.
Infatti -32+24=-8.
Si vuole codificare il Innanzitutto si codificano in binario la parte intera e
numero reale 8.25 frazionaria della mantissa e lesponente (utilizzando
utilizzando la la rappresentazione per eccessi a 2l-1) ottenendo 0
rappresentazione in 111.01 * 200000000.
virgola mobile nel formato Normalizzando la mantissa, si ottiene:
a singola precisione. 0 1.1101 * 210000010

Esempio 7 Alcuni esempi di conversione

1.3. Gli operatori booleani


Sulle stringhe di bit sono anche definiti operatori che lavorano bit a bit (bitwise
operator). Essi sono detti booleani e sono:
- AND: dati due bit restituisce il valore 1 se e solo se i bit erano entrambi
posti a 1, in tutti gli altri casi il risultato 0; lAND detto anche prodotto
logico.
- OR: dati due bit restituisce il valore 0 se e solo se i bit erano entrambi
posti a 0, in tutti gli altri casi il risultato 1; lOR anche detto somma
logica.
- NOT: dato un bit restituisce il valore 0 se esso era posto a 1, restituisce
invece 1 se il bit era posto a 0; il NOT viene anche detto operatore di
negazione o di complementazione.
La figura che segue riporta la definizione completa dei tre operatori: la tabella
viene anche detta tavola di verit.
Linformazione e le sue rappresentazioni 27

Tabella 16 AND, OR, NOT


Si noti che la somma logica di 1 OR 1 fa 1 e non 0 con riporto 1 come nel
caso della somma aritmetica. Di seguito si riportano alcuni esempi di applicazione
dei tre operatori a dei byte.

Tabella 17 Esempi di AND, OR, NOT

1.4. La convergenza digitale


Negli ultimi anni tantissimi settori produttivi hanno migrato i loro sistemi realizzati
con tecnologie, anche molto diverse tra loro, in sistemi capaci di trattare
linformazione in modo digitale.
Lo sviluppo della tecnologia dei sistemi di comunicazione e di gestione delle
informazioni digitali nei campi delleditoria, della televisione, del cinema ha
comportato non solo benefici economici notevoli, ma soprattutto la capacit di
integrare e di elaborare informazioni provenienti da fonti diverse. E lintegrazione
digitale tanto pi significativa quanto pi consente di far condividere a soggetti
differenti e distanti il proprio patrimonio informativo.
Il fenomeno, detto convergenza digitale, si caratterizza per la concomitanza di
diversi fattori:
28 Capitolo primo

- la convergenza della codifica in quanto linformazione in una sua


qualsiasi forma viene rappresentata con un solo alfabeto di base: il codice
binario;
- la convergenza tecnologica perch uno stesso strumento, il calcolatore
elettronico, che elabora e trasmette informazioni differenti;
- la convergenza del mercato che vede applicazioni diverse dotate di
elementi comuni attraverso cui integrarsi.
Oggi viviamo in un mondo caratterizzato da una straordinaria ricchezza di
sorgenti di informazione (suoni, voci, rumori, musiche, immagini, fotografie,
filmati) e differenti canali di comunicazione (radio, televisione, satellite, rete
Internet, CD, DVD) e ritroviamo nel mondo digitale la stessa variet di forme
comunicative.
La trasformazione della realt analogica in forma digitale offre quindi
immense e nuove opportunit: la pi evidente che ogni informazione pu essere
scambiata in processi di comunicazione. Secondo Marshall McLuhan, che negli
anni 60 diede forza agli studi sulla teoria della comunicazione, i concetti
emergenti che nascono dallanalisi delle tecnologie digitali sono la globalit della
comunicazione (il cosiddetto villaggio globale) e i medium. Sempre secondo
McLuhan:
- La nuova interdipendenza elettronica ricrea il mondo come immagine di
un villaggio globale
- I media sono estensioni delluomo: tecnologie e prodotti che danno ai
nostri sensi nuove possibilit di ricevere informazioni
Il termine medium deriva dal latino e significa mezzo: va pertanto inteso come
mezzo di comunicazione. Con multimedialit si indica invece la combinazione di
diversi codici espressivi (testo, audio, immagini, video) per realizzare un unico
oggetto comunicativo che, grazie alle tecnologie digitali, si rappresenta con il
medesimo linguaggio basato su stringhe di bit.
La forza della multimedialit risiede nel convincimento che lintegrazione di
diverse forme espressive migliori la comunicazione. Ma lo studio della
comunicazione non pu prescindere dallo studio delle tecnologie dei mezzi di
comunicazione in quanto questi ultimi non sono neutri, ossia possono:
- condizionare le modalit di rappresentazione delle informazioni;
- alterare la percezione del messaggio,
- spezzare la simmetria di comunicazione coinvolgendo diversi destinatari
passivi (ad esempio radio, televisione),
- alterare le relazioni temporali tra gli interlocutori (ad esempio i messaggi
registrati).

La trasformazione di testo, audio, immagini, video in oggetti digitali pu


avvenire in modo diretto o attraverso dispositivi capaci di effettuare la conversione
che vengono detti ADC (Analogue to Digital converter). Nel primo caso esistono
applicazioni informatiche (elaborazione di testi) o macchine elettroniche (macchine
fotografiche o cineprese digitali) che forniscono direttamente le informazioni in
binario. I dispositivi del secondo tipo, quali ad esempio gli scanner, servono al
recupero in digitale di informazioni rappresentate nei loro formati tradizionali.
In entrambi i casi la trasformazione dellinformazione analogica in digitale
avviene con due processi distinti e disposti luno dopo laltro:
Linformazione e le sue rappresentazioni 29

- il campionamento e
- la quantizzazione.
Il campionamento il processo che provvede a selezionare il sottoinsieme
discreto di informazioni da rappresentare in digitale da quello pi ampio offerto
dalla realt. il partizionamento di un flusso continuo di informazione in quantit
discrete, rispetto al tempo, allo spazio o ad entrambi. La scelta dei campioni viene
effettuata in modo che linformazione rappresentata sia utilizzabile. Ad esempio
non ha molta importanza nel caso delle comunicazioni telefoniche, selezionare un
numero di campioni molto elevato nellunit di tempo della voce, perch lorecchio
umano non coglierebbe affatto le differenze.

Figura 9 Campionamento di un segnale con periodi differenti

Nel caso di grandezze dipendenti dal tempo la frequenza di campionamento


il numero di campioni prelevati in un secondo (unit di tempo). La frequenza si
misura in hertz (1 campione in un secondo) ed linverso dellintervallo di tempo
che intercorre tra lacquisizione di un campione e il suo successivo, che viene detto
periodo di campionamento.
La quantizzazione invece il processo che misura le caratteristiche (ad
esempio grandezza, intensit, colore) dei campioni selezionati attribuendo loro un
valore numerico. Di norma, i campioni selezionati vengono codificati in binario
30 Capitolo primo

sulla base dellappartenenza a dati intervalli di valori, detti intervalli di


quantizzazione.

Figura 10 Quantizzazione di un segnale

Sia campionamento che quantizzazione introducono unapprossimazione della


realt: il primo processo seleziona un sottoinsieme discreto di un insieme di valori
solitamente infinito, il secondo misura le caratteristiche scelte con un numero di
cifre prefissato.
Numero di campioni e numero di bit determinano anche la dimensione della
rappresentazione della grandezza reale: ad esempio nella figura la grandezza G
necessita in un caso di 88 bit, nellaltro di soli 66 bit. In tutti i processi di
digitalizzazione si deve pertanto raggiungere un compromesso tra qualit e
dimensione della rappresentazione: pi sono i campioni e i bit utilizzati, maggiore
la fedelt della rappresentazione e quindi anche la sua qualit. Ma quanto pi si
privilegia la qualit della rappresentazione, tanto pi si rallentano le elaborazioni e
lo scambio delle informazioni rappresentate.
Per risolvere i problemi connessi con le dimensioni elevate sono stati
introdotti processi di compressione che riducono lo spazio occupato mediante o la
diminuzione del numero di bit necessari per codificare una singola informazione
(compressione entropica) o la diminuzione del numero di informazioni da
memorizzare o trasmettere (compressione differenziale, compressione semantica).
La compressione pu conservare integralmente o no il contenuto della
rappresentazione originale secondo due tecniche principali:
- la compressione senza perdita di informazione (lossless, reversibile) che
sfrutta le ridondanze nella codifica del dato;
Linformazione e le sue rappresentazioni 31

- la compressione con perdita di informazione (lossy, irreversibile) che


invece sfrutta le ridondanze nella percezione dellinformazione.
La compressione lossless avviene tramite una classe di algoritmi che
consentono di ricostruire tutta linformazione iniziale partendo da quella
compressa. Non sempre si ottengono riduzioni significative. I metodi lossy
comportano riduzioni notevoli delle dimensioni, ma la ricostruzione
dellinformazione da quella compressa non per identica a quella iniziale. Tali
metodi rimuovono parti che possono non essere percepite come avviene nel caso di
immagini, video e suoni. Ad esempio gli algoritmi di compressione usati nei
formati GIF e JPEG per immagini fisse sfruttano la caratteristica dellocchio
umano di essere poco sensibile a lievi cambiamenti di colore in punti contigui, e
quindi eliminano questi lievi cambiamenti appiattendo il colore dellimmagine.
Tra le tecniche di compressione lossless si ricordano:
- la Run-length encoding (RLE) che codifica sequenze di valori uguali
premettendo un indicatore di ripetizioni al valore codificato;
- la codifica di Huffman che assegna un numero inferiore di bit alle
sequenze pi probabili attraverso un vettore di codifica;
- la compressione Lempel-Ziv-Welch (LZW) che costruisce dinamicamente
una tabella di codifica con numero variabile di bit sulla base delle
sequenze incontrate;
- la codifica differenziale in cui ogni dato rappresentato come differenza
rispetto al dato precedente.
- Tra le tecniche di compressione lossy si ricordano:
- la compressione JPEG per le immagini che applica una trasformata nel
dominio delle frequenze (Discrete Cosine Transform) che permette di
sopprimere dettagli irrilevanti riducendo il numero di bit necessari per la
codifica;
- la compressione MPEG per i video che codifica parte dei frame come
differenze rispetto ai valori previsti in base ad una interpolazione;
- la compressione MP3 per laudio che si basa alle propriet psicoacustiche
delludito umano per sopprimere le informazioni inutili.
1.4.1. La codifica delle informazioni testuali
Il testo uno degli oggetti digitali pi diffuso nel mondo informatico. Molte sono
le applicazioni che generano e manipolano i cosiddetti documenti elettronici. Un
testo digitale una stringa di simboli ad ognuno dei quali viene associato un codice
binario secondo un prefissato standard.

Figura 11 - Esempio di codifica di un testo

Alla fine degli anni sessanta l'ente americano di standardizzazione ANSI


(American National Standards Institute) decise di fissare un alfabeto che
32 Capitolo primo

consentisse a tutti i calcolatori, anche di produttori diversi, di poter comunicare tra


loro o con i dispositivi ad essi collegati. I simboli dellalfabeto vennero elencati in
una tabella per codificare, attraverso la posizione assunta da loro in essa, vari tipi
di caratteri: alfabetici, numerici, di punteggiatura, simbolici, e anche alcuni codici
da usare come controllo della comunicazione tra una macchina e l'altra (per
esempio, per segnalare linizio o la fine di una trasmissione). Il trasferimento di un
insieme di informazioni da un calcolatore all'altro su una rete poteva cos essere
effettuato attraverso un linguaggio comune, costituito da tale forma di codifica.
La tabella fu chiamata ASCII, ossia American Standard Code for Information
Interchange. Le prime 32 posizioni (da 0 a 31) sono occupate da codici di
controllo. La posizione o codice 32 si riferisce allo spazio, dopo di esso seguono
tutti caratteri visualizzabili. Per esempio, l'alfabeto (inglese) maiuscolo occupa le
posizioni da 65 a 90, e quello minuscolo le posizioni da 97 a 122. Le cifre
occupano le posizioni da 48 a 57. In totale ci sono 128 codici, da 0 a 127, e quindi
sono sufficienti 7 bit per la codifica della tabella ASCII.
La tabella stata definita per rendere comoda l'elaborazione dei caratteri: per
esempio, i codici di controllo hanno i due bit a sinistra uguali a zero, e quindi basta
guardare tali due bit per capire se un carattere di controllo o stampabile. Un'altra
caratteristica quella di aver disposto le cifre in sequenza, da 0 a 9, cos che, se si
sottrae il codice di '0' (che 48) dal codice di qualunque altra cifra, si ottiene il
valore numerico di tale cifra. Anche l'alfabeto elencato in successione, cos che
sottraendo dal codice di qualunque lettera il codice della prima lettera dell'alfabeto
(cio 'A' per le maiuscole, codice 65, oppure 'a' per le minuscole, codice 97) si
ottiene la posizione della lettera nell'alfabeto. Inoltre la posizione relativa delle
lettere maiuscole e minuscole fissa, e per la precisione ogni minuscola dista dalla
corrispondente maiuscola esattamente 32 posizioni. Quindi passare da maiuscolo a
minuscolo molto semplice: basta sommare 32 al codice, e sottrarre 32 per la
conversione inversa.
Un testo cos rappresentato dalla sequenza di byte associati ai caratteri che
lo compongono, nell'ordine in cui essi compaiono. Un testo di 1000 caratteri
richiede 1000 byte (1 Kb) per essere rappresentato.
La proposta iniziale dello standard ASCII ha come limite quello di essere
stato pensato per la sola lingua inglese americana in quanto mancano tutte le lettere
accentate in uso nei paesi europei. Per superare la localizzazione, cio la
dipendenza da una determinata area geografica e culturale, sono state proposte
varianti della tabella ASCII.
Lo standard ISO 8859 definisce un ASCII che usa 8 bit per estendere la
tabella con ulteriori 128 caratteri. Le tabelle ASCII estese, quindi coincidono con il
codice americano nei primi 127 caratteri. Ogni nazionalit, poi, pu localizzare
l'insieme dei caratteri disponibili aggiungendo quelli necessari alle proprie
esigenze nel nuovo spazio disponibile, quello dei codici da 128 a 255. Esistono
cos diverse varianti dell'ISO-8859: la versione ISO-8859-1 usata in Europa ed
detta anche ISO-latin-1, la sua configurazione col simbolo dell'euro la ISO-8859-
15.
Linformazione e le sue rappresentazioni 33

Tabella 18 Codice ASCII esteso

Con la diffusione di Internet a livello mondiale, anche i codici ASCII estesi


hanno per mostrato la loro inadeguatezza. Basta pensare alle lingue che usano
ideogrammi anzich alfabeti per rendersi conto che un insieme di soli 127 simboli
largamente insufficiente. Uno standard che si propone di affrontare il problema
del multilinguismo Unicode (Universal Encoding). Unicode un sistema di
codifica che assegna un numero univoco ad ogni simbolo in maniera indipendente
dal programma, dalla piattaforma e dalla lingua (e relativo alfabeto): il suo scopo
quello di creare una codifica delle scritture a livello universale. Unicode si basa
sulla codifica ASCII, ma va oltre la limitazione dell'alfabeto latino potendo
codificare caratteri scritti in tutte le lingue del mondo. Originariamente si basava su
una codifica a 16 bit che dava la possibilit di codificare pi di 65 mila caratteri.
Per rappresentare qualunque carattere, compresi quelli cinesi e tutte le loro
varianti, stato proposto lo standard Unicode (ISO-10646) che utilizza l'UTF
(Unicode Transformation Format) che supporta tre forme di codifica per
rappresentare un repertorio comune di caratteri che pu essere esteso fino a
rappresentarne circa un milione.
34 Capitolo primo

I formati UTF possono essere a 8, 16 e 32 bit. L'UTF-8 si basa su parole di 8


bit (1 byte) per la codifica dei caratteri; ed usa da 1 a 4 byte per carattere: i primi
128 valori, che iniziano col bit 0, utilizzano 1 byte per carattere e corrispondono
all'ASCII, i successivi 1920 (dal 128 al 2047) utilizzano 2 bytes per codificare
greco, cirillico, copto, armeno, ebraico, arabo. Per gli altri caratteri si usano 3 o 4
bytes. UTF-16 utilizza parole di 16 bit per codificare i caratteri, viene utilizzato da
Java, ed la rappresentazione interna usata da Windows e Mac OS-X.
Una interessante conseguenza della gestione dei testi digitali la possibilit di
costruirne una strutturazione diversa da quella sequenziale dei documenti, alla
quale i libri hanno abituato i lettori. La suddetta possibilit ha portato alla nascita
dei cosiddetti ipertesti. Un ipertesto un documento strutturato in cui un insieme di
frammenti di testo detti nodi vengono collegati per mezzo di riferimenti detti link.
In un ipertesto la fruizione del documento consiste nel muoversi da un nodo
allaltro seguendo i collegamenti. Lidea formalizzata di ipertesto nasce nella met
del secolo scorso, la maturazione tecnologica avviene solo negli anni 80.
Lapproccio ipertestuale levoluzione di un approccio non sequenziale alla lettura
dei documenti gi utilizzato nella realizzazione di quotidiani, enciclopedie, libri
con annotazioni e riferimenti, manuali, cataloghi. La digitalizzazione dei testi ne ha
consentito una pervasiva applicazione come testimoniato dal mondo di Internet.
Il testo digitale ha, tra i tanti vantaggi, quello di poter essere facilmente
trasmesso in reti di calcolatori per essere mostrato sugli schermi o stampato su
fogli di carta. Per garantire la presentazione elettronica o cartacea vengono
aggiunte informazioni che fissano caratteristiche di formato quali il tipo e la
dimensione del carattere, lo spazio tra una riga e laltra, il formato della pagina. La
tecnica pi utilizzata per la codifica consiste nell'inserire, assieme al testo,
informazioni speciali di formattazione che vengono interpretate in fase di
presentazione finale.
Il linguaggio HTML l'esempio pi diffuso per la codifica di testo formattato
finalizzato ad una consultazione in rete. Il codice HTML testuale e intuitivo.
Infatti le specifiche di formato vengono racchiuse tra parentesi che prendono il
nome di TAG. I TAG si distinguono dal resto del testo perch sono inclusi tra
parentesi angolate: con <nometag> si apre una indicazione di formato e con
</nometag> la si chiude. Ad esempio:

<font color=red> che bello </font>

prescrive la visualizzazione di che bello in rosso, mentre:

<font size=+1>HTML</font>

consente di scrivere HTML con caratteri di dimensioni pi grandi.


Il DOC invece il formato pi diffuso dei documenti formattati a causa
dellampia diffusione delleditor che lo gestisce (MicroSoft Word). Il Postscript
un altro linguaggio per la codifica di testo formattato finalizzato ad una
presentazione cartacea. Una sua evoluzione il PDF, sviluppato nel 1992 da
Adobe Systems, che stato pensato sia per la riproduzione cartacea che elettronica.
Con tale formato i documenti consultati a video hanno lo stesso identico aspetto
del documento stampato.
Linformazione e le sue rappresentazioni 35

1.4.2. La codifica delle immagini


Le immagini sono informazioni continue in tre dimensioni, due spaziali ed
una colorimetrica, e per codificarle occorre operare tre discretizzazioni. Le due
discretizzazioni spaziali riducono limmagine ad una matrice di punti detti pixel
(da picture element) mentre la terza limita linsieme di colori che ogni pixel pu
assumere ad un sottoinsieme definito.
Limmagine digitale quindi una matrice bidimensionale di numeri, ciascuno
dei quali la misura di una propriet fisica (colore) di unarea elementare della
scena rappresentata. Una immagine digitale pu essere generata:
- mediante acquisizione da immagini analogiche (ad esempio le fotografie,
le diapositive) con dispositivi detti scanner;
- da scene del mondo reale catturate con camere digitali;
- da applicazioni di grafica.
Le immagini digitali riproducono la scena dividendola in una griglia fatta di
aree di cui viene misurata la luminosit o il colore. Ad ogni area viene fatto
corrispondere un pixel la cui forma si discosta dalla superficie ripresa. Infatti per le
caratteritiche della maggioranza dei dispositivi elettronici di acquisizione e
visualizzazione delle immagini i pixel hanno la forma di un ellisse con lasse
verticale pi lungo rispetto a quello orizzontale. Il rapporto tra i due assi viene
detto rapporto di aspetto e serve, nelle applicazioni grafiche, per correggere
eventuali deformazioni dovute a rappresentazioni diverse di uno stesso segmento
nelle due direzioni ortogonali.

Figura 12 - Immagine come griglia di pixel

Il processo di campionamento applicato ad una immagine consiste quindi nel


far corrispondere ad ogni pixel una porzione dellimmagine reale. Pi la
dimensione dei pixel piccola, minore lapprossimazione tra immagine digitale e
quella reale. Con il termine di risoluzione si indica il numero di pixel per pollice
(dpi - dot per inch) perch le dimensioni di unimmagine (larghezza e altezza) sono
misurate in pollici. La dimensione dellimmagine viene anche espressa indicando
separatamente il numero di pixel orizzontali e il numero di pixel verticali, ad
esempio 600 x 800 pixel. Solitamente la risoluzione orizzontale uguale a quella
verticale. Ad ogni pixel viene poi assegnato un indirizzo che ne determina le
coordinate verticali ed orizzontali (bit mapping).
Il concetto di risoluzione legato a quanto sono fitti i punti che visualizzano
limmagine. Maggiore la risoluzione dellimmagine, maggiore la possibilit di
36 Capitolo primo

distinguere dettagli in essa presenti. Tutti i pixel contenuti in una immagine


digitale hanno dimensioni identiche. La loro dimensione determinata dalla
risoluzione alla quale limmagine viene digitalizzata: ad esempio la risoluzione di
600 dpi indica che ciascun pixel misura 1/600 di pollice.
Ad ogni pixel dellimmagine vengono associati l bit che misurano
caratteristiche di colore. Ma con l bit solo 2l sono le sfumature di colore
rappresentate degli infiniti valori della realt, e tutte le sfumature intermedie sono
approssimate con il valore di luminosit pi prossimo fra quelli codificati.
Poich la porzione di immagine associata ad un unico pixel ha una luminosit
uniforme, senza che dettagli in detta porzione possano essere distinti, minore il
numero dei livelli di quantizzazione, minore la qualit dellimmagine. La
profondit di colore la misura della capacit di rappresentare o distinguere varie
sfumature di colore. Unimmagine rappresentata con una profondit di colore di 6
bit, riesce a distinguere tra 64 livelli di colore, e allaumentare del numero di bit,
aumenta il livello di dettaglio. Se limmagine in bianco e nero, basta associare un
1 ai pixel neri, e uno 0 a quelli bianchi. Per immagini a livelli di grigio si usano 4 o
8 bit mentre per quelle a colori 8, 24, 32 bit.

Figura 13 - Immagini a diverse profondit di colore

Si parla di colori veri quando ad un pixel corrispondono 24 bit per un totale di


16.7Mega colori diversi; con 48 bit viene oggi gestita lalta definizione.
La rappresentazione accurata di una immagine dipende dal numero di pixel e
dalla profondit di colore. Una elevata qualit comporta una elevata quantit di
informazione data proprio dal prodotto:
numero pixel numero bit
Per fare alcuni semplici esempi si passa dai 440KByte di una immagine
televisiva con 256 colori (1 byte) per una risoluzione di 720x625 pixel, ai
440MByte di una foto con 16 milioni di colori (3 byte) per la risoluzione di ben
15.000x10.000 pixel.
La misura del colore oggetto di studio della colorimetria. Due sono i metodi
usati per formare il colore: la sintesi del colore di tipo additiva e quella di tipo
sottrattiva.
Linformazione e le sue rappresentazioni 37

Figura 14 - Sintesi del colore

Nel primo caso un colore pu essere ottenuto attraverso la miscelazione di


gradazioni dei tre colori primari: il rosso, il verde e il blu. Per i colori su cui si basa
viene detto modello RGB (da red, green, blue). Unendo il rosso e il verde si
ottengono i colori dal giallo allarancio, unendo il rosso e il blu si ottengono dal
porpora al viola. Se i colori primari sono sommati alla loro massima potenza
producono il bianco per questo motivo il modello di tipo additivo.
Il secondo modello detto invece CMY perch usa i colori ciano (Cyan),
magenta, giallo (Yellow). Esso si usa soprattutto nei processi di stampa su carta
perch si basa sulla capacit propria dellinchiostro di assorbire la luce. Quando la
luce bianca colpisce gli inchiostri, alcune lunghezze donda visibili vengono
assorbite, mentre altre vengono riflesse e quindi viste: per questo motivo il modello
di formazione del colore si dice sottrattivo. Anche se il nero pu essere derivato
direttamente dalla combinazione di ciano, magenta e giallo (ossia assorbendo tutti
e tre i colori base), nelle stampanti, per motivi pratici, si una anche linchiostro
nero (black) e il modello prende il nome di CMYK.
In entrambi i casi i bit associati ai pixel di una immagine esprimono la misura
de tre colori base. Nel caso di una profondit di 24 bit e codifica RGB, vengono
assegnati 8 bit per la percentuale di rosso, 8 bit per quella di verde e 8 per quella di
blu. Poich si utilizzano 3 byte per rappresentare ogni pixel, una immagine a colori
di 100x100 pixel avr bisogno di 100 x 100 x 3 byte = 30.000 byte per essere
rappresentata.
Per ridurre la dimensione della rappresentazione si pu utilizzare un sistema
di codifica dei colori mediante tavolozza di colori (detta anche palette o CLUT da
Color Look-Up Table). La palette una codifica dei colori, solitamente con
profondit di 8 bit per pixel, che consente di scegliere 256 colori diversi tra i
milioni di colori esistenti. Si basa sullipotesi che difficilmente in una immagine
sono presenti contemporaneamente 16 milioni di colori diversi. Consiste
nellutilizzare una tabella numerica in cui sono codificati solo i colori
effettivamente presenti nellimmagine: ciascun pixel sar codificato con un numero
limitato di bit (da 4 a 8) che identifica la posizione in tabella del colore da usare. I
colori della palette cambiano a seconda dellimmagine e dipendono dal suo
contenuto: la tavolozza contiene infatti solo il sottoinsieme dei colori
rappresentabili che compare nella foto. Possono essere anche modificati in
38 Capitolo primo

funzione dellutilizzo dellimmagine (stampa o visualizzazione). Se ad una


immagine si cambia la CLUT, cambiano ovviamente le sue sfumature di colore. In
tale codifica ogni immagine viene accompagnata dalla sua palette.

Figura 15 - Codifica mediante palette

Il formato di rappresentazione di immagini per punti detto bitmap o raster.


Esso usato per riprodurre fotografie, dipinti e tutte le immagini per le quali non
ha importanza lindividuazione degli elementi riprodotti. Nelle immagini bitmap
quindi il pixel con le sue caratteristiche lelemento di riferimento.
Il singolo pixel da solo detiene un contenuto informativo limitato, se viene
invece considerato in combinazione allinsieme di pixel adiacenti si possono
estrarre caratteristiche pi significative. Elaborare unimmagine significa
modificarne il contenuto allo scopo di evidenziare alcune caratteristiche.
Analizzare unimmagine significa invece studiarne il contenuto allo scopo di
inferire informazioni relative alla scena rappresentata.
I settori della Computer Vision e della Computer Graphics studiano algoritmi
che cercano di ricostruire dai tanti pixel di una immagine raster sia struttura che
significato degli oggetti presenti in una scena. Ad esempio gli algoritmi OCR
(optical character regognition) restituiscono il testo in formato digitale estraendolo
dalla fotografia raster di un foglio dattiloscritto acquisita tramite scanner.
I formati di rappresentazione pi diffusi sono:
Linformazione e le sue rappresentazioni 39

- il TIFF (Tagged Image File Format) che permette di gestire le immagini


in varie modalit: bianco e nero, scala di grigio, colori RGB, colori
CMYK. Il TIFF prevede un sistema di compressione chiamato LZW
(Lempel-Ziv-Welch) non distruttiva, che non elimina alcuna informazione
n degrada la qualit dellimmagine e che produce buone riduzioni della
quantit di bit della rappresentazione;
- il formato EPS (Encapsulated PostScript File) impiegato inizialmente per
i disegni vettoriali si poi diffuso come standard anche per le immagini
raster e deve la sua importanza al linguaggio PostScript;
- il JPEG (Joint Photographic Expert Group) nato con lo scopo di
standardizzare diversi formati per immagini con compressione di qualit.
La sua principale caratteristica quella di poter far scegliere il livello di
compressione e di modulare quindi il rapporto tra la qualit dellimmagine
e la quantit di bit; la compressione con perdita e si possono raggiungere
livelli di compressione alti (fino a 20:1 contro il 4:1 del GIF);
- il GIF (Graphics Interchange Format) trova largo uso in Internet per la
rappresentazione di elementi grafici come pulsanti, scritte, logo. Permette
inoltre di rendere lo sfondo degli oggetti trasparente per integrarli nelle
pagine del web. un formato con poca quantit di bit, in quanto riduce a
256 la gamma dei colori, utilizzando una codifica che si basa sulluso di
una palette;
- il PNG (Portable Network Graphics) stato inventato per sostituirsi a
GIF nella trasmissione di immagini sulla rete. Gestisce la trasparenza
dello sfondo. Non supporta lanimazione. Presenta un algoritmo di
compressione lossless migliore di quello del formato GIF;
- il BMP (Bitmap) che stato sviluppato per essere compatibile con tutte le
applicazioni del mondo Windows per immagini in b/n, in scala di grigi, in
scala di colore (RGB ma non in CMYK). Non prevede lapplicazione di
metodi di compressione per cui la quantit di bit resta consistente.
Quando le immagini hanno caratteristiche geometriche ben definite, come nel
disegno tecnico, possibile adottare una tecnica pi efficiente per codificare le
figure. Nel caso di progettazione architettonica, meccanica o elettronica, (CAD da
Computer Aided Design) il disegno da memorizzare pu essere facilmente
scomposto in elementi base come una linea o un arco di circonferenza e non
conveniente rappresentare limmagine in termini di pixel ma si procede
descrivendo gli elementi che compongono la figura in termini matematici.
Gli oggetti geometrici che compongono il disegno, quali punti, rette, linee,
curve, cerchi, ellissi, rettangoli, vengono rappresentati secondo formule
matematiche e parametri che li descrivono: ad esempio un punto tramite le
coordinate, la retta tramite la sua equazione, il rettangolo mediante le coordinate
dei quattro vertici; la circonferenza tramite le coordinate del vertice e la
dimensione del raggio. Tale tipo di rappresentazione si definisce vettoriale. In essa
presente tutta linformazione necessaria a riprodurre limmagine, a prescindere
dalle dimensioni del dispositivo di visualizzazione. Un grande vantaggio delle
immagini vettoriali rispetto a quelle raster risiede nella minor quantit di bit usata
per la loro rappresentazione e nella capacit di essere variate di dimensioni senza
subire alcuna distorsione.
40 Capitolo primo

Le immagini bitmap, invece, se ridimensionate rispetto alle dimensioni


originali di acquisizione, hanno la tendenza a perdere di risoluzione risultando
distorte o sfocate. Un ulteriore vantaggio della rappresentazione vettoriale risiede
nel fatto che tutti gli oggetti che compaiono nella figura mantengono la loro
identit in termini di caratteristiche descrittive per cui sono facilitate le operazioni
di modifica dellimmagine come solitamente accade nei settori della progettazione.
Ovviamente non adatta per rappresentare immagini composte da continue
variazioni di colore, quali ad esempio le fotografie.

Figura 16 Immagine vettoriale e raster

1.4.3. Immagini in movimento o video


Il problema della rappresentazione delle immagini in movimento (o video)
viene risolto allo stesso modo in cui il cinema o la televisione lo hanno affrontato:
sfruttando un limite della capacit percettiva dell'occhio umano. La retina
dellocchio umano ha la caratteristica di mantenere impressa unimmagine per
alcuni millisecondi prima che svanisca. Se si proietta una successione di immagini
a determinate velocit, locchio non si accorge che ci che vede una sequenza
discreta e percepisce il movimento come un continuo.

Figura 17 Video come sequenza di immagini

Un video una sequenza di immagini disposte in successione temporale, ossia


una dopo laltra. La sequenza continua di immagini della realt viene quindi
discretizzata ottenendo una serie di immagini (detti frame) che variano
velocemente, ma a intervalli stabiliti. Il frame-rate il numero di frame mostrati
per secondo (fps). Al cinema il frame-rate di 24 fps. Il sistema televisivo europeo
(PAL) ha un frame-rate di 25 fps mentre quello americano (NTSC) ne prevede 30
fps.
Linformazione e le sue rappresentazioni 41

Per digitalizzare limmagine in movimento necessario digitalizzare ogni


singolo frame con la tecnica vista per le bit-map. In questo modo la quantit di bit
usati per la rappresentazione dipende dalla risoluzione di ogni singola immagine,
dalla sua profondit di colore e dalla durata del video che fissa il numero di frame
complessivi. Ad esempio un minuto di trasmissione video con frame di 320x240
pixel e 256 colori richiede:
320 240 (pixel per frame) 25 (frame per sec) 1 (byte per pixel) 60 (secondi)
= 115 Mbyte/min
Un CD non conterebbe pi di 5 minuti di video. quindi necessario applicare
tecniche di compressione.
I CODEC (CODifica e la DECodifica) sono gli algoritmi (o le applicazioni
che li realizzano) utilizzati per comprimere ed espandere i video digitali in modo
da renderne pi efficiente la gestione e la trasmissione.
Lo standard MPEG (Moving Picture Experts Group), associa alla semplice
codifica di ciascuna immagine anche tecniche per il suono e, soprattutto, modalit
di compressione che sfruttano il fatto che la differenza tra un frame e il successivo
minima. Invece di conservare le informazioni di ogni frame, vengono conservate
solo quelle essenziali a ricostruire la scena originaria e quelle che si modificano,
tralasciando le variazioni impercettibili. Facendo riferimento allesempio di figura
14 nella codifica MPEG vengono codificati solo il primo frame e le differenze tra
ogni frame ed il successivo (zone delle immagine in cui si muove la pallina). E
cos immediato dato un frame ricostruire il successivo aggiungendo al precedente
le sole differenze.
MPEG-1 fu definito nel 1989 e rilasciato nel 1992. Questo sistema di
compressione del segnale audio-video, ideato per i CD-Rom e per la visione di
piccoli filmati su Internet, consente di vedere filmati televisivi con una qualit
paragonabile a quella di un videoregistratore. Tra il 1992 e il 1994 si afferma
MPEG-2, lo standard pensato per la trasmissione di contenuti multimediali sulla
televisione digitale via satellite e via cavo.
Oggi tutte le televisioni digitali degli Stati Uniti, buona parte di quelle
europee, ed i DVD si basano sullo standard MPEG-2. Nel 1998 viene approvato
MPEG-4 che rappresenta i frame a partire dagli oggetti di cui sono composti che
mantengono una loro individualit sia nella fase di codifica che in quella di
rappresentazione finale. Ad esempio, in un video composto da un paesaggio e da
un motociclista che si muove, non necessario ritrasmettere pi volte le
componenti invarianti del paesaggio, ma sufficiente trasmettere solo quelle che
cambiano legate agli spostamenti della moto e del suo guidatore.
Lorganizzazione ad oggetti l'aspetto innovativo di MPEG-4: qualsiasi
filmato pu essere arricchito di ulteriori oggetti quali immagini fisse, videoclip,
sorgenti audio, che vengono attivate grazie alla presenza di oggetti cliccabili e
navigabili come su Internet. Si interviene quindi sul video rendendolo interattivo.
Nel 2001 viene proposto MPEG-7 che pu essere definito uno standard di
descrizione piuttosto che di compressione. MPEG-7 non sostituisce le versioni
precedenti, ma le affianca consentendo di estrarre informazioni da tutti gli oggetti
audiovisivi esistenti per una indicizzazione e catalogazione sul modello di un
motore di ricerca.
42 Capitolo primo

1.4.4. La codifica del suono


Il suono un segnale analogico funzione del tempo consistente in vibrazioni
che formano unonda, la cui ampiezza misura laltezza dellonda e il periodo la
distanza tra due onde.
Anche il suono deve essere campionato e discretizzato per poter essere
digitalizzato. Se il campionamento troppo rado e vengono usati pochi bit per
misurare ogni valore istantaneo, la qualit del suono degrada nel senso che il suono
riprodotto diverso da quello originale. L'operazione di campionamento
discretizza il segnale con una frequenza dell'ordine delle decine di KHz (migliaia
di campioni al secondo) perch dimostrato che lorecchio umano percepisce
fedelmente il suono originale se il suo campionamento non inferiore a 30KHz.
Particolare circuiti elettronici ricostruiscono il segnale originale e Nyquist ha
dimostrato che per ottenere il segnale iniziale senza perdite necessario
campionare con una elevata frequenza di campionamento, pari ad almeno due volte
la frequenza massima del segnale stesso. La quantizzazione , diversamente da un
buon campionamento, un processo irreversibile che conduce ad una sicura perdita
di informazioni; tanto pi l'operazione accurata tanto pi la qualit del suono
preservata riducendo al minimo quello che viene detto rumore di quantizzazione.
La quantit di bit usati per rappresentare il suono dipende allora dal numero di bit
usato per la quantizzazione, chiamato anche profondit del suono, dalla frequenza
di campionamento e quindi dalla durata del suono.
Ad esempio per una linea telefonica sufficiente una frequenza di
campionamento di soli 8KHz con una quantizzazione a 256 livelli (codificati con 8
bit) per riprodurre la voce umana ai due estremi del collegamento garantendo la
comprensione del parlato. Nel caso di musica stereo la quantit di bit raddoppia
perch vanno separatamente digitalizzati i segnali per il lato destro e per quello
sinistro.

Tipo Frequenza di Profondit Mono/stereo Dimensione


campionamento (bit) per un minuto
(Hz)
Telefono 8.000 8 mono 469,00 Kb
Parlato 11.025 8 mono 646,00 Kb
Radio mono 22.050 16 mono 2,52 Mb
Radio stereo 22.050 16 stereo 5,05 Mb
Audio Cassetta 44.100 16 stereo 10,10 Mb
Compact Disk 48.000 16 stereo 11,00 MB
Tabella 19 Frequenze di campionamento per il suono

Da MPEG-1 ha avuto origine Mp3 (abbreviazione di MPEG-1 layer 3). Mp3


una codifica del segnale audio che consente la compressione di brani musicali della
durata di 3-6 minuti con pochi MB rendendone possibile la distribuzione nella rete
Internet.
Linformazione e le sue rappresentazioni 43

1.5. Dati e metadati


Nella realt di tutti i giorni molte attivit operano con informazioni di natura e
forma diverse (testo, video, audio) e si costruiscono sistemi che gestiscono e
elaborano informazioni.
Linformazione quindi un oggetto che ha un rapporto stretto con la realt
dalla quale pu emergere se e solo se un determinato insieme o classe di oggetti
assume stati o configurazioni differenti. In tale accezione linformazione non
altro che la scelta di una delle possibili configurazioni in cui si trova un esemplare
della classe di oggetti. Allora, il concetto di informazione strettamente legato a
quello di scelta di uno fra pi oggetti di un particolare insieme e non esiste
informazione se non si effettua una scelta. Ad esempio, la frase sto studiando
elementi di informatica, fornisce un'informazione in quanto esprime la scelta della
materia di studio e l'identificazione, quindi, della materia elementi di
informatica, tra tutte le possibili materie del piano di studio.
In informatica stato introdotto il termine dato che deriva dal latino datum e
significa letteralmente fatto. Mentre luomo tratta informazioni lelaboratore tratta
dati. Con dato si indica la rappresentazione di fatti e concetti in modo formale
perch sia possibile una loro elaborazione da parte di strumenti automatici. Il dato
da solo, senza un contesto, pu non avere significato: uno stesso numero pu
esprimere cose diverse in situazioni diverse; cos come una stessa parola pu avere
significato dipendente dal contesto.
Lambiguit pu essere risolta dando al dato una interpretazione. Linformazione
non altro che la percezione del dato attraverso un processo di interpretazione. In altre
parole linformazione cattura il significato del dato. Quando lelaborazione consente di
trattare dati eterogenei in modo integrato si parla di elaborazione multimediale.
Il termine metadato apparso abbastanza recentemente anche se indica
tipologie di informazioni diffuse da molto tempo. Nella vita reale i metadati
vengono impiegati principalmente per organizzare informazioni o cose, e,
ovviamente per effettuare ricerche tra informazioni o cose classificate, come
avviene nei cataloghi delle biblioteche dove ogni libro viene etichettato con una
scheda (riportante titolo, autore, anno di pubblicazione, casa editrice, argomenti
trattati, etc.) di cui si conosce luso.
I metadati indicano dati che descrivono altri dati riportandone struttura,
significato o descrizione. Possono essere distinti nella categorie di metadati
descrittivi finalizzati al recupero dei dati ed in metadati gestionali necessari alla
gestione dei dati. Anche lattributo di un dato un altro esempio di metadato in
quanto descrive il ruolo svolto da una variabile in un contesto applicativo. I
metadati sono solitamente pi facili da trattare dei dati che rappresentano perch
hanno un formato prestabilito mentre il formato dei dati dipende da molti fattori.
Un aspetto interessante dei metadati che anchessi sono dati e come tali
possono essere gestiti nel senso che possono essere descritti da altri metadati, e
cos via. Il numero di metalivelli da specificare dipende dalle caratteristiche delle
applicazioni e dalle specifiche esigenze.
Secondo le nuove proposte del web semantico il metadato linformazione
che da significato al dato rendendolo machine understandable, ossia
comprensibile alle macchine. Esso costituisce lo strumento principale del Web
44 Capitolo primo

Semantico in quanto permettono di introdurre la semantica per descrivere il


contenuto dei documenti web.
LeXensible Markup Language o XML oggi il linguaggio standard su cui si
innestato lo sviluppo del Web Semantico e la sua principale caratteristica consiste
nel fatto che permette di definire delle strutture dati indipendenti da qualsiasi
piattaforma e che possono essere elaborate in modo automatico. XML non un
linguaggio di programmazione ma un linguaggio di marcatura (markup) con una
sintassi semplice per rendere agevole sia la lettura diretta che la elaborazione
automatica
Capitolo secondo

Il modello di esecutore

2.1. Processi e processori


Linformatica ha avviato alla fine del ventesimo secolo una rivoluzione che ha
prodotto effetti analoghi a quelli osservati all'epoca della rivoluzione industriale.
Ma mentre la rivoluzione industriale ha segnato il potenziamento della forza fisica
dell'uomo (amplificazione dei suoi muscoli) la rivoluzione informatica ha portato
ad un aumento della potenza della mente dell'uomo (amplificazione del suo
cervello). Cos come le macchine meccaniche sostituiscono l'uomo in azioni
ripetitive o faticose, le macchine informatiche o computer sostituiscono l'uomo
nelle attivit ripetitive della sua mente.
Un computer un apparecchio elettronico che, strutturalmente, non ha niente
di diverso da un televisore, uno stereo, un telefono cellulare o una calcolatrice
elettronica, semplicemente progettato per eseguire autonomamente attivit
diverse sia nello stesso tempo, che in tempi diversi. Come tutte le macchine, non
ha nessuna capacit decisionale o discrezionale, ma si limita a compiere
determinate azioni secondo procedure prestabilite. Si pu anzi affermare,
paradossalmente, che il computer una macchina che in maniera automatica
esegue operazioni elementari ad altissima velocit. L'altissima velocit di
elaborazione (milioni di istruzioni per secondo) fa s che operazioni complesse
(espresse mediante un gran numero di operazioni semplici) siano eseguite in tempi
ragionevoli per l'ambiente esterno.
Come tutti gli esecutori di ordini anche il computer pu compiere solo quei
lavori che possono essere specificati mediante operazioni che in grado di
comprendere e mettere in pratica. Lalgoritmo la descrizione di un lavoro da
svolgere. Allora se si vuole usare un computer bisogna non solo progettare
preliminarmente un algoritmo, ma anche provvedere a comunicarglielo in modo
che gli risulti comprensibile.
L'esecuzione di un algoritmo da parte di un esecutore si traduce in una
successione di azioni che vengono effettuate nel tempo. Si definisce processo il
lavoro svolto eseguendo l'algoritmo, e processore il suo esecutore. Il processo non
altro che lelenco delle azioni effettivamente svolte come si susseguono nel
tempo. Ogni algoritmo evoca da uno a pi processi, nel senso che, a seconda delle
condizioni in cui il lavoro viene svolto, si possono verificare comportamenti
diversi da parte dellesecutore.
46 Capitolo secondo

Il computer un tipo speciale di processore che evolve in automatico


(funziona senza l'intervento umano), ha un'alta velocit elaborativa (se confrontata
con un esecutore uomo) ed capace di eseguire processi differenti.

2.2. Modello di Von Neumann


Per comprendere i motivi che rendono un computer diverso dalle altre macchine, si
introduce uno schema di riferimento nel quale sono messi in evidenza tre blocchi
fondamentali.

Figura 1 Modello di riferimento di Von Neumann

Lo schema presentato uno schema di principio ed rappresentativo delle


macchine tradizionali. Prende il nome da Von Neumann, il primo ricercatore che
lo propose nel 1945.
La Central Processing Unit (CPU) coordina lesecuzione delle operazioni
fondamentali; la memoria contiene l'algoritmo che descrive le operazioni da
eseguire e i dati su cui l'algoritmo stesso opera; i dispositivi di input e output sono
le interfacce della CPU nei confronti del mondo esterno, rispettivamente sono
lunit che consente l'inserimento di algoritmo e dati in memoria, e quella che
presenta i risultati dell'attivit della CPU.
Queste unit fondamentali formano l'hardware del computer, ossia l'insieme
di tutti i componenti elettronici, elettrici e meccanici che costituiscono un sistema
elaboratore.
Il prototipo proposto da Von Neumann era basato sul concetto di programma
memorizzato: la macchina immagazzinava nella propria memoria i dati su cui
lavorare e le istruzioni per il suo funzionamento. Una tale flessibilit operativa fece
s che macchine nate allo scopo di alleviare i problemi di calcolo per tecnici e
scienziati, potessero essere in seguito impiegate nella risoluzione di problemi di
natura completamente diversa come problemi di tipo amministrativo, gestionale e
produttivo.
Le caratteristiche che un sistema di tale tipo presenta, e che ne hanno
decretato la rapida diffusione in molti campi applicativi, sono:
- uno schema di funzionamento semplice nelle sue linee generali,
Il modello di esecutore 47

- la velocit e l'affidabilit nella esecuzione degli algoritmi;


- una adeguata capacit di memoria;
- un costo vantaggioso.
La velocit di esecuzione si aggira attualmente sui milioni di istruzioni svolte
dalla CPU in un secondo e per tale motivo come unit di misura della capacit
elaborativa dei computer stato usato il MIPS (milioni di istruzioni per secondo).
Vale la pena osservare che, nonostante la velocit dei computer tenda ad
aumentare, esistono problemi che presentano soluzioni informatiche non pratiche
poich il loro tempo di esecuzione resta comunque lungo.
Dal punto di vista dellaffidabilit si pu affermare che un computer non
commette errori e gli errori dovuti a guasti o a cattivi funzionamenti hardware sono
subito riscontrabili, alcune volte persino in maniera automatica. Inoltre un
computer non commette mai errori di algoritmo poich un esecutore obbediente
dell'algoritmo, la cui esecuzione gli stata affidata.
Per memorizzazione delle informazioni si intende il compito della memoria di
conservare informazioni per la CPU. La memorizzazione pu essere temporanea,
permanente o definitiva. Con capacit di memoria si fa riferimento al numero di
informazioni che possono essere gestite. Tale numero varia in base al tipo di
memoria usato, all'architettura della memoria stessa ed al tipo di informazione. La
capacit la misura del numero di informazioni immagazzinabili nella memoria ed
oggi si misura in numero di byte.
Per quanto riguarda il costo dei computer si pu sicuramente considerare che
esso basso se paragonato ai tempi di lavoro necessari affinch esseri umani
portino a termine gli stessi compiti. Ed anche in conseguenza di ci che i
computer vanno sempre pi diffondendosi nei settori produttivi della societ.
Larchitettura di un computer nella realt molto pi complessa. Nelle linee
generali per il funzionamento interno di un qualsiasi computer si pu ricondurre
al semplice schema presentato che non molto dissimile da uno antropomorfo che
vede un essere umano sostituire con il suo cervello la CPU, fogli di carta alla
memoria centrale, una calcolatrice con le operazioni fondamentali all'ALU
(Aritmetic Logic Unit), ovvero il componente della CPU che effettua tutte le
operazioni di calcolo logico e aritmetico.
Per concludere si deve notare che i dispositivi di input e di output
interfacciano la CPU con l'ambiente esterno provvedendo a tutte le trasformazioni
necessarie a rendere comprensibili le informazioni sia alla CPU che agli utenti
esterni del computer. Essi vengono progettati in modo confacente ai meccanismi di
comunicazione delle informazioni dell'ambiente in cui il computer immerso.
Nella maggior parte delle applicazioni pratiche l'uomo l'utente del computer,
ma esistono applicazioni nelle quali il computer scambia informazioni con
macchinari o sonde che rappresentano le informazioni sotto forma di segnali
elettrici. Nelle comunicazioni con un utente umano i dispositivi di input ed output
provvedono alla trasformazione della rappresentazione delle informazioni dal
linguaggio naturale al linguaggio binario e viceversa. In tali casi il tipico organo di
input la tastiera mentre quello di output uno speciale televisore detto monitor o
video. La tastiera fatta pertanto da tasti sui quali sono riportati lettere, cifre e
simboli speciali: mediante la pressione dei tasti si inviano le informazioni in
memoria. Il video o monitor riporta i risultati distribuendoli su un numero di righe
limitate in modo che possano essere letti agevolmente. Si ricordano inoltre il
48 Capitolo secondo

mouse, la penna ottica, la tavoletta grafica e lo scanner come altri esempi di


dispositivi di input; mentre tra quelli di output il plotter e le stampanti ad aghi, a
getto dinchiostro o laser per riportare i risultati su foglio di carta.
2.2.1. Le memorie
In generale le memorie possono essere viste come un insieme di contenitori fisici,
detti anche registri, di dimensioni finite e fissate a cui si pu far riferimento
mediante la posizione occupata nell'insieme detta indirizzo di memoria. La
dimensione di un registro si misura in numero di bit. Il bit un dispositivo capace
di assumere due sole condizioni:
- nelle memorie di tipo elettronico sono circuiti detti flip-flop che mostrano
un valore di tensione o uguale a 5 Volt o a 0 Volt;
- nelle memorie di tipo magnetico una sorta di calamita polarizzata o
positivamente o negativamente;
- nelle memorie di tipo ottico una superficie con o senza un buco in modo
da riflettere diversamente il raggio laser che la colpisce.
In ogni caso il dispositivo di lettura deve essere in grado di associare allo stato
del bit il valore 1 (ad esempio tensione a 5 volt, polo positivo, assenza di buco) o il
valore 0 (tensione a 0 volt, polo negativo, presenza di buco).
Memorie con registri di otto bit sono dette a byte o caratteri; con pi di otto
(solitamente 16 o 32) vengono invece dette a voce. I calcolatori moderni sono
dotati di memorie a byte e le memorie a voce sono solo un ricordo del passato.
Le operazioni consentite su un registro sono di lettura e di scrittura. Con la
prima si preleva l'informazione contenuta nel registro senza per distruggerla; con
la seconda si inserisce una informazione nel registro eliminando quella precedente.
Per comprendere il funzionamento di un registro di memoria si pu pensare ad una
lavagna il cui uso pu essere cos esemplificato:
- leggere informazioni a patto che vi siano state scritte;
- la lettura non cancella quanto scritto;
- la scrittura di nuove informazioni obbliga a cancellare quelle precedenti
che pertanto vengono perse.
La memoria un sistema che assolve al compito di conservare il dato,
depositandolo in un registro nel caso di operazione di scrittura, e di fornire il dato
conservato in un registro, in caso contrario di operazione di lettura. Le due
operazioni vengono anche dette di store (per la scrittura del dato) e di load (per la
lettura). Il funzionamento della memoria in linea del tutto generale alquanto
semplice. La CPU indica preventivamente lindirizzo del registro interessato
dalloperazione; la memoria decodifica tale indirizzo abilitando solo il registro ad
esso corrispondente affinch:
- per uno store copi il dato del buffer nel registro;
- per un load copi il dato del registro nel buffer.
dove il buffer pu essere vista come unarea di transito dei dati dalla CPU alla
memoria e viceversa.
Le operazioni di load e store richiedono tempi di attuazione che dipendono
dalle tecnologie usate per la costruzione delle memorie e dalle modalit di accesso.
Le prestazioni di un componente di memoria vengono misurate in termini di tempi
di accesso. Le operazioni di load e store possono avere tempi di accesso differenti.
Il modello di esecutore 49

Nel caso di load, il tempo di accesso misura il tempo che trascorre tra la
selezione del registro di memoria e la disponibilit del suo contenuto nel registro di
buffer. Il tempo di accesso nel caso dello store misura invece il tempo necessario
alla selezione del registro e il deposito del contenuto del registro di buffer in esso.
Le memorie devono mostrare tempi di accesso adeguati alle capacit della CPU,
nel senso che non devono introdurre ritardi quando essa trasferisce dati. Per tale
motivo gli sforzi tecnologici sono rivolti alla costruzione di memorie con tempi di
accesso bassi anche se tale parametro contrasta con quello del costo degli stessi
componenti.

Figura 2 Schema di funzionamento per le operazioni di load e store

La selezione di un registro viene detta:


- casuale quando il tempo di accesso non dipende dalla posizione: memorie
di questo tipo vengono dette RAM (Random Access Memory);
- sequenziale quando invece il tempo di accesso dipende dalla posizione
come avviene nei nastri magnetici.
Alcune memorie vengono realizzate in modo che sia possibile una sola
scrittura di informazioni. Tali memorie vengono dette a sola lettura o ROM (da
Read Only Memory). L'uso di queste memorie necessario quando si desidera che
alcune istruzioni o dati non siano mai alterati o persi. Le memorie composte da
registri sui quali sono consentite le operazioni di lettura e scrittura vengono anche
dette RAM per contrapposizione alle memorie ROM, anche se il termine non
molto appropriato.
Infine si soliti distinguere le memorie in base alla capacit di conservare le
informazioni, anche quando i sistemi che le contengono non sono alimentati. Si
dicono volatili le memorie che perdono le informazioni in esse registrate quando il
50 Capitolo secondo

sistema viene spento; sono, di contro, permanenti gli altri tipi di memorie. Sono
volatili le memorie elettroniche; sono invece permanenti le memorie di tipo
magnetico, ottico e tutti i tipi di ROM.
Lo schema iniziale di Von Neumann stato nel tempo modificato per
affiancare alla memoria centrale delle unit di memoria ausiliarie caratterizzate da
una elevata capacit, dette per questo motivo memorie di massa.

Figura 3 Modello di Von Neumann modificato

La differenza fondamentale fra la memoria centrale e quella di massa, dal


punto di vista funzionale, risiede nel fatto che:
- le informazioni contenute nella memoria centrale possono essere
direttamente prelevate dalla CPU, mentre quelle contenute nella memoria
di massa devono essere dapprima trasferite nella memoria centrale e
successivamente elaborate;
- le informazioni prodotte dalla CPU, viceversa, devono essere depositate
in memoria centrale per poi essere conservate nelle memorie di massa.
Il modello di esecutore 51

Figura 4 Trasferimento di informazioni tra memorie

Unaltra differenza tra la memoria centrale e quella di massa la maggiore


velocit della prima nella gestione dei dati.
Le memorie di massa hanno tempi di accesso maggiori dovuti alle tecnologie
impiegate per realizzarle. Solitamente queste ultime sono di natura magnetica e i
maggiori tempi di accesso si giustificano pensando alle diverse attivazioni di
componenti elettromeccanici necessari a portare i dispositivi di lettura e scrittura
nelle posizioni selezionate. Per ovviare alla differenza di velocit tra i due
dispositivi si impiegano tecniche che prevedono che la memoria centrale non solo
contenga dati e istruzioni ma anche aree di accumulo dei dati in transito verso tutti
i dispositivi esterni. Tali aree vengono dette, come gi anticipato buffer.
Un buffer di input ha quindi il compito di accumulare dati in memoria
ricevendoli da un dispositivo lento prima che la CPU provveda ad elaborarli. Cos
la CPU, solitamente molto pi veloce nelle sue elaborazioni di qualsiasi dispositivo
di output, accumula tutti i dati prodotti in un buffer di uscita prima di abilitarne il
trasferimento. Con i buffer si procede verso una separazione dei compiti tra i
componenti del modello di Von Neumann nellottica di far cooperare dispositivi
caratterizzati da velocit di trattamento dati diverse tra loro. I buffer non sono altro
che magazzini di dati e svolgono le stesse funzioni dei magazzini di una fabbrica,
che regolano i tempi diversi di produzione dei beni da quelli relativi alla loro
vendita: quando la produzione pi veloce la merce si accumula dando tempo ai
venditori di procedere con i loro tempi pi lunghi.
Solitamente le memorie di massa sono di tipo magnetico (nastri, dischi e
tamburi) o ottico (CD, DVD) in modo da mantenere le informazioni in modo
permanente, a differenza delle RAM di tipo elettronico che sono volatili. Le
capacit delle memorie centrali, inoltre, si aggirano sui milioni di informazioni
mentre quelle delle memorie di massa sono dell'ordine delle centinaia o milioni di
milioni.
2.2.2. La CPU
La CPU contiene i dispositivi elettronici in grado di acquisire, interpretare ed
eseguire il programma contenuto nella memoria centrale operando la
trasformazione dei dati. Il processore centrale composto da tre parti
fondamentali: l'Unit di Controllo o Control Unit (CU), l'Unit Logico Aritmetica
(ALU) e un insieme di registri detti interni per distinguerli da quelli della
memoria centrale.
52 Capitolo secondo

Figura 5 Schema interno di una CPU

L'unit di controllo della CPU l'organo preposto all'interpretazione delle


singole istruzioni ed allattivazione di tutti i meccanismi necessari al loro
espletamento. In particolare la CU ha il compito di prelevare ogni istruzione dalla
memoria centrale, di decodificarla, di prelevare i dati dalla memoria se servono
allistruzione, e infine di eseguire listruzione. Per esempio: se l'istruzione
prelevata di tipo aritmetico e richiede due operandi, la CU predispone dapprima il
prelievo dalla memoria di tali operandi, attiva poi l'ALU perch esegua
l'operazione desiderata, ed infine deposita il risultato di nuovo in memoria. Al
termine dell'esecuzione di una istruzione la CU procede al prelievo dalla memoria
della successiva istruzione secondo un ordine rigidamente sequenziale: ossia
lesecuzione di una istruzione pu avere inizio solo se la precedente stata portata
a termine.
Perch lintero sistema possa avere avvio la CU deve essere informata
dell'indirizzo del registro di memoria che contiene la prima istruzione da eseguire.
A partire da questa operazione iniziale detta di boot la CU esegue ininterrottamente
lalgoritmo detto ciclo del processore fino allo spegnimento del sistema.
Le tre fasi del ciclo vengono anche dette fase fetch, operand assembly ed
execute.
Lunit logico aritmetica esegue operazioni aritmetiche, di confronto o bitwise
sui dati della memoria centrale o dei registri interni. Lesito dei suoi calcoli viene
segnalato da appositi bit in un registro chiamato Condition Code. A seconda dei
processori lALU pu essere molto complessa. Nei sistemi attuali lALU viene
affiancata da processori dedicati alle operazioni sui numeri in virgola mobile detti
processori matematici.
Il modello di esecutore 53

Figura 6 Ciclo del Processore

Durante le sue elaborazioni la CU pu depositare informazioni nei suoi


registri interni in quanto sono pi facilmente individuabili e hanno tempi di accesso
inferiori a quelli dei registri della memoria centrale. Il numero e tipo di tali registri
varia a seconda dellarchitettura della CPU.
Quelli che si trovano in molte CPU sono l'Istruction Register (IR), il Prossima
Istruzione (PI), l'Accumulatore (ACC) e il Condition Code (CC).
Il primo contiene l'istruzione prelevata dalla memoria e che l'unit di controllo
sta eseguendo. Il PI invece ricorda alla CU la posizione in memoria della
successiva istruzione da eseguire. Nei casi in cui ogni registro di memoria
contenga unintera istruzione, e l'insieme delle istruzioni del programma sia
disposto ad indirizzi consecutivi, la CU incrementa di uno il valore contenuto in PI
dopo ogni prelievo di una istruzione dalla memoria. L'ACC serve come deposito di
dati da parte dell'ALU nel senso che contiene prima di unoperazione uno degli
operandi, e al termine della stessa operazione il risultato calcolato. In questo caso i
registri Op1 e Op2 diventano interni allALU. Il CC indica le condizioni che si
verificano durante l'elaborazione, quali risultato nullo, negativo e overflow.
2.2.3. I bus
La CPU comunica con la memoria e tutti i dispositivi di input ed output tramite tre
canali detti anche bus. I bus collegano due unit alla volta abilitandone una alla
trasmissione e laltra alla ricezione: il trasferimento di informazioni avviene sotto il
controllo della CPU.
Il termine bus indica un canale di comunicazione condiviso da pi utilizzatori.
Esso fisicamente costituito da uno o pi fili su cui possono transitare uno o pi
bit contemporaneamente. A seconda delle informazioni trasportate si distinguono
in:
- bus dati (data bus)
54 Capitolo secondo

- bus indirizzi (address bus)


- bus comandi o di controllo (command o control bus)

Figura 7 I bus

Il control bus serve alla C.U. per indicare ai dispositivi cosa essi devono fare.
Tipici segnali del control bus sono quelli di read e write mediante i quali la CU
indica ai dispositivi se devono leggere un dato dal data bus (read) o scriverlo su di
esso (write).

Figura 8 Control Bus

Il data bus permette ai dati di fluire da CPU a registro di memoria selezionato


per operazioni di store e viceversa per quelle di load. La CU controlla anche il
flusso di informazioni con il mondo esterno abilitando il transito delle informazioni
dalla memoria verso le risorse di output e viceversa da quelle di input.
Nello schema le memorie di massa sono rappresentate in un blocco a parte
solo per la loro importanza come memoria permanente del sistema, anche se il loro
funzionamento quello di un dispositivo che opera sia in input che in output.
Laddress bus serve alla CU per comunicare l'indirizzo del dispositivo interessato
da una operazione di lettura o scrittura. In questa ottica anche i dispositivi di input
Il modello di esecutore 55

od uno di output sono identificati da un indirizzo alla stessa stregua dei registri di
memoria.
Tutti i componenti del sistema (memoria, input, output, memoria di massa,
etc.) devono essere dotati della capacit di riconoscere sulladdress bus il proprio
indirizzo. In altri termini attraverso laddress bus la CU effettua la selezione del
dispositivo a cui sono rivolti i comandi e i dati.
I bus realizzano lo scambio di informazioni tra tutti i componenti
caratterizzato dalle seguenti regole:
- la CPU lunico elemento che fornisce lindirizzo alladdress bus;
- memorie e dispositivi di input ed output devono ascoltare laddress bus
per attivarsi quando su di esso compare il proprio indirizzo identificativo;
nel caso della memoria lattivazione avviene quando viene riconosciuto
lindirizzo corrispondente ad uno dei registri di cui essa composta;
- il dispositivo attivo deve interpretare i segnali del control bus per eseguire
i comandi della CU;
- le memorie prelevano dati dal data bus o immettono dati in esso in
funzione del comando impartito dalla CU;
- i dispositivi di input possono solo immettere dati sul data bus;
- viceversa i dispositivi di output possono solo prelevare dati dal data bus.
Un bus costituito da un solo filo chiamato bus seriale e su di esso i bit
transitano uno dietro laltro. Un bus costituito da n fili chiamato bus parallelo
perch su di esso transitano n bit alla volta. Tipici sono i bus a 8 e 32 fili sui quali
si possono trasferire rispettivamente 8 e 32 bit (4 Byte) alla volta.
Laddress e il data bus sono paralleli e le loro dimensioni caratterizzano i
sistemi di calcolo. Il numero di bit delladdress bus indica la capacit di
indirizzamento della CPU: ossia la sua capacit di gestire la dimensione della
memoria centrale e il numero di dispositivi di input ed output. Infatti un address
bus con n bit consente di selezionare un registro tra 2n. La dimensione del data bus
condiziona invece la velocit di scambio delle informazioni tra i diversi dispositivi
in quanto con m fili solo m bit possono viaggiare contemporaneamente.
2.2.4. Il clock
I componenti del modello di Von Neumann vengono coordinati dalla CU della
CPU secondo sequenze prestabilite che corrispondono alle sue diverse capacit. Ad
ogni operazioni che la CU in grado di svolgere corrispondono ben prefissate
sequenze di attivazione dei diversi dispositivi. Le attivit di tutti i dispositivi non si
svolgono per casualmente ma vengono sincronizzate tra loro mediante un
orologio interno chiamato clock che scandisce i ritmi di lavoro.
Il clock un segnale periodico di periodo fisso, unonda quadra caratterizzata
da un periodo T (detto ciclo) e da una frequenza f (f=1/T) misurata in Hertz (Hz).
Ad esempio un clock composto da 10 cicli al secondo ha la frequenza f = 10 Hz e il
periodo T= 100ms. La frequenza dei clock presenti nei moderni sistemi spazia dai
MHz (1 MHz corrisponde a un milione di battiti al secondo) ai GHz (1 GHz
corrisponde a un miliardo di battiti al secondo).
Il clock un segnale che raggiunge tutti i dispositivi per fornire la cadenza
temporale per lesecuzione delle operazioni elementari.
56 Capitolo secondo

Figura 9 Clock

La velocit di elaborazione di una CPU dipende dalla frequenza del suo clock
come il suono prodotto da un musicista dipende dal metronomo: pi accelerato il
battito del clock maggiore la velocit di esecuzione.
Alla frequenza del clock legato il numero di operazioni elementari che
vengono eseguite nellunit di tempo dalla CU. Ad esempio, se si assume che ad
ogni ciclo di clock corrisponde esattamente lesecuzione di una sola operazione,
allora la frequenza del clock indica il numero di operazioni che vengono eseguite
nellunit di tempo dalla CU. Per esempio con un clock a 3 GHz si ha che il
processore in grado di eseguire 3 miliardi di operazioni al secondo.
In realt tale ipotesi non sempre vera in quanto lesecuzione di una
operazione pu richiedere pi cicli di clock sia per la complessit delle operazioni
che per la lentezza dei dispositivi collegati alla CPU.
Per comprendere limportanza del clock si osservi il trasferimento di dati e
istruzioni tra CPU e Memoria Centrale riportato in una forma semplificata in figura
10.

Figura 10 Trasferimento dati tra CPU e Memoria


Il modello di esecutore 57

Entrambe le operazioni di load e store avvengono sotto lo stretto controllo


della CU. Nel primo caso la CU procede eseguendo nellordine:
- con il primo battito di clock ponendo lindirizzo del registro di memoria
di cui vuole leggere il contenuto sulladdress bus;
- con il secondo battito segnalando alla memoria che si tratta di una
operazione di read;
- con il terzo battito prendendo il dato dal data bus dove la memoria ha
provveduto a depositarlo.
Nel caso di una operazione di store la CU provvede:
- con il primo battito di clock a porre lindirizzo del registro di memoria di
cui vuole leggere il contenuto sulladdress bus;
- con il secondo battito a depositare il dato sul data bus;
- con il terzo battito a segnalare alla memoria che si tratta di una operazione
di write e quindi che il dato pronto per essere depositato nel registro
selezionato.
Nellesempio si fatta lipotesi che la memoria sia in grado di gestire sia
linserimento del dato sul data bus che il prelievo del dato da esso in un solo ciclo
di clock. Nella realt le memorie possono essere pi lente introducendo ritardi che
portano la stessa operazione a completarsi con un maggior numero di clock. La
memoria centrale infatti realizzata mediante moduli che hanno prestazioni
decisamente inferiori rispetto alla tecnologia utilizzata per costruire le CPU; per
questo motivo si realizzano dei bus che rallentano la trasmissione di un fattore 10
rispetto al clock.

2.3. Firmware, software e middleware


Lo scopo del modello di Von Neumann quello di eseguire i comandi memorizzati
nella sua memoria centrale. I comandi prendono anche il nome di istruzioni non
solo perch istruiscono la CPU sul da farsi ma anche per effettuare una distinzione
con i dati che sono gli oggetti rappresentati in memoria centrale su cui si svolgono
le attivit. Linsieme delle istruzioni prende il nome di programma. Tutti i
programmi sono quindi formati da insiemi di istruzioni che la CU della CPU
esegue mediante il coordinamento di tutti i componenti del modello di Von
Neumann.
Le istruzioni sono operazioni semplici quali:
- trasferimento dati da un registro ad un altro (da memoria a memoria, da
memoria a registri della CPU o viceversa, da memoria a output, da input a
memoria);
- operazioni aritmetiche o logiche eseguite dallALU;
- controllo di condizioni riportate dal registro CC o deducibili dal confronto
di due registri.
La CU un automa che ripete senza sosta il prelievo di una istruzione dalla
memoria e la sua interpretazione con relativa esecuzione. Lesecuzione di una
istruzione da parte della CU consiste nellinoltro di una sequenza di abilitazioni dei
dispositivi il cui effetto corrisponde alla operazione richiesta. Le prime CU erano
realizzate con circuiti, detti a logica cablata, che evolvevano in tanti modi diversi
quante erano le istruzioni che essa era in grado di svolgere.
58 Capitolo secondo

Figura 11 CU a logica cablata

Le moderne UC sono invece realizzate in logica microprogrammata. Ad ogni


istruzione corrisponde una sequenza di microistruzioni conservate in una memoria
interna alla CU. La sequenza di microistruzioni ha il compito di generare le
abilitazioni necessarie alla attuazione della istruzione. A tal fine un circuito interno
alla UC provvede alla generazione di indirizzi per individuare una dopo laltra le
microistruzioni che un decodificatore trasforma in segnali di abilitazione.
Listruzione nel registro IR determina la posizione della prima microistruzione.

Figura 12 CU a logica micorprogrammata

In effetti si ripropone in piccolo il modello di Von Neumann per la


realizzazione del suo componente principale. Linsieme dei microprogrammi
composti dalle microistruzioni memorizzate nella memoria interna alla CU prende
il nome di firmware.
Lesecuzione di un qualsiasi programma si traduce nel far applicare la CPU su
un compito specifico interagendo con il mondo esterno tramite i dispositivi di input
ed output. Tipiche applicazioni dei computer sono lelaborazione di documenti, la
ricerca di informazioni in Internet, il foglio elettronico, la gestione della segreteria
studenti di una universit, il sistema operativo a finestre. Linsieme di tutte le
applicazioni del computer, quindi di tutti i programmi per computer, prende il
nome di software. In una accezione pi ampia il termine software pu essere inteso
Il modello di esecutore 59

come tutto quanto pu essere preteso dallhardware: basta infatti inserire in


memoria un programma diverso perch il sistema cambi le sue attivit. Tra tutte le
macchine automatiche il computer un sistema polifunzionale in quanto pu
eseguire infinite funzioni sempre che venga progettato un programma per ogni
applicazione.

Figura 12 Hardware, Firmware e Software


Nel variegato ed immenso mondo di applicazioni dei computer si soliti fare
una distinzione tra i programmi che servono a tutti gli utenti del sistema da quelli
che risolvono problemi specifici. I primi vengono classificati come software di
base e riguardano i sistemi operativi e i traduttori dei linguaggi di
programmazione. I programmi che non rientrano in tale categoria vengono detti del
software applicativo.

Figura 13 Software di base ed applicativo

Tra le applicazioni del software di base pi importanti si trova il sistema


operativo. Senza di essa gli elaboratori non mostrerebbero quella semplicit di uso
che ne sta caratterizzando la diffusione estesa nella societ. Il sistema operativo
un insieme di programmi che deve garantire la gestione delle risorse hardware in
modo semplice ed efficiente a tutti gli utenti del sistema, siano essi persone che
interagiscono tramite tastiera e monitor che altre applicazioni. I primi calcolatori
non avevano il sistema operativo. In essi il programmatore doveva prevedere tutto:
dai calcoli alla gestione dei dispositivi di input ed output; doveva anche provvedere
al caricamento del programma in memoria prima di attivare la CPU perch lo
60 Capitolo secondo

eseguisse. Al termine dellesecuzione del programma il programmatore o


loperatore del sistema doveva provvedere ad un nuovo caricamento in memoria ed
ad una successiva attivazione. Con il sistema operativo il passaggio da una
applicazione ad unaltra svolto in automatico mediante linterpretazione di
comandi che lutente inserisce da tastiera. La CPU si trova cos ad eseguire i
programmi del sistema operativo in alternanza con quelli applicativi.

Figura 14 Schema di funzionamento di un Sistema Operativo


I programmi del sistema operativo vengono eseguiti allavvio del sistema,
quando termina unapplicazione o quando una applicazione ha bisogno di gestire
una risorsa hardware.
Altre applicazioni del software di base stanno sempre pi assumendo un
rilievo particolare, soprattutto in relazione al funzionamento di pi sistemi tra loro
interconnessi attraverso canali di comunicazione di cui Internet il pi importante
esempio. Per far s che i sistemi possano mostrarsi uguali tra loro si sovrappone al
sistema operativo uno strato software chiamato middleware che ha il compito di
interagire con lapplicazione utente. Il middleware il software che fornisce
unastrazione di programmazione che maschera leterogeneit degli elementi
sottostanti (reti, hardware, sistemi operativi, linguaggi di programmazione) e la
loro distribuzione tra i diversi nodi della rete. Il middleware definisce una
macchina generalizzata fissandone modalit di interazione con le applicazioni.

Figura 15 Middleware
Il modello di esecutore 61

2.4. Evoluzione del modello di Von Neumann


Nel tempo sono state apportate modifiche al modello di Von Neumann con lo
scopo di rendere il suo funzionamento pi veloce. Il primo intervento ha riguardato
la struttura dei dispositivi di input ed output. Nei primi sistemi di calcolo la CPU
controllava tutti i componenti del sistema, anche quelli interni ai dispositivi
periferici. Inoltre, data la natura rigidamente sequenziale del modello di Von
Neumann, non era possibile sovrapporre i tempi delle operazioni di input con
quelli delloutput. Per ovviare a tali limitazioni, sono stati realizzati sistemi
dedicati il cui compito scaricare la CPU della gestione di attivit specifiche. I
sistemi dedicati, detti anche canali, con la loro autonomia possono lavorare anche
contemporaneamente con la CPU. I primi canali introdotti sono stati quelli di input
ed output. Oggi esistono in un elaboratore processori dedicati alla grafica, alle
operazioni sui numeri reali, alla acquisizione di segnali analogici.
Da soli i canali non possono per garantire la piena autonomia di
funzionamento. Per rendere indipendenti i processori dedicati stato introdotto
nellarchitettura hardware un segnale detto delle interruzioni mediante il quale una
qualsiasi entit esterna alla CPU pu richiederle attenzione.

Figura 16 - Interruzioni

Con la presenza del segnale di interruzione la CPU pu attivare un processore


periferico e disinteressarsi delle sue attivit. Quando un processore dedicato
termina il suo compito, avanza una richiesta di interruzione al processore centrale e
aspetta che gli venga rivolta attenzione. Mentre i processori periferici lavorano, la
CPU pu lavorare anchessa a meno che non sia indispensabile quanto richiesto
allo specifico processore: in questo caso la CPU aspetta che il processore concluda
quanto richiesto. Solitamente le attivit svolte dai processori dedicati sono lente,
per cui la CPU pu svolgere attivit diverse dando limpressione allutente esterno
di farle contemporaneamente. Le richieste di interruzione sono diverse, tante quanti
sono i processori dedicati, e si verificano in momenti diversi ed in modo non
sincrono con il lavoro della CPU. Per consentire alla CU di accorgersi del
verificarsi di una interruzione il registro di condizione CC stato dotato di un bit
che diventa uguale ad uno quando arriva una interruzione. La CU controlla il bit al
termine delle esecuzione di ogni istruzione: se uguale zero procede normalmente
con il prelievo dellistruzione successiva; in caso contrario comincia lesecuzione
di un programma del sistema operativo, detto ISR (interrupt service routine) che ha
come compito primario di capire la causa della interruzione, ossia quale dispositivo
ha avanzato la richiesta. Nel caso si accorga della presenza di pi richieste
62 Capitolo secondo

stabilisce quale servire per prima secondo criteri di importanza o priorit di


intervento.

Figura 17 Modifica del ciclo del processore


Con i canali e il sistema delle interruzione si introdotto una prima forma di
parallelismo nello svolgere le diverse attivit richieste da un programma. Ad
esempio la CPU dopo aver attivato il canale di output affinch stampi una
sequenza di dati, pu attivare il canale di input perch prelevi da tastiera un
insieme di dati. Nellattesa che i due canali segnalino di aver terminato, la CPU
pu procedere in parallelo eseguendo altre operazioni. La gestione dei canali
svolta dai programmi del sistema operativo, come del resto la gestione di tutti i
componenti del modello di Von Neumann, memoria compresa.
Anche alla memoria centrale sono stati apportati cambiamenti per evitare che
la CPU si dovesse adeguare ai tempi pi lenti di gestione dei dati da essa garantiti.
Si fino ad oggi verificato che componenti di memoria veloci avessero costi che
ne impedivano una significativa presenza allinterno dei sistemi. Per tale motivo,
per ridurre i tempi di trasferimento dalla memoria centrale ai registri interni della
CPU, viene replicata una porzione di memoria e posta tra memoria e CPU stessa.
Tale memoria, molto veloce, viene chiamata cache e fa da buffer per il prelievo di
informazioni dalla memoria centrale. Con operazioni particolari istruzioni e dati
vengono trasferiti dalla memoria centrale nella cache secondo la capacit di
questultima. La CU procede nelle tre fasi del suo ciclo al prelievo di istruzioni e
operandi dalla cache. Quando la CU si accorge che il prelievo non pu avvenire
scatta un nuovo travaso dalla memoria centrale. Poich la cache molto pi veloce
della memoria centrale il sistema ne guadagna complessivamente in efficienza.
Dato lelevato costo dei componenti con i quali si realizzano le cache, si
soliti riscontrare processori con 256k byte o 512 k byte di memoria cache. Solo
sistemi che devono garantire elevate prestazioni in applicazioni critiche presentano
cache da 1Mbyte ed oltre. Se la cache interna alla CPU viene detta di primo
livello (L1); le cache di secondo livello (L2) sono invece esterne e solitamente un
p pi lente di quelle di primo livello ma sempre pi veloci della memoria centrale.
Infatti la cache L2 risulta 4 o 5 volte pi lenta della cache L1 mentre la RAM lo
addirittura 20 o 30 volte. I due livelli possono coesistere.
La memoria viene cos ad essere strutturata in maniera gerarchica. La
gerarchia consente di offrire ai programmi lillusione di avere una memoria grande
Il modello di esecutore 63

e veloce. Nella gerarchia i livelli pi prossimi alla CPU sono anche quelli pi
veloci. Ma sono anche quelli con dimensioni pi piccole visto il loro elevato costo.
Invece, quelli pi lontani sono quelli che mostrano una capacit massima ed anche
tempi di accesso maggiori. Partendo dalla CPU ogni livello fa da buffer al livello
successivo.

Figura 18 Gerarchia di memorie

2.5. Il modello astratto di esecutore


La macchina di Von Neumann il modello di riferimento che consente di
comprendere le modalit con le quali un elaboratore esegue in modo automatico
una qualsiasi applicazione pensata per esso. Il modello si basa sul concetto di
automa capace di eseguire un programma residente nella memoria centrale. In
generale un programma un insieme di istruzioni la cui descrizione dipende dalle
capacit di comprensione di un linguaggio da parte del componente che svolge le
funzioni di CPU. La CPU, come automa capace di interpretare un prefissato
linguaggio, esemplifica il comportamento di un qualsiasi esecutore di programmi,
sia esso umano o macchina. Tra tutti i linguaggi di programmazione il linguaggio
macchina quello direttamente interpretabile da una CPU reale presente in un
sistema informatico. Dato il suo basso potere espressivo anche detto linguaggio
di basso livello.
Linsieme di istruzioni (repertorio) che si possono descrivere comprendono
operazioni che:
- spostano stringhe di bit da un registro allaltro di memoria;
- attivano lALU per effettuare la somma aritmetica, lAND, lOR tra
coppie di stringhe di bit, o la negazione (NOT) del contenuto
dellaccumulatore;
- eseguono lo scorrimento o la rotazione a destra o a sinistra dei bit
contenuti nellaccumulatore;
- provvedono ad interrogare i bit del registro di condizione (CC) per
determinare come procedere nellesecuzione del programma;
- consentono di saltare ad un qualsiasi punto del programma.
Tutte le istruzioni del programma devono essere allocate nei registri di
memoria prima che la CPU possa procedere alla loro interpretazione ed
esecuzione. Lo schema di allocazione deve essere definito dal programmatore
rispettando un principio fondamentale secondo cui deve sempre esistere una
64 Capitolo secondo

separazione netta tra le porzioni di memoria occupate dai dati da quelle occupate
dalle istruzioni. Un tale principio serve a garantire che in ogni istante la CPU stia
eseguendo effettivamente il programma progettato dal programmatore. Infatti
lallocazione in memoria di dati e programmi pu essere statica o dinamica. Nel
primo caso lallocazione avviene prima dellinizio dellesecuzione del programma;
nel secondo durante la sua esecuzione. Nel caso di allocazione dinamica di dati pu
avvenire che, per errori di programmazione, alcuni dati vadano ad allocarsi
nellarea riservata alle istruzioni cambiando il contenuto dei registri di memoria e
cambiando di fatto la struttura del programma.
Lallocazione in memoria comporta unassociazione precisa tra istruzioni e
dati e registri. In un modello di memoria a voce ad ogni istruzione o dato
corrisponde un ed un solo registro di memoria. Nelle memorie a byte istruzioni o
dati possono occupare pi registri di memoria. Per semplicit si proceder
pensando ad una memoria organizzata a voce.
Il riferimento ad una istruzione o ad un dato avviene specificando lindirizzo
di memoria occupato. Lindicazione di un indirizzo di memoria contenente un dato
si dir puntatore a dato, il puntatore a istruzione invece un indirizzo di un registro
di memoria nel quale collocata una istruzione.
Si pu allora definire una istruzione in linguaggio macchina come una
quadrupla: i = (Cop, Pdi, Pdo, Pis), in cui:
- Cop il codice operativo, ossia il codice che indica alla UC della CPU
loperazione da compiere; linsieme dei Cop prendere il nome di
repertorio di istruzioni e dipende dalla specifica CPU;
- Pdi sono i puntatori ai dati che servono per svolgere loperazione Cop detti
anche di input; si noti che esistono istruzioni che non hanno operandi di
input;
- Pdo sono i puntatori ai dati prodotti dalloperazione Cop detti anche di
output; si noti che esistono istruzioni che non hanno operandi di output;
- Pis il puntatore allistruzione da svolgere al termine dellesecuzione di
quella corrente.
Il puntatore Pis serve a comprendere la corrispondenza tra struttura di un
programma e schema di allocazione in memoria. Un programma una sequenza di
istruzioni da svolgere una dopo laltra. Ogni istruzione occupa un registro di
memoria. Il puntatore Pis serve a legare tra loro i registri di memoria contenenti
istruzioni in modo che sia chiara la sequenza del programma.
Il modello di esecutore 65

Figura 19 Esecuzioni di programmi nel modello astratto di processore

La definizione della struttura dellistruzione e dello schema di allocazione dei


programmi in memoria permettono di dettagliare le fasi del ciclo del processore.
La fase fetch inizia con il prelievo dellistruzione dalla memoria. Per farlo la CU
comunica alla memoria il valore del puntatore ad istruzione presente nel registro
PI. La risposta della memoria viene depositata nel registro IR cos da consentire
alla CU di:
- interpretare il codice operativo dellistruzione da eseguire;
- conoscere i puntatori ai dati di input ed output;
- ricevere il puntatore allistruzione da eseguire successivamente.
La fase fetch si conclude con laggiornamento del registro PI con il valore del
puntatore allistruzione successiva presente in IR.
La fase operand assembly serve alla CU per predisporre gli operandi che
servono al codice operativo. Per farlo la CU usa i puntatori ai dati contenuti nel
registro IR.
La fase execute consiste nel mettere in essere le azioni richieste con il codice
operativo presente nel registro di IR. Nel caso vengano prodotti risultati, ne verr
effettuata la memorizzazione negli indirizzi specificati dai puntatori ai dati di
output presenti nel registro IR.

Figura 20 Aggiornamento registri CPU


66 Capitolo secondo

Al termine dellesecuzione di una istruzione la CU riprende il suo cammino


partendo dal contenuto del registro PI. Le istruzioni del programma vengono
eseguite una dopo laltra indipendentemente dalla loro disposizione in memoria. Si
pu allora introdurre una notevole semplificazione imponendo al programmatore di
disporre le istruzioni ad indirizzi consecutivi di memoria e facendo in modo che la
CU nella fase fetch aggiorni il PI semplicemente incrementando di uno il suo
contenuto. In tale modalit le istruzioni non devono pi riportare il Pis in quanto
implicitamente il suo valore dato dal valore del registro PI pi uno.

Figura 21 Aggiornamento registri CPU con istruzioni consecutive in memoria

Perch il ciclo del processore possa avere inizio si deve predisporre in modo
che il registro PI contenga lindirizzo del registro di memoria contenente la prima
istruzione da eseguire. La fase iniziale di boot ha solo il compito di inizializzare il
PI con tale valore. Una volta avviato, il ciclo del processore non termina mai e
quindi ad ogni istruzione deve sempre seguirne unaltra da eseguire
successivamente. Questo spiega perch quando termina unapplicazione un
elaboratore torna ad eseguire i programmi del sistema operativo.
Dai programmi del sistema operativo si passa ad unaltra applicazione in
unalternanza che fa s che la CU possa procedere con il suo ciclo. Ma perch tutto
ci proceda nel rispetto del modello di Von Neumann, deve avvenire che in
memoria siano sempre presenti i programmi e i dati del sistema operativo mentre
quelli delle applicazioni vengono caricati in memoria dal sistema operativo su
richiesta dellutente prima che ne venga attivata la esecuzione. Nella memoria di
un elaboratore moderno si possono pertanto individuare in ogni istante cinque aree
distinte:
- linsieme dei registri nei quali si trovano i programmi del sistema
operativo;
- quelli occupati dai dati del sistema operativo;
- quelli nei quali si trovano le applicazioni di utente;
- quelli con i dati dei programmi di utente;
- ed infine linsieme dei registri che servono come buffer per il
trasferimento dati da e verso i dispositivi di input ed output.
Il modello di esecutore 67

Figura 22 Programmi in memoria

Il modello di Von Neumann pu essere generalizzato. La memoria si pu


sostituire con un foglio di lavoro sul quale sono segnate le istruzioni. Il foglio serve
anche per scrivere i dati. Lesecutore un processore di Von Neumann se in
grado di:
- leggere le istruzioni una alla volta dal foglio di lavoro;
- interpretare il linguaggio con il quale le istruzioni sono scritte;
- leggere e scrivere i dati sul foglio di lavoro;
- compiere le azione prescritte dalle istruzioni.

2.6. I microprocessori
Come gi descritto, un processore centrale (CPU) conforme al modello di Von
Neumann si compone logicamente di:
- una unit di controllo (UC) capace di interpretare i comandi ad esso
rivolti (detti anche istruzioni), di svolgere le azioni richieste da tali
comandi e di interagire con lambiente esterno attraverso dispositivi
periferici capaci di trasformare i segnali in modo tale che siano
comprensibili dalla UC da una parte, e, dagli utenti del sistema dallaltra;
- una unit logico aritmetica (ALU) per l'esecuzione delle operazioni di
tipo aritmetico (solitamente somma) e logico (somma, prodotto e
negazione logici).

Figura 23 Schema di una CPU


68 Capitolo secondo

L'architettura di Von Neumann viene detta di tipo SISD (Single Istruction


stream, Single Data stream) in quanto le istruzioni di un programma vengono
eseguite una dopo laltra serialmente con lunit di controllo che interpreta le
singole istruzioni generando comandi per tutti gli altri dispositivi, e con l'unit di
elaborazione che esegue le operazioni di tipo aritmetico o logico.
La disponibilit di registri interni come propri organi di memoria per compiti
speciali e/o per contenere informazioni temporanee, consente di ridurre i tempi di
esecuzione delle istruzioni non solo perch si riducono gli accessi alla memoria
centrale ma anche perch i trasferimenti interni al processore sono pi veloci. Il
programma e i dati sono contenuti in memoria ed una singola istruzione viene
eseguita mediante le seguenti fasi:
1. lettura dalla memoria dell'istruzione da eseguire;
2. determinazione dell'indirizzo della successiva istruzione da eseguire;
3. determinazione del significato del codice operativo per individuare
lazione da eseguire;
4. eventuale determinazione degli indirizzi degli operandi;
5. esecuzione delle sequenze di operazioni elementari richieste dalla
istruzione.
Il processore una macchina sequenziale capace di svolgere unazione alla
volta: pertanto unistruzione viene eseguita in passi successivi con azioni
elementari abilitate dal segnale di tempificazione (clock) e il suo tempo di
esecuzione dipende dal numero di passi per eseguirla e dalla frequenza del clock.
I microprocessori sono dispositivi elettronici in grado di contenere allinterno
di un unico circuito integrato le funzioni di unintera CPU. Il microprocessore
interagisce con tutti gli altri dispositivi attraverso i collegamenti dei bus di dati
(data bus), di indirizzo (address bus) e di controllo (control bus). I microprocessori
hanno bus dati a 8, 16, 32, 64 bit. La dimensione del bus dati esprime la capacit
di elaborazione del processore, ossia la quantit di bit che possono essere elaborati
in parallelo. Il bus indirizzi esprime, di contro, la capacit di memorizzazione del
processore, ossia il numero di celle diverse a cui si pu accedere (2m celle di
memoria, se m il numero dei bit del bus). La tabella riporta alcuni valori tipici del
parallelismo esterno.

Bit Data BUS Bit Address BUS Capacit di indirizzamento


8 16 64 KByte
16 20-24 1-16 MByte
64 64 fino a circa 1019 Byte

Tabella 1 Capacit di indirizzamento

Molti sono oggi i microprocessori presenti sul mercato ed una loro


classificazione pu essere fatta sulla base dei seguenti parametri:
- parallelismo esterno espresso come numero di bit trasferiti o prelevati in
un singolo accesso in memoria (8, 16, 32, 64,...) e caratterizzanti quindi il
suo data bus;
- capacit di indirizzamento legata alla dimensione in bit del suo address
bus
Il modello di esecutore 69

- numero, tipo e parallelismo dei registri interni;


- tecniche di indirizzamento intese come la modalit con la quale costruire
lindirizzo logico con il quale prelevare o salvare il valore delloperando
di una istruzione;
- gestione delle periferiche di input ed output;
- repertorio delle istruzioni inteso come numero e tipo di istruzioni
costituenti il suo linguaggio macchina;
- tempi necessari allesecuzione di alcune istruzioni fondamentali come
l'addizione da utilizzare per la valutazione del MIPS con il quale
effettuare confronti sulle prestazioni.
I microprocessori sono quindi caratterizzati anche dal numero e tipo di registri
interni di cui sono dotati. Nel tempo il numero di registri interni aumentato per
rendere pi veloce lesecuzione delle istruzioni consentendo lattivazione in
parallelo di alcune microoperazioni della unit di controllo. Linsieme minimo di
registri interni che sicuramente presente in qualsiasi microprocessore moderno
formato da:
- Prossima Istruzione (PI) o anche Program Counter: che nella fase fetch
cambia il proprio contenuto passando da puntatore in memoria
allistruzione da prelevare allinizio della fase a puntatore allistruzione
successiva da eseguire al termine della stessa;
- Accumulatore (ACC): utile a conservare dati temporanei o necessario per
attivare le operazioni logiche ed aritmetiche dellALU; infatti attraverso
esso i dati vengono forniti allALU prima di una operazione e in esso si
trova il risultato delloperazione eseguita; alcuni microprocessori possono
presentare anche due accumulatori;
- Condition Code (CC): che riporta lo stato dellelaborazione indicato dai
diversi bit di cui si compone:
o Bit Segno (S): indica con 1 la presenza in ACC di un valore
negativo; con 0 il caso opposto;
o Bit Zero (Z): indica con 1 la presenza in ACC di un valore uguale
a zero; con 0 il caso opposto;
o Bit Overflow (O): indica con 1 la presenza in ACC di un valore
non corretto in quanto loperazione aritmetica ha generato un
risultato con pi bit di quelli rappresentabili; con 0 il caso
opposto;
o Bit Riporto o Carry (C): indica con 1 la presenza in ACC di un
risultato che ha generato un ulteriore bit nel calcolare una
somma; con 0 il caso opposto;
o Bit Interruzione (I): indica con 1 che il sistema delle interruzioni
ha generato una richiesta di attenzione; con 0 il caso opposto;
- Registo Indice (X): con il quale poter calcolare lindirizzo delloperando
con quella che sar chiamata tecnica di indirizzamento relativa;
- Stack Pointer (SP): utile alla gestione del salti a sottoprogrammi per il suo
modo di gestire gli indirizzi di memoria; lo stack pointer contiene infatti
un puntatore alla memoria ad una area che viene chiamata stack;
attraverso SP si accede a tale area con operazioni di inserzione (PUSH) o
di estrazione (POP) con la tecnica LIFO (last in first out), che comporta
che lultimo elemento inserito sia anche il primo ad essere estratto.
70 Capitolo secondo

Laccumulatore si interfaccia direttamente con il data bus presentando la


stessa dimensione in numero di bit. I registri prossima istruzione, indice e stack
pointer sono collegati invece con laddress bus al quale comunicano lindirizzo
dopo averlo costruito secondo quanto richiesto dalle diverse istruzioni.

Figura 24 Registri interni di un microprocessore

La figura 24 illustra le dimensioni dei registri in un architettura classica che


vede il parallelismo del data bus fissato ad 8 bit ed una capacit di indirizzamento
(parallelismo delladdress bus) a 16 bit. I moderni processori operano con registri
di accumulatore a 16 o 32 bit e parallelismo delladdress bus a 32 o 64 bit.
A tali registri fondamentali si soliti aggiungere tre ulteriori registri:
- Istruction Register (IR): contenente al termine della fase fetch listruzione
prelevata dalla memoria centrale completa di tutte le sue parti (codice operandi
e puntatori ad operandi se necessari);
- Data buffer (DB): interfaccia con il data bus del quale rappresenta lo stato, in
altri termini il registro DB indica il valore che assume il data bus;
- Address buffer (AB): interfaccia con laddress bus del quale rappresenta lo
stato, in altri termini il registro AB indica il valore che assume laddress bus.
Tali tre registri vengono introdotti per schematizzare il comportamento della
CPU nella sua interazione con la memoria centrale. Essi riportano lo stato del
processore durante le diverse fasi (fetch, operand assembly ed execute) del suo
ciclo.

Figura 25 Schema di una CPU


Il modello di esecutore 71

In figura 25 si riporta larchitettura di riferimento di un processore dotato


dellinsieme di registri indicati con le principali connessioni tra essi.
Nella costruzione dellindirizzo di un operando di una istruzione le tecniche di
indirizzamento pi diffuse sono:
- indirizzamento immediato che indica che il valore contenuto gi
nellistruzione;
- indirizzamento diretto con il quale viene riportato nellistruzione lindirizzo
del registro di memoria che contiene il valore o nel quale depositare il valore;
- indirizzamento indiretto che riporta nellistruzione lindirizzo del registro di
memoria al cui interno specificato lindirizzo del registro dal quale prelevare
un valore o nel quale depositare un valore;
- indirizzamento relativo con il quale lindirizzo del registro di memoria che
contiene il valore o nel quale depositare il valore specificato nel registro
interno del processore detto indice.
Le diverse tecniche di indirizzamento vengono indicate nellistruzione, o
diversificando il codice operativo, o aggiungendo dei bit appositi il cui valore
indica alla UC come costruire lindirizzo.
Ad esempio per la semplice istruzione per il caricamento dellaccumulatore si
potrebbero avere in linguaggio macchina (rappresentato in esadecimale) le quattro
istruzioni di tabella:

Cod Operando Tecnica Commento Accessi in memoria


Op. nella fase
Operand Assembly
60 00ff Immediata LOAD ACC con il valore nessuno in quanto il dato
255 prelevato nella fase fetch
con listruzione
61 00ff Diretta LOAD ACC con il un solo accesso in
contenuto del registro di memoria
memoria di indirizzo 255
62 00ff Indiretta LOAD ACC con il due accessi in memoria: il
contenuto del registro di primo per prelevare
memoria il cui indirizzo lindirizzo alla posizione
contenuto nel registro di indicata; il secondo per
indirizzo 255 prelevare il dato
63 Relativa LOAD ACC con il un solo accesso in
contenuto del registro di memoria
memoria il cui indirizzo
presente nel registro indice
X

Tabella 2 Esempi di indirizzamento

In uno stato del processore come quello riportato in figura 26, gli effetti delle
diverse tecniche di indirizzamento per quanto attiene alla esecuzione della
istruzione di caricamento dellaccumulatore sono mostrati in figura 27.
72 Capitolo secondo

Figura 26 Stato iniziale della CPU

Immediato Diretto

Indiretto Relativo

Figura 26 Effetti delle tecniche di indirzzamento

Nella gestione delle periferiche di input ed output (I/O) i microprocessori si


dividono in quelli che usano la tecnica memory-mapped e in quelli che invece
adottano lI/O-mapped. Con la tecnica memory mapped lUC usa le stesse
istruzioni, utilizzate per leggere e scrivere in memoria, anche per accedere ai
dispositivi di I/O. I dispositivi di I/O hanno quindi dei propri indirizzi che devono
essere riservati e non sovrapposti a quelli usati per la memoria. I dispositivi di I/O
controllano il bus indirizzi e rispondono solo quando riconoscono un indirizzo a
loro assegnato. Con lI/O-mapped vengono invece usate istruzioni specifiche per
l'esecuzione dell'input/output. I dispositivi di I/O hanno uno spazio indirizzi
separato da quello della memoria, e un segnale del control bus serve alla UC per
specificare se si tratta di un accesso alla memoria o ad un dispositivo periferico. Il
vantaggio dell'uso del memory-mapped che, non richiedendo da una parte
hardware aggiuntivo per la gestione della periferia e dallaltra un insieme di
Il modello di esecutore 73

istruzioni specifiche, consente la realizzazione di CPU con una complessit


inferiore, pi economiche, veloci e facili da costruire.
Il repertorio delle istruzioni ha indirizzato i costruttori di microprocessori
verso due distinte tecnologie: CISC (Complex Instruction Set Computer) e RISC
(Reduced Instruction Set Computer). I processori CISC sono quelli nei quali il
crescere delle potenzialit stato accompagnato da un aumento delle operazioni
che sono capaci di svolgere, inserendo nel linguaggio macchina istruzioni con
potenza espressiva prossima a quella dei linguaggi di programmazione di alto
livello. I processori CISC sono caratterizzati quindi da un ampio repertorio di
istruzioni anche se molte di esse non risultano strettamente necessarie, potendosi
ottenere con lesecuzione di sequenze di istruzioni pi semplici. Il gran numero di
istruzioni di cui sono dotati i processori CISC ha comportato una loro maggiore
complessit costruttiva. La caratteristica di un microprocessore RISC quella di
possedere un repertorio costituito da un ridotto ed essenziale insieme di istruzioni
al fine di ottenere processori pi veloci e di costo ridotto, data la minore
complessit del loro progetto. Le due tecnologie hanno implicazioni diverse a
seconda della tipologia di programmazione adottata. Nel caso di programmazione
direttamente in linguaggio macchina, il ricco repertorio di istruzioni del CISC
rende lo sviluppo di programmi pi semplice. La maggiore complessit dello
sviluppo dei programmi nell'architettura RISC legata alla necessit di dovere
realizzare con istruzioni semplici e in numero ridotto qualsiasi operazione pi
complessa: per tale motivo, diviene di primaria importanza la ottimizzazione del
codice. Se per si analizza l'utilizzazione pratica di set di istruzioni estese dei
CISC, si trova che statisticamente solo un numero molto ridotto di essi viene utilizzato, e
ci non solo perch il 90% di esse pu essere sintetizzato in un restante sottoinsieme del
10%, ma anche perch l'utilit di disporre di un ampio set di istruzioni diminuito nel
tempo a fronte dei progressi compiuti dalle tecniche di sviluppo dei compilatori. Se infatti
si analizza il codice generato da un compilatore, si constata che solo una parte delle
istruzioni vengono impiegate. L'obiettivo fondamentale dell'approccio RISC , in
definitiva, disporre di tale insieme fondamentale di istruzioni per ridurre al minimo il
numero dei cicli di macchina (clock) necessari per loro esecuzione. Tutte le istruzioni
RISC fondamentali hanno la stessa durata (un ciclo macchina), la stessa lunghezza e lo
stesso formato. In questa accezione il RISC rappresenta un nuovo livello di
ottimizzazione tra hardware e software, in cui il primo viene semplificato al massimo per
raggiungere la massima velocit operativa, mentre il secondo si assume l'onere di
compensare la rigidit introdotta nell'hardware.
Relativamente alla tipologia di istruzioni esiste un ulteriore elemento caratterizzante
i microprocessori e consistente nel numero di operandi espliciti presenti nellistruzione.
Si possono avere pertanto microprocessori il cui linguaggio macchina gestisce:
- un solo operando;
- due operandi;
- tre operandi.
Si noti che se da un lato il maggior numero di operandi semplifica lattivit di
programmazione offrendo istruzioni pi compatte, dallaltra rende anche il
processore pi complesso.
74 Capitolo secondo

2.7. Un modello di processore


Da unanalisi dei processori esistenti, si pu ricavare per fini didattici un modello
capace di farne comprendere non solo il funzionamento. ma anche le modalit che
ne permettono la programmazione in linguaggio macchina. Tale processore verr
da qui di seguito indicato con MP, o Modello di Processore. Per semplificare la
presentazione dei concetti di base, al posto del linguaggio macchina in binario o in
formato pi compatto esadecimale, si introduce il linguaggio assemblativo.
In un linguaggio assemblativo si mantiene la corrispondenza uno ad uno con il
linguaggio macchina, ma al codice operativo si associa un codice mnemonico pi
semplice da comprendere e ricordare, ed al posto di indirizzi e valori da riportare in
binario si introducono i valori nella loro rappresentazione esterna (i numeri in
decimale, i caratteri nel formato ASCII). Ad ogni istruzione si pu affiancare
unetichetta per far riferimento ad essa in altre istruzioni, e si pu evidenziare nella
istruzione la tecnica di indirizzamento scelta.
Lassemblatore un programma che esegue la traduzione di un programma,
scritto in linguaggio assemblativo, in linguaggio macchina ed il pi semplice
traduttore di linguaggi presente in informatica. Non deve far altro che:
- far corrispondere ai codici mnemonici del codice operativo il rispettivo
codice binario;
- convertire da decimale a binario indirizzi e valori dei dati;
- determinare gli indirizzi delle etichette associate alle istruzioni;
- convertire dati alfanumerici nella loro rappresentazione binaria.
Per la semplicit del linguaggio assemblativo, la struttura di una istruzione
rigida si pu vedere composta delle seguenti parti:

Label Codice Tecnica Operando Commento


Op. Indirizzamento

La label non sempre presente cos come il commento a fine frase che serve a
spiegare le ragioni per le quali viene introdotta listruzione nel programma. Il
campo Tecnica Indirizzamento indica la modalit di composizione dellindirizzo;
pi precisamente valgono le corrispondenze in tabella 3.
Notazione Tecnica indirizzamento
= Immediata
^ Diretta
(^) Indiretta
(X) Relativa
Tabella 3 Modalit di indirizzamento e notazioni

Non tutte le istruzioni prevedono un campo operando: ovvio che se


loperando non previsto, anche la notazione relativa alla tecnica di
indirizzamento risulta essere assente.
Il processore MP ha allora le seguenti caratteristiche:
- dotato dei registri interni PI, IR, SP, X, ACC e CC;
- I/O mapped;
- di tipo CISC;
Il modello di esecutore 75

- gestisce la rappresentazione per complemento alla base considerando il bit di


peso maggiore dellACC come indicatore del segno (1 per numeri negativi e
zero in caso contrario);
- ha una struttura delle istruzioni ad un operando;
ed a sua volta parte di una architettura composta da:
- una memoria centrale di grandi dimensioni i cui registri di memoria sono
contenitori di informazioni di qualsiasi tipo e dimensione;
- un canale di input (detto standard input) per gestire limmissione dati da
tastiera;
- un canale di output (detto standard output) per la gestione della presentazione
dei risultati su di un monitor.
-

Figura 28 Schema del processore MP

La caratteristica dei registri di memoria di essere contenitori di informazioni


di qualsiasi tipo e dimensione viene introdotta per esemplificare il funzionamento
del modello, senza peraltro dover descrivere in dettaglio le operazioni sui diversi
dati in funzione della specificit della loro rappresentazione. Si potr sempre
dimostrare che un registro di dimensione non specificata si riconduce ad una
sequenza di registri posti ad indirizzi consecutivi contenenti tutti gli elementi posti
nellunico contenitore.
Se ad esempio nel nostro modello si assume che un registro possa contenere il
messaggio Errore, in un sistema reale fatto di una memoria organizzata a byte
serviranno 6 registri contenenti ciascuno le lettere del messaggio. Anche
laccumulatore, per la stessa motivazione, sar considerato un contenitore di
informazioni di qualsiasi tipo e dimensione. Coerentemente con tale ipotesi si potr
assegnare ad un registro un valore numerico o una informazione alfanumerica: nel
primo caso un $ davanti al numero ne indica una rappresentazione esadecimale
($F0AC); nel secondo caso le virgolette racchiuderanno la sequenza di caratteri
(questo un esempio).
Lipotesi semplificativa fatta impatta anche sulla allocazione delle istruzioni in
quanto consente di assumere che una intera istruzione venga ad essere contenuta in un
unico registro. Se una siffatta impostazione ha riguardato i primi calcolatori dotati di una
struttura della memoria detta a voce, nelle architetture moderne organizzate a byte le
istruzioni hanno una lunghezza variabile. Solitamente il repertorio delle istruzioni riesce
ad essere gestito con un solo byte mentre loperando, se presente pu occupare pi byte a
seconda del valore espresso o della capacit di memoria nel caso si tratti di un indirizzo.
Nel caso reale lUC riconosce dal codice operativo dellistruzione anche la sua lunghezza
76 Capitolo secondo

e ne opera il prelievo ad indirizzi consecutivi a quello espresso dal PI: in tale caso, alla
fine della fase fetch, il PI viene pertanto ad essere incrementato di un valore uguale
proprio alla lunghezza dellistruzione. Il repertorio di istruzioni di MP si compone di:
- istruzione di lettura e modifica dei registri interni e di memoria;
- istruzioni di tipo aritmetico;
- istruzioni di tipo logico;
- istruzioni di salto;
- istruzioni di input ed output per la gestione della interazione con il mondo
esterno.
Nel primo sottoinsieme rientrano tutte le istruzioni di gestione dei registri di
memoria con una delle tecniche di indirizzamento introdotte, dei registri interni
ACC, X, CC e SP. Le istruzioni di tipo aritmetico e logico depositano il loro
risultano nellaccumulatore modificando i bit del CC di segno, riporto, zero ed
overflow. Le istruzioni di salto alterano il normale flusso di controllo del
programma prescrivendo che la esecuzione non proceda con listruzione successiva
il cui indirizzo specificato in PI, ma con quella indicata dal valore delloperando
secondo modalit diverse.
Per ogni istruzione verr riportato il codice operativo (CodOP) in linguaggio
assemblativo, loperando se previsto, la operazione eseguita, una breve descrizione
e le eventuali modifiche apportate ai bit del CC (0 o 1 a seconda dei casi, o A ad
indicare la dipendenza dal valore assunto dallaccumulatore). Con la notazione
[registro] si indicher il contenuto del registro specificato (ad esempio [X] indica il
contenuto del registro indice), mentre con M([registro]) si indicher il registro di
memoria il cui indirizzo specificato in registro. La presenza nel campo operando
di OP indica che listruzione richiede che venga determinato un valore sulla base di
una delle tecniche di indirizzamento specificate:
- proprio OP per limmediato,
- M(OP) per il diretto,
- M([M(OP)]) per lindiretto
- M([X]) per il relativo.
Per semplificare si indicher con [OP] il valore determinato.

Le istruzioni di gestione dellaccumulatore sono quelle riportate in tabella 4.


CodOP Operando Operazione Descrizione
LDA OP ACC = [OP] copia in ACC il dato come determinato dalla
tecnica di indirizzamento
STA OP [OP] = ACC copia nel registro di memoria, il cui indirizzato
determinato dalla tecnica di indirizzamento, il
valore di ACC
PSHA M([SP]) = ACC prima copia ACC nellarea stack di memoria,
SP = SP - 1 ossia allindirizzo contenuto in SP; dopo viene
decrementato il valore di SP per consentire un
successivo inserimento nellarea
PULA SP = SP + 1 dopo aver incrementato il contenuto del registro
ACC = M([SP]) SP, copia in ACC il contenuto del registro di
memoria indicato da SP
CLRA ACC = 0 azzera il contenuto di ACC
NEGA ACC=0 - [ACC] calcola il complemento alla base del contenuto di
ACC
Tabella 4 Istruzioni per la gestione dellaccumulatore
Il modello di esecutore 77

Le istruzioni di gestione del registro X sono quelle in tabella 5.


CodOP Operando Operazione Descrizione
LDX OP X = [OP] copia in X il dato come determinato
dalla tecnica di indirizzamento
STX OP [OP] = X copia nel registro di memoria, il cui
indirizzato determinato dalla tecnica di
indirizzamento, il valore di X
Tabella 5 Istruzioni per la gestione del registro indice

Le istruzioni di gestione del registro SP sono quelle in tabella 6.


CodOP Operando Operazione Descrizione
LDSP OP SP = [OP] copia in SP il dato come determinato
dalla tecnica di indirizzamento
STSP OP [OP] = SP copia nel registro di memoria, il cui
indirizzato determinato dalla tecnica di
indirizzamento, il valore di SP
Tabella 6 Istruzioni per la gestione del registro SP

Le istruzioni di tipo aritmetico sono quelle in tabella 7.


CodOP Operando Operazione Descrizione
INCA ACC = [ACC] +1 modifica il contenuto di ACC
aggiungendo 1
DECA ACC = [ACC] -1 modifica il contenuto di ACC sottraendo
1
INCX X = [X] +1 modifica il contenuto di X aggiungendo
1
DECX X = [X] -1 modifica il contenuto di X sottraendo 1
INCS SP = [SP] +1 modifica il contenuto di SP aggiungendo
1
DECS SP = [SP] -1 modifica il contenuto di X sottraendo 1
ADDA OP ACC = [ACC] + [OP] Somma al contenuto di ACC il valore
determinato sulla base della tecnica di
indirizzamento
SUBA OP ACC = [ACC] - [OP] Sottrae al contenuto di ACC il valore
determinato sulla base della tecnica di
indirizzamento
Tabella 7 Istruzioni aritmetiche

Le istruzioni di tipo logico in tabella 8.


CodOP Operando Operazione Descrizione
NOTA ACC = not[ACC] complemento di ACC; i bit 1 vengono
cambiati in 1 e quelli 0 in 1
ANDA OP ACC = [ACC] and Prodotto logico tra il contenuto di ACC e il
[OP] valore determinato sulla base della tecnica
di indirizzamento; land viene eseguito sui
singoli bit coinvolgendo quelli che
occupano la stessa posizione
ORA OP ACC = [ACC] or [OP] Somma logica tra il contenuto di ACC e il
valore determinato sulla base della tecnica
di indirizzamento; lor viene eseguito sui
singoli bit coinvolgendo quelli che
occupano la stessa posizione
Tabella 8 Istruzioni di tipo logico

Le istruzioni di confronto, utili a modificare i bit del CC, sono in tabella 9.


78 Capitolo secondo

CodOP Operando Operazione Descrizione


BITA OP [ACC] and [OP] Se Z diverso da zero, indica che ACC
ha i bit uguali a 1 nelle stesse posizioni
di OP
CMPA OP [ACC] - [OP] Se Z uguale a zero ACC OP hanno la
stessa configurazione di bit
TST OP [OP] 0 Se OP uguale a zero Z uguale ad 1
Se OP negativo S uguale ad 1
TSTA [ACC] 0 Se ACC uguale a zero Z uguale ad 1
Se ACC negativo S uguale ad 1
Tabella 9 Istruzioni di confronto

Le istruzioni di salto sono in tabella 10.


CodOP Operando Operazione Descrizione
JMP Address PI = Address Salto allistruzione presente allindirizzo
specificato
BRZ Address Z=1 PI = Address Se il bit Z 1 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRNZ Address Z=0 PI = Address Se il bit Z 0 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRS Address S=1 PI = Address Se il bit S 1 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRNS Address S=0 PI = Address Se il bit S 0 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRO Address O=1 PI = Address Se il bit O 1 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRNO Address O=0 PI = Address Se il bit O 0 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRC Address C=1 PI = Address Se il bit C 1 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
BRNC Address C=0 PI = Address Se il bit C 0 salta allistruzione
allindirizzo specificato altrimenti
prosegui in sequenza
Tabella 10 Istruzioni di salto

Mentre il JMP (jump) un salto incondizionato, tutti i BRANCH sono salti


condizionati al valore del bit del CC interessato dallistruzione. Se la condizione
non viene verificata, il PI non viene modificato e lesecuzione continua con
listruzione successiva a quella di salto.
Le istruzioni di gestione dei sottoprogrammi sono in tabella 11.
CodOP Operando Operazione Descrizione
JSR Address M([SP]) = PI (Jump to subroutine)
SP = [SP] - 1 Salto allistruzione indicata da address
dopo aver salvato il valore di PI
PI = Address nellarea stack
RTS SP = [SP] + 1 (Return from subroutine)
PI = M([SP]) Salta allistruzione il cui indirizzo viene
prelevato dallarea stack
Tabella 11 Istruzioni di gestione sottprogrammi
Il modello di esecutore 79

Le istruzioni di gestione del CC sono in tabella 12.


CodOP Operando Operazione Descrizione
CLS S=0 pone a zero il bit S
SETS S=1 pone a uno il bit S
CLZ Z=0 pone a zero il bit Z
SETZ Z=1 pone a uno il bit Z
CLO O=0 pone a zero il bit O
SETO O=1 pone a uno il bit O
CLC C=0 pone a zero il bit C
SETC C=1 pone a uno il bit C
CLI I=0 pone a zero il bit I
SETI I=1 pone a uno il bit I
Tabella 12 Istruzioni di gestione del registro CC

Infine le istruzioni di input ed output sono quelle in tabella 13.


CodOP Operando Operazione Descrizione
IN ACC = [input Il dato prelevato dallesterno (per
standard] inserimento da tastiera) dal canale di
input viene depositato in ACC
OUT output standard = Il valore di ACC viene fornito al canale
[ACC] di output per essere mostrato allesterno
(sul monitor)
Tabella 13 Istruzioni di I/O
Si pu osservare che non tutte le istruzioni sono realmente necessarie. Infatti
molte di esse possono essere ricavate da altre. Non a caso il processore MP stato
classificato come CISC proprio perch stata privilegiata la presenza di un ricco
numero di istruzioni al fine di renderne pi semplice la programmazione.
In tabella 14 sono riportati alcuni esempi di ridondanza del repertorio
introdotto.
Codice Operativo Equivalenza
INCA STA (^)2000
LDA (=)1
ADDA (^)2000
CLRA LDA (=)0
NEGA NOTA
INCA
Tabella 14 Istruzioni Equivalenti

2.7.1. La programmazione in linguaggio assemblativo


La programmazione nel linguaggio assemblativo resa difficile non solo dalla
bassa potenza espressiva delle istruzioni che devono essere utilizzate, ma anche
dallobbligo che ha il programmatore di pianificare la disposizione in memoria di
dati ed istruzioni. Per ogni programma si deve provvedere a suddividere la
memoria in tre aree fondamentali:
- unarea istruzioni necessaria per contenere lintero programma;
- unarea dati per gestire i valori delle informazioni da trattare;
- unarea stack importante per gestire sottoprogrammi e interruzioni.
80 Capitolo secondo

Le tre aree devono essere adeguatamente dimensionate affinch non capiti che durante
lesecuzione del programma una di esse sconfini nelle altre. Se ci accadesse si avrebbero
effetti non prevedibili e di difficile diagnosi. Ad esempio, se durante lesecuzione alcuni dati
venissero memorizzati nellarea riservata alle istruzioni, accadrebbe che la UC incontrerebbe
istruzioni diverse da quelle inserite dal programmatore. Altra causa di errore pu generarsi per
effetto di una espansione non controllata dellarea di stack a scapito dellarea dati: la
sovrapposizione cambia il valore dei registri di memoria riservate a contenere i valori delle
informazioni alterando quanto previsto dal programmatore. Se ad esempio in un registro di
memoria stato inserito un valore costante da cui dipende la correttezza dellalgoritmo, e tale
registro viene ad essere modificato per effetto della espansione dellarea stack, si ha come
naturale conseguenza la generazione di una condizione di errore.
La memoria viene pertanto suddivisa ponendo:
- larea istruzioni ad indirizzi bassi in quanto lallocazione delle istruzioni
del programma deve essere fatta ad indirizzi consecutivi crescenti;
- larea stack ad indirizzi alti in quanto le operazioni di inserimento
avvengono decrementando lo SP
- larea dati ad indirizzi intermedi tra le due precedenti aree.
Supponendo quindi di disporre di una memoria con una capacit di 1000
registri, tutti i programmi dovrebbero almeno prevedere come prima istruzione
quella di caricamento di SP con 999. Per comodit si assumer anche che la prima
istruzione sia collocata sempre nel registro di memoria di indirizzo uno. Con tale
ipotesi perch il processore MP inizi lesecuzione di un qualsiasi programma
baster forzare il PI ad azzerarsi in fase di boot.
A seconda delle necessit, il programmatore dovr disporre i dati in indirizzi
compresi tra 1 e 999 dopo aver dimensionato lo spazio necessario a contenere le
istruzioni del programma e larea stack.
Un primo e semplice programma per il nostro MP quello in tabella 15.

IM Label CodOp TI Operando Commento


1 LDSP = 999 posizionamento iniziale di SP
2 LDA = Inserire carica una stringa in accumulatore
dato
3 OUT visualizza messaggio
4 IN input di un dato da tastiera
5 STA ^ 500 conserva primo dato
6 LDA = Inserire carica una stringa in accumulatore
dato
7 OUT visualizza messaggio
8 IN input di un secondo dato da tastiera
9 ADDA ^ 500 sommalo al primo dato prelevato da
tastiera
10 OUT presenta il risultato al monitor
Tabella 15 Esempio di programma per MP

Per comodit stata inserita la colonna IM (indirizzo di memoria) per


indicare lallocazione in memoria delle singole istruzioni. Per comprendere cosa il
programma faccia se ne pu tracciare la esecuzione elencando in successione non
solo le azioni svolte, ma anche i suoi effetti sui registri interni e di memoria.
Il modello di esecutore 81

Allo scopo viene inserita la tabella di trace (vedi tabella 16) che comprende
tante colonne quanti sono i registri da osservare e tante righe quante sono le azioni
svolte. Ogni riga riporta la fotografia dello stato in cui viene a trovarsi il sistema:
linsieme degli stati nellordine temporale di esecuzione rappresenta il processo
svolto. Nella tabella di trace si aggiungono due colonne per elencare le interazioni
del sistema con il mondo circostante: infatti i processi svolti dipendono fortemente
da tale interazioni e sono casi particolari quelli nei quali ad un programma
corrisponde un unico processo di esecuzione qualsiasi siano i dati immessi. Le due
colonne aggiunte sono pertanto:
- il file di output (FO) nel quale si elenca tutto ci che viene presentato
sulloutput standard per effetto di operazioni d OUT;
- il file di input (FI) dove sono elencati i dati di prova che possono essere
inseriti dallinput standard per effetto di operazioni di IN.

Nel caso in cui si fissi che i programmi siano caricati a partire dallindirizzo 1,
larea dati inizi allindirizzo 500, larea stack parta da 999, si pu strutturare la
tabella di trace del programma precedente nel modo seguente riportando lo stato
del sistema al termine della fase execute dellUC.

PI IR ACC SZOC X SP M(500) M(501) M(502) M(503) M(997) M(998) M(999) FO FI


2 LDSP 999
=999
3 LDA Inserire 0000
=Inseri dato
re dato
4 OUT Inserire
dato
5 IN 33 33
6 STA 33
^500
7 LDA Inserire
=Inseri dato
re dato
8 OUT Inserire
dato
9 IN 22 22
10 ADDA 55
^500
11 OUT 55
Tabella 16 Tabella di trace

Si noti che per comodit di lettura nelle celle vengono riportati solo i
cambiamenti sottintendendo che lultimo valore scritto quello che rimane nel
registro fin quando non interviene una successiva modifica.
Il trace mostra che il programma esegue la somma di due numeri. Non si
comprende per cosa accade dopo lultima istruzione di OUT soprattutto
considerando che il ciclo del processore non ha mai termine e dopo la fase execute
deve sempre occorrere una successiva fase di fetch. Per gestire tale situazione tutti
i programmi che verranno presentati successivamente prevederanno come ultima
listruzione un JMP sis_op che verr illustrata solo alla fine del paragrafo.
82 Capitolo secondo

Il programma seguente esegue lo scambio tra due registri di memoria nel


senso che porta nel primo il valore del secondo e nel secondo quello del primo: per
evitare che nello scambio uno dei due valori si perda deve essere usato un terzo
registro che fa da buffer. Per semplificare la progettazione il programmatore pu
associare un nome ai registri di memoria usati per conservare dati. Ad esempio
creata la seguente corrispondenza:

Nome Indirizzo di memoria


info01 500
info02 501
buffer 503
Tabella 17 Corrispondenza nomi-indirizzi di memoria

si potranno usare i nomi al posto degli indirizzi rendendo il programma pi


comprensibile. Un altro esempio di programma quello in tabella 18.

IM Label CodOp TI Operando Commento


1 LDSP = 999 posizionamento iniziale di SP
2 LDA = Dato carica una stringa in
1> accumulatore
3 OUT visualizza messaggio
4 IN input di un dato da tastiera
5 STA ^ info01 conserva primo dato
6 LDA = Dato carica una stringa in
2> accumulatore
7 OUT visualizza messaggio
8 IN input di un secondo dato da
tastiera
9 STA ^ info02 conserva secondo dato
10 scambio LDA ^ info1 inizia scambio
11 STA ^ buffer conserva il primo valore
12 LDA ^ info2 preleva il secondo valore
13 STA ^ info01 copialo nel primo registro
14 LDA ^ buffer riprendi il primo valore
15 STA ^ info02 portalo nel secondo registro
16 Stampa LDA = Dato1: carica messaggio
17 OUT visualizza messaggio
18 LDA ^ info01
19 OUT visualizza valore
20 LDA = Dato2: carica messaggio
21 OUT visualizza messaggio
22 LDA ^ info02
23 OUT visualizza valore
24 Fine JMP sis_op salta allindirizzo sis_op
Tabella 18 Esempio di programma per MP
Il modello di esecutore 83

Il trace del programma quello riportato nella tabella 19.


PI IR ACC SZO X SP info info buffer M(997) M(998) M(999) FO FI
C 01 02
2 LDSP 99
=999 9
3 LDA Dato 0000
= 1>
Dato1>
4 OUT Dato
1>
5 IN 33 33
6 STA 33
^info01
7 LDA Dato
= 2>
Dato 2>
8 OUT Dato
2>
9 IN 22 22
10 STA 22
^info02
11 LDA 33
^info01
12 STA 33
^buffer
13 LDA 22
^info02
14 STA 22
^info01
15 LDA 33
^buffer
16 STA 33
^info02
17 LDA Dato 1:
=Dato 1:
18 OUT Dato
1:
19 LDA 22
^info01
20 OUT 22
21 LDA Dato 2:
=Dato 2:
22 OUT Dato
2:
23 LDA 33
^info02
24 OUT 33
Tabella 19 Tabella di trace

Per evitare di dover ripetere sequenze identiche di istruzioni si possono


introdurre i sottoprogrammi con le istruzioni JSR e RTS. Infatti la JSR esegue un
salto allindirizzo specificato dopo aver conservato nellarea di memoria gestita
dallo stack il valore assunto dal PI: tale valore indica la posizione in memoria della
istruzione successiva al JSR. Il salto fa procedere lesecuzione con le istruzioni che
compongono il sottoprogramma. Listruzione RTS, posta al termine del
sottprogramma, ripristina nel PI il valore che era stato conservato allatto del JSR
riprendendo in tale modo lesecuzione del programma chiamante.
84 Capitolo secondo

Nella figura seguente si organizzato come sottoprogramma la sequenza


formata dalla stampa il valore dellaccumulatore e dallinput di un nuovo dato da
tastiera.

Figura 29 Gestione Sottoprogrammi

Il trace in tabella 20 seguente mostra in dettaglio come avviene sia il salto al


sottoprogramma che il ritorno da esso.

PI IR ACC SZOC X SP dato1 dato2 M(997) M(998) M(999) FO FI


2 LDSP 99
=999 9

101 LDA Dato 0000


= Dato 1>
1>
102 JSR 300 99 102
8
301 OUT Dato
1>
302 IN 33 33
102 RTS 99
9
103 STA 33
^dato1
104 LDA Dato
= Dato 2>
2>
105 JSR 300 99 105
8
301 OUT Dato
1>
302 IN 33 33
Il modello di esecutore 85

102 RTS 99
9
10 STA 22
^dato2
Tabella 20 Tabella di trace

Lintroduzione dei sottoprogrammi obbliga il programmatore a pianificarne


lallocazione in memoria in area diversa da quella occupata dal programma
principale. Per semplificare il lavoro del programmatore si potr associare un nome
allindirizzo occupato dalla prima istruzione del sottoprogramma cos come stato
gi fatto per i dati. I programmi prodotti saranno molto pi leggibili.
Si scriva adesso un programma che:
- carichi in memoria una sequenza di dati numerici di tipo intero, maggiori
di zero prelevandoli da tastiera;
- termini il prelievo quando viene inserito un valore nullo;
- effettui la somma dei dati inseriti;
- determini il valore minimo tra quelli inseriti;
- determini il valore massimo tra quelli inseriti.
Per prima cosa si organizzino i sottoprogrammi per:
- LEGGI: per la stampa di un messaggio, linserimento da tastiera e il
salvataggio in memoria;
- CONTA: per incrementare una variabile contatore;
- IN_VET: per leggere la sequenza dei numeri determinando quanti sono;
- SOMMA: per effettuare la sommatoria dei dati inseriti;
- MAX: per determinare il valore massimo e
- MIN: per determinare il valore minimo degli stessi dati.
Se si definiscono i nomi per le variabili e per le etichette di istruzioni come in
tabella 21 (tabella dei simboli),

Simbolo Indirizzo Memoria Tipo Descrizione


Vettore 600 variabile inizio sequenza dati
(si assume che possano
essere massimo 100)
n 700 variabile numero dati inseriti
i 701 variabile indice di ciclo
totale 702 variabile valore somma
max 703 variabile valore massimo
min 704 variabile valore mnimo
leggi 100 label sottoprogramma
conta 110 label sottoprogramma
in_vet 120 label sottoprogramma
somma 150 label sottoprogramma
minimo 200 label sottoprogramma
massimo 250 label sottoprogramma
Tabella 21 Tabella dei simboli

si pu procedere con la programmazione.


86 Capitolo secondo

IM Label CodOp TI Operando Commento


100 LEGGI OUT stampa messaggio
101 IN leggi dato
102 STA (X) memorizza dato
103 RTS termina
Tabella 21 Programma LEGGI

Si noti che LEGGI prevede prima di iniziare che :


- in ACC sia contenuto il messaggio da stampare
- in X sia contenuto lindirizzo di memoria dove conservare il dato preso da
tastiera.
Al suo termine il dato inserito da tastiera rimane in ACC e si trova anche
allindirizzo di memoria contenuto in X.
IM Label CodOp TI Operando Commento
110 CONTA LDA ^ n carica valore contatore
111 INCA incrementa
112 STA ^ n aggiorna contatore
113 RTS termina

Tabella 22 Programma CONTA

Si noti che CONTA preleva ed aggiorna il valore di n e non ha bisogno di


scambiare dati attraverso gli atri registri.
IM Label Cod Op TI Operando Commento
120 IN_VET LDX = vettore carica in X indirizzo di
vettore
121 CLRA azzera contatore
122 STA ^ n
123 CICLO LDA = Inserisci carica messaggio
124 JSR LEGGI Salta a sottoprogramma
125 BRZ FINE_CICLO salto condizionato alla
presenzadi uno zero in ACC
(terminazione sequenza di
input)
126 INCX se il salto non avviene il
dato inserito diverso da
zero e si deve procedere al
successivo inserimento in
una posizione di memoria
seguente
127 JSR CONTA incrementa contatore
128 JMP CICLO riprendi linserimento
129 FINE_CICLO RTS termina
Tabella 23 Programma IN_VET
Si noti che IN_VET restituisce il valore di n e le n locazioni di memoria che
partono da vettore caricate con i dati inseriti da tastiera.
Il modello di esecutore 87

IM Label CodOp TI Operando Commento


150 SOMMA LDX = vettore carica in X indirizzo di
vettore
151 CLRA
152 STA ^ tot azzera somma
153 STA ^ i salva valore indice
154 CICLO_SOM LDA (X) preleva dato da sequenza
155 ADDA ^ tot aggiungi la somma
precedente
156 STA ^ tot conserva il valore
calcolato
157 INCX incrementa la posizione
nella sequenza
158 LDA ^ i carica valore indice
159 INCA incrementa
160 STA ^ i salva valore indice
161 CMPA ^ n confronta con il numero di
elementi
162 BRNZ CICLO_SOM se non sono uguali
continua la somma
163 RTS
Tabella 24 Programma SOMMA
IM Label CodOp TI Operando Commento
200 MINIMO LDX = vettore carica in X indirizzo di vettore
201 LDA (X) preleva primo dato da sequenza
202 STA ^ min posiziona in valore min
203 LDA = 1
204 STA ^ i posiziona ad 1 indice
205 CICLO_MIN INX incrementa la posizione nella
sequenza
206 LDA (X) preleva dato da sequenza
207 SUBA ^ min fai la differenza con min
208 BRNS CONTINUA se la differenza non negativa
lelemento pi grande del
presunto minimo
209 LDA (X) riprendi il dato
210 STA ^ min aggiorna minimo
211 CONTINA LDA ^ i carica valore indice
212 INCA incrementa
213 STA ^ i salva valore indice
214 CMPA ^ n confronta con il numero di
elementi
215 BRNZ CICLO_MIN se non sono uguali continua i
confronti
216 RTS
Tabella 25 Programma MINIMO
IM Label CodOp TI Operando Commento
250 MASSIMO LDX = vettore carica in X indirizzo di vettore
251 LDA (X) preleva primo dato da sequenza
88 Capitolo secondo

252 STA ^ max posiziona in valore max


253 LDA = 1
254 STA ^ i posiziona ad 1 indice
255 CICLO_MAS INX incrementa la posizione nella
sequenza
256 LDA ^ max preleva max
257 SUBA (X) fai la differenza con dato da
sequenza
258 BRNS PROSEGUI se la differenza non negativa il
presunto max pi grande
dellelemento della sequenza
259 LDA (X) riprendi il dato
260 STA ^ max aggiorna massimo
261 PROSEGUI LDA ^ i carica valore indice
262 INCA incrementa
263 STA ^ i salva valore indice
264 CMPA ^ n confronta con il numero di elementi
265 BRNZ CICLO_MAS se non sono uguali continua i
confronti
266 RTS
Tabella 26 Programma MASSIMO

Si pu adesso scrivere il programma principale.


IM Label Cod TI Operando Commento
Op
1 LDSP = 999 posizionamento iniziale di SP
2 JSR IN_VET lettura della sequenza
3 JSR SOMMA calcola la somma degli elementi
4 LDA ^ Totale
5 OUT stampa il risultato della somma
6 JSR MINIMO determina valore minimo
7 LDA ^ Min
8 OUT stampa valore minimo
6 JSR MASSIMO determina valore massimo
7 LDA ^ Max
8 OUT stampa valore massimo
9 JMP sist_op
Tabella 27 Programma MAIN
Si noti che si fatto ricorso ai sottoprogrammi anche e soprattutto per
evidenziare sequenze di istruzioni con un compito preciso. In tale modo dal
programma principale si evincono subito le operazioni fondamentali senza doverle
scoprire attraverso il trace.
Un altro aspetto che emerge dallesempio che i richiami dei sottoprogrammi
possono essere nidificati: ossia allinterno di un sottoprogramma si possono
richiamare altri sottoprogrammi. Il collegamento tra le diverse componenti del
programma garantito dalla gestione dellarea di memoria attraverso il registro SP.
Ad ogni salto al sottoprogramma viene inserito (operazione di PUSH) lindirizzo di
ritorno nellarea stack di memoria. Listruzione RTS preleva (operazione di POP)
Il modello di esecutore 89

lultimo indirizzo inserito a cui tornare. I push conservano gli indirizzi di ritorno
nellordine in cui si sono determinati; i pop li prelevano nellordine inverso.

Figura 30 Gestione sottoprogrammi nidificati

Lassemblatore stato uno dei primi programmi realizzati. Nel tempo si


sempre pi arricchito di funzionalit che semplificassero la difficile attivit di
programmazione. Negli attuali assemblatori il programmatore non ha bisogno di
definire la tabella dei simboli in quanto viene calcolata automaticamente durante la
traduzione in linguaggio macchina. Per farlo lassemblatore opera solitamente in
due passi: nel primo costruisce la tabella dei simboli associando ad ognuno di essi
posizione in memoria e caratteristica, nel secondo pu procedere alla sostituzione:
- dei codici mnemonici con quelli macchina,
- e dei simboli con i valori determinati.

Il programmatore pu anche fornire allassemblatore direttive con le quali


guidare la traduzione. Per esempio pu indicare allassemblatore:
- dove allocare le istruzioni:
#AREAPROG AT address
- dove allocare i dati definendone anche le dimensioni:
#AREADATI AT address
- le dimensioni dei singoli dati con direttive del tipo:
#DATO nome SIZE dimensione
- dove far iniziare larea di stack:
#AREASTACK AT address
- dove collocata la prima istruzione da eseguire che pu essere diversa da
quella allocata in prima posizione:
#START AT address
- quando termina lesecuzione del programma
#STOP
90 Capitolo secondo

Un tale assemblatore consentirebbe di scrivere i programmi precedenti senza


dover segnare a fianco di istruzioni e dati la loro allocazione in memoria come
lesempio seguente mostra.

#START AT 200
#AREADATI AT 500
#DATO vettore SIZE 100
#DATO n SIZE 1
#DATO i SIZE 1
#DATO totale SIZE 1
#DATO max SIZE 1
#DATO min SIZE 1
#AREASTACK AT 999
#AREAPROG AT 200

JSR IN_VET
JSR SOMMA
LDA ^ totale
OUT
JSR MINIMO
LDA ^ min
OUT
JSR MASSIMO
LDA ^ max
OUT
#STOP

AREAPROG AT 300

LEGGI OUT
IN
STA (X)
RTS

CONTA LDA ^ n
INCA
STA ^ n
RTS

IN_VET LDX = vettore


CLRA
STA ^ n
CICLO LDA = Inserisci
JSR LEGGI
BRZ END_CICLO
INCX
JSR CONTA
JMP CICLO
END_CICLO RTS

SOMMA LDX = vettore


CLRA
STA ^ tot
STA ^ i
CICLO_SOM LDA (X)
ADDA ^ tot
Il modello di esecutore 91

STA ^ tot
INCX
LDA ^ i
INCA
STA ^ i
CMPA ^ n
BRNZ CICLO_SOM
RTS

MINIMO LDX = vettore


LDA (X)
STA ^ min
LDA = 1
STA ^ i
CICLO_MIN INX
LDA (X)
SUBA ^ min
BRNS CONTINUA
LDA (X)
STA ^ min
CONTINUA LDA ^ i
INCA
STA ^ i
CMPA ^ n
BRNZ CICLO_MIN
RTS

MASSIMO LDX = vettore


LDA (X)
STA ^ max
LDA = 1
STA ^ i
CICLO_MAS INX
LDA ^ max
SUBA (X)
BRNS PROSEGUI
LDA (X)
STA ^ max
PROSEGUI LDA ^ i
INCA
STA ^ i
CMPA ^ n
BRNZ CICLO_MAS
RTS

Lassemblatore inserir in automatico le istruzioni:

LDS = address_area_stack
JMP start_address

allinizio del programma, e:

JMP sistema_operativo
al posto della direttiva #STOP.
92 Capitolo secondo

Lultima direttiva utile per comprendere due aspetti della architettura che
sono stati fino a questo momento trascurati:
- come inserire un programma in memoria prima che il processore MP
possa eseguirlo;
- cosa accade quanto tale programma termina coerentemente con lipotesi
fatta sul ciclo del processore che prevede che dopo una fase execute ci sia
sempre una fase fetch successiva.
Per rispondere alla prima domanda si potrebbe far riferimento ai primi sistemi
di calcolo che erano dotati di un lettore di nastro di carta perforato e di due pulsanti
di LOAD e di RUN. Il programmatore era costretto a scrivere il proprio
programma su di un nastro di carta con un sistema perforatore che faceva un buco
ogni volta che un bit era uguale ad uno. Scritto il nastro lo caricava con il pulsante
di LOAD nella memoria centrale del sistema di calcolo e solo al termine del
travaso poteva avviare la CPU con il comando di RUN. Per eseguire un altro
programma si doveva ripetere la procedura di caricamento e di avvio. La modifica
ad un programma costringeva il programmatore alla riscrittura dellintero nastro di
carta. La CPU restava a lungo inutilizzata in quanto iniziava lesecuzione solo
quando il pulsante di RUN veniva premuto dalloperatore di sistema.
E anche larchitettura del processore MP potrebbe funzionare nello stesso
modo. Si pu per costruire un programma che affidi proprio a MP lonere di
effettuare il caricamento in memoria delle istruzioni di un altro programma
prelevandole dallinput standard: a caricamento avvenuto la MP pu procedere alla
sua esecuzione per poi ritornare al caricamento di un successivo programma. Si
chiami LOADER il programma di caricamento e UTENTE il programma caricato. In
ogni istante il sistema si trova o ad eseguire il LOADER o lUTENTE.

Figura 31: MP e caricamento programmi

Ad esempio il LOADER per larchitettura MP caratterizzato da:


- occupazione delle prime posizioni di memoria sia per area codice che
dati;
- prima istruzione da eseguire collocata allindirizzo uno;
- caricamento delle programma UTENTE fissata con inizio a partire
dallindirizzo 100;
Il modello di esecutore 93

- riconoscimento di MEM come posizione a partire dalla quale iniziare


il caricamento; per semplicit si assume che lindirizzo di
caricamento venga inserito successivamente a MEM;
- riconoscimento di END come terminazione del caricamento.

Si noti che MEM ed END sono dichiarazioni che vengono introdotte per
guidare il LOADER e non corrispondono quindi a istruzioni che dovranno essere
eseguite da MP. comunque lassemblatore ad introdurle nel programma tradotto
in linguaggio macchina. Il codice del LOADER potrebbe essere allora il seguente.

Caricando le istruzioni a partire dalla prima posizione, la label SIST_OP


assume il valore 10 e tutto il codice del LOADER occupa solo 28 registri di
memoria. Per comprendere il programma di LOADER si effettui il trace nellipotesi
che il programma da caricare sia quello di somma di due numeri. Si supponga che
tale programma sia prodotto dallassemblatore che ha inserito le direttive MEM e
END. Inoltre, per rendere pi leggibile lesempio si sono mantenute le istruzioni in
linguaggio assemblativo invece di riportarne il codice binario prodotto
dallassemblatore.
PI IR ACC SZOC X SP M(80) M(81) M(82) M(83) M(84) M(85) M(100) M(101) M(200) FO FI
2 LDSP 99
=99
3 LDA Prompt> 0000
=Prompt>
4 STA ^80 Prompt>

5 LDA =100 100

6 STA ^81 100


94 Capitolo secondo

7 LDA MEM
=MEM
8 STA ^82 MEM

9 LDA END
=END
10 STA ^83 END

11 LDX ^81 100

12 LDA ^80 Prompt>

13 OUT Prompt>

14 IN LDSP LDSP^999
^999
15 STA ^84 LDSP
^999
16 CMPA ^83 1000

17 BRZ 28

18 LDA ^84 LDSP 0000


^999
19 CMPA ^82 1000

20 BRNZ 24

25 LDA ^84 LDSP 0000


^999
26 STA (X) LDSP
^999
27 INCX 101

28 JMP 11

12 LDA ^80 Prompt>

13 OUT Prompt>

14 IN LDSP JMP100
^999
15 STA ^84 LDSP
^999
16 CMPA ^83 1000

17 BRZ 28

18 LDA ^84 JMP100 0000

19 CMPA ^82 1000

20 BRNZ 24

25 LDA ^84 JMP100 0000

26 STA (X) JMP


100
27 INCX 102

28 JMP 11

12 LDA ^80 Prompt>

13 OUT Prompt>

14 IN MEM MEM

15 STA ^84 MEM

16 CMPA ^83 1000

17 BRZ 28

18 LDA ^84 MEM 0000

19 CMPA ^82 1100


Il modello di esecutore 95

20 BRNZ 24

21 IN 200 0000 200

22 STA ^85 MEM

23 LDX ^85 200 200

24 JMP 11

12 LDA ^80 Prompt>

13 OUT Prompt>

14 IN IN IN

15 STA ^84 IN

16 CMPA ^83 1000

17 BRZ 28

18 LDA ^84 IN 0000

19 CMPA ^82 1000

20 BRNZ 24

25 LDA ^84 IN 0000

26 STA (X) IN

27 INCX 201

28 JMP 11

12 LDA ^80 Prompt>

13 OUT Prompt>

14 IN END END

15 STA ^84 IN

16 CMPA ^83 1100

17 BRZ 28

29 JMP 100

101 LDSP =999

102 JMP 200

201 IN

206 JMP 10

11 LDX ^81 100

12 LDA ^80 Prompt>

13 OUT Prompt>

Tabella 27 Tabella di Trace del LOADER

Nel trace sono state saltate alcune righe perch identiche alle precedenti se
non nei dati inseriti e nei valori di X, aventi valori via via crescenti. Cos non
96 Capitolo secondo

stato condotto il trace del programma UTENTE mostrando solo la sua


terminazione con il salto al LOADER che fa riprendere il caricamento di un
successivo programma in memoria.

Il LOADER stato il primo componente di un insieme di programmi che


hanno consentito al sistema stesso di adempiere a tutta la sua gestione. Tali
programmi sono detti Sistema Operativo. Se le istruzioni del LOADER sono
conservate in una ROM e allatto dellaccensione del sistema si forza il PI ad
assumere il valore zero con circuiteria apposita, vengono ad essere soddisfatte le
condizioni previste dalla fase di boot e necessarie affinch il ciclo del processore
MP possa avere inizio.

Da ultimo si vuole rimuovere lipotesi introdotta riguardante la strutturazione


dei registri in contenitori di informazioni di qualsiasi tipo. Lesempio che segue
confronta una istruzione di MP con un caso reale di processore che opera con
registri di memoria a byte. Nellesempio si fatto ricorso ai codici ASCII dei
caratteri che compongono il messaggio.

Processore MP Processore a Byte


LDA =CIAO LDA =C
OUT OUT
LDA =I
OUT
LDA =A
OUT
LDA =O
OUT

Si comprende dallesempio che lipotesi stata introdotta solo per la


semplificazione degli esempi.
Capitolo terzo

Algoritmi e programmi

3.1. Informatica come studio di algoritmi


Aver definito linformatica come la scienza e la tecnica dellelaborazione dei
dati o, pi in generale, del trattamento automatico delle informazioni, porta
inevitabilmente a riflettere sul fatto che per elaborare linformazione sia necessario
preliminarmente comprendere il modo in cui procedere nella sua elaborazione.
In un tale contesto linformatica allarga i suoi orizzonti diventando lo studio
sistematico dei processi che servono al trattamento delle informazioni o pi in
generale della definizione della soluzione di problemi assegnati. Obiettivo di tale
studio nellordine:
- lanalisi dettagliata di ci che serve al trattamento dellinformazione,
- il progetto di una soluzione applicabile alla generazione di informazioni
prodotte da altre informazioni,
- la verifica della correttezza e della efficienza della soluzione pensata,
- la manutenzione della soluzione nella fase di funzionamento in esercizio.

Se si utilizza il termine algoritmo, introdotto nella matematica per specificare


la sequenza precisa di operazioni il cui svolgimento necessario per la soluzione di
un problema assegnato, allora linformatica diventa lo studio sistematico degli
algoritmi. Va ribadito che tale definizione deve essere considerata in una accezione
pi ampia di quella che pone i calcolatori elettronici al centro dellattenzione,
sebbene linteresse principale dellinformatica quello di rendere comprensibili ed
eseguibili gli algoritmi per un sistema di calcolo.
Il calcolatore tra tutti gli esecutori di algoritmi (compreso luomo) quello
che si mostra pi potente degli altri e con una potenza tale da permettere di gestire
quantit di informazioni altrimenti non trattabili. Ed questa, forse, una delle
possibili chiavi di lettura del ruolo che linformatica va sempre pi a rivestire nelle
societ evolute. Lo studio dellInformatica considera quindi il computer come uno
scienziato utilizza il proprio microscopio: uno strumento per provare le proprie
teorie e, nel caso specifico, verificare i propri ragionamenti o algoritmi.
3.1.1. La soluzione dei problemi
In pochi anni linformatica ha fatto passi da gigante, ed naturale quindi chiedersi
quali sono stati gli aspetti che ne hanno determinato la rapida evoluzione: una
98 Capitolo terzo

evoluzione tanto rapida che oggi le macchine informatiche si incontrano in tutti i


settori produttivi.
Il primo e pi importante aspetto che le macchine informatiche risolvono un
gran numero di problemi in modo pi veloce e conveniente degli esseri umani e
trovare soluzioni a problemi una attivit che impegna luomo quotidianamente.
Senza entrare nel merito della definizione di problema, che si pu considerare
acquisita, possibile per i seguenti noti problemi:
a) preparare una torta alla frutta,
b) trovare le radici di un'equazione di 2 grado conoscendone i coefficienti
a,b e c,
c) individuare il massimo tra tre numeri,
d) calcolare tutte le cifre decimali di ,
e) inviare un invito ad un insieme di amici,
f) individuare le tracce del passaggio di extraterrestri;
osservare che:
1) la descrizione del problema non fornisce, in generale, indicazioni sul
metodo risolvente; anzi in alcuni casi presenta imprecisioni e ambiguit
che possono portare a soluzioni errate;
2) per alcuni problemi non esiste una soluzione;
3) alcuni problemi, invece, hanno pi soluzioni possibili; e quindi bisogna
studiare quale tra tutte le soluzioni ammissibili risulta quella pi
vantaggiosa sulla base di un insieme di parametri prefissati (costo della
soluzione, tempi di attuazione, risorse necessarie alla sua realizzazione,
etc.)
4) per alcuni problemi non esistono soluzioni eseguibili in tempi ragionevoli
e quindi utili.

Nel caso a), seppur ne sia noto il risultato, ossia la torta da gustare, non si
riesce a ricavare alcuna indicazione sulla ricetta da seguire che, tra laltro, non
facile individuare in un libro di cucina per la sua formulazione generica. Il caso b)
un noto e semplice problema di matematica per il quale si conosce chiaramente il
procedimento risolvente. Il caso c) un esempio di problema impreciso ed
ambiguo in quanto non specifica se va cercato il valore massimo o la sua posizione
allinterno della terna dei tre numeri assegnati. Il caso d) invece indicativo di un
problema con una soluzione nota che per non arriva a terminazione in quanto le
cifre da calcolare sono infinite. Per il caso e) si pu osservare che esistono sia
soluzioni tradizionali basate sulla posta ordinaria, che soluzioni pi moderne quali i
messaggi SMS dei telefoni cellulari o i messaggi di posta elettronica. Bisogna
quindi scegliere la soluzione pi conveniente: ad esempio quella che presenta un
costo pi basso. Il caso f) un chiaro esempio di problema che non ammette
soluzione: o, come si dice, non risolvibile.
Comunque tutti i problemi risolvibili presentano una caratteristica comune:
prescrivono la produzione di un risultato a partire da fissate condizioni iniziali
secondo lo schema di figura. Lo schema mette in luce gli elementi che concorrono
alla soluzione dei problemi. Essi sono:
- l'algoritmo, ossia un testo che prescrive un insieme di operazioni od azioni
eseguendo le quali possibile risolvere il problema assegnato. Se si indica
Algoritmi e programmi 99

con istruzione la prescrizione di una singola operazione, allora l'algoritmo


un insieme di istruzioni da svolgere secondo un ordine prefissato;

Figura 1 Algoritmo ed esempi

- l'esecutore, cio l'uomo o la macchina in grado di risolvere il problema


eseguendo l'algoritmo. Ma se un algoritmo un insieme di istruzioni da
eseguire secondo un ordine prefissato, allora lesecutore non solo deve
comprendere le singole istruzioni ma deve essere anche capace di
eseguirle. E pu eseguirle una dopo laltra secondo un ordine rigidamente
sequenziale che impone linizio dellesecuzione di una nuova istruzione
solo al termine di quella precedente; oppure pu eseguire pi istruzioni
contemporaneamente svolgendole in parallelo;
- le informazioni di ingresso (anche dette input), ossia le informazioni che
devono essere fornite affinch avvengano le trasformazioni desiderate;
- le informazioni di uscita (anche dette output), ossia i risultati prodotti
dall'esecutore del dato algoritmo.
3.1.2. La calcolabilit degli algoritmi
Lalgoritmo composto da una sequenza finita di passi che portano alla risoluzione
automatica di un problema. Il singolo passo unazione elaborativa che produce
trasformazioni su alcuni dati del problema. Da un punto di vista generale il
concetto di elaborazione pu sempre essere ricondotto a quello matematico di
funzione Y=F(X) in cui X sono i dati iniziali da elaborare, Y i dati finali o risultati e
F la regola di trasformazione.
Lautoma a stati finiti fornisce unastrazione per il concetto di macchina che
esegue algoritmi ed introduce il concetto di stato come particolare condizione di
100 Capitolo terzo

funzionamento in cui pu trovarsi la macchina. Lautoma uno dei modelli


fondamentali dellinformatica ma applicabile a qualsiasi sistema che evolve nel
tempo per effetto di sollecitazioni esterne. Ogni sistema se soggetto a sollecitazioni
in ingresso risponde in funzione della sua situazione attuale eventualmente
emettendo dei segnali di uscita, leffetto della sollecitazione in ingresso il
mutamento dello stato del sistema stesso. Il sistema ha sempre uno stato iniziale di
partenza da cui inizia la sua evoluzione. Pu terminare in uno stato finale dopo
aver attraversato una serie di stati intermedi.
Un automa M (a stati finiti) pu essere definito da una quintupla di elementi
(Q,I,U,t,w) dove:
- Q un insieme finito di stati interni caratterizzanti levoluzione del
sistema;
- I un insieme finito di sollecitazioni in ingresso;
- U un insieme finito di uscite;
- t la funzione di transizione che trasforma il prodotto cartesiano Q I in
Q (t: QxI Q)
- w la funzione di uscita che trasforma Q I in U (w: QxI U).
Il modello degli automi a stati finiti torva larga applicazione soprattutto per la
capacit di descrivere il comportamento dei sistemi. Alla formulazione matematica
si accompagna una rappresentazione grafica immediata caratterizzata da un grafo
composto da due semplici elementi: un cerchio per rappresentare gli stati del
sistema e degli archi orientati ad indicare le transizioni. Nel grafo si individuano:
- gli stati intermedi rappresentati da cerchi che hanno archi entranti ed
uscenti,
- lo stato iniziale come lunico cerchio che non ha archi entranti;
- lo stato finale, se esiste, come cerchio che non ha archi uscenti.

Figura 2 Rappresentazioni di un automa

Al grafo pu essere associata una rappresentazione pi matematica in forma


tabellare con tante righe quanti sono gli ingressi, e tante colonne quanti sono gli
stati. Nella tabella si indicano gli stati nei quali il sistema si sposta per effetto delle
sollecitazioni in ingresso con lindicazione delleventuale uscita prodotta.
Algoritmi e programmi 101

Il modello di automa fornisce un concetto generale di esecutore di azioni.


un modello generico nel quale non sono precisate la natura di ingressi ed uscite
utili ad individuare un insieme di possibili azioni elaborative.
Il modello di Macchina di Turing un particolare automa per il quale sono
definiti linsieme degli ingressi e delle uscite come insiemi di simboli; inoltre
definito un particolare meccanismo di lettura e scrittura delle informazioni. un
modello fondamentale nella teoria dellinformatica, in quanto permette di
raggiungere risultati teorici sulla calcolabilit e sulla complessit degli algoritmi.
La macchina di Turing un automa con testina di scrittura/lettura su nastro
bidirezionale potenzialmente illimitato. Ad ogni istante la macchina si trova in uno
stato appartenente ad un insieme finito e legge un simbolo sul nastro. La funzione
di transizione in modo deterministico, fa scrivere un simbolo, fa spostare la testina
in una direzione o nell'altra, fa cambiare lo stato. La macchina si compone di:
a) una memoria costituita da un nastro di dimensione infinita diviso in celle;
ogni cella contiene un simbolo oppure vuota;
b) una testina di lettura scrittura posizionabile sulle celle del nastro;
c) un dispositivo di controllo che, per ogni coppia (stato, simbolo letto)
determina il cambiamento di stato ed esegue unazione elaborativa.

Figura 3 Macchina di Turing

Formalmente la macchina di Turing definita dalla quintupla:


A, S, fm , fs, fd

dove:
- A linsieme finito dei simboli di ingresso e uscita;
- S linsieme finito degli stati (di cui uno quello di terminazione);
- fm la funzione di macchina definita come A S A;
- fs la funzione di stato A S S;
- fd la funzione di direzione A S D = {Sinistra, Destra,
Nessuna}

La macchina capace di:


- leggere un simbolo dal nastro;
- scrivere sul nastro il simbolo specificato dalla funzione di macchina;
- transitare in un nuovo stato interno specificato dalla funzione di stato;
- spostarsi sul nastro di una posizione nella direzione indicata dalla
funzione di direzione.
102 Capitolo terzo

La macchina si ferma quando raggiunge lo stato di terminazione. Definita la


parte di controllo, la macchina capace di risolvere un dato problema. Una
macchina di Turing che si arresti e trasformi un nastro t in uno t rappresenta
lalgoritmo per lelaborazione Y=F(X), ove X e Y sono codificati rispettivamente in
t e t.
Una macchina di Turing la cui parte di controllo capace di leggere da un
nastro anche la descrizione dellalgoritmo una macchina universale capace di
simulare il lavoro compiuto da unaltra macchina qualsiasi. Ma leggere dal nastro
la descrizione dellalgoritmo richiede di saper interpretare il linguaggio con il
quale esso stato descritto. La Macchina di Turing Universale diventa cos
linterprete di un linguaggio modellando il concetto di elaboratore di uso generale.
Dalla macchina di Turing discendono alcune tesi, che seppur non dimostrate,
restano fondamentali per lo studio degli algoritmi. La tesi di Church-Turing dice
che non esiste alcun formalismo, per modellare una determinata computazione
meccanica, che sia pi potente della Macchina di Turing e dei formalismi ad essi
equivalenti. Ogni algoritmo pu essere codificato in termini di Macchina di Turing
ed quindi ci che pu essere eseguito da una macchina di Turing. Un problema
non risolubile algoritmicamente se nessuna Macchina di Turing in grado di
fornire la soluzione al problema in tempo finito. Se dunque esistono problemi che
la macchina di Turing non pu risolvere, si conclude che esistono algoritmi che
non possono essere calcolati. Sono problemi decidibili quei problemi che possono
essere meccanicamente risolvibili da una macchina di Turing; sono indecidibili
tutti gli altri. Se la tesi di Church asserisce che non esiste un formalismo n una
macchina concreta che possa calcolare una funzione non calcolabile secondo
Turing, si conclude che:
- se per problema esiste un algoritmo risolvente questo indipendente dal
sistema che lo esegue se vero che per esso esiste una macchina di
Turing;
- lalgoritmo indipendente dal linguaggio usato per descriverlo visto che
per ogni linguaggio si pu sempre definire una macchina di Turing
universale.
La teoria della calcolabilit cerca di comprendere quali funzioni ammettono
un procedimento di calcolo automatico. Nella teoria della calcolabilit la tesi di
Church-Turing unipotesi che intuitivamente dice che se un problema si pu
calcolare, allora esister una macchina di Turing (o un dispositivo equivalente,
come il computer) in grado di risolverlo (cio di calcolarlo). Pi formalmente
possiamo dire che la classe delle funzioni calcolabili coincide con quella delle
funzioni calcolabili da una macchina di Turing.
La macchina di Turing e la macchina di von Neumann sono due modelli di
calcolo fondamentali per caratterizzare la modalit di descrizione e di esecuzione
degli algoritmi.
La macchina di Von Neumann fu modellata dalla Macchina di Turing
Universale per ci che attiene alle sue modalit di computazione. La sua memoria
per limitata a differenza del nastro di Turing che ha lunghezza infinita. La
macchina di Von Neumann, come modello di riferimento per sistemi non solo
teorici, prevede anche la dimensione dellinterazione attraverso i suoi dispositivi di
input ed output.
Algoritmi e programmi 103

3.1.3. La trattabilit degli algoritmi


Calcolabilit e trattabilit sono due aspetti importanti dello studio degli algoritmi.
Mentre la calcolabilit consente di dimostrare lesistenza di un algoritmo risolvente
un problema assegnato ed indipendente da qualsiasi automa, la trattabilit ne studia
la eseguibilit da parte di un sistema informatico. Infatti esistono problemi
classificati come risolvibili ma praticamente intrattabili non solo dagli attuali
elaboratori ma anche da quelli, sicuramente pi potenti, del futuro. Sono noti
problemi che pur presentando un algoritmo di soluzione, non consentono di
produrre risultati in tempi ragionevoli neppure se eseguiti dal calcolatore pi
veloce. Sono noti altri problemi la cui soluzione di per s lenta e quindi
inaccettabile.
Il concetto di trattabilit legato a quello di complessit computazionale con
la quale si studiano i costi intrinseci alla soluzione dei problemi, con l'obiettivo di
comprendere le prestazioni massime raggiungibili da un algoritmo applicato a un
problema. La complessit consente di individuare i problemi risolvibili che siano
trattabili da un elaboratore con costi di risoluzione che crescano in modo
ragionevole al crescere della dimensione del problema. Tali problemi vengono
detti trattabili. Nello studio della trattabilit delle soluzioni dei problemi due sono i
tipi di complessit computazionale fra loro interdipendenti che consentono di
misurare gli algoritmi:
- la spaziale intesa come la quantit di memoria necessaria alla
rappresentazione dei dati necessari allalgoritmo per risolvere il problema;
- la temporale intesa come il tempo richiesto per produrre la soluzione.
Oggi la complessit spaziale non viene pi presa in grande considerazione in
quanto i sistemi moderni presentano memorie di grandi capacit. La complessit
temporale un indicatore della velocit di risposta di un elaboratore (detta anche
efficienza). Si noti che lefficienza non un parametro che va considerato in
assoluto ma nel relativo del contesto nel quale il problema viene risolto. Un
algoritmo trattabile se fornisce risposte in tempi che siano utili allambiente
circostante. Tra due soluzioni di uno stesso problema una soluzione pi efficiente
dellaltra se produce i risultati in minor tempo.
La complessit di un algoritmo corrisponde quindi a una misura delle risorse
di calcolo consumate durante la computazione ed tanto pi elevata quanto
maggiori sono le risorse consumate. Le misure possono essere statiche se sono
basate sulle caratteristiche strutturali (ad esempio il numero di istruzioni)
dellalgoritmo e prescindono dai dati di input su cui esso opera. Sono invece
misure dinamiche quelle che tengono conto sia delle caratteristiche strutturali
dellalgoritmo che dei dati di input su cui esso opera.
Un primo fattore che incide sul tempo impiegato dallalgoritmo per produrre
un risultato, o tempo di esecuzione, sicuramente la quantit di dati su cui
lalgoritmo deve lavorare. Per questa ragione, il tempo di esecuzione solitamente
espresso come una funzione f(n) della dimensione n dei dati di input. Si dir, ad
esempio, che un algoritmo ha un tempo di esecuzione n2 se il tempo impiegato
pari al quadrato della dimensione dellinput. Ma da sola la dimensione dei dati di
input non basta. Infatti il tempo di esecuzione dipende anche dalla configurazione
dei dati in input oltre che dalla loro dimensione. Si possono allora fare tre tipi di
analisi:
104 Capitolo terzo

- analisi del caso migliore per calcolare il tempo di esecuzione quando la


configurazione dei dati presenta difficolt minime di trattamento. Spesso
questo tipo di analisi non fornisce informazioni significative;
- analisi del caso peggiore per calcolare il tempo di esecuzione quando la
configurazione dei dati presenta difficolt massime di trattamento. Si
tratta di unanalisi molto utile, perch fornisce delle garanzie sul tempo
massimo che lalgoritmo pu impiegare;
- analisi del caso medio per calcolare il tempo di esecuzione quando la
configurazione presenta difficolt medie di trattamento.
In generale, nel decidere come caratterizzare il tempo di esecuzione di un
algoritmo, si considerano solo quelle particolari operazioni che rappresentano il
procedimento dominante della soluzione. Ad esse si attribuisce un tempo unitario
di esecuzione per ottenere una misura indipendente da una macchina particolare.
Inoltre ci che veramente importa non la quantit precisa di operazioni effettuate
e di dati trattati, ma come questi crescono al crescere della dimensione dei dati.
Interessa cio sapere come lordine di grandezza del tempo di esecuzione cresce al
limite, ossia per dimensioni dellinput sufficientemente grandi quando la funzione
f(n) tende ai suoi asintoti. Lo studio della condizione asintotica della complessit
di un algoritmo permette ulteriormente di trascurare in un algoritmo operazioni non
significative concentrando lattenzione solo su quelle predominanti. Cos dati due
algoritmi diversi che risolvono lo stesso problema e presentano due diverse
complessit f(n) e g(n), se f(n) asintoticamente inferiore a g(n) allora esiste una
dimensione dellinput oltre la quale lordine di grandezza del tempo di esecuzione
del primo algoritmo inferiore allordine di grandezza del tempo di esecuzione del
secondo. La complessit asintotica dipende solo dallalgoritmo, mentre la
complessit esatta dipende da tanti fattori legati alla esecuzione dellalgoritmo.
Per comprendere la dipendenza della trattabilit dalla complessit temporale si
consideri un elaboratore capace di eseguire un milione istruzioni al secondo (1
MIPS). Per esso si costruisca una tabella in cui le colonne riportano possibili
dimensioni di dati di input e le righe complessit di tipo polinomiale (n, n2, n3, n5)
ed esponenziale (2n, 3n).

10 20 30 40 50
n 0,00001 sec 0,00002 sec 0,00003 sec 0,00004 sec 0,00005 sec
n2 0,0001 sec 0,0004 sec 0,0009 sec 0,0016 sec 0,0025 sec
n3 0,001 sec 0,008 sec 0,027 sec 0,064 sec 0,125 sec
n5 0,1 sec 3,2 sec 24,3 sec 1,7 min 5,2 min
2n 0,001 sec 1,0 sec 17,9 min 12,7 giorni 35,7 anni
3n 0,059 sec 58 min 6,5 anni 3,855 secoli 200.000.000 secoli

Tabella 1 Complessit temporale

Si nota che gli algoritmi di tipo polinomiale si comportano meglio di quelli


esponenziali. Ma laspetto pi evidente che gli algoritmi con complessit
esponenziale possono operare con dati di piccole dimensione: se i dati crescono
anche di poco essi diventano intrattabili.
Algoritmi e programmi 105

3.2. La descrizione degli algoritmi


Quando si affronta un problema di fondamentale importanza, qualunque sia
l'esecutore (uomo o macchina), capire preliminarmente se il problema ammette
soluzioni e successivamente, nel caso ne ammetta, individuare un metodo
risolutivo (algoritmo) e, infine, esprimere tale metodo in un linguaggio
comprensibile all'esecutore a cui rivolto.
Alcune di tali attivit rientrano nelle consuetudini della vita quotidiana. Per
rendersene conto, si pu chiedere ad un amico di correggere gli errori lessicali
presenti nel testo di figura 4a. Si pu ad esempio suggerire di svolgere una dopo
l'altra le azioni della figura 5. Ci si accorge allora di usare naturalmente costrutti
che fissano l'ordine in cui le diverse azioni devono essere svolte. Il pi semplice tra
essi quello che stabilisce che le azioni devono essere svolte una dopo l'altra.
Nell'esempio, tale ordine, fissato dalla numerazione delle frasi ma pu anche
coincidere con quello lessicografico, ossia quello che naturalmente si adotta
leggendo un qualsiasi testo nel mondo occidentale: si scorrono i righi dall'alto
verso il basso e si impone che ogni rigo contenga un comando o unistruzione per
l'esecutore. Si chiameranno tali costrutti col nome di costrutti di sequenza. Altri
costrutti possono per stravolgere l'ordine sequenziale. Nell'esempio, un altro
costrutto stabilisce che alcune azioni devono essere svolte solo se si verificano
determinate condizioni (la frase se la parola sbagliata, allora correggila,
altrimenti non fare niente prescrive la correzione soltanto in presenza di un
errore). Si chiameranno tali costrutti con il nome di costrutti di selezione. Infine, un
ultimo costrutto usato in figura dice che alcune azioni devono essere ripetute un
numero di volte prestabilito (per ogni parola del rigo fai) o determinato dal
verificarsi di certe condizioni (ripeti le azioni da 1) a 4) fino alla terminazione del
testo). Si chiameranno tali costrutti con il nome di costrutti iterativi.
In tutti gli algoritmi si possono individuare due classi fondamentali di frasi:
- quelle che prescrivono la esecuzione di determinate operazioni;
- e quelle che indicano all'esecutore l'ordine in cui tali operazioni devono
essere eseguite.
Alle prime si dar il nome di istruzioni, mentre alle seconde quello di schemi
di controllo, o istruzioni di controllo o anche strutture di controllo.
L'esempio conferma che molti degli strumenti necessari per esprimere gli
algoritmi sono noti essendo essi parte del linguaggio naturale. E tutti i linguaggi
usati per comunicare algoritmi ai calcolatori, detti linguaggi di programmazione,
avranno una parte della loro grammatica composta di costrutti del tipo di quelli
illustrati nellesempio precedente. Cambier la sintassi della specifica frase ma non
la tipologia dei costrutti disponibili anche perch, a differenza del linguaggio
naturale, per il quale il significato delle frasi dipende fortemente dal contesto in cui
vengono usate, i linguaggi di programmazione hanno una semantica indipendente
dal contesto dovendo essere chiaro e deterministico leffetto che ogni frase deve
produrre.
106 Capitolo terzo

Figura 4a - Testo da correggere Figura 4b - Testo


corretto

Figura 5 - Un algoritmo di correzione del testo di figura 2

Cos nella vita quotidiana spesso ci si confronta con descrizioni di


procedimenti da seguire (ad esempio una ricetta di cucina o il libretto di istruzione
del telefonino) o si portati a descrivere programmi di lavoro, come, in modo pi
specialistico, gli esperti dellinformatica fanno per prescrivere al calcolatore cosa
deve fare per risolvere uno specifico problema.
Nella soluzione di un problema la difficolt maggiore consiste, allora,
nell'individuare un algoritmo e nel dimensionarlo alle capacit dell'esecutore. Tra
laltro luso di un linguaggio per scrivere e comunicare algoritmi tanto pi
difficile quanto minori sono le capacit dell'esecutore a cui rivolto. Si possono
allora classificare le istruzioni anche in funzione dello stretto legame esistente tra
istruzioni e capacit dellesecutore definendo:
- elementari quelle istruzioni che l'esecutore in grado di comprendere ed
eseguire;
- non elementari quelle non note all'esecutore.
Ovviamente perch un'istruzione non elementare possa essere eseguita
dall'esecutore a cui rivolta, deve essere specificata in termini pi semplici. Il
procedimento che trasforma una istruzione non elementare in un insieme di
istruzioni elementari, prende il nome di raffinamento o specificazione
dell'istruzione non elementare. Il processo di raffinamento molto importante.
Senza di esso si dovrebbero esprimere gli algoritmi direttamente nel linguaggio di
programmazione disponibile. E molte volte tale linguaggio ha una potenza
espressiva tanto bassa o talmente artificioso da concentrare l'attenzione pi verso
le difficolt di uso del linguaggio, che verso l'individuazione dell'algoritmo
Algoritmi e programmi 107

risolutivo. Invece, l'individuazione e la descrizione di un algoritmo deve avvenire


per passi: prima lo si esprime usando il linguaggio naturale e poi si continua con un
procedimento di raffinamenti che procede fino a che tutte le istruzioni non
elementari contenute nell'algoritmo sono definite in termini di istruzioni
appartenenti al "repertorio" dell'esecutore. Ovviamente tutti i raffinamenti devono
essere integrati al posto delle istruzioni non elementari che li hanno generati perch
si abbia lalgoritmo nella versione da affidare allesecutore per lesecuzione.
3.2.1. Sequenza statica e dinamica di algoritmi
Le operazioni che compongono un algoritmo devono essere dotate delle seguenti
caratteristiche:
- finitezza: ossia devono avere termine entro un intervallo di tempo finito
dall'inizio della loro esecuzione;
- descrivibilit: ossia devono produrre, se eseguite, degli effetti descrivibili,
per esempio fotografando lo stato degli oggetti coinvolti sia prima che
dopo lesecuzione delloperazione;
- riproducibilit: ossia devono produrre lo stesso effetto ogni volta che
vengono eseguite nelle stesse condizioni iniziali;
- comprensibilit: ossia devono essere espresse in una forma comprensibile
all'esecutore che deve eseguirle.
Ne discende che lintero algoritmo, come insieme di operazioni, gode delle
stesse propriet di finitezza, descrivibilit, riproducibilit e comprensibilit.
L'algoritmo serve a risolvere un problema permettendo all'esecutore (uomo o
macchina) di eseguirlo senza essere necessariamente coinvolto nella sua
definizione. L'esecuzione di un algoritmo da parte di un esecutore si traduce in una
successione di azioni che vengono effettuate nel tempo. Si dice che l'esecuzione di
un algoritmo evoca un processo sequenziale, cio una serie di eventi che occorrono
uno dopo l'altro, ciascuno con un inizio e una fine identificabili. Si definisce
sequenza di esecuzione la descrizione del processo sequenziale. La sequenza di
esecuzione l'elenco di tutte le istruzioni eseguite, nell'ordine di esecuzione, e per
questo motivo viene anche detta sequenza dinamica. Ad esempio, nel caso
dell'algoritmo di calcolo delle radici di un'equazione di 2 grado viene evocato un
unico processo sequenziale, descritto da una sola sequenza di esecuzione che
coincide proprio con la descrizione dell'algoritmo.

Calcolo
d b 2 4ac
Calcolo la prima radice come
b d
x1
2a
Calcolo la seconda radice come
b d
x2
2a

Esempio 1 Algoritmo per il calcolo delle radici di unequazione di 2 grado


108 Capitolo terzo

L'esempio mostra un caso semplice con una sola sequenza di esecuzione.


Solitamente un algoritmo evoca pi sequenze di esecuzioni. In alcuni casi il
numero di sequenze di esecuzione pu essere infinito e il programma non ha una
terminazione. Lanalisi delle sequenze dinamiche serve proprio a capire se un dato
algoritmo abbia o meno una terminazione. Se si modifica lalgoritmo di calcolo
delle radici di una equazione di 2 grado per controllare la esistenza di radici reali,
si comincia ad osservare come esso genera comportamenti diversi dipendenti dal
valore dei dati di input a, b e c.

Calcolo
b2 4ac
Se 0
Allora Calcolo
d
Calcolo la prima radice come
b d
x1
2a
Calcolo la seconda radice come
b d
x2
2a
Altrimenti Calcola radici complesse
Esempio 2 Algoritmo per il calcolo delle radici di unequazione di 2 grado

In questo caso il processo evocato non pi fisso, ma dipende dai dati iniziali
da elaborare. Difatti sono possibili le due sequenze di esecuzione mostrate di
seguito.

Calcolo
b2 4ac
Verifico che 0 risultata vera
Calcolo
d
Calcolo la prima radice come
b d
x1
2a
Calcolo la seconda radice come
b d
x2
2a

Calcolo
b2 4ac
Verifico che 0 risultata non vera
Calcolo radici complesse

Esempio 3 Possibili sequenze di esecuzione per lalgoritmo per il calcolo delle radici di
unequazione di 2 grado
Algoritmi e programmi 109

A seconda che i valori assegnati ai coefficienti forniscano un discriminante


positivo o nullo e negativo. Uno stesso algoritmo ha quindi generato due sequenze
di esecuzione tra loro diverse. Si consideri adesso lalgoritmo seguente che
schematizza un gioco che si fa con le 52 carte francesi e che viene detto solitario
del carcerato per il fatto che non riesce quasi mai o solo dopo molto tempo.

Fintantoch (il mazzo ha ancora carte) ripeti:


Mischia le carte
Prendi 4 carte dal mazzo e disponile sul tavolo di gioco
Se (le 4 carte hanno la stessa figura) allora levale dal tavolo di gioco

Esempio 4 Algoritmo per il solitario del carcerato

Si comprende che il gioco ha termine quando tutte le carte sono state


eliminate. Si osservi che se si fortunati si eliminano le carte al primo tentativo
evocando la sequenza di esecuzione nellesempio 5, mentre, se sono uguali al
secondo tentativo si ha a sequenza di esecuzione dellesempio 6, o dopo n tentativi
usando una notazione pi sintetica si ha la sequenza nellesempio 7. Infine, el caso
sfortunato di non trovare mai quattro carte uguali si ha la sequenza di esecuzione
nellesempio 8.

Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata vera
Tolte le 4 carte dal tavolo di gioco
Esempio 5 Sequenza di esecuzione per lalgoritmo per il solitario del carcerato

Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata falsa
Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata vera
Tolte le 4 carte dal tavolo di gioco
Esempio 6 Sequenza di esecuzione per lalgoritmo per il solitario del carcerato

ripetuto n-1 volte


Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata falsa
Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata vera
Tolte le 4 carte dal tavolo di gioco
Esempio 7 Sequenza di esecuzione per lalgoritmo per il solitario del carcerato

ripetuto infinite volte


Mischiate le carte
Prese le 4 carte dal mazzo e messe sul tavolo di gioco
Verificato che (le 4 carte hanno la stessa figura) risultata falsa
Esempio 8 Sequenza di esecuzione per lalgoritmo per il solitario del carcerato
110 Capitolo terzo

L'esempio mostra che un algoritmo pu prescrivere pi di una sequenza di


esecuzione. Se poi l'algoritmo prescrive un processo ciclico, ossia la ripetizione di
un insieme di operazioni, allora pu accadere che il numero di sequenze sia
addirittura infinito. In questo caso l'algoritmo prescrive un processo che non ha mai
termine.
In un programma (che la descrizione dell'algoritmo in un linguaggio di
programmazione) la sequenza lessicografica (anche chiamata sequenza statica)
delle istruzioni (descrizione delle azioni da svolgere nel linguaggio di
programmazione) descrive una pluralit di sequenze dinamiche differenti.
Il numero di sequenze dinamiche non noto a priori e dipende dai dati da
elaborare. La valutazione sia del tipo che del numero delle sequenze dinamiche di
fondamentale importanza per valutare soluzioni diverse dello stesso problema in
modo da poter dire quale di esse presenta un tempo di esecuzione migliore, e per
poter affermare se una soluzione ha terminazione o meno.

3.3. I linguaggi di programmazione


Un programma la descrizione di un algoritmo in un linguaggio comprensibile al
processore macchina e linguaggio di programmazione tale linguaggio. Il
linguaggio di programmazione quindi una notazione formale per descrivere
algoritmi e, come ogni linguaggio, dotato di un alfabeto, un lessico, una sintassi
ed una semantica.
L'aspetto formale del linguaggio si manifesta soprattutto nella presenza di
regole rigide per la composizione di programmi a partire dai semplici caratteri
dell'alfabeto. L'insieme di queste regole costituisce la grammatica del linguaggio.
Un limitato e fondamentale insieme di queste regole definisce la struttura lessicale
del programma come formato da unit elementari, cio le parole del linguaggio. Il
lessico, quindi, permette di strutturare l'insieme limitato dei caratteri dell'alfabeto
in uno pi vasto, il vocabolario, fatto di simboli aventi una notazione pi leggibile
e comprensibile per chi li usa. L'organizzazione delle parole in frasi invece
guidata da regole che compongono la sintassi del linguaggio. Infine l'attribuzione
di un significato alle frasi oggetto delle regole semantiche.
Un programma, cos come l'algoritmo che esprime, dunque una sequenza di
frasi, ognuna delle quali specifica operazioni che l'esecutore (computer) pu
comprendere ed eseguire. La natura delle frasi o istruzioni dipende dal linguaggio
di programmazione che si usa.
Esistono oggi numerosi linguaggi di programmazione, ed ognuno ha un
proprio repertorio di istruzioni. Ovviamente, quanto pi semplice il linguaggio,
tanto pi semplice il processore che lo deve interpretare; invece quanto pi
sintetico il linguaggio, tanto pi semplice risulter descrivere un qualsiasi
algoritmo. In un computer il linguaggio pi semplice quello che direttamente
compreso dalla CPU. Chiameremo linguaggio macchina tale linguaggio per
evidenziare il suo stretto legame con l'hardware. Il linguaggio macchina offre da un
lato il vantaggio di un'alta velocit di esecuzione e di una ottimizzazione nell'uso
delle risorse hardware, e dall'altro lo svantaggio di non permettere la trasportabilit
dei programmi tra processori differenti, di non permettere cio che un programma
scritto per una data CPU possa essere eseguito da una CPU con caratteristiche
diverse. Programmare in linguaggio macchina non facile sia perch le istruzioni
Algoritmi e programmi 111

esprimono funzionalit tanto elementari che la costruzione di ogni algoritmo


richiede un gran numero di comandi, sia perch la CPU comprende istruzioni
espresse sotto forma di sequenze di bit (ad esempio 1001100111111111 potrebbe
indicare la somma di due numeri). Per superare questa ultima difficolt al
programmatore offerta la possibilit di usare i linguaggi assemblativi che pur
mantenendo uno stretto legame con le potenzialit offerte dal linguaggio macchina,
rendono la programmazione a questo livello pi agevole in quanto sostituiscono
alle sequenze di bit dei codici mnemonici pi facili da interpretare e ricordare. I
linguaggi macchina e assemblativi sono anche comunemente detti linguaggi di
basso livello, in quanto si pongono al livello della macchina. Essi, come gi
descritto, comunicano direttamente con la CPU, utilizzando i codici operativi
(binari o mnemonici) dello stesso processore, comportando difficolt di scrittura e
di verifica del corretto funzionamento dei programmi.
Per ovviare alla difficolt di programmare in linguaggi di basso livello, sono
nati dei linguaggi di programmazione che, con istruzioni pi sintetiche, ossia con
istruzioni pi vicine al tradizionale modo di esprimere i procedimenti di calcolo da
parte di un essere umano, rendono l'attivit di programmazione pi semplice; per il
fatto che questi linguaggi sono pi comprensibili dagli uomini che non dalle CPU,
li chiameremo linguaggi di alto livello. Essi fanno uso di uno pseudo-linguaggio
umano, utilizzando per il loro scopo parole-chiave o codici operativi ispirati quasi
esclusivamente alla lingua inglese. Ovviamente ci facilita molto sia la stesura che
la rilettura di un programma, ma non mette il computer in condizione di capire
direttamente il programma. Per ottenere il risultato finale dunque necessario
applicare un interprete che traduca il linguaggio simbolico e decisamente pi
sintetico, in reali istruzioni interpretabili dalla CPU. A tale scopo si potrebbe
pensare di migliorare le capacit della CPU fino a fargli interpretare il linguaggio
stesso. Ma questa risulterebbe una soluzione poco economica (per la complessit
della CPU) e poco flessibile (un piccolo cambiamento nel linguaggio
costringerebbe a buttar via la CPU). Allora la soluzione pi adottata quella di
tradurre i programmi espressi nei linguaggi di alto livello, in programmi espressi in
linguaggio macchina; la traduzione pu essere svolta dallo stesso computer che
poi esegue il programma, o addirittura da un computer completamente diverso.
Cos, la scrittura dei programmi in linguaggio di alto livello fa in modo che essi
non dipendano pi dalla CPU. E' difatti sufficiente che ciascuna CPU abbia il suo
traduttore o interprete per garantire che lo stesso programma sia eseguito da
macchine diverse. Il traduttore pi semplice chiaramente quello che mette in
corrispondenza i codici mnemonici del linguaggio assemblativo con le sequenze di
bit corrispondenti comprensibili dalla CPU: tale traduttore detto assemblatore.
Poich quanto pi di alto livello sono i linguaggi, ossia quanto pi sono vicini
all'uomo, tanto pi facile l'attivit di programmazione (svolta dall'uomo) e pi
difficile la loro traduzione (svolta dalla macchina), a partire dagli anni cinquanta
sono stati proposti e progettati, diversi linguaggi di programmazione.

3.4. I metalinguaggi
I metalinguaggi sono particolari tipologie di linguaggi con i quali si presentano le
regole della grammatica di un qualsiasi linguaggio. Un metalinguaggio descrive
quindi le propriet sintattiche e semantiche relative a un altro linguaggio o al
112 Capitolo terzo

linguaggio stesso. I pi diffusi sono la notazione Backus Normal Form o BNF e le


carte sintattiche.
La BNF, sviluppata da John Backus e Peter Naur nel 1960, prescrive che le
frasi, che compongono un linguaggio, possono essere specificate a partire da un
unico simbolo iniziale di alto livello. Ogni simbolo di alto livello (non terminale)
pu essere sostituito da una frase fra un insieme di sottofrasi, comprendenti simboli
sia non terminali che di basso livello (terminali), mentre i simboli terminali non
possono essere sostituiti. Il processo si arresta quando si ottiene una sequenza di
soli simboli terminali. Il linguaggio definito da una BNF costituito cos da tutte le
sequenze di simboli terminali ottenute applicando questo processo a partire dal
simbolo iniziale di alto livello. I simboli non terminali sono racchiusi fra parentesi
angolari (<), i terminali fra virgolette ("), le diverse alternative per un non
terminale sono separate da una barra verticale (|) e il segno := indica le possibili
sostituzioni per il non terminale. Ad esempio:

<Frase> := <Soggetto> <Predicato verbale> <Complemento oggetto>

dice che una frase si compone di un soggetto, di un predicato verbale e di un


complemento oggetto. Le espressioni che seguono specificano quali sono i
possibili valori dei simboli non terminali:

<Soggetto> := io | tu | mario
<Predicato verbale> := "mangia" | beve
<Complemento oggetto> := mela | lacqua

Una frase costruita seguendo le indicazioni delle espressioni del BNF sono
frasi corrette del linguaggio.
Una estensione della BNF, detta Extendend BNF (EBNF), stata introdotta da
Niklaus Wirth per specificare la sintassi del linguaggio di programmazione Pascal.
Nella EBNF i simboli {, }, (, ) e * possono comparire nel lato destro di una frase.
Una sequenza di simboli racchiusa fra {} indica che tale sequenza opzionale,
mentre un simbolo, o una sequenza racchiusa fra (), seguito da *, indica un
numero arbitrario di ripetizioni della sequenza, incluso 0.
Le carte sintattiche sono invece uno strumento di tipo grafico usate per la
descrizione delle regole del linguaggio. Una carta sintattica un grafo in cui linee
orientate uniscono delle scatole di formato differente: seguendo le frecce ed
interpretando opportunamente il contenuto delle scatole si costruiscono frasi
sintatticamente corrette. Le scatole rettangolari in figura sono dette simboli non
terminali in quanto il loro contenuto non compare direttamente nelle frasi. Esse
fanno riferimento ad altre carte sintattiche (quelle il cui nome coincide col
contenuto della scatola) che virtualmente devono essere inserite nella posizione
assunta dal nodo del grafo.
Le scatole tonde della figura sono dette simboli terminali n quanto contengono
caratteri o sequenze di caratteri che devono apparire direttamente nella frase, nella
posizione assunta dal nodo del grafo.
Algoritmi e programmi 113

Figura 6 Simboli Terminali (a) e Non Terminali (b) per le carte sintattiche

Le carte sintattiche non solo permettono un rapido apprendimento delle regole


della grammatica del linguaggio grazie allimmediatezza fornita dalla
rappresentazione di natura grafica, ma mettono anche nella condizione di scoprire
facilmente eventuali errori presenti nella frase. Difatti cos come data una carta si
in grado di costruire una frase corretta del linguaggio, partendo dalla frase si pu
controllarne la correttezza ed in caso negativo si pu anche individuare la causa
degli errori.

3.5. La programmazione strutturata


Un esecutore esegue un processo se:
a) stato progettato lalgoritmo che descrive come il processo deve essere
svolto;
b) l'algoritmo stato espresso con un opportuno linguaggio di
programmazione (programma) ad esso comprensibile.
Il ruolo degli algoritmi fondamentale se si pensa che essi sono indipendenti
sia dal linguaggio in cui sono espressi sia dal computer che li esegue. Si pensi ad
una ricetta per una torta alla frutta:
- il procedimento lo stesso indipendentemente dall'idioma usato;
- la torta prodotta la stessa indipendentemente dal cuoco.
Il linguaggio di programmazione e il computer hanno lo scopo di far
comprendere l'algoritmo e di far eseguire il processo. Ovviamente anche i
computer e i linguaggi di programmazione sono importanti. Gli sviluppi
tecnologici consentono di realizzare computer capaci di eseguire gli algoritmi in
modo pi rapido, pi economico e pi affidabile, rendendo esplorabili nuove aree
applicative. Linguaggi di programmazione pi sintetici rendono pi facile il
compito di esprimere gli algoritmi, con conseguente diminuzione dello sforzo
umano speso nella programmazione.
Ma tra gli aspetti o le propriet degli algoritmi da valutare con pi attenzione
sicuramente il pi importante proprio il progetto che si presenta come onerosa
attivit intellettuale (molto pi onerosa di quella di esprimere l'algoritmo con un
linguaggio di programmazione) che richiede creativit ed intuito. E si noti che non
esiste un algoritmo per il progetto degli algoritmi. Un altro aspetto la valutazione
della complessit della soluzione individuata: se ci sono algoritmi diversi per
descrivere lo stesso processo, la complessit ci dice quale di essi migliore,
ossia quale viene eseguito nel minor tempo con la minima occupazione di
memoria, pi in generale con il miglior utilizzo di tutte le risorse disponibili.
Inoltre, lo studio della correttezza un altro aspetto importante che ci consente di
valutare l'aderenza della soluzione alle specifiche del problema. Essere sicuri della
114 Capitolo terzo

correttezza un'attivit tanto pi complessa quanto pi complesso risulta il


progetto dell'algoritmo.
Negli ultimi anni, il settore informatico stato caratterizzato da un notevole
incremento della produzione del software nei riguardi dell'hardware, e questo si
riflette sui costi di un sistema informatico. Con queste premesse risulta necessario
evitare di produrre software in base alle esperienze e/o alle iniziative del
programmatore: il processo di produzione del software non pu essere un processo
di tipo artigianale (negli anni '60 il programmatore usava mille trucchi per
risparmiare memoria!), ma deve servirsi di metodologie e tecniche sistematiche di
progettazione e programmazione con fissati parametri di qualit e in maniera
standard.
La software engineering (ingegneria del software) la branca dell'Ingegneria
Informatica che raccoglie il patrimonio di metodi e tecniche per la produzione del
software.
Il processo di industrializzazione del software, introducendo metodi e
standard, riduce i margini di creativit e personalismo e consente una produzione
che soddisfi i seguenti requisiti:
- buon livello qualitativo;
- produttivit medio-alta;
- impiego di personale non troppo specializzato (la specializzazione
fornita dallo standard);
- riduzione sensibile del costo del prodotto.
In questo modo la produzione del software non risulta dissimile da quella di
un qualsiasi prodotto industriale e anche per esso si pu introdurre il concetto di
ciclo di vita. Con il termine ciclo di vita del software si intende l'insieme delle
fasi attraverso le quali si sviluppa il prodotto software come schematizzato nella
figura seguente.

Figura 7 Fasi del ciclo di vita di un software


Le fasi del ciclo di vita del software ruotano intorno all'idea di prodotto
concentrandosi sulla sua progettazione, la sua produzione e infine il suo
mantenimento in vita.
Nell'ambito della software engineering si sono sviluppate tecniche, metodi e
metodologie. Le tecniche mettono a disposizione un linguaggio e degli standard
Algoritmi e programmi 115

che supportano normalmente alcune fasi del processo di produzione del software. I
metodi consistono in un insieme di tecniche il cui uso guidato da indicazioni
formali. Le metodologie comprendono un insieme di tecniche il cui uso guidato
da regole procedurali ben precise. Le metodologie, a partire dalla formulazione del
problema, consentono:
- di individuare gli oggetti da elaborare e l'algoritmo;
- formulare oggetti e algoritmo in modo non ambiguo;
- progettare oggetti e algoritmi nell'ambiente disponibile.
L'obiettivo principale della programmazione strutturata consiste nella
costruzione di programmi con le seguenti caratteristiche:
- leggibilit: un programma non esaurisce la propria esistenza dopo poche
esecuzioni. Pertanto deve essere comprensibile ad altri programmatori;
- documentabilit: un programma deve contenere al suo interno il
significato e la motivazione di tutte le scelte di progetto effettuate;
- modificabilit: un programma deve essere strutturato in modo da
permettere un rapido adattamento ad una eventuale variazione di alcuni
parametri del progetto;
- provabilit: un programma deve essere costruito in modo da facilitare le
attivit di testing e debugging (controllo della correttezza e correzione
degli errori) fin dalle prime fasi del progetto software.
Comunque, si noti che la regola fondamentale per ottenere programmi di
buona qualit di eliminare tutti quei particolari che inficiano la costruzione logica
del programma e quindi la sua chiarezza. Le caratteristiche fondamentali della
programmazione strutturata sono:
- la modularit,
- l'uso di strutture di controllo ad un ingresso e ad una uscita,
- l'applicazione del metodo top-down o di quello bottom-up nella fase di
progettazione.
La modularizzazione ci dice che un programma deve essere composto di
moduli funzionali. Ogni modulo funzionale deve possedere un singolo e ben
precisato compito. Ogni modulo inoltre deve essere dotato di un solo ingresso e di
una sola uscita. La modularizzazione comporta una regolarit della struttura dei
programmi ed un valido supporto per la fase di progetto, in quanto rispecchia la
limitazione degli esseri umani ad esaminare un solo aspetto di un problema alla
volta.
Le strutture di controllo sono da considerarsi degli schemi di composizione
dei moduli costituenti il programma. Esse devono assolutamente avere un solo
ingresso ed una sola uscita. Tale condizione discende dalla necessit che un
modulo, composto dall'integrazione di altri moduli tramite le strutture di un
controllo, abbia un solo punto di ingresso ed un solo punto di uscita cos come i
singoli moduli componenti. Un valido contributo alla scelta delle strutture di
controllo stato apportato dal teorema di Bhm e Jacopini.
Il top-down e lo stepwise refinement costituiscono il modo procedurale di
raggiungimento della soluzione. Tale approccio parte dalla considerazione che la
complessit di un problema da risolvere non consente di tener conto
contemporaneamente di tutte le decisioni realizzative. Sar quindi necessario
procedere per raffinamenti successivi procedendo dal generale al particolare.
Ovvero: si analizza il problema al pi alto livello possibile di astrazione
116 Capitolo terzo

individuandone gli elementi pi importanti e supponendo di avere a disposizione


un sistema adatto ad eseguire gli elementi funzionali individuati. Ogni elemento,
a sua volta, diventa il problema da analizzare subendo una suddivisione in
problemi pi elementari. Il procedimento continua fino a raggiungere un livello di
scomposizione comprensibile all'esecutore (o software del sistema in uso).

Figura 8 Approccio Top Down

In figura 8 si riporta un esempio di approccio top-down e step-wise


refinement per il semplice problema del calcolo di una percentuale. Si pu notare
che si procede dal livello astratto definito dall'utente (liv. 1) fino alla procedura
dettagliata prossima all'esecutore (liv. 3) attraverso raffinamenti successivi. In
questo modo la soluzione ad un problema si presenta come un albero in cui :
- la radice corrisponde al problema,
- i nodi rappresentano le differenti decisioni di progetto,
- le foglie, infine, vengono associate alla descrizione della soluzione in
modo comprensibile all'esecutore.

Figura 9 Soluzione di un approccio Top-Down


Esiste un altro approccio per il raggiungimento della soluzione. Il metodo
bottom-up difatti parte considerando il sistema reale a disposizione e creando man
mano moduli elementari che opportunamente integrati formano moduli capaci di
compiere operazioni pi complesse. Il procedimento continua fino a quando stato
creato un modulo che corrisponde proprio alla soluzione del problema. Ripensando
alla struttura ad albero, come se si procedesse dalle foglie verso la radice.
Algoritmi e programmi 117

Figura 8 Approccio Bottom-Up

Senza entrare nel merito dei due metodi possiamo sicuramente affermare che
mentre il top-down un metodo deduttivo, quindi pi adatto alla media degli esseri
umani, il bottom-up un metodo induttivo che richiede molta intuizione ed
inventiva.
3.5.1. La progettazione dei programmi di piccole dimensioni
La progettazione dei programmi costituisce un'attivit complessa che richiede
un'attenta fase di analisi del problema e un continuo processo di valutazione delle
decisioni che in ogni momento vengono prese.
Una delle esigenze maggiormente sentita quella di una separazione netta, in
fase progettuale, tra il cosa (analisi dei requisiti e specifiche funzionali) e il
come (progetto a diversi livelli di dettaglio). In effetti la distinzione tra il cosa
e il come comune a qualsiasi tipo di progetto ed un modo per esprimere con
altre parole la separazione fra analisi e sintesi.
Nell'ambito di un progetto software, l'analisi richiede la capacit di acquisire
tutte le informazioni necessarie alla comprensione del problema e di strutturarle in
un modello che esprima, in un linguaggio adeguato, una rappresentazione coerente
e completa di cosa si deve fare.
Molto spesso, in passato, queste informazioni erano frutto di conoscenze
generiche dell'analista sui problemi da affrontare, proprio perch questa fase
veniva ritenuta di poco peso e si passava subito a scelte di realizzazione. Le
informazioni, viceversa, devono essere ricavate sia dai colloqui con gli utenti di
qualsiasi livello, ovvero con coloro che sono coinvolti nell'uso del programma sia a
livello direttivo che esecutivo, che da un esame dell'ambiente in cui il programma
sar utilizzato: queste attivit costituiscono la cosiddetta fase di definizione dei
requisiti.
Il compito dell'analista , a questo punto, quello di trarre, dall'insieme confuso
e a volte contraddittorio di esigenze ed obiettivi, un modello che esprima il
problema con un formalismo atto ad aumentarne la comprensibilit. Questo
modello dovrebbe contenere sia i requisiti funzionali (cosa deve fare il programma
118 Capitolo terzo

e su quali dati deve operare) sia i requisiti non funzionali (quali prestazioni il
programma deve offrire) e dovrebbe fornire un'indicazione delle priorit con le
quali i requisiti, funzionali o no, devono essere presi in considerazione.
Il passaggio dall'acquisizione dei requisiti alla formulazione del modello
rappresenta la cosiddetta fase di analisi di un problema.
Il progetto, invece, richiede la capacit di prendere decisioni che permettano
di realizzare un programma che soddisfi tutti i requisiti funzionali, nei limiti
stabiliti dai requisiti non funzionali. Ai fini della manutenibilit del prodotto,
necessario evitare sconfinamenti dalla fase di analisi a quella di progetto, ovvero
non si devono assumere decisioni atte a definire la soluzione di un problema
(progetto), mentre si sta ancora definendo il problema stesso (analisi); tali scelte,
infatti, sono difficilmente documentabili. In tal modo si opera una separazione, di
tipo verticale, fra le attivit di analisi e quelle di progettazione utile ad riduzione
delle difficolt. Ricapitolando, i motivi alla base di tale separazione sono:
- la possibilit di documentare in maniera completa i requisiti del problema
e quindi, indirettamente, le scelte della fase di progetto;
- l'impossibilit d'inficiare i risultati dell'analisi a causa di scelte anticipate
di progetto;
- la possibilit di rendere indipendente l'analisi dai vincoli di realizzazione.
Un'altra distinzione, in senso orizzontale, avviene fra dati e funzioni che
rappresentano gli aspetti duali, ma strettamente legati, di ogni problema che si
esamina; tale separazione dovuta sia a ragioni intrinseche, in quanto dati e
funzioni sono caratterizzati da propriet differenti, che a ragioni metodologiche in
quanto opportuno trattare separatamente funzioni da un lato e dati dall'altro, in
modo da ottimizzarne gli aspetti relativi in maniera indipendente dai
condizionamenti che, viceversa, un'analisi complessiva comporterebbe.
Ricapitolando, la separazione orizzontale tra dati e funzioni consente di ottenere:
- l'esame accurato dell'aspetto semantico dei dati;
- la completezza dell'analisi, in quanto essa viene compiuta da differenti
punti di vista;
- l'assicurazione che dati e funzioni assumano il loro giusto peso in analisi e
non si enfatizzino gli uni rispetto agli altri.
Le problematiche discusse riguardano sia i progetti software di grandi
dimensioni che la stesura di un semplice programma. Pertanto verr fornita una
descrizione di criteri applicabili alla realizzazione di programmi di piccole
dimensioni quali quelli che nel testo saranno presentati.
Linsieme di tali criteri non pu considerarsi come una metodologia di
progettazione ma un primo approccio introduttivo utile alla comprensione delle
problematiche di carattere generale. Nel seguito, i concetti introdotti verranno
applicati come approccio metodologico alla progettazione dei programmi.
In particolare le principali fasi dello sviluppo di un programma possono essere
ricondotte a:
- fase di analisi dei requisiti e delle funzioni
- fase di progetto
- analisi critica della soluzione
La fase di analisi dei requisiti e delle funzioni ha lo scopo di definire in
maniera non ambigua cosa il programma deve fare. la fase pi importante in
quanto solitamente i problemi si presentano in una forma alquanto imprecisa ed
Algoritmi e programmi 119

fondamentale che le imprecisioni siano eliminate quanto prima per evitare che esse
incidano sulle fasi successive del progetto. Infatti i costi di correzione degli errori
aumentano quanto pi si avanza nel progetto e sono massimi se erroneamente si
risolve un problema diverso da quello desiderato. allora necessario, per scoprire
le ambiguit, verificare che ogni aspetto delle specifiche abbia un'unica
interpretazione nel contesto delle applicazioni che si descrivono ed effettuare delle
esemplificazioni degli effetti delle trasformazioni tra dati di ingresso e dati di
uscita. Tali esemplificazioni costituiscono la base per un confronto del programma
con l'utente che permette di verificare la correttezza delle specifiche. Sempre ai fini
della correttezza occorrer:
- verificare che nelle specifiche non vi siano inconsistenze;
- verificare che le specifiche coprano tutte le possibili situazioni coinvolte
nel problema.
Al termine della fase di analisi si deve disporre della documentazione su:
- la definizione dei dati di ingresso al problema;
- la definizione dei dati in uscita dal problema;
- la descrizione di un metodo risolutivo che sulla carta risolva le specifiche
del problema.
La fase di progetto pu iniziare solo dopo un'accurata fase di definizione dei
requisiti e si articola nelle attivit di raffinamento successivo dei dati e
dell'algoritmo. Si gi detto che la scelta delle strutture dati con cui rappresentare
gli oggetti coinvolti dal problema gioca un ruolo fondamentale nella scelta
dell'algoritmo risolutivo. Inizialmente va scelta la struttura astratta che risponde in
maniera pi naturale alle caratteristiche del problema. Successivamente, tra tutte le
realizzazioni possibili occorrer scegliere quella che opera il compromesso ottimo
dal punto di vista della efficienza e della comprensibilit. Per affrontare la scelta in
modo adeguato fondamentale la conoscenza del numero e tipo di operazioni sui
dati previste dal problema. Costruire un algoritmo equivale ad esaminare una
specifica realt (il problema assegnato), costruirne un'astrazione, e infine
rappresentare una tale astrazione in maniera formale in un linguaggio di
programmazione. Se il problema complesso, le varie scelte di astrazione e di
rappresentazione si sovrappongono, cosicch non si riesce pi a controllare il
processo di progettazione dei programmi. In genere la mente umana non in grado
di tenere contemporaneamente sotto controllo gli effetti intrecciati di tutte le scelte
che occorre effettuare. La tecnica top-down si presenta come un approccio guida
con l'obiettivo preciso di ridurre la complessit e di offrire uno strumento di
composizione di un'architettura modulare dei programmi. Il modo di procedere di
tale approccio una diretta applicazione del metodo analitico deduttivo che si
rilevato, storicamente, il pi adatto alla media degli esseri umani. Una tale tecnica,
come gi visto. viene anche detta per raffinamenti successivi (step-wise
refinement), in quanto consente di trasformare un problema in una gerarchia di
problemi di difficolt decrescente associando a tale gerarchia di problemi una
gerarchia di linguaggi per la descrizione dell'algoritmo. Ogni passo di raffinamento
implica alcune decisioni progettuali ed importante che queste decisioni siano rese
esplicite e che il programmatore sia conscio del criterio decisionale adottato e
dell'esistenza di soluzioni alternative. Fra i criteri progettuali vanno menzionati la
chiarezza e la regolarit della struttura del programma.
120 Capitolo terzo

Un criterio guida nel processo di raffinamento per passi consiste nel


decomporre quanto pi possibile le decisioni per distinguere aspetti che sono
soltanto formalmente interdipendenti e per ritardare pi a lungo possibile quelle
decisioni che concernono dettagli di rappresentazione.
Un modo di procedere quello per livelli di astrazione. L'astrazione consiste
nell'estrazione di dettagli essenziali mentre vengono omessi i dettagli non
essenziali. Ogni livello della decomposizione presenta una visione astratta dei
livelli pi bassi in cui i dettagli vengono spinti, quanto pi possibile, ai livelli
ancora pi bassi. I moduli di livello pi alto specificano gli obiettivi di qualche
azione oppure cosa deve essere fatto, mentre quelli di livello pi basso descrivono
come l'obiettivo verr raggiunto. Il modulo pi basso nella gerarchia della struttura
del programma dipende dal linguaggio con cui si lavora. Tale approccio aiuta cos
a rendere il programma pi versatile, isolando la dipendenza dalla macchina in
pochi moduli a basso livello. Il passo di raffinamento iterativo produce, a partire
dal problema, una prima decomposizione dell'algoritmo e prosegue con successivi
raffinamenti, sempre pi vicini all'espressione finale dell'algoritmo nel linguaggio
di programmazione. E durante le varie decomposizioni possono essere introdotte
strutture dati necessarie alla definizione dell'algoritmo; per esse valgono le
considerazioni fatte sul raffinamento dei dati. Ad ogni passo della decomposizione
si devono organizzare i sottoproblemi in:
- sequenza; quando dall'analisi del problema ci accorgiamo che l'insieme
delle attivit devono essere svolte una di seguito all'altra;
- alternativa; quando si deve scegliere tra una o pi attivit;
- iterativa; quando una o pi attivit devono essere eseguite pi volte.
Ogni sottoproblema che si individua pu essere espresso con una frase del
linguaggio naturale sintetica ed espressiva (se si vogliono ritardare decisioni di
progetto relative all'implementazione della funzionalit individuata), o direttamente
con un insieme di istruzioni del linguaggio di programmazione (se la funzionalit
facilmente descrivibile). Nel primo caso il sottoproblema diventa un nuovo
problema da affrontare e per esso devono essere riapplicati tutti i criteri di
decomposizione descritti. In particolare, devono essere definite e documentate le
variabili di ingresso e di uscita e le specifiche funzionali di ogni sottoproblema.
Inoltre deve essere posta particolare attenzione alle interfacce tra i vari
sottoproblemi in modo che i risultati di un sottoproblema siano coerenti in numero
e tipo con i dati di ingresso del sottoproblema posto in sequenza.
Lanalisi critica l'ultima fase dell'approccio metodologico. In essa occorre
effettuare una minuziosa valutazione della soluzione adottata. Dapprima si verifica
la correttezza della versione dell'algoritmo, mediante ad esempio una simulazione
della sua esecuzione con il trace fissando un set di dati in ingresso.
Successivamente possibile compiere una valutazione dell'efficienza della
soluzione adottata confrontandola con altre soluzioni oppure studiando l'impatto di
una particolare scelta di progetto. Ognuna delle azioni descritte deve essere
opportunamente documentata in modo che unitamente alle specifiche iniziali si
possa avere a disposizione un insieme esaustivo di specifiche utilizzabili per una
futura ristrutturazione dell'algoritmo.
Algoritmi e programmi 121

3.5.2. La documentazione dei programmi


La documentazione dei programmi lo strumento fondamentale per la chiarezza e
la leggibilit dei programmi. Tali caratteristiche di leggibilit consentono:
1) una pi semplice comprensione di quale sia il problema che il programma
risolve e quindi della correttezza del programma stesso;
2) una pi semplice prosecuzione del progetto ogni qualvolta lo si sia
interrotto;
3) una pi elementare comunicazione delle scelte di progetto;
4) una pi semplice modificabilit del programma al variare delle specifiche
del problema.
La regola principale della documentazione, e forse anche la pi disattesa,
quella di produrre la documentazione nel corso stesso del progetto in quanto si pu
essere certi della efficacia e della completezza della documentazione soltanto se si
documentano le scelte nel momento in cui esse vengono fatte. Inoltre, un'altra
regola importante da seguire quella di inserire la documentazione quanto pi
possibile all'interno del programma in modo che viva con il programma stesso,
cambi e cresca con esso, e quindi sia sempre aggiornata.
Comunque una buona documentazione deve essere articolata in due livelli:
a) documentazione esterna del programma;
b) documentazione interna del programma.
La documentazione esterna il primo livello di documentazione e va
compilato preliminarmente nella fase di analisi dei requisiti. Essa costituisce lo
strumento fondamentale per l'utente del programma in quanto descrive soltanto il
"cosa" fa il programma e non il "come" lo fa. Inoltre, la documentazione esterna
deve segnalare dettagli operativi tali da rendere autonomo l'utente del programma
nell'uso dello stesso. Di essi i pi importanti sono:
a) funzionalit esterne;
b) attivazione del programma;
c) diagnostiche di errore;
d) configurazione richiesta del sistema;
e) indicazione sull'installazione del programma;
f) versione e data di aggiornamento.
La documentazione interna descrive la struttura interna del programma in
termini di scelte sulle strutture dati e sull'algoritmo. Tra le principali tecniche a
disposizione del progettista per generare la documentazione interna del programma
si ricordano:
1) evidenziazione della struttura del programma mediante l'uso
dell'indentazione (indentare un programma significa mettere in evidenza
nel testo del programma, mediante opportuni incolonnamenti, blocchi di
istruzioni che svolgono una funzionalit ben precisa);
2) documentazione top-down, ossia facendo comprendere come il
programma stato generato attraverso i vari raffinamenti;
3) uso di nomi di variabili autoesplicativi, ossia tali da spiegare il ruolo da
esse svolte nel corpo del programma;
4) commento del programma attraverso le frasi di commento di cui tutti i
linguaggi di programmazione sono dotati. Queste frasi consentono di
descrivere il significato di un blocco di istruzioni (motivazioni) o
122 Capitolo terzo

specificare lo stato in cui si trovano le variabili del programma tutte le


volte che il controllo passa per il punto individuato dalla linea di
commento (asserzioni).
Le motivazioni vanno utilizzate all'inizio di ciascun frammento di programma
che realizzi una funzionalit significativa. Infatti, hanno lo scopo di spiegare cosa il
frammento di programma si accinge a calcolare indipendentemente da come lo
calcola.
Le motivazioni possono essere evidenziate anteponendo alla frase di commento la
sigla M:.
(*M: calcolo la somma degli n numeri*)
(*M: inverto la matrice *)
Particolarmente importante il commento di motivazione globale posto
all'inizio del programma in cui si descrive in modo succinto il problema che il
programma risolve.
Si osservi che l'applicazione della tecnica top-down comporta una generazione
pressoch naturale dei commenti motivazione. Infatti le frasi del linguaggio
naturale, introdotte durante le fasi di decomposizione, diventano le motivazioni
delle istruzioni che le specificano nel raffinamento successivo.
Le asserzioni devono essere inserite al termine di ciascun frammento di
programma in quanto consentono di definire lo stato di una o pi variabili a seguito
dell'esecuzione delle istruzioni precedenti. Una frase di questo tipo ha lo scopo di
chiarire le relazioni logiche che sussistono tra le variabili in quel punto del
programma e pu essere espressa anteponendo alla frase di commento la sigla "A:".

(*A: X=A*2+C-1 con A>C*)

Si noti che la derivazione delle relazioni logiche tra le variabili obbliga ad una
comprensione profonda del significato del programma. Per questo motivo le
asserzioni possono essere utilizzate per effettuare una prova qualitativa della
correttezza del programma. Tra tutte le asserzioni particolare cura va posta su
quelle riguardanti le variabili di input in quanto con esse si specificano le
condizioni limite nelle quali la soluzione adottata si trover a lavorare.
Capitolo quarto

La struttura dei programmi

4.1. Le frasi di un linguaggio di programmazione


Tutti i linguaggi di alto livello prevedono quattro tipologie di frasi diverse:
- le istruzioni che tradotte in linguaggio macchina indicano al processore le
operazioni da svolgere;
- le strutture di controllo che definiscono lordine di esecuzione delle
istruzioni;
- le frasi di commento che permettono lintroduzione di frasi in linguaggio
naturale utili a rendere pi comprensibili i programmi ad un lettore
umano; le frasi di commento non vengono tradotte in linguaggio
macchina e si distinguono in asserzioni e motivazioni; le asserzioni sono
commenti destinati a fissare in un punto del programma lo stato di una o
pi informazioni. Per tale motivo permettono di chiarire le condizioni
nelle quali vengono scritte le istruzioni successive. Le motivazioni sono
invece commenti destinati a chiarire le ragioni e/o gli obiettivi per i quali
il blocco di programma, successivo al commento, viene scritto. In altri
termini, un'asserzione si riferisce alle conseguenze delle elaborazioni che
la precedono, mentre la motivazione serve a dire a priori cosa si intende
fare con le istruzioni successive;
- le dichiarazioni con le quali il programmatore da ordini al traduttore del
linguaggio di programmazione; anche le dichiarazioni non vengono
tradotte in linguaggio macchina poich servono solo a guidare il processo
di traduzione.
4.1.1. Le dichiarazioni
Tra le tante dichiarazioni le pi importanti sono quelle con cui si definiscono le
variabili sulle quali si svolgono le elaborazioni dellalgoritmo. Ad una variabile
corrisponde una porzione di memoria la cui dimensione e le cui regole di uso
dipendono dal suo tipo.
La definizione di tipo consente di introdurre dei modelli degli oggetti della
realt in quanto ne fornisce le caratteristiche strutturali (cosa sono) e funzionali (a
cosa servono).
Una definizione di tipo di dato sufficientemente rigorosa e particolarmente
adatta agli usi di tipo che verranno fatti in seguito la seguente: per tipo di dato
si intende un insieme di valori associati a delle operazioni definite su di essi. Con
124 Capitolo quarto

le definizioni di tipo possibile trattare l'informazione in maniera astratta, cio


prescindendo dal modo concreto con cui essa rappresentata all'interno di una
macchina. In molti linguaggi esistono dichiarazioni per la definizione di tipi:

type t = T;

dove t il nome del nuovo tipo e T un descrittore di tipo, cio un costrutto


sintattico del linguaggio atto a definire il tipo t. Il descrittore T pu essere anche un
tipo gi definito o predefinito nel linguaggio, in modo da introdurre dei tipi
sinonimi.
L'istanziazione di variabile avviene poi semplicemente con frasi dichiarative
come quella seguente:

var v : T;
4.1.2. Le frasi di commento
Le frasi di commento sono frasi in linguaggio naturale prive di ogni valore
esecutivo o dichiarativo che consentono di migliorare la leggibilit e la chiarezza
del programma. Si distinguono in asserzioni e motivazioni.
Le asserzioni sono commenti destinati a fissare in un punto del programma lo
stato di una o pi variabile. Per tale motivo permettono di chiarire le condizioni
nelle quali vengono ad operare le istruzioni successive. Le asserzioni sono molto
importanti per controllare la correttezza dei programmi.
Le motivazioni sono invece commenti destinati a chiarire le ragioni e/o gli
obiettivi per i quali il blocco di programma, successivo al commento, viene scritto.
Le motivazioni sono essenziali perch un programma possa essere compreso da
altre persone.
In altri termini, un'asserzione si riferisce alle conseguenze delle elaborazioni
che la precedono, mentre la motivazione serve a dire a priori cosa si intende fare
con le istruzioni successive.
Per indicare le frasi di commento si usano delle sequenze di caratteri
(marcatori) che indicano linizio (ad esempio /* in C o (* in Pascal) e la fine
(rispettivamente */ e *) ) del commento che cos pu occupare pi righi. In alcuni
casi il commento occupa un solo rigo ed allora lo si indica con un solo marcatore
iniziale (ad esempio // del C). Le due modalit possono coesistere nello stesso
linguaggio.
I linguaggi non forniscono strumenti per specificare il tipo di commento: per
farlo il programmatore potr anteporre alla frase la notazione A: per le asserzioni
e M: per le motivazioni come gli esempi seguenti illustrano.

(*A: alfa deve avere valore negativo *)


/*A: i>=10 implica condizione di errore */
x= totale / numero_elementi //M: Calcolo della media
4.1.3. Listruzione di calcolo ed assegnazione
Con le istruzioni elementari di calcolo ed assegnazione si prescrive il calcolo di
una qualche espressione con memorizzazione del risultato. In tutti i linguaggi di
programmazione essa presente in una forma del tipo:
La struttura dei programmi 125

v espressione;

che indica che lesecutore deve prima risolvere lespressione presente nel
secondo membro e, solo quando ne ha prodotto il risultato, assegnare questultimo
alla variabile v posta a primo membro. Listruzione viene anche scritta in una delle
forme seguenti:

v := espressione;
v = espressione;

Lesecuzione in due tempi distinti e successivi del calcolo dellespressione e


della memorizzazione del risultato consente di scrivere istruzioni del tipo:

i = i + 1;

Infatti lesecutore prima opera sul secondo membro (somma uno al valore di i)
e poi deposita il risultato in i: per cui se in i si trova 5 prima dello svolgimento
dellistruzione, al suo termine si trover 6.
4.1.4. I costrutti di controllo
I costrutti di controllo indicano all'esecutore l'ordine in cui le operazioni devono
essere eseguite. Essi devono essere scelti in modo da rispecchiare quanto pi
possibile i meccanismi che naturalmente vengono usati quando si descrive (ad
esempio in italiano) una qualsiasi successione di operazioni. Essi si dividono in
costrutti di sequenza, selezione ed iterazione.
Il costrutto di controllo pi semplice quello che specifica che due o pi
operazioni (elementari o no) devono essere eseguite una dopo l'altra. Tali costrutti
sono detti costrutti di sequenza e vengono indicati nel seguente modo:

PRIMA stacca il contatore


POI sostituisci la presa
QUINDI riattacca il contatore

o anche con una notazione pi compatta che usa il carattere punto e virgola
come indicatore dell'istruzione successiva:

stacca il contatore;
sostituisci la presa;
riattacca il contatore
Il punto e virgola consente anche di scrivere pi azioni della sequenza su di
uno stesso rigo:

stacca il contatore; sostituisci la presa;


riattacca il contatore
126 Capitolo quarto

Se poi si vuole marcare la funzionalit che l'intera sequenza rappresenta,


indicandone precisamente l'inizio e la fine, si possono introdurre le due parentesi
BEGIN ed END o le parentesi graffe come di seguito riportato.

BEGIN
stacca il contatore; stacca il contatore;
sostituisci la presa; sostituisci la presa;
riattacca il contatore riattacca il contatore
END

L'uso delle parentesi importante per evidenziare le varie parti dell'algoritmo


e non perdere traccia dell'eventuale processo di raffinamento, migliorando cos la
leggibilit del programma complessivo. Difatti il blocco presentato si pu vedere
come raffinamento dell'istruzione non elementare:

(*M: operazioni di intervento su presa elettrica *)

Inoltre un programma composto con blocchi di questo tipo anche pi


facilmente gestibile perch la correzione, sostituzione o modifica di un blocco
richiede un intervento locale alla coppia di parentesi.
I costrutti condizionali consentono di subordinare l'esecuzione di una certa
operazione al verificarsi o meno di una specificata condizione. La struttura di
selezione pi semplice quella tra due alternative:

SE (la carta scoperta quadri)


ALLORA vinci
ALTRIMENTI perdi

o anche, con un'altra notazione, tipica dei linguaggi di programmazione:

IF (la carta scoperta quadri)


then vinci
else perdi

In alcuni casi i costrutti di sequenza possono prescrivere la selezione di una


sola operazione:

SE (hai fame) IF (hai fame)


ALLORA mangia then mangia

Altre volte, invece, si pu voler selezionare un'operazione tra pi di due


alternative:
NEL CASO (in cui il colore del semaforo) CASE (colore del semaforo) OF
ROSSO: fermati ROSSO: fermati
VERDE: passa l'incrocio VERDE: passa l'incrocio
GIALLO: passa con prudenza o fermati GIALLO: passa con prudenza o fermati
END
La struttura dei programmi 127

I costrutti iterativi prescrivono di ripetere l'esecuzione di una o pi


operazioni; tale ripetizione viene sospesa al verificarsi di un evento. Sono costrutti
iterativi:

RIPETI REPEAT
i compiti i compiti
FINCHE' (suona la sveglia) UNTIL (suona sveglia)
MENTRE (piove) WHILE (piove)
DEVI usare l'ombrello DO usa l'ombrello
PER (10 giorni) FOR giorni:=1 TO 10
DEVI non venire all'universit DO non venire all'universit

Si osservi che il primo costrutto ha termine quando diventa vera la condizione


(la sveglia suona), il secondo invece quando la condizione diventa falsa (finisce di
piovere). Infine nel terzo esempio il numero di ripetizioni noto a priori:
chiameremo queste iterazioni cicliche o iterazioni enumerative per distinguerle
dalle altre due.
Per poter confrontare costrutti con caratteristiche simili si introducono i
concetti di equivalenza e di equivalenza funzionale. Si dicono equivalenti due
programmi che evocano le stesse sequenze di esecuzione. Sono invece
funzionalmente equivalenti due programmi che, sollecitati nello stesso modo,
producono lo stesso risultato. Si noti che due programmi equivalenti sono anche
funzionalmente equivalenti, mentre non vero, in generale, che due programmi
funzionalmente equivalenti sono anche equivalenti.
Ad esempio i due programmi seguenti:

assegna valore ad x e y; assegna valore ad x e y;


if (x<0) if (y>0)
then stampa il valore di x+y then stampa il valore di x*y
else stampa il valore di x*y else stampa il valore di x/y

producono lo stesso risultato (il prodotto di x per y) se le due variabili sono


positive, e risultati diversi negli altri casi (la somma e la divisione se sono
entrambe negative, la somma o il prodotto e il prodotto e il rapporto se il loro
segno discorde). L'equivalenza funzionale si riferisce cos ad un ben preciso
insieme di valori di ingresso: nel caso delle variabili x e y entrambe positive i due
programmi sono funzionalmente equivalenti, mentre non lo sono negli altri casi.
L'equivalenza funzionale utile per comprendere le differenze tra le varie strutture
di controllo e per giustificare da un punto di vista pratico la necessit di costrutti
simili.
Per quanto riguarda la selezione sempre possibile ricondurre un costrutto if-
then-else ad una sequenza di soli if-then. Cos il costrutto:

if (condizione)
then azione 1
else azione 2
128 Capitolo quarto

che indica che in caso di verit della condizione deve essere svolta la prima
azione, mentre in caso contrario (falsit della condizione) deve essere svolta la
seconda, funzionalmente equivalente alla sequenza dei due if-then:
if (condizione)
then azione 1
if (not condizione)
then azione 2

Le due sequenze non sono equivalenti perch in azione 1 ci potrebbero essere


operazioni che alterano il valore di condizione facendola diventare falsa generando
una sequenza di esecuzione composta da entrambe le azioni. Comunque,
disponendo della prima notazione non ha senso usare la seconda forma perch
meno chiara e sintetica. Inoltre la riscrittura di condizione crea molti problemi di
gestione quali errori che possono avvenire nella scrittura del testo, duplicazione
delle eventuali correzioni, ed altri.
La struttura case, che prescrive la valutazione di una espressione (anche detta
selettore) e la scelta dell'azione a cui stato associato il valore ottenuto da tale
valutazione, pu essere ricondotta ad un insieme di if disposti l'uno dentro l'altro.
Cos il seguente costrutto case:

case (espressione) of
a: azione 1
b: azione 2
c: azione 3
end;
equivalente a:
if (espressione=a)
then azione 1
else
if (espressione=b)
then azione 2
else
if (espressione=c)
then azione 3

che, come si nota, comporta la riscrittura dell'espressione pi volte ed una


notazione molto pi pesante. In genere non vale il passaggio inverso: ossia non
detto che una struttura di if-then-else nidificati (inseriti uno dentro l'altro)
esprimibile con un case. Ad esempio quando le condizioni degli if sono diverse
come nel caso che segue:

if (espressione 1)
then azione 1
else
if (espressione 2)
then azione 2
else
if (espressione 3)
then azione 3
La struttura dei programmi 129

Per quanto riguarda le due strutture iterative while e repeat si noti che
sempre possibile ricondurre l'una all'altra. Il while prescrive prima la valutazione
della condizione e dopo l'esecuzione delle azioni qualora il valore ottenuto sia
vero. Il ciclo termina quando la condizione diventa falsa. evidente che il ciclo
non avviene se la condizione falsa la prima volta che calcolata. Il repeat invece
prescrive l'esecuzione delle azioni e, dopo, la valutazione della condizione per cui
qualsiasi ne sia il valore, le azioni vengono eseguite almeno una volta. La
ripetizione delle azioni termina quando la condizione diventa vera. Si noti che, in
entrambi casi, quando il ciclo ha avuto inizio, si deve far in modo che le azioni
eseguite ad ogni ripetizione alterino le variabili presenti nella condizione se si
vuole che il ciclo termini. Da quanto detto discende che:

repeat Azione
azione while (not condizione)
until (condizione) do azione

sono equivalenti, cos come lo sono:

while (condizione) repeat


do azione if (condizione)
then azione
until (not condizione)

comunque evidente come le strutture presentate per prime siano da preferire


per la loro sinteticit.
Da ultimo, anche la struttura ciclica riconducibile ad una iterativa, e di
conseguenza anche all'altra. Difatti un ciclo iterativo prescrive la ripetizione di
azioni un numero di volte fissato a priori e determinato dal fatto che una variabile
detta contatore di ciclo, a partire da un valore iniziale raggiunge un valore finale o
per valori crescenti (indicato dal to) o decrescenti (indicato dal downto). Allora,
fissato vp<vg (con vp Valore Piccolo e vg Valore Grande), si ha che le strutture
nella colonna di sinistra sono funzionalmente equivalenti a quelle nella colonna di
destra.

for i:=vp to vg i:= vp;


do azione while i<vg
do begin
azione;
i:= i +1
end

for i:=vg downto vp i:= vg


do azione while i>vp
do begin
azione;
i:=i-1
End
130 Capitolo quarto

Si noti per come i costrutti ciclici sono:


- pi espressivi, perch mostrano su una sola linea tutti i parametri che
governano l'iterazione;
- pi sintetici, perch risparmiano la scrittura delle frasi di inizializzazione,
controllo e modifica della variabile;
- pi sicuri, in quanto garantiscono che non si verifichino cicli senza fine
(dovuti ad errori di gestione della variabile contatore di ciclo).
In generale i costrutti ciclici consentono anche di specificare il passo nel caso
sia diverso da 1 con una notazione del tipo:

for i:=vp to vg STEP v


do azione
for i:=vg downto vp STEP v
do azione

4.2. La potenza espressiva


Le strutture di controllo presentate sono state introdotte sulla base di motivazioni
puramente intuitive. Ci si pu chiedere se tale scelta pu in qualche modo essere
giustificata. In particolare possiamo domandarci se le strutture di controllo
introdotte siano sufficienti ad esprimere tutti gli algoritmi che possono interessare e
se siano tutte realmente necessarie.
La risposta a queste domande stata data da Bhm e Jacopini i quali, nel
1966, hanno dimostrato che in pratica tutti gli algoritmi possono essere espressi
utilizzando:
- una sola struttura di sequenza
- una sola struttura selettiva
- un sola struttura iterativa.
Difatti non a caso queste strutture possono considerarsi i tre fondamentali
modelli di pensiero mediante i quali siamo in grado di descrivere qualunque
successione di eventi. Comunque si fa generalmente uso di pi costrutti per ogni
schema di controllo scegliendo in funzione della potenza espressiva e della
praticit d'uso.
Inoltre si pu ulteriormente osservare che alcuni costrutti diventano non
necessari se si introduce nel linguaggio un meccanismo di riferimento delle
istruzioni. In alcuni linguaggi difatti possibile etichettare con un numero o un
nome le istruzioni. L'uso di tali etichette permette di prescrivere che l'istruzione
successiva da eseguire non sia quella scritta nel rigo seguente ma quella
identificata dalla etichetta specificata. Ad esempio nella sequenza:

100 azione 1;
azione 2M
if (condizione)
then goto 100;
azione 3

l'istruzione goto 100 prescrive che l'esecuzione continui con l'istruzione


etichettata con il numero 100 e non con l'azione 3. Nei linguaggi che prevedono
La struttura dei programmi 131

tali istruzioni, dette istruzioni di salto incondizionato, i costrutti sono esprimibili in


termini di if-then opportunamente composto con istruzioni di salto come di seguito
riportato:
if (condizione) if (condizione)
then azione 1 then begin
else azione 2; azione 1;
azione 3 goto 100
end;
azione 2;
100 azione 3
while (condizione) 100 if (condizione)
do azione then begin
azione;
goto 100
end
repeat 100 azione;
azione if (not condizione)
until (condizione) then goto 100
case (espressione) of if (espressione=a)
a : azione 1 then begin
b : azione 2 azione 1;
c : azione 3 goto 100
end; end
azione 4 if (espressione=b)
then begin
azione 2:
goto 100
end
if (espressione=c)
then begin
azione 3;
goto 100
end
100 azione 4

Per lunghi anni il goto stato largamente usato dai programmatori. Poi
Dijkstra, in un suo articolo del 1968, notando che la capacit dei programmatori
era inversamente proporzionale all'uso che facevano del goto, propose con molto
scalpore la sua abolizione dai linguaggi di programmazione. Egli fece notare come
l'uso indiscriminato del goto portasse a dei programmi con molti intrecci, senza un
filo logico, e quindi poco chiari. Difatti con i goto si possono creare blocchi che
hanno pi ingressi e pi uscite, possibile entrare nel mezzo di funzionalit ben
evidenziate nel testo, possibile fare tutto quanto inficia la costruzione logica di un
programma. Ad esempio, nel programma riportato di seguito, si nota come ci siano
tre punti di ingresso (istruzioni etichettate con 100, 200 e 300), due punti di uscita
(goto 400 e la fine della sequenza), e l'interruzione del for (goto 300) nonostante
tale costrutto debba essere usato quando il numero di volte sia fissato a priori.
Tutto ci non favorisce la chiarezza del testo, n una sua facile sostituzione o
modifica ed quindi da evitare. In genere l'uso di goto in avanti (verso istruzioni
132 Capitolo quarto

disposte successivamente nel testo) un modo poco ortodosso di realizzare delle


forme di selezione, mentre salti all'indietro corrispondono alla realizzazione di
forme di iterazione.

100 azione 1;
azione 2;
200 azione 3;
if (condizione 1)
then goto 200
else goto 400;
300 azione 4;
for i:=e1 to es
do begin
azione 5;
if (condizione 2)
then goto 300;
azione 6
end

In alcuni casi non si pu fare a meno di usare il goto: o perch non sono
presenti altri costrutti di controllo o perch, per ragioni dettate dal tipo di problemi
risulta necessario l'abbandono completo di porzioni di programma (per esempio per
segnalare subito errori catastrofici). In questi casi l'uso dell'istruzione di salto deve
essere valutato con molta attenzione e segnalato con appositi commenti. In
conclusione, l'uso dell'istruzione di salto non favorisce la costruzione logica
dell'algoritmo, in quanto non naturale esprimere i propri ragionamenti in termini
di interruzioni in avanti o verso cose ancora da specificare. Per tale motivo il goto
non verr usato. stato presentato in quanto in alcuni casi diventa indispensabile,
nel processo di raffinamento, per la specificazione di quei costrutti che possono
mancare nel linguaggio di programmazione usato per comunicare i programmi
all'esecutore macchina.
In tutti gli esempi che sono stati introdotti per illustrare le strutture di
controllo, stato usato il termine azione per sottolineare il fatto che in quel punto
della struttura pu comparire sia una istruzione semplice che una non elementare,
ossia composta a sua volta da un insieme di altre istruzioni e strutture di controllo.
In altre parole le strutture di controllo possono essere sia disposte in sequenza tra di
loro che inserite le une dentro le altre con una modalit detta di innestamento o
nidificazione. Se sono disposte l'una dopo l'altra, allora dopo aver espletato le
azioni indicate da una struttura di controllo, si procede prendendo in
considerazione quella ad essa successiva nella sequenza statica. Nel caso della seguente
sequenza statica:

I0;
case (espressione) of
1: if (condizione1)
then begin
I1 ;
I2
end
La struttura dei programmi 133

else I3;
5: for i:=1 to 3
do I4
8: I5
end
if (condizione2)
then I6
I f;

le sequenze di esecuzione (si) evocate sono:

s1 s2 s3 s4 s5 s6 s7 s8 s9 s10
I0 I0 I0 I0 I0 I0 I0 I0 I0 I0
I1 I3 I4 I5 I6 I1 I3 I4 I5 If
I2 I6 I4 I6 If I2 If I4 If
I6 If I4 If If I4
If I6 If
If

Tabella 1 Sequenze di esecuzioni evocate

Una sequenza di istruzioni semplici e strutture di controllo detta istruzione


composta. Una istruzione composta pu contenere al suo interno altre strutture di
controllo con una gerarchia che a livello pi alto termina nel programma. Poich le
istruzioni semplici (l'assegnazione di valore, le procedure di input e di output e le
operazioni definite sulle strutture dati) presentano un solo punto di ingresso e di
uscita, la loro composizione attraverso le strutture di controllo IF-THEN-ELSE, IF-
THEN, CASE, REPEAT-UNTIL, WHILE-DO, FOR-DO, porta ad una istruzione
composta che mostra complessivamente ancora un unico punto di ingresso e di
uscita. Tale caratteristica viene anche indicata dicendo che la sequenza di tipo
one-in e one-out. Luso di istruzioni di salto impedisce la costruzione di sequenze
di tipo one-in e one-out.
Il numero di sequenze di esecuzione evocate da una istruzione composta
dipende dal tipo di strutture di controllo utilizzate e dal modo in cui queste sono
composte tra loro. Se le strutture sono considerate singolarmente, allora entrambe
le strutture di controllo IF-THEN-ELSE e IF-THEN generano due sequenze di
esecuzione, il CASE tante sequenze di esecuzione quanti sono i valori previsti per
il selettore, mentre non possibile fare previsioni per le strutture iterative in quanto
il numero di sequenze di esecuzione dipende dai valori che assumono le variabili di
controllo dei cicli durante l'esecuzione. Le tabelle seguenti riportano alcuni
semplici esempi di strutture di controllo selettive disposte in sequenza e innestate
con a lato tutte le sequenze di esecuzione evocate.

s1 s2 s3 s4
if ca then I1 I1 I1 I2 I2
else I2; I3 I4 I3 I4
if cb then I3 If If If If
else I4;
If ;
134 Capitolo quarto

s1 s2 s3 s4 s5 s6 s7 s8
if ca then I1 I1 I1 I1 I1 I2 I2 I2 I2
else I2; I3 I3 I4 I4 I3 I3 I4 I4
if cb I5 I6 I5 I6 I5 I6 I5 I6
then I3 If If If If If If If If
else I4;
if cd
then I5
else I6;
If ;
Tabelle 2,3 Istruzioni selettive e sequenze di esecuzioni evocate

Due sequenze per un solo if, quattro per due e otto per tre. Si comprende
allora che una sequenza di n strutture selettive evoca 2n sequenze di esecuzione.

s1 s2 s3
if ca then I1 I2 I3
if cb then I1 If If If
else I2;
else I3;
If ;

s1 s2 s3 s4
if ca then I1 I2 I3 I4
if cb then If If If If
if cd then I1
else I2;
else I3;
else I4;
If ;

Tabelle 4,5 Istruzioni selettive e sequenze di esecuzioni evocate

Due sequenze per un solo if, tre per due e quattro per tre. Si comprende che un
tale innesto di n strutture selettive evoca n+1 sequenze di esecuzione.
Infine, la tabella seguente mostra come, nel caso di strutture iterative, il
numero di sequenze di esecuzione vari in funzione dei valori assunti, durante
l'esecuzione, dalle variabili che governano le condizioni della iterazione.

s1 s2 s3
I0; (ei=1 es=3) (ei=8 es=0) (ei=50 es=50)
for i:=ei to es I0 I0 I0
do I1; I1 If I1
If ; I1 If
I1
If
Tabelle 5 Istruzioni iterative e sequenze di esecuzioni evocate
La struttura dei programmi 135

4.3. La modularit
L'applicazione della tecnica top-down permette di ottenere un programma
composto da moduli funzionali, ciascuno dei quali realizza un singolo e ben
preciso compito e avente un solo punto di ingresso e di uscita. Una tale
impostazione risulta un valido aiuto per l'attivit di programmazione, in quanto
rispetta la limitazione degli esseri umani che, solitamente, sono in grado di
esaminare un solo aspetto di un problema alla volta. Inoltre, il processo di
raffinamento iterativo produce una gerarchia di sottoproblemi di complessit
decrescente associando ad essa una gerarchia di linguaggi per la descrizione
dell'algoritmo. Difatti, ogni sottoproblema individuato viene espresso con una frase
del linguaggio naturale sintetica ed espressiva per ritardare decisioni di progetto
relative alla sua implementazione.
Un tale approccio per non consente ancora di affrontare in modo adeguato i
seguenti problemi:
- evitare riscritture inutili di sottoproblemi dello stesso tipo in pi punti del
programma;
- integrare soluzioni gi disponibili di alcuni sottoproblemi;
- non perdere la sinteticit delle frasi in linguaggio naturale introdotte per
descrivere i vari sottoproblemi;
- verificare la correttezza della soluzione del problema per passi: ossia
verificando dapprima la correttezza dei singoli sottoproblemi e
successivamente dell'insieme da essi costituito.
Per ovviare a tutti questi inconvenienti, i linguaggi di programmazione
prevedono l'uso dei sottoprogrammi: permettono cio di assegnare ad una sequenza
di istruzioni un nome che pu essere utilizzato come sua abbreviazione e che pu
essere inserito al suo posto nel programma. Inoltre se il nome rappresenta anche un
risultato, che pu essere inserito in una espressione o in una istruzione, il
sottoprogramma viene chiamato funzione: in tutti gli altri casi viene anche
chiamato procedura.
L'indicazione del nome di un sottoprogramma viene chiamata indicazione
della procedura (o della funzione) corrispondente; l'impiego di una procedura in
un programma viene detto chiamata della procedura (quello di una funzione,
viene detto chiamata della funzione). L'indicazione del sottoprogramma si
compone di due parti: il titolo e il corpo. Nel titolo del sottoprogramma vengono
indicati il suo identificatore (il nome) e altre informazioni; il corpo si compone
della sequenza di dichiarazioni e istruzioni denotata dal nome.

sottoprogramma prepara_la crema;

SP1: sbatti le uova con lo zucchero;


SP2: stempera la farina nel latte;
SP3: versa il latte nelle uova e nello zucchero;
SP4: mette sul fuoco e porta ad ebollizione

Queste convenzioni, osservando con attenzione il mondo che ci circonda, si


presentano spesso anche nella realt. Difatti, anche nella vita reale si fa
136 Capitolo quarto

frequentemente ricorso ai riferimenti come mezzo per evitare inutili ripetizioni. Si


consideri per esempio il testo della ricetta di una torta alla frutta ricopiato da un
libro di cucina:

programma torta;

I1: impasta farina, burro, uova, sale e zucchero fino ad ottenere una pasta soffice;
I2: inforna la pasta per una decina di minuti;
I3: prepara_la_crema;
I4: distribuisci la crema sulla sfoglia;
I5: ricopri con frutta di stagione tagliata a dadini e gelatina

Si pu notare nella terza istruzione l'uso del riferimento ad un'altra ricetta che
ha permesso allo scrittore di non perdere tempo a ricopiarla. L'esecutore della torta
dovr:
- spostarsi sulla ricetta della crema quando trova il suo riferimento;
- riportarsi sulla ricetta della torta nel momento in cui ha terminato la
crema.
In altre parole la chiamata di procedura pu essere vista come una particolare
istruzione di salto alla prima istruzione della procedura. La terminazione della
procedura genera poi un ulteriore salto alla istruzione successiva a quella di
chiamata.

Figura 1: Chiamata a Sottoprogramma

Cos la sequenza dinamica evocata in figura risulta essere:

I1;I2;SP1;SP2;SP3;SP4;I4;I5;

L'uso dei sottoprogrammi non serve solo ad abbreviare il lavoro di scrittura,


ma anche, e in modo essenziale, ad articolare, suddividere e strutturare un
programma in componenti fra loro coerenti. Un'adeguata struttura determinante
per la comprensibilit di un programma, soprattutto quando esso complicato e il
La struttura dei programmi 137

testo ha dimensioni che non permettono di scorrerlo con un unico sguardo.


Un'appropriata articolazione in sottoprogrammi indispensabile per una
documentazione comprensibile e per una facile verifica. Difatti un sottoprogramma
rappresenta una precisa e definita funzionalit ed dotato di una altrettanto ben
definita interfaccia con l'esterno. Entrambe queste propriet ne garantiscono il
controllo di correttezza a prescindere dal resto del programma che ne fa uso. Cos
un programma organizzato in sottoprogrammi pu essere pi facilmente
controllato di un programma senza sottoprogrammi per il fatto che l'attivit di
controllo viene dapprima esercitata sui singoli sottoprogrammi e successivamente
sulla loro integrazione. Per questi motivi utile indicare una sequenza di istruzioni
con un sottoprogramma (assegnandole quindi un nome) anche se essa compare in
un sol punto del programma e l'introduzione del sottoprogramma non porta ad un
testo pi breve. L'adozione del metodo top down comporta un uso naturale dei
sottoprogrammi.
Difatti nel passaggio da una frase del linguaggio naturale, o istruzione non
direttamente esprimibile nel linguaggio di programmazione, al suo raffinamento si
pu far ricorso all'uso di procedure o funzioni ogni qualvolta la funzionalit
individuata:
1 viene utilizzata in varie sezioni del programma;
2 gi disponibile in una libreria di sottoprogrammi (si pensi ad una
funzione matematica);
3 pu essere utile inserirla in una libreria per poterla riutilizzare in altri
progetti;
4 dipende fortemente dal particolare elaboratore che si sta usando (si pensi a
funzioni di gestioni del video);
5 deve nascondere le modalit con cui vengono effettuate le elaborazioni al
suo interno, al fine di eliminare turbative all'ambiente esterno per
modifiche interne. Ci viene realizzato mediante comunicazioni con
l'ambiente esterno che avvengono solo attraverso un numero ristretto di
parametri;
6 deve contenere astrazioni sui dati in modo che si possa interagire con un
particolare tipo di dato soltanto attraverso le operazioni di accesso al tipo
senza interessarsi della reale rappresentazione del dato stesso.

L'applicazione di questi criteri consente non solo di migliorare la


comprensibilit del programma finale ma anche e soprattutto la verificabilit (in
particolare i punti 1, 2, 5 e 6), la manutenibilit (in particolare 1, 5 e 6) e la
portabilit del prodotto software (punto 4). Inoltre procedendo in tale modo pi
facile pensare alla suddivisione del lavoro, nel caso in cui il progetto deve essere
realizzato da pi persone.

4.3.1. La parametrizzazione del codice


Spesso accade che una sequenza di istruzioni compaia in punti diversi non
esattamente nella stessa forma. Particolare attenzione merita il caso in cui la
differenza consiste nell'uso di operandi diversi. Si considerino ad esempio le due
sequenze:
138 Capitolo quarto

stampa('Dammi riempimento:'); stampa('Numero fogli :');


leggi(riemp) leggi(num_fogli)

esse differiscono per le costanti da stampare ('Dammi riempimento :' e 'Numero


fogli :') e per le variabili di cui si devono leggere i valori (riemp e num_fogli).
Allora possibile estrarre uno schema comune:

stampa(messaggio);
leggi(x)

definendo parametricamente le variabili su cui operare. In questo modo


possibile ricondurre le due sequenze allo schema, a patto che si crei un
meccanismo che associ rispettivamente:

'Dammi riempimento :' => messaggio


x => riemp

'Numero fogli :' => messaggio


x => num_fogli

Difatti messaggio deve ricevere la stringa da stampare mentre x deve restituire


il valore letto. Si noti che messaggio un parametro di input alla procedura mentre
x di output per essa.
Si definiscono parametri formali gli oggetti utilizzati nel corpo della
procedura. Essi devono essere indicati nel titolo della procedura. Gli oggetti da
sostituire al posto dei parametri formali, prima di ogni esecuzione, sono detti
parametri attuali (o effettivi) e devono essere specificati in ogni chiamata della
procedura o della funzione. Si osservi che esistono vari modi di sostituire i
parametri formali in quelli effettivi.
In altre parole, i parametri formali indicano genericamente su quali oggetti il
sottoprogramma deve agire (servono quindi alla sua formulazione), mentre quelli
effettivi precisano gli oggetti sui quali il sottoprogramma deve effettivamente
operare.
I parametri formali devono riferirsi, durante l'esecuzione del sottoprogramma,
ai parametri effettivi e, perch ci possa avvenire, devono essere compatibili con
essi (devono essere dello stesso tipo). Nel titolo della procedura si specificano sia il
tipo dei parametri che il meccanismo di sostituzione. Inoltre, tra il titolo della
procedura e la sua chiamata si stabilisce una corrispondenza tra la lista dei
parametri effettivi e formali di tipo posizionale: cio al primo parametro effettivo
viene fatto corrispondere il primo parametro formale, e cos via per i successivi. I
parametri attuali devono quindi essere forniti con rispetto di numero, tipo e ordine
rispetto a quelli formali.
La struttura dei programmi 139

I meccanismi di sostituzione, in generale ricadono in una delle tre seguenti


tipologie:
- per valore
- per riferimento (o per variabile)
- per nome.
La sostituzione per valore assegna al parametro formale del sottoprogramma il
valore del corrispondente parametro effettivo. Il parametro effettivo pu essere
un'espressione e come casi particolari di espressione una costante o una variabile.
Se un'espressione, se ne calcola il valore e lo si assegna al corrispondente
parametro formale.
Nel caso di variabili, la sostituzione per valore garantisce che la variabile
passata come parametro effettivo non venga alterata dal sottoprogramma. Difatti il
sottoprogramma dopo averne copiato il valore nella corrispondente variabile
formale al momento della chiamata, lavora in sostanza su una sua copia (il
parametro formale) e tutte le modifiche effettuate su tale copia non riguardano in
alcun modo il corrispondente parametro effettivo. Questo significa che, se il
parametro formale di tipo strutturato, all'atto della chiamata l'intera struttura del
parametro effettivo viene ricopiata in esso, con conseguente consumo di tempo
(per la copiatura) e di spazio (per l'occupazione di memoria della struttura).
La sostituzione per riferimento fornisce al parametro formale del
sottoprogramma l'indirizzo di memoria del corrispondente parametro effettivo. Per
tale motivo il parametro effettivo pu essere soltanto una variabile. A differenza
della sostituzione per valore, il parametro formale non una copia ma
un'informazione attraverso cui si lavora direttamente sul parametro effettivo (tipo
puntatore) e la sua occupazione di memoria esclusivamente quella necessaria per
contenere l'indirizzo del parametro attuale.
Esiste un ultimo meccanismo di sostituzione detto per nome che citiamo
soltanto per motivi di completezza, in quanto, ormai, lo si ritrova soltanto in
pochissimi linguaggi.
Secondo tale modalit il parametro formale viene testualmente sostituito dai
parametri effettivi senza alcuna valutazione. Questa modalit differisce
sostanzialmente dai precedenti meccanismi in quanto la sostituzione non avviene
all'atto della chiamata del sottoprogramma ma durante la sua esecuzione, ogni
qualvolta che esso fa uso del parametro formale. In altre parole come se
avvenisse una riscrittura del sottoprogramma ad ogni sua attivazione in modo da
sostituire l'identificatore del parametro formale con quello del corrispondente
effettivo.
Per quanto concerne la scelta del metodo di sostituzione dei parametri si
possono seguire le seguenti regole base:
- quando un parametro rappresenta un argomento di una procedura, si
sceglie la sostituzione per valore;
- quando un parametro rappresenta invece un risultato, occorre usare la
sostituzione per riferimento.
Osservando tale problema da una visuale differente, possiamo classificare i
parametri formali in:
- parametri di ingresso al sottoprogramma;
- parametri di uscita dal sottoprogramma;
- parametri modificabili dal sottoprogramma.
140 Capitolo quarto

I primi sono parametri che forniscono i valori a partire dai quali il


sottoprogramma inizia le proprie elaborazioni; i secondi rappresentano i risultati da
esso prodotti; infine i terzi sono quelli che contemporaneamente possono
considerarsi di ingresso e di uscita. Una tale classificazione ci torna utile per la
scelta del meccanismo di sostituzione. Difatti, se i parametri sono solo di ingresso
al sottoprogramma conviene scegliere la sostituzione per valore che impedisce
l'alterazione dei parametri effettivi da parte del sottoprogramma. Invece, negli altri
due casi, affinch dopo la chiamata possano essere visibili gli effetti del
sottoprogramma, si deve scegliere la sostituzione per riferimento che permette alle
istruzioni del sottoprogramma di lavorare direttamente sui parametri effettivi. Per
comprendere il modo di scegliere il meccanismo di sostituzione si pensi, ad
esempio, ad uno scrittore che per svolgere la sua attivit pu aver bisogno di un
correttore di bozze per eliminare errori di stampa e di un traduttore per la
traduzione del libro in una lingua diversa dalla sua. Mentre il primo deve produrre
il libro corretto, il secondo deve fornire anche un nuovo libro: quello tradotto. Se
l'autore accorto, prima di fornire il libro al traduttore, ne effettua una fotocopia in
modo che l'originale non sia alterato da qualsiasi cosa il traduttore possa aver
intenzione di fare. Invece, nel caso del libro da correggere, l'autore deve lavorare
sullo stesso libro del correttore se vuole controllare il lavoro svolto. In altri termini,
la sostituzione per riferimento permette a due unit di condividere una stessa area
di lavoro, mentre quella per valore le separa anche se assumono lo stesso valore
solo all'atto dell'attivazione del sottoprogramma.
4.3.2. Le funzioni
Ricapitolando, le procedure sono caratterizzate dalle seguenti propriet:
- sono unit di programma subordinate che sono eseguite solo mediante una
esplicita attivazione (chiamata);
- svolgono compiti ben definiti;
- si interfacciano con il programma chiamante scambiando con esso
informazioni mediante il meccanismo di sostituzione per valore o per
riferimento (accettando cos le informazioni da elaborare e restituendo i
risultati della loro elaborazione).
Da un punto di vista sintattico le procedure sono caratterizzate da:
- dichiarazione del titolo e del corpo;
- esplicitazione nel titolo del meccanismo di sostituzione e del tipo dei
parametri formali;
- meccanismo di attivazione.
Quando una procedura fornisce un unico risultato, pu essere organizzata in
funzione, in modo che il suo nome corrisponda proprio a tale risultato. Per
esempio, si organizzano in funzione le funzioni matematiche che devono essere
utilizzate all'interno del programma, o le espressioni o porzioni di esse che devono
essere usate pi volte all'interno di uno stesso programma. In tali casi si ha che:
- il nome della funzione l'unico risultato della procedura;
- poich il nome della procedura una variabile a tutti gli effetti, deve
essere dotata di un tipo che deve essere indicato nell'intestazione;
- si pu assegnare valore a tale variabile soltanto nel corpo della funzione
stessa;
La struttura dei programmi 141

- si pu usare il valore di tale variabile inserendone il nome in espressioni


che si trovano all'esterno del corpo della funzione.
In altri termini la presenza all'interno della funzione del suo stesso nome nella
parte sinistra di un'assegnazione permette di trasmettere al programma chiamante il
risultato delle sue elaborazioni, mentre il richiamo della funzione avviene
inserendone semplicemente il nome in una espressione. Per esempio, una funzione
che calcola la somma di due numeri potrebbe essere definita da:

funzione somma(a,b:interi):intera

somma:=a+b

ed essere utilizzata in uno dei seguenti modi:


x:=a+somma(3,y)/3;
stampa(somma(alfa,beta));
Ad esempio, considerate le seguenti istruzioni:

Y:=3*XA+LN(XB-1); K:=SIN(Y)+3*Z+LN(M-1)+X;
WRITELN(SQR(X)-9*X+SQR(X1)-10*X1);
Y:=SIN(X0-Y0/2)*9+5*(SIN(X0+1-(Y0+1)/2)*3);
se vengono definite le tre funzioni riportate di seguito:

funzione F1(x,y:reale):reale; funzione F2(x,y:reale):reale; funzione F3(x,y:reale):reale;

F1:=3*x+LN(y-1); F2:=SQR(x)-9*x ; SIN(x-y/2)*3;

si possono riscrivere nella forma:

Y:=F1(XA,XB); K:=SIN(Y)+F1(Z,M)+X;
WRITELN(F2(X)+F2(X1)-1);
Y:=F3(X0,Y0)*3+5*F3(X0+1,Y0+1);

con un notevole miglioramento della leggibilit del programma.


Tutti i linguaggi di programmazione mettono a disposizione del
programmatore alcune procedure o funzioni che sono gi definite all'interno del
linguaggio stesso. Esse non richiedono una definizione esplicita e per questo
motivo vengono anche dette implicite o standard. Solitamente sono funzioni
standard le funzioni matematiche per il calcolo del seno, coseno, logaritmo
naturale, l'esponenziale, il valore assoluto di un numero, la radice quadrata, il
quadrato, ed altre ancora. In genere si ritrovano come funzioni o procedure
predefinite quei moduli che hanno un'alta probabilit di essere impiegati in alcuni
campi di applicazione, per cui lasciarne la definizione all'utente risulterebbe
dispendioso in termini di efficienza complessiva, o che sono indispensabili per la
completa definizione e utilizzazione di costrutti del linguaggio, come per esempio
si pu osservare a proposito dei meccanismi di ingresso e uscita.
D'altro canto si pu notare come l'uso dei sottoprogrammi sia un potente
strumento di espansione del linguaggio in quanto consente al programmatore
l'inserimento in esso di nuove parole chiave, i nomi delle procedure e delle
142 Capitolo quarto

funzioni appunto, la cui definizione indipendente dagli algoritmi che ne fanno


uso. Cos possibile costruire linguaggi con potenze espressive sempre maggiori
con una notevole facilitazione dell'attivit di programmazione. Si noti infine che
tale modo di procedere alla base del metodo induttivo di risolvere i problemi, che
stato chiamato approccio bottom-up.
4.3.3. La visibilit
L'uso dei sottoprogrammi permette di costruire programmi non costituiti da
una unica sequenza di istruzioni ma da una gerarchia di unit di programma (o
anche macchine astratte se si vuole dare risalto al cosa fanno e non al modo in cui
sono realizzate), ciascuna delle quali realizza una particolare istruzione in modo
autonomo, con proprie definizioni di tipi, dichiarazioni di variabili e istruzioni.
Ogni unit forma la base per il livello superiore (le unit che la chiamano) e si
appoggia eventualmente su un livello di macchina inferiore (le procedure che sono
chiamate al suo interno).
Si chiamer programma principale quella unit di programma che si
interfaccia direttamente con il sistema operativo. Nella figura, per esempio, A pu
essere il programma principale, A.1 e A.2 il livello su cui A si appoggia, e A.1.1 e
A.1.2 quello su cui si appoggia A.1.

A.1.1

A.1

A.1.2
A

A.2

Figura 2: Struttura di un prgramma

Evidenzieremo il programma principale racchiudendone gli elementi


fondamentali (dichiarazioni ed istruzioni) nella struttura:

program .......;
.....
begin
.....
end.

mentre abbiamo racchiuso gli elementi di una procedura nella struttura:


La struttura dei programmi 143

procedure .... (...);


.....
begin
.....
end;

o in:

function ..... (....): ....;


.....
begin
.....
end;

se si tratta di una funzione.


In tale ambito, un altro concetto fondamentale sottolinea il ruolo delle
procedure dal punto di vista della strutturazione dei programmi. Spesso, certe
variabili vengono impiegate soltanto all'interno di una sequenza di istruzioni,
mentre non hanno influenza nel resto del programma. La comprensione del
programma aumenta considerevolmente quando la localizzazione delle variabili
posta in chiara evidenza. In ogni caso, i campi di influenza delle variabili (cio,
dove il loro valore influenza l'esecuzione) devono risultare con chiarezza dalla
struttura del programma. Con il termine regole di scope (visibilit) si fa riferimento
a quelle regole che consentono di determinare i campi di influenza di una variabile
(e pi in generale di un qualunque oggetto) in tutte le varie parti costituenti un
programma. In altre parole si dice scope di un oggetto la porzione di programma
che in grado di usarla.
L'organizzazione in procedure il modo pi opportuno per porre in risalto lo
scope degli oggetti. Se un oggetto - una costante, un tipo, una variabile, una
procedura o una funzione - definito ed usato solo all'interno di una determinata
procedura, allora viene detto locale a quella procedura. Se, viceversa, definito
nell'unit di programma chiamante, ma risulta visibile alla procedura chiamata
attraverso qualche meccanismo, allora viene detto non locale alla procedura. Infine
viene detto globale se risulta definito nel programma principale, perch tale unit
l'unica che pu rendere visibili i propri oggetti a tutte le altre in quanto rappresenta
la radice della gerarchia di unit di programma (in altre parole l'unica unit che
chiama tutte le altre e che non chiamata da nessun'altra).
Si noti che non esiste alcun inconveniente se si sceglie per un oggetto locale
ad una unit di programma lo stesso identificatore utilizzato per un altro oggetto di
una diversa unit di programma. Tale caratteristica molto importante poich
senza di essa non soltanto i rischi di errori sarebbero molto grandi, ma sarebbe
praticamente impossibile impiegare procedure di biblioteca o procedure scritte da
altri. Tale propriet deriva dal fatto che un oggetto locale ad una unit di
programma visibile soltanto dalle istruzioni di tale unit e pertanto qualsiasi
modifica del suo valore non visibile all'esterno di essa.
Per quanto riguarda invece gli oggetti che genericamente abbiamo detto non
locali o globali esistono dei meccanismi espliciti o impliciti che consentono di
estendere la visibilit di un oggetto a pi unit di programma. Tali meccanismi
144 Capitolo quarto

differiscono in funzione del modo in cui, nei vari linguaggi, possibile organizzare
il programma nella gerarchia di unit di programma illustrata precedentemente.
A tale proposito esistono dei linguaggi (es. Pascal, Basic) in cui i vari
sottoprogrammi (e funzioni) possono essere inseriti nel corpo del programma
principale. Si definiscono sottoprogrammi interni tale tipo di sottoprogrammi.
Viceversa, esistono altri linguaggi (ad esempio il FORTRAN) in cui ogni unit di
programma risulta staccata da tutte le altre unit di programma. Si definiscono
sottoprogrammi esterni tale tipo di sottoprogrammi.
Nei sottoprogrammi interni esistono dei meccanismi impliciti tali che, se un
identificatore definito in una unit di programma, visibile, allora, da tutte le
unit interne ad essa, salvo il caso in cui esso sia ridefinito localmente in una di
queste unit interne. Ad esempio nel programma:

Procedure A;
var x,y:integer;
......
procedure B;
var x:integer;
......
......
begin
......
......
end;
......

begin
......
B;
......
end;

la variabile y di A visibile da B, mentre la x di A non lo in quanto la


dichiarazione di una variabile in B con lo stesso nome ha creato una variabile locale
che nasconde quella definita nella procedura chiamante. In altre parole, tutte le
modifiche fatte da B su y influenzano anche A, mentre quelle effettuate su x da B
non si propagano sulla x di A (in quanto sono due variabili differenti).

Nei sottoprogrammi esterni esistono invece dei meccanismi espliciti che


consentono a pi unit di programma di condividere gli stessi oggetti. Ad esempio
in FORTRAN possibile, con opportune dichiarazioni, raggruppare un insieme di
variabili in un'area di memoria prestabilita. Tale area viene chiamata common
(comune) perch condivisibile da pi unit di programma differenti. L'uso del
common in due unit di programma ha l'effetto di assegnare le medesime locazioni
di memoria (quelle dell'area common appunto) a variabili dell'uno e dell'altro. Ad
esempio l'uso del common nelle quattro unit di programma di seguito riportate:
La struttura dei programmi 145

program main
integer a,b,c,d
common a,b,c,d
......
end

subroutine sub1
integer x,y
common x,y
......
end

subroutine sub2
integer i
common i
......
end

subroutine sub3
integer k,f,v,z
common k,f,v,z
......
end

comporta che a, x, i, e k sono associati alla prima locazione di memoria


dell'area common; b, y, e f alla seconda; c e v alla terza; e infine d e z alla quarta.
La globalit di una variabile risulta cos definita dalla posizione assunta nella zona
comune e non dal nome delle variabili.
Ricapitolando, una procedura pu usare una variabile dell'unit di programma
chiamante o attraverso la corrispondenza parametri formali ed effettivi o mediante
l'uso delle regole di visibilit collegate ai meccanismi di comunanza. Senza
pretendere in questa sede di discutere a fondo i vantaggi e gli inconvenienti dei due
metodi, bene fare le osservazioni generali, riportate di seguito.
- A priori, se alcuni argomenti devono essere trasmessi in molte chiamate,
la trasmissione esplicita pu essere pesante e fastidiosa. Un meccanismo
di comunanza dati preferibile soprattutto per le procedure chiamate
frequentemente perch pi veloce.
- Per altro si deve notare che l'utilizzazione del meccanismo di comunanza
dati corrisponde a passare implicitamente dei dati del tipo dati
modificabili. Cresce cos il rischio di introdurre nella procedura
chiamante errori indesiderati e difficilmente controllabili se la visibilit
delle variabili molto estesa: errori che derivano dalla possibilit offerta
alle procedure chiamate di modificare le variabili non locali senza tener
conto di come esse siano usate nel programma chiamante. Per tale motivo
l'utilizzazione di un identificatore non locale una pratica pericolosa e
poco raccomandabile. Inoltre, nei linguaggi con sottoprogrammi esterni,
esistono anche altri inconvenienti: non possibile eliminare le variabili
inutili (o giudicate tali dopo un rapido esame) dallarea comune e quindi il
rischio di generare errori per l'inserzione di modifiche non previste reale
146 Capitolo quarto

se si pensa che l'eliminazione di una variabile da una dichiarazione fa


saltare la corrispondenza delle altre nell'area comune.
In funzione di queste osservazioni possiamo formulare alcuni consigli.
- meglio riservare la comunanza implicita al caso in cui il programma
principale e i suoi sottoprogrammi manipolano un gruppo di variabili
veramente comuni (cio sarebbe arbitrario per queste distinguere
argomenti reali e argomenti formali).
- quando le variabili sono in comune meglio che abbiano lo stesso nome
ovunque usate. Si eviter cos nei linguaggi con sottoprogrammi interni di
ridefinire in una procedura gli identificatori gi definiti in un blocco
esterno. Analogamente, se si utilizzano delle aree comuni, sar opportuno
mantenere sempre le stesse liste di identificatori.
- se per motivi di efficienza si sceglie il meccanismo di comunanza, si deve
documentare in modo preciso sia dove l'identificatore definito sia tutte
le unit di programma che ne fanno uso, in modo da effettuare
velocemente i controlli incrociati necessari per valutare gli effetti
complessivi che la modifica di una variabile non locale comporta.
4.3.4. L'allocazione dinamica
Tutti i sottoprogrammi sono, come abbiamo visto, unit di programma con
oggetti locali, cio validi nell'ambito ristretto dell'unit, che possono essere usati
anche da altre unit o mediante la sostituzione dei parametri o mediante un
meccanismo di comunanza. Una volta terminata l'esecuzione del sottoprogramma,
tutte le sue variabili locali diventano inaccessibili fino a quando il sottoprogramma
non viene richiamato; ma, nella chiamata successiva, i valori iniziali di queste
variabili saranno diversi da quelli finali della chiamata precedente. Questo perch
l'allocazione in memoria centrale delle variabili locali avviene all'atto della
chiamata del sottoprogramma per cercare di ridurre l'occupazione complessiva di
memoria. Difatti alcuni sottoprogrammi potrebbero non essere mai attivati, e
l'allocazione in memoria delle rispettive variabili locali risulterebbe alquanto
inutile. Risulterebbe altrettanto inutile allocare le variabili di quei sottoprogrammi
non eseguiti mai contemporaneamente. Cos, al termine di un sottoprogramma
l'area di memoria occupata dalle sue variabili locali viene resa disponibile per
l'allocazione delle variabili locali di un diverso sottoprogramma. In altre parole, la
corrispondenza tra identificatore di variabile e indirizzo del registro di memoria
viene determinata dinamicamente durante l'esecuzione.
Diremo questo schema di allocazione dinamico per distinguerlo da quello
statico che prevede che l'allocazione venga fissata all'inizio dell'esecuzione del
programma e non cambi finch il programma non sia terminato.
Nella gerarchia di unit di programma, le variabili globali (quelle definite nel
programma principale) sono statiche per ovvie ragioni ( l'unit che chiama tutte le
altre), mentre quelle locali ai vari sottoprogrammi sono dinamiche.

Per una completa comprensione degli effetti della gestione differenziata


dell'allocazione delle variabili si osservi l'output del seguente esempio:
La struttura dei programmi 147

program P;
var I,A : integer;

procedure Y;
var B: integer;
begin
A:=A+1;
B:=A*A
writeln('B =',B:2)
end;

procedure Z;
var C: integer;
begin
A:=A+1;
C:=C+1;
writeln('C =',C:2)
end;

begin
A:=0;
for i:=1 to 2
do begin
Y;
Z;
end;
writeln('A =',A:2)
end.

OUTPUT:
B=1
C=2
B=9
C =10
A=4

Lo schema che segue uno schema di principio che mostra, passo dopo passo,
come ci avvenga mettendo in evidenza l'allocazione delle variabili subito dopo la
chiamata delle procedure e poco prima della loro terminazione. I passi sono:
1) prima dell'esecuzione del ciclo for del programma principale;
I A
0
2) prima chiamata di Y;
I A B
1 0
3) terminazione di Y;
I A B
1 1 1
148 Capitolo quarto

4) prima chiamata di Z;
I A C
1 1 1
5) terminazione di Z;
I A C
1 2 2
6) seconda chiamata di Y;
I A B
2 2 2
7) terminazione di Y;
I A B
2 3 9
8) seconda chiamata di Z;
I A C
2 3 9
9) terminazione di Z.
I A C
2 4 10

Se invece tutte le variabili, senza distinguere tra locali e non, fossero state
allocate staticamente all'atto dell'attivazione del programma lo schema risulterebbe
uguale a:
I A B C

permettendo di generare il seguente output:

B= 1
C =98
B= 9
C =99
A= 4

come facilmente si pu dimostrare.


Si noti il valore strano assunto la prima volta da C. Esso si spiega osservando
che l'allocazione delle variabili associa ad esse un indirizzo di uno o pi registri di
memoria senza interessarsi minimamente del loro contenuto. Alcuni linguaggi, per
limitare i danni legati all'indeterminatezza del valore iniziale delle variabili, fanno
seguire all'allocazione una inizializzazione delle celle di memoria compatibile con
il tipo di dato. comunque buona norma non fare affidamento su tali
inizializzazioni perch possono, tra l'altro, variare da macchina a macchina, ed
inizializzare con esplicite istruzioni di assegnazione tutte le variabili che si usano.
Ma, tornando alla differenza tra allocazione statica e dinamica, resta solo da dire
che in alcuni linguaggi (ad esempio il FORTRAN) possibile rendere statiche le
variabili locali dei sottoprogrammi con opportune dichiarazioni (save).
La struttura dei programmi 149

4.3.5. La ricorsione
La ricorsione una propriet dei sottoprogrammi e delle funzioni che consente
l'uso, all'interno della definizione di un'unit di programma, della chiamata ad essa
stessa. una propriet molto importante in quanto molto problemi possono essere
definiti in modo semplice solo usando la ricorsione. La definizione di un oggetto si
dice ricorsiva se contiene un riferimento all'oggetto stesso.
Tale principio usato con naturalezza nella vita comune. Nel linguaggio
matematico numerosi oggetti sono definiti ricorsivamente, per esempio il fattoriale
di un numero n dato dal numero n moltiplicato per il fattoriale di (n-1) con
eccezione del fattoriale di 0 che uguale a 1:

0! = 1
n! = n * (n-1)!

per ogni n>0.


Non tutti i linguaggi per prevedono la ricorsione: laddove prevista si fa
ricorso ad essa inserendo nel corpo della procedura o della funzione il richiamo
alla procedura stessa. Per esempio, sempre per il fattoriale di n:

function fatt(n:integer):integer;
begin
if n=0 then fatt:=1
else fatt:=n*fatt(n-1)
end;

Comunque la ricorsione sempre riconducibile ad una iterazione, e ci fa


comprendere quanto sia importante studiare la condizione di terminazione degli
algoritmi ricorsivi.
4.3.6. Gli effetti collaterali
L'uso dei sottoprogrammi pu introdurre errori che non sono facilmente
individuabili e che sono essenzialmente legati ai meccanismi con i quali si espande
la visibilit di una informazione tra le diverse componenti di un programma. A tale
riguardo si osservi, per esempio, che la sostituzione per riferimento fa s che una
stessa variabile si presenti sotto differenti denominazioni in diverse unit di
programma. Difatti, fissata la seguente procedura:
procedure quadrato(var x:integer);
begin
x:=x*x;
end;

se la si richiama nel contesto seguente:


for i:=1 to n
do begin
.....
quadrato(i);
.....
end;
150 Capitolo quarto

si genera la modifica della variabile contatore del ciclo, operazione pericolosa se


non addirittura vietata in alcuni linguaggi, in quanto, per effetto del meccanismo di
sostituzione adottato, le operazioni svolte dal sottoprogramma su x si svolgono di
fatto su i.
Chiameremo side effect (effetto collaterale) l'effetto non desiderato che si
genera a causa della modifica di un parametro formale nel corpo di un
sottoprogramma che si ripercuote anche all'interno del programma chiamante.
Un'altra fonte di effetto collaterale l'uso della sostituzione per riferimento
per uno dei parametri formali di una funzione. Difatti se il parametro in questione
viene modificato nel corpo della funzione si ha come effetto collaterale che la
procedura genera pi di un risultato contravvenendo alla definizione stessa di
funzione. Per esempio la funzione:

function radice(var x:real):real;


begin
x:=abs(x);
radice:=sqrt(x)
end;

che effettua il calcolo della radice quadrata del valore assoluto di un numero
assegnato, fornisce due risultati: il valore assoluto del numero, tramite l'unico
parametro formale, e il valore della radice, attraverso il nome della funzione. In
casi del genere si pu facilmente ovviare all'effetto collaterale sostituendo il
meccanismo di sostituzione per riferimento con quello per valore. Alcune volte
per, si fa volutamente ricorso al meccanismo di sostituzione per riferimento sia
per motivi di efficienza (si evita la ricopiatura) che per non aumentare
l'occupazione di memoria (non si duplicano le informazioni). Si pensi ad esempio
ad un sottoprogramma per il calcolo del determinante di una matrice quadra: la
scelta della sostituzione per valore comporterebbe la copia della matrice nel
parametro formale con una perdita di tempo e di spazio proporzionale alle
dimensioni di tutta la matrice. La scelta della sostituzione per riferimento laddove
dovrebbe essere usata quella per valore, pu essere fatta solo quando, a progetto
terminato, ci si accorge che il sottoprogramma non opera sul parametro formale e,
quindi, non introduce degli effetti collaterali non desiderati.
Per la loro pericolosit, tali scelte vanno documentate in modo chiaro ed
evidente nel corpo del sottoprogramma soprattutto perch un programma non cessa
di essere utilizzato nello stesso stato in cui stato creato la prima volta. Difatti
durante la sua vita molto probabile che dovr subire diverse modifiche sia per
rimuovere eventuali errori di programmazione sia per adattarsi a cambiamenti delle
specifiche iniziali.
A questo riguardo si pensi ad un semplice calcolo della ritenuta IVA su una
fattura: fino a qualche anno fa l'aliquota da applicare era del 18 per cento mentre
oggi del 19 per cento. Intervenendo allora su di un sottoprogramma in cui non
sono state documentate le ipotesi di correttezza, si rischia di alterarne i rapporti con
l'esterno introducendo effetti collaterali che nella versione di partenza non
esistevano.
La struttura dei programmi 151

4.3.7. Il riuso dei sottoprogrammi


In genere quanto maggiore lo sforzo investito nella realizzazione di un
programma, tanto maggiore sar il desiderio da parte di chi lo ha realizzato di
prolungarne la vita e quindi maggiore sar la probabilit di intervenire per
correggerlo o modificarlo. Tale attivit prende il nome di manutenzione e, ormai,
opinione diffusa che la manutenzione di un grande progetto software un
problema addirittura pi complesso e costoso della sua realizzazione. Senza entrare
nel merito di tale affermazione, diciamo soltanto che l'unico modo per diminuire la
complessit della manutenzione progettare un software ben organizzato e
documentato: i sottoprogrammi sono un utile meccanismo per arrivare ad un
progetto con questi requisiti sia perch sono un potente strumento di astrazione sia
perch godono di una certa autonomia che ne consente l'organizzazione in librerie
utilizzabili in progetti diversi. L'autonomia di fondamentale importanza non solo
per la riutilizzabilit dei programmi, ma anche per ridurre i tempi di sviluppo e
quelli di manutenzione di un progetto software. Difatti, per quanto potenti oggi
siano i calcolatori attuali, la compilazione di programmi molto lunghi pu risultare
assai onerosa e quindi lenta e costosa.
Per questo motivo alcuni linguaggi introducono il concetto di sottoprogrammi
esterni, ossia di sottoprogrammi compilabili separatamente dal loro contesto. Cos,
durante lo sviluppo di un progetto, si compilano soltanto i moduli nuovi o quelli
che sono stati oggetto di modifiche, con un notevole risparmio di tempo. Inoltre
l'autonomia favorisce la manutenzione in quanto permette di verificare
separatamente la correttezza di ogni singolo modulo e successivamente quella del
programma che li integra.
Ma l'autonomia di un sottoprogramma non per illimitata. Gli effetti
collaterali precedentemente illustrati ne sono un esempio. In molti casi un
sottoprogramma risulta completamente definito solo se immerso nel contesto che
lo usa. Tanto per fare un ulteriore esempio, si pensi ad un sottoprogramma i cui
calcoli dipendano da una (o anche pi di una) variabile non locale in un ambiente
come il Pascal o da una variabile inserita in area comune per ambienti con
sottoprogrammi di tipo esterno: per provare la correttezza del sottoprogramma si
deve disporre anche della parte di programma che d valore alla variabile prima
della chiamata del sottoprogramma stesso.
Per favorire quindi l'autonomia dei sottoprogrammi auspicabile ridurre l'uso
di meccanismi che possono introdurre effetti collaterali o quantomeno giustificarne
l'adozione, con una dettagliata documentazione, in tutti quei casi in cui si ottenga
una stesura pi semplice del programma.
4.3.8. L'information hiding
Un altro modo di aumentare l'autonomia dei sottoprogrammi cercare di non
usare informazioni al di fuori dei moduli che sono stati creati apposta per trattarli.
In altre parole, si deve cercare di nascondere le informazioni (dall'inglese
information hiding) che vengono usate a certi livelli di astrazione del metodo top
down ai livelli superiori, se si vuole aumentare l'indipendenza dei singoli moduli.
In altri termini lintestazione di un sottoprogramma deve contenere tutto quanto
serve alla comprensione di come esso pu essere usato. Per comprendere
l'importanza del problema si consideri il rapporto che esiste tra i sottoprogrammi e
152 Capitolo quarto

i tipi astratti. Si visto che non sempre il linguaggio mette a disposizione del
programmatore strumenti che permettono di modellare gli oggetti della realt, e ci
non deve rappresentare un impedimento durante la progettazione. Difatti, se una
informazione essenzialmente caratterizzata da struttura ed operazioni, si pu
sempre raffinare il tipo astratto usando una struttura che si presta ad una sua
realizzazione e costruendo intorno ad essa funzioni e sottoprogrammi che
arricchiscono il linguaggio con parole chiavi tali da dare la sensazione di disporre
proprio di un tale tipo. Per esempio un numero complesso pu essere raffinato
introducendo il seguente tipo:

type num_complex = record


parte_reale,
parte_immaginaria : real
end;

e le seguenti operazioni:

function somma_complex(x,y:num_complex):num_complex;
function prodotto_complex(x,y:num_complex):num_complex;

noto che i numeri complessi possono essere rappresentati in modo


alternativo indicando modulo ed argomento (un angolo). Cos, se per qualche
motivo si sceglie di cambiare la rappresentazione del tipo, si potranno modificare
solo la dichiarazione di tipo e il corpo delle funzioni somma_complex e
prodotto_complex nel caso in cui non siano state disseminate all'interno del
programma istruzioni del tipo:

if x.parte_reale then
z:=num.parte_reale*3

ossia se stata nascosta la struttura del tipo num_complex al programma


stesso.
Si noti che nessun linguaggio costringe al rispetto del principio
dellinformation hiding all'interno di un programma. Di conseguenza compito del
buon progettista cercare di disciplinarsi o disciplinare gli altri quando il progetto
condotto da pi persone, se vuole ottenere un progetto in cui tutti moduli godano di
quella reale autonomia cos fondamentale per un pi semplice controllo.
Capitolo quinto

I dati

5.1. Informazione e dato


Nella realt di tutti i giorni molte attivit operano con informazioni di natura e
forma diverse (testo, video, audio) e si costruiscono sistemi che gestiscono ed
elaborano tale tipologie di informazioni.
Linformazione quindi un oggetto che ha un rapporto stretto con la realt
dalla quale pu emergere se e solo se un determinato insieme o classe di oggetti
assume stati o configurazioni differenti. In tale accezione linformazione non
altro che la scelta di una delle possibili configurazioni in cui si trova un esemplare
della classe di oggetti. Allora, il concetto di informazione strettamente legato a
quello di scelta di uno fra pi oggetti di un particolare insieme e non esiste
informazione se non si effettua una scelta. Ad esempio, la frase sto studiando
elementi di informatica, fornisce un'informazione in quanto esprime la scelta della
materia di studio e l'identificazione, quindi, della materia elementi di
informatica, tra tutte le possibili materie del piano di studio.
Mentre luomo tratta informazioni, lelaboratore tratta dati. Come le
informazioni anche i dati che le rappresentano sono di tipo numerico,
alfanumerico, alfabetico, immagine, audio. Quando lelaborazione consente di
trattare dati eterogenei in modo integrato si parla di elaborazione multimediale.
Con dato si indica una rappresentazione di fatti e concetti in modo formale perch
sia possibile una loro elaborazione da parte di strumenti automatici. Il dato da solo,
senza un contesto, pu non avere significato: uno stesso numero pu esprimere
cose diverse in situazioni diverse; cos come una stessa parola pu avere significato
diverso dipendente dal contesto. Lambiguit viene risolta dando al dato una
interpretazione. Linformazione non altro che la percezione del dato attraverso un
processo di interpretazione. In altre parole linformazione cattura il significato del
dato. Perch un dato diventi informazione si devono pertanto specificare:
- un tipo, ossia l'insieme degli elementi in cui si effettua la scelta;
- un valore, ossia il particolare elemento scelto;
- l'attributo, ossia l'identificatore (o anche metadato) che conferisce
significato all'elemento scelto.
Il tipo l'insieme degli oggetti entro cui si effettua la scelta. Nella prassi
quotidiana tale insieme non sempre esplicitamente definito. Tra laltro
l'attribuzione di un dato ad un tipo piuttosto che ad un altro dipende, dal contesto:
154 Capitolo quinto

ad esempio, pu non avere interesse in alcuni casi trattare separatamente con i tipi
giorno, mese ed anno piuttosto che con un unico tipo data che li accorpa.
Ciascun tipo di dato caratterizzato poi dal numero di elementi di cui
composto. Tale numero detto cardinalit del tipo. In un tipo con cardinalit N, la
scelta di un elemento avviene tra tutti gli N; ne discende che la scelta pi
elementare che si possa effettuare quella fra due soli oggetti e pertanto il dato pi
elementare quello che appartiene ad un tipo con cardinalit 2. Un tale dato viene
detto binario se i valori di un tale insieme sono [0,1], ma anche vero e falso; e si
soliti usare il termine bit per indicare sia l'informazione binaria sia i valori 0 e 1 da
essa assunti.
Da un punto di vista teorico la cardinalit di un tipo pu essere finita o
infinita. Da un punto di vista pratico i processi elaborativi trattano solo tipi a
cardinalit finita. Difatti, per poter essere gestiti da un elaboratore, i dati,
opportunamente rappresentati, devono essere inseriti in contenitori (memoria
dell'elaboratore) con dimensioni proporzionali alla cardinalit dei tipi: chiaro che
a cardinalit infinita corrisponderebbero contenitori di dimensione infinita.
Il valore di un dato un elemento di un tipo. Tale definizione risulta per
generica se non viene collegata alla definizione di tipo. Si osservi che il concetto di
valore un concetto che comporta una certa astrazione e non deve essere confuso
con il problema della rappresentazione dell'informazione che pu essere diversa in
contesti differenti: basti pensare al modo di identificare un oggetto in lingue
diverse (padre e father) o alle differenti rappresentazioni dei valori dei numeri
(1/10 o 0.1).
L'attributo conferisce il significato al valore specificato dal dato. Il tipo e il
valore da soli non sono sufficienti alla caratterizzazione di una informazione. Ad
esempio il valore 1000 del tipo numeri interi non ci dice nulla di significativo:
potrebbe benissimo essere il prezzo di un biglietto del tram o anche il numero di
matricola di uno studente. Il concetto di attributo analogo a quello matematico di
variabile e, come questo, si pu rappresentare mediante simboli letterali o nomi da
associare alle informazioni per specificarne il significato. Si pu cos chiamare rad
la radice di una equazione e totale_fattura l'ammontare di una fattura.
L'individuazione dei tipi di dato con cui trattare strettamente legata alla
natura delle elaborazioni da effettuare e pu variare dunque da elaborazione ad
elaborazione. La definizione di tipo consente di introdurre dei modelli degli oggetti
della realt in quanto ne fornisce le caratteristiche strutturali (cosa sono) e
funzionali (a cosa servono). Una definizione di tipo di dato sufficientemente
rigorosa e particolarmente adatta agli usi di tipo che verranno fatti in seguito la
seguente: per tipo di dato si intende un insieme di valori associati a delle
operazioni definite su di essi. Con le definizioni di tipo possibile trattare
l'informazione in maniera astratta, cio prescindendo dal modo concreto con cui
essa rappresentata all'interno di una macchina.
Un tipo si definisce alla stessa stregua degli insiemi, ossia per:
1) enumerazione degli elementi
{Lunedi, Martedi, Mercoledi, Giovedi, Venerdi, Sabato, Domenica}
2) elencando le propriet di cui godono i suoi elementi
{C: centravanti di una squadra nazionale di calcio di serie A e B}
Elementi fondamentali di una elaborazione non sono soltanto i tipi su cui essa
agisce, ma anche le operazioni che si possono effettuare sui rispettivi valori di un
I dati 155

tipo. Tali operazioni possono essere definite assiomaticamente con il tipo e


possono essere interne oppure esterne ad esso. Le prime producono un risultato di
tipo uguale a quello degli operandi mentre le seconde di tipo diverso. Ad esempio
la somma di due numeri interi di tipo interno mentre esterna la divisione tra due
numeri interi in quanto fornisce sia risultati di tipo intero (8:4 => 2) che di tipo
reale (5:2 => 2.5).
Fra i valori di un tipo pu essere definita una relazione d'ordine che fissa che
uno specifico valore ha alcuni altri valori che lo precedono e altri ancora che lo
seguono: la relazione dordine pu essere totale (se coinvolge tutti gli elementi) o
in alcuni casi parziale (se definita su sottoinsiemi). Nella pratica tale relazione
implicita nella natura del tipo e corrisponde alla posizione che le sue costanti
occupano nella sua definizione per enumerazione. Sono ad esempio ordinati gli
insiemi dei numeri interi, delle lettere e delle cifre. I tipi ordinati sono anche detti
scalari.
Tra due costanti di un tipo ordinato sono definite a priori, oltre ai confronti di
uguaglianza e disuguaglianza, validi anche per tipi non ordinati, le relazioni
d'ordine di minore, maggiore, minore o uguale e maggiore o uguale. Le diverse
relazioni vengono indicati con opportuni operatori (vedi tabella 1).

Confronto Operatore Operatore


uguale = ==
diverso <> !=
minore < <
maggiore > >
minore o uguale <= <=
maggiore o uguale >= >=
Tabella 1 - Relazioni su tipi ordinati

Tra le costanti di un tipo sono possibili operazioni di relazione (confronto):


operazioni, cio, che trasformano valori di un qualsiasi tipo nei valori logici VERO
e FALSO (e pertanto sono operazioni esterne).

Confronto Relazione Valore determinato


3>1 Verificata VERO
7=9 Non verificata FALSO
Tabella 2 - Operazioni di confronto

Infine, sui tipi ordinati sono definite le seguenti funzioni:


- SUCC(x) che fornisce il successore di x nell'insieme;
- PRED(x) che fornisce il predecessore di x nell'insieme;
- ORD(x) che fornisce la posizione di x nell'insieme (la prima posizione si
assume per convenzione essere uguale a 0).
Si noti che le funzioni succ e pred sono interne al tipo a cui sono applicate,
mentre ord esterna perch fornisce una posizione intera qualsiasi sia il tipo di x.
Ad esempio, fissato l'insieme delle lettere, si ha che SUCC(A)=B, PRED(B)=A,
ORD(A)=0 e ORD(B)=1. Le prime due sono operazioni interne mentre le ultime due
sono esterne.
156 Capitolo quinto

5.2. La classificazione dei tipi


Nei linguaggi di programmazione esistono dichiarazioni per la definizione di tipo:

type t = T;

dove t il nome del nuovo tipo e T un descrittore di tipo, cio un costrutto


sintattico del linguaggio atto a definire il tipo t. Il descrittore T pu essere anche un
tipo gi definito o predefinito nel linguaggio, in modo da introdurre dei tipi
sinonimi. L'istanziazione di variabile, ossia lintroduzione di una variabile da poter
utilizzare nel programma, avviene poi semplicemente con frasi dichiarative come
quella seguente:

var v : T;

Allinstanziazione di variabile corrisponde lallocazione in memoria della


variabile, ossia lassociazione al nome della variabile dellindirizzo del registro di
memoria nel quale verranno depositati i valori della variabile e da dove gli stessi
valori verranno letti. Il numero di bit, e quindi il numero di registri associati al
nome della variabile saranno determinati sulla base della rappresentazione dei
valori in memoria.
I tipi di dato si possono classificare in funzione della modalit con la quale
possibile definirli o in funzione della loro struttura. Se il tipo predefinito nel
linguaggio, allora lo si dir primitivo: in caso contrario, quando il programmatore
che ne deve definire la composizione e in alcuni casi anche le operazioni ammesse
sui suoi valori, si dir che un tipo derivato. Tutti i linguaggi di programmazione
comprendono nella loro grammatica dei costruttori di tipo.
Un tipo si dice atomico quando i valori di cui si compone non possono essere
scomposti in elementi pi semplici; si dice invece strutturato quando presenta
valori che sono aggregazioni di altri valori che possono a loro volta essere semplici
o strutturati. Il colore di un oggetto una informazione di tipo atomico; la data di
nascita invece strutturata perch in essa si ritrovano aggregati le informazioni del
giorno, del mese e dellanno.
La classificazione di un tipo in atomico e strutturato dipende fortemente
dalluso dellinformazione. La stessa informazione per alcune elaborazioni pu
essere considerata atomica mentre per altre strutturata. Ad esempio, se si considera
un libro, si pu notare che per il libraio che lo deve vendere un oggetto di tipo
atomico, ma per tante altre persone (il lettore, il tipografo, leditore) pu essere
visto organizzato in pagine, le pagine in righe, le righe in parole e le parole in
caratteri, a secondo dello specifico punto di vista.
Sono tipi atomici:
- il tipo logico o booleano
- i tipi numerici intero e reale
- il tipo carattere
- il tipo puntatore
sono tipi strutturati:
- il tipo array ad una o a pi dimensioni
- il tipo record
I dati 157

- il tipo file
- la pila o stack
- la coda
- la tabella
In tutti i linguaggi di programmazione esistono i costruttori per definire array,
record e file.

5.3. I tipi atomici


I tipi si dicono atomici quando i valori di cui sono composti non sono
scomponibili in elementi pi semplici dalle applicazioni che ne fanno uso. Per tale
motivo facile fornire una loro definizione mediante lenumerazione delle costanti
appartenenti al tipo o definendo le propriet di cui le stesse costanti godono. Tra le
propriet vanno considerate le operazioni interne ed esterne al tipo.
5.3.1. Il tipo booleano
Il tipo booleano indica l'insieme dei due valori di verit, true e false, ed il suo
nome deriva dall'ideatore del calcolo logico, George Boole (1915-1964). Sui valori
del tipo logico sono definiti i seguenti operatori:

- OR: equivalente alla disgiunzione inclusiva (O logico), anche detto


somma logica;

non si fa la lezione se
il docente malato
O
gli studenti non vengono

- AND: equivalente alla congiunzione (E logico), anche detto prodotto


logico;

l'esame si supera se
si fa bene l'esercizio
E
si risponde bene all'orale

- NOT: equivalente alla negazione (NON logico).

oggi NON piove

La tabella 3 riporta come gli operatori logici vengono indicati in diversi


linguaggi.

Operazione Operatore
OR ||
AND &&
NOT !
Tabella 3 - Operatori logici
158 Capitolo quinto

Per capire gli operatori logici definiamo proposizione una espressione


linguistica della quale si pu dire se vera o falsa. Ad esempio Parigi la capitale
della Francia una frase che universalmente riconosciuta essere vera. Invece
definiamo proposizioni variabili o predicati le espressioni linguistiche delle quali
si pu dire che sono vere solo se si assegna un valore alle informazioni in esse
contenute. Ad esempio per la frase:
oggi piove
possibile pronunciarsi solo dopo aver osservato il cielo. Si dice valutazione
del predicato l'operazione che, noti i valori delle informazioni che vi compaiono,
consente di stabilirne il valore di verit (cio di dire se il predicato vero o falso).
Allora dato un predicato P se ne pu costruire un altro facendolo precedere dal
simbolo NOT: il predicato che si ottiene si dice opposto o negazione del primo ed
ha i valori di verit opposti rispetto al primo. Cio se P vero allora NOT P falso
e viceversa. Si noti che ovviamente che: NOT(NOT P1) = P1.
Dati invece due predicati P1 e P2, se ne pu costruire un terzo mediante la
congiunzione logica AND. Il predicato ottenuto P1 AND P2 risulter vero solo
quando sia P1 che P2, sono veri mentre sar falso in tutti gli altri casi.
Infine, dati due predicati P1 e P2, se ne pu costruire un terzo mediante la
disgiunzione logica O. Il predicato ottenuto P1 OR P2 risulter falso solo quando
sia P1 che P2, sono falsi mentre sar vero in tutti gli altri casi.
Dalle definizioni date possibile riempire le seguenti tabelle che vengono
dette tavole di verit (la prima utilizzando false e true, la seconda 0 e 1).

P1 P2 P1 AND P2 P1 OR P2 NOT P1
FALSE FALSE FALSE FALSE TRUE
FALSE TRUE FALSE TRUE
TRUE FALSE FALSE TRUE FALSE
TRUE TRUE TRUE TRUE

P1 P2 P1 AND P2 P1 OR P2 NOT P1
0 0 0 0 1
0 1 0 1
1 0 0 1 0
1 1 1 1

Tabelle 4,5 Tavole di verit


Inoltre valgono le seguenti propriet

commutativa:: X OR Y = Y OR X

associativa: (X OR Y) AND Z=(X AND Z) OR (Y AND Z)

nonch le due relazioni di DE MORGAN:

NOT (X OR Y)=(NOT X) AND (NOT Y)


NOT (X AND Y)=(NOT X) OR (NOT Y)
I dati 159

che si dimostrano con le tavole di verit in tabella 6.

X Y X OR Y NOT (X OR Y) NOT X NOT Y (NOT X) AND


(NOT Y)
FALSE FALSE FALSE TRUE TRUE TRUE TRUE
FALSE TRUE TRUE FALSE TRUE FALSE FALSE
TRUE FALSE TRUE FALSE FALSE TRUE FALSE
TRUE TRUE TRUE FALSE FALSE FALSE FALSE
Tabella 6 Tavole di verit

Inoltre, si noti che gli operatori di relazione, per definizione stessa di


confronto, trasformano due o pi valori di un tipo in un valore del tipo logico.
Difatti A confronto con B assume il valore TRUE se il confronto ha successo e il
valore FALSE in caso contrario.
Si noti che linsieme degli operatori di relazione riconducibile a due soli
operatori di relazione (l'uguale e il minore ad esempio) e ai tre operatori logici.
Operazione Equivalenza
X<>Y NOT (X = Y)
X<=Y (X < Y) OR (X = Y)
X>=Y NOT (X < Y)
X>Y NOT ((X < Y) OR (X = Y))
Tabella 6 Equivalenza tra operatori

Se in una espressione logica sono presenti operatori logici e di relazione e


sono assenti le parentesi devono essere eseguite nell'ordine il NOT, l'AND, l'OR, e
infine gli operatori di relazione.
5.3.2. Il tipo carattere
Il tipo carattere un tipo di fondamentale importanza in quanto contiene
l'insieme dei simboli medianti i quali un calcolatore comunica con l'esterno
attraverso i dispositivi di ingresso e uscita. Se si considera come unione degli
insiemi delle lettere, delle cifre e dei simboli di interpunzione, matematici e
speciali, allora si presenta come parzialmente ordinato poich non ha senso definire
un ordinamento tra le lettere e le cifre o tra i caratteri di interpunzione. Da un punto
di vista pratico, per, si presenta come ordinato.
Inoltre, sempre per motivi pratici, legati alla necessit di differenziazione in
fase di visualizzazione, nell'insieme dei caratteri si ritrovano sia le lettere
minuscole che maiuscole. I motivi che hanno condotto all'ordinamento del tipo
carattere sono legati alla necessit di definire un insieme di caratteri che fosse
accettato da tutte le case costruttrici di computer e di periferiche quali stampanti e
video. Difatti solo definendo un insieme standard di caratteri stato possibile far
comunicare sistemi diversi tra loro o adattare periferiche di una casa a sistemi di
altre case.
Lo standard ormai universalmente accettato quello definito dall'American
Standard Code for Information Interchange (ASCII). Si basa su 128 codici di cui i
primi trentadue vengono anche chiamati Control per la loro caratteristica di servire
come comandi di gestione delle periferiche. Ai codici di controllo non corrisponde
160 Capitolo quinto

un simbolo visibile, ma l'esecuzione di un comando da parte della periferica che lo


riceve. Di essi ricordiamo:
- Cr (detto anche RETURN o anche IMMISS) che serve al computer per
comunicare alla stampante o al video di spostare l'elemento di stampa ad
inizio rigo (la levetta di una macchina da scrivere per andare daccapo);
- Lf o Line Feed, che serve al computer per comunicare alla stampante o al
video di spostare l'elemento di stampa sul rigo seguente;
- BLANK o Space per introdurre spazi di separazione tra le parole.
L'ASCII introduce un ordinamento tra i simboli che funzione della loro
posizione nella tabella di codifica. Per tale ordinamento:
- le cifre precedono le lettere;
- le lettere maiuscole precedono quelle minuscole.
Sul tipo carattere ordinato sono solitamente definite le funzioni (ad esempio
CHR e ORD) che pongono in corrispondenza biunivoca l'insieme dei simboli con la
loro posizione all'interno del tipo. In particolare la funzione CHR restituisce il
simbolo della posizione specificata e, viceversa, la ORD restituisce la posizione di
un dato simbolo (le posizioni partono da zero e arrivano a 127). Ad esempio,
osservando la tabella ASCII si pu verificare che ORD(B)=66 e CHR(65)=A;
ovviamente CHR(ORD(A))=A e ORD(CHR(66))=66.
5.3.3. Il tipo intero
Il tipo intero (o integer) si definisce come un sottoinsieme finito e definito
dell'insieme dei numeri interi:
type integer = { n | n appartiene [- m, M] }
Spesso si ha che m = M. In questo caso tale valore viene detto MAXINT e si ha
che i valori rappresentabili dal tipo intero sono compresi nell'intervallo:
[-MAXINT,MAXINT]
Le costanti del tipo intero sono sequenze di cifre eventualmente precedute da
un segno. Ad esempio sono numeri interi 30000, +400, 500, -678 e -1. La
tabella che segue indica le operazioni definite sul tipo intero e gli operatori
solitamente usati in diversi linguaggi per indicarle. Nella tabella x e y sono due
variabili di tipo intero.
Operazione Operatore Operatore Esempi
Somma + + x+y
Sottrazione - - xy
Moltiplicazione * * x*y
Divisione (esterna) / / x/y
Divisione intera DIV / x DIV y
x/y
Resto MOD % x MOD y
x%y
Tabella 7 Operatori su tipo intero
Si noti che se si definisce insieme di overflow l'insieme dei valori interi tali
che:
x : |x| > MAXINT
I dati 161

(ossia l'insieme dei numeri interi esterni al tipo intero), si ha che le operazioni
elementari della aritmetica applicati a valori del TIPO INTERO valgono se e solo
se (a op b) non assume valori nell'insieme di overflow.
Ossia se e solo se:

| a op b | MAXINT

dove op = {+,-,*},
In pratica la condizione di overflow pu tradursi in vario modo all'interno di
una macchina: per esempio pu generare una condizione di errore con interruzione
del programma.
5.3.4. Il tipo reale
Il tipo reale ( o real) diverso dall'insieme dei numeri reali poich in un
intervallo reale comunque piccolo esistono infiniti valori (i numeri reali formano
un continuo). Allora il tipo reale si definisce come l'insieme che contiene un
numero finito di valori reali ognuno dei quali rappresenta un intervallo del
continuo. In altri termini, diviso l'insieme dei numeri reali in intervalli di fissata
dimensione, si ha, come la figura mostra, che ogni x appartenente all'intervallo
[Xi,Xi+1[ viene sostituito con Xi.

Figura 1 Il tipo reale

La sostituzione di un numero reale x con il valore X rappresentante l'intervallo


a cui x appartiene, pone notevoli problemi di approssimazione in tutti i calcoli che
usano valori del tipo reale.
Il tipo reale si definisce come un sottoinsieme DISCRETO dei numeri reali. In
concreto il tipo reale si definisce come l'insieme dei numeri reali che godono della
seguente propriet:
162 Capitolo quinto

x X
X:
X
dove rappresenta l'errore relativo che si commette sostituendo x con X. dipende
dalla rappresentazione finita (numero finito di cifre) utilizzata per i numeri reali.
Ad esempio disponendo di una calcolatrice con una aritmetica a quattro cifre
decimali che applica le note regole di arrotondamento sull'ultima cifra, si hanno gli
errori di rappresentazione in tabella 8.

NUMERO ARROTONDAMENTO ERRORE


0.00347 0.0035 3*10-5 =0.3 *10-4
0.000347 0.0003 47*10-6 =0.47*10-4
0.00987 0.0099 3*10-5 =0.3 *10-4
0.000987 0.0010 13*10-6 =0.13*10-4
Tabella 8 Errori di rappresentazione

In generale se n sono le cifre decimali l'errore che si commette :


1 n
10
2

Per il tipo reale, si definisce insieme di overflow l'insieme costituito da tutti i


valori:
x non appartenenti a [-m , M ]

ossia dei valori pi grandi di quelli rappresentabili; e insieme di underflow


quello costituito da tutti i valori:
x appartenenti a ]- , [ tali che X = 0

ossia l'insieme di valori che vengono confusi con lo zero.


Le operazioni definite sul tipo reale sono la moltiplicazione (*), la divisione
(/), laddizione (+) e la sottrazione (-). Le operazioni che richiedono maggiore
attenzione sono l'addizione e la sottrazione. Infatti, la causa principale degli errori
di calcolo numerico risiede nella sottrazione di numeri di valore quasi uguale; in tal
caso le cifre pi significative si eliminano fra loro e la differenza risultante perde
un certo numero di cifre significative o anche tutte (fenomeno detto cancellazione).
Altra causa di errori la divisione per valori molto piccoli, poich il risultato pu
facilmente superare il valore di overflow. Quindi deve essere evitata non solo la
divisione per lo zero ma anche per valori ad esso prossimi.
Nei linguaggi di programmazione il tipo intero e il tipo reale sono due tipi
distinti, anche se il primo un sottoinsieme del secondo, in quanto le operazioni
sui numeri interi forniscono risultati esatti e sono pi veloci. Comunque, si
conviene definire funzioni di conversione esplicite ed implicite tra i due tipi. In una
espressione con valori reali, un qualsiasi operando intero viene implicitamente
convertito in reale. Viceversa le funzioni di troncamento e arrotondamento (ad
esempio trunc e round) consentono la conversione esplicita da reale ad intero. La
funzione trunc(X) restituisce il numero intero che si ottiene troncando le cifre
frazionarie di X. La funzione round(X) arrotonda X troncando il valore dopo avergli
aggiunto 0.5.
I dati 163

5.3.5. Il tipo per enumerazione


Il tipo per enumerazione un tipo di utente in quanto viene definito
elencando l'insieme dei valori che lo costituiscono. Ad esempio:

type GIORNO = (lun,mar,mer,gio,ven,sab,dom)


type SESSO = (maschio,femmina)

Anche se a priori una raccolta disordinata di valori, solitamente si conviene


di definire un ordinamento al suo interno in funzione dell'ordine di apparizione
delle costanti nella definizione di tipo. Per tale motivo:

lun<mar<mer<gio<ven<sab<dom
maschio<femmina

In questo modo, per le costanti di un tipo per enumerazione sono definite le


funzioni PRED(), SUCC() e ORD() ed possibile applicare ad esse tutti gli operatori
di relazione.
5.3.6. Il tipo subrange
Il tipo subrange si definisce specificando un sottoinsieme di un tipo
predefinito ed ordinato e per questo motivo un tipo di utente. La costruzione del
tipo avviene specificando due estremi di un tipo ordinato (ossia i tipi integer, char,
per enumerazione con esclusione del tipo real) separati da una coppia di punti
come mostrato di seguito:

type FERIALE = lun..ven

type CODICI_MESE = 1..12

La definizione corretta se e solo se


limite inferiore < limite superiore

Il tipo cos generato conterr tutti gli elementi compresi tra i due estremi
(estremi inclusi) ed erediter le operazioni del tipo genitore (anche detto base), cio
quello di cui si scelto l'intervallo.
L'introduzione del tipo subrange importante perch aumenta la chiarezza
del modo in cui analizzata la realt del problema. Difatti in taluni casi un tipo
contiene un numero eccessivo di valori per rappresentare alcune informazioni. Ad
esempio, se risulta naturale rappresentare l'informazione anno come un intero (i
numeri negativi potrebbero servire per gli anni prima di Cristo), eccessivo
attribuire all'informazione giorno tutti i valori dello stesso tipo. Allora definire:
type giorno = 1..31
consente di introdurre dei vincoli sulle informazioni rappresentanti i giorni, vincoli
che si concretizzano in una serie di controlli introdotti implicitamente dal
traduttore del linguaggio che vietano l'assunzione errata di valori esterni
all'intervallo di definizione.
164 Capitolo quinto

5.4. I tipi strutturati


Si dice che un'informazione di tipo strutturato se composta da altre
informazioni pi semplici. Quindi un tipo strutturato se un'aggregazione di
informazioni. I tipi strutturati sono di fondamentale importanza perch tramite essi
vengono gestite aggregazioni di informazioni della realt individuate da un unico
attributo. Ad esempio, la data indica il giorno, il mese, l'anno; un mazzo di carte
indica la prima carta, la seconda, e cos via fino all'ultima carta.
Le strutture di informazioni che possibile osservare si presentano in modi
diversi e gli elementi caratterizzanti sono fondamentalmente:
- il tipo degli elementi che compongono la struttura;
- il modo in cui vengono aggregati;
- le operazioni che consentono di estrarre una componente o insiemi di
componenti da tutta la struttura;
- le operazioni che si possono fare su tutta la struttura.
Per tali ragioni un tipo strutturato si pu definire:
1. specificando il tipo delle informazioni componenti (si noti che i
componenti del tipo strutturato possono essere sia atomici che, a loro
volta, strutturati creando cos strutture di strutture);
2. indicando il costruttore necessario alla creazione della struttura, ossia le
operazioni da fare sui componenti per formare il tipo strutturato;
3. indicando il selettore (anche detto funzione di accesso) necessario alla
estrazione di un componente dalla struttura, ossia le operazioni che sul
tipo strutturato possono essere fatte per individuare uno specifico
componente della struttura
4. elencando le operazioni che sull'informazione di tipo strutturato
possono essere fatte; operazioni definite o assiomaticamente sul tipo o
mediante operazioni sui valori componenti la struttura (quasi sempre
assegnazione di valori e test di uguaglianza).
Da quanto detto ne consegue che i tipi strutturati sono tipi di utente in quanto
l'utente che ne specifica i componenti, mentre i linguaggi di programmazione
mettono a disposizione i costruttori e i selettori.
Il prodotto cartesiano e la sequenza sono i costruttori pi importanti.
Assegnati gli insiemi A e B (distinti o non), si dice prodotto cartesiano di A per B,
l'insieme costituito da tutte le coppie:

(a,b) con a appartenente ad A e b a B

Ad esempio, assegnati gli insiemi

A {1,2,3} e B {4,5}
si ha che il prodotto cartesiano di AxB :

{(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)}

Il prodotto cartesiano tra n insiemi (I1xI2xxIn) produce una ennupla


(v1,v2,vn) con v1 appartenente a I1, v2 ad I2 e vn ad In.
I dati 165

Si riportano qui di seguito alcuni esempi pratici.


- Le coordinate dei punti del piano sono, detto R l'insieme dei numeri reali,
il prodotto cartesiano RxR, per cui un punto P individuato dalla coppia
(x,y) con x e y appartenenti a R: x detta ascissa mentre y ordinata del
punto.
- Detto I l'insieme dei numeri interi e M l'insieme dei nomi dei mesi, una
data rappresentata dal prodotto cartesiano I x M x I secondo la seguente
convenzione DATA=(giorno,mese,anno). Esempi di date sono
(02,gennaio,1954), (10,dicembre,2000).
- Definito il tipo carta come l'insieme dei quattro semi {C,Q,F,P} (ossia
Cuori, Quadri, Fiori Picche), un mazzo di carte francesi il prodotto
cartesiano: Carta1 x Carta2 x ... x Carta52. Un mazzo pu essere
descritto come (prima carta, seconda carta, ... , cinquantaduesima carta) e
possibili valori sono (C,C,F,F,P,...,Q), (F,F,P,Q,Q,...,F).
Si osservi che per quanto riguarda gli insiemi che compongono il prodotto
cartesiano si ha che:
- il loro tipo pu essere distinto o uguale;
- il loro numero definito e finito;
- i loro attributi possono variare o meno a seconda della posizione
all'interno della ennupla, e nel caso in cui sono tutti uguali, la
individuazione di un elemento fatta attraverso la sua posizione.
La sequenza un costruttore che genera successioni (anche dette stringhe
ordinate) di elementi tutti dello stesso tipo e in numero non definito a priori. Le
sequenze hanno quindi una lunghezza K che pu assumere valori maggiori od
uguali a zero. Se la sequenza ha lunghezza nulla si parla allora di sequenza vuota o
stringa nulla.
Sul piano pratico non possibile avere stringhe a lunghezza infinita: pertanto
si ha una limitazione superiore K < MAX con MAX che dipende dall'ambiente e dal
tipo costruito con la sequenza.
Sulle sequenze sempre definita l'operazione di concatenazione di due o pi
stringhe: nel caso di due stringhe la concatenazione definita come l'accodamento
della seconda alla prima, mentre nel caso di pi stringhe si definisce come
l'accodamento della seconda alla prima, quindi della terza alla stringa cos ottenuta,
e si continua in questo modo fino all'ultima stringa. La concatenazione si pu
indicare con +,&,//. Ad esempio, date le due stringhe:

s1 = abc s2 = efg

la concatenazione s1 + s2 definisce la stringa abcefg.


Sulle sequenze sono anche definite le operazioni di estrazione del primo
elemento first(s1) = a, e dell'ultimo elemento last(s1) = c.
I tipi strutturati che sono presenti nella maggioranza dei linguaggi di
programmazione (nel senso che il linguaggio offre i costruttori per la loro
definizione) sono: array monodimensionale, bidimensionale e pluridimensionale,
record, stringa di caratteri, file sequenziale.
Per i tipi: pila o stack, coda, tabella, anche se assenti dai linguaggi di
programmazione, verr comunque data la definizione per il ruolo importante che
essi assumono in una molteplicit di elaborazioni.
166 Capitolo quinto

In generale l'assenza di un costruttore di tipo, non deve condizionare il


programmatore dall'uso di un tipo astratto. Difatti solo la definizione precisa
(struttura e operazioni) del tipo pu portare ad una sua reale definizione o
simulazione coi meccanismi presenti nel linguaggio usato.
5.4.1. Gli array
Con l'array monodimensionale, anche detto vettore, si assegna un nome
collettivo ad un insieme ordinato e finito di oggetti dello stesso tipo. L'insieme
ordinato nel senso che ogni elemento occupa una posizione ben precisa ed finito
perch il numero di elementi che lo compongono per motivi pratici limitato.
L'array pu anche essere definito come il prodotto cartesiano di elementi tutti dello
stesso tipo e con lo stesso attributo.
La funzione di accesso ottenuta specificando la posizione della componente
nella ennupla del prodotto cartesiano. Per, se si fissa una corrispondenza tra un
insieme di valori e l'insieme delle posizioni nella ennupla, allora si pu utilizzare
tale insieme di valori come funzione di accesso. Questo insieme detto insieme
indice ed ha la propriet che ad ogni suo valore associato un solo elemento
dell'array secondo il seguente schema.

Figura 2: Mapping tra indici ed elementi di un array


I tipi subrange dei tipi intero, carattere e di quello definito per enumerazione
sono usabili come tipi indice. Difatti la corrispondenza tra il valore del tipo e la
posizione nell'array definita implicitamente dalla posizione del valore stesso
nell'intervallo. Il tipo indice definisce cos l'intervallo di valori che pu essere
specificato nella selezione di un componente dell'array.
Per quanto riguarda le operazioni sull'array, esse sono tutte quelle definite sul
tipo delle informazioni componenti. Allora un tipo strutturato si definisce come
array quando sono specificati:
- l'attributo dell'array;
- il tipo dei componenti;
I dati 167

- il tipo dell'informazione indice;


- il numero dei componenti chiamato anche cardinalit dellarray e
implicitamente definito dalla cardinalit del tipo indice.
Si noti che solitamente si usano intervalli del tipo intero come tipo per
l'indice. In questo caso il numero di componenti dell'array dato da estremo
superiore meno estremo inferiore pi uno perch entrambi gli estremi devono
essere considerati. In alcuni linguaggi l'estremo inferiore si pu omettere quando
coincide con il valore uno, e si deve quindi indicare soltanto l'estremo superiore. In
questi casi le due definizioni di array di 10 numeri reali:

type vettore=array [1..10] of integer


e
type vettore=array [10] of integer

sono equivalenti.
La selezione di un componente si effettua facendo seguire al nome dell'array il
valore dell'indice racchiuso tra parentesi quadre: con vettore[1] si accede al primo
elemento dellarray se lindice parte da uno. anche possibile selezionare un
elemento dell'array mediante espressioni o variabili il cui valore sia un valore
appartenente al tipo indice. In questo caso la posizione viene calcolata
dinamicamente durante l'elaborazione.
Ad esempio vettore[I-1] comporta la determinazione del valore della variabile
I e il suo decremento di una unit per individuare la posizione nell'array. Allora se I
ha il valore 4 vettore[I-1] coincide con vettore[3], mentre vettore[I] coincide con
vettore[4]. Per questo motivo la posizione in genere un parametro d'uso nel senso
che dipende dalla elaborazione in corso: in altre parole la selezione dell'elemento
dell'array fatta dopo aver valutato il valore della variabile o dell'espressione.
Come gi detto, le operazioni sull'array sono tutte quelle definite sul tipo delle
informazioni componenti. Qualche volta possibile l'assegnazione del valore di
tutti i componenti di un vettore B a quelli di un altro vettore A dello stesso tipo. In
questi casi A:=B corrisponde a:

A[1]:=B[1]
A[2]:=B[2]
: ::
: ::
A[n]:=B[n]

o addirittura sono consentite operazioni di somma, prodotto, divisione, per


cui, ad esempio, A:=B+C corrisponde a:

A[1]:=B[1]+C[1]
A[2]:=B[2]+C[2]
: :: ::
A[n]:=B[n]+C[n]
ma sono casi molto rari.
In una elaborazione non detto che tutti gli elementi di un array vengono
necessariamente utilizzati. Difatti avviene spesso che solo una parte del numero
totale di elementi utile alla elaborazione in corso. Per tali motivi si soliti
168 Capitolo quinto

accompagnare la struttura array con una ulteriore informazione di tipo intero che
conta quante sono le posizioni occupate durante lelaborazione. A tale
informazione viene dato il nome di grado di riempimento dellarray o
semplicemente riempimento.
Il riempimento rappresenta il numero di componenti effettivamente usato
nella elaborazione in corso e non va confuso con il numero di componenti
dell'array (cardinalit dell'array). Solitamente il riempimento minore o al
massimo uguale alla cardinalit. Allinizio del programma il riempimento deve
assumere il valore zero per indicare che nellarray non sono stati inseriti valori.
Diverse possono essere le strategie per disporre valori diversi nelle diverse
posizioni dellarray. Il modo pi semplice di inserirli in posizioni successive a
partire dalla prima cosicch ad ogni inserimento il riempimento non solo indica
quanti elementi sono stati allocati ma anche quale lultima posizione occupata.
Nella tabella 9 che segue si presentano diversi algoritmi che inseriscono nellarray
vet gli elementi prodotti da una funzione generica produci_valore; in tutti i casi il
riempimento indicato dalla variabile n mentre la cardinalit dalla costante cmax.
Negli esempi si distinguono i casi in cui la prima posizione dellarray zero da
quella in cui uno. Nei primi due esempi il numero di elementi prodotti
predeterminato.

Caricamento Caricamento Caricamento Caricamento


vettore con vettore con vettore con vettore con
posizione iniziale posizione iniziale posizione iniziale posizione iniziale
uguale a zero e uguale ad uno e uguale a zero e uguale ad uno e
numero elementi numero elementi numero elementi numero elementi
predeterminato predeterminato non predeterminato non
predeterminato
n := fissa_riemp; n := fissa_riemp; n:=0; n:=0;
for i:=0 to n-1 for i:=1 to n while (termina while (termina
do vet[i]:=produci_valore; do vet[i]:=produci_valore; AND n<cmax) AND n<cmax)
do begin do begin
n:=n+1; n:=n+1;
vet[n-1]:=produci_valore; vet[n]:=produci_valore;
termina:= termina:=
verifica_terminazione; verifica_terminazione;
end end
Tabella 9 - Caricamento di vettori

In tutti i casi n indica il riempimento del vettore: nel caso di uso della
posizione zero n indica la posizione successiva a quella occupata per ultima; negli
altri casi indica proprio lultima posizione occupata. Si noti che la scelta della
cardinalit di un array (cmax negli esempi) di estrema importanza in quanto deve
essere fatta pensando che lo stesso programma pu essere eseguito in condizioni
diverse: cmax deve comprenderle tutte in quanto un suo sottodimensionamento
porta il programma in una condizione di errore gestita in modi diversi dal
compilatore del linguaggio.
Negli esempi luscita dal ciclo per n<cmax non pi verificata, comporta che
alcuni dati prodotti dallambiente non vengano presi in considerazione. In
definitiva non si deve sovradimensionare l'array introducendo componenti mai
utilizzati occupando inutilmente la memoria centrale, e non si deve neppure
introdurre un array troppo piccolo per le diverse richieste dell'elaborazione.
I dati 169

Un array si dice bidimensionale se i suoi componenti sono array


monodimensionali. Una possibile definizione di un tipo array bidimensionale di
interi la seguente:

type matrice=array [1..10,1..10] of integer

In questo caso la funzione di accesso composta da due indici:


- il primo che individua l'array componente;
- il secondo che individua il componente dell'array selezionato con il primo
indice.
Ad esempio matrice[I,J] il componente di posto J dell'array I-esimo. Gli array
bidimensionali vengono usati nei problemi di analisi per la rappresentazioni delle
matrici. Gli esempi che seguono riportano alcune modalit di uso degli array
bidimensionali.

Caricamento matrice Caricamento matrice non Copia di una


quadrata per righe quadrata per colonne matrice in unaltra
invertendo righe e
colonne (entrambe
quadrate di ordine
n)
n:=fissa_ordine; n:=fissa_ordine; for I:=1 to n
for I:=1 to n m:=fissa_ordine; do begin
do begin for J:=1 to m for J:=1 to n
for J:=1 to n do begin do begin
do begin for I:=1 to n A[J,I]:= B[I,J];
matrice[I,J]:=determina_valore; do begin end
end matrice[I,J]:=determina_valore; End
end end
End
Tabella 10 - Caricamento di matrici

Gli array pluridimensionali sono array di array di array con funzione di


accesso A[I,J,K,...]. Solitamente il numero di dimensioni ammesse per un array
finito e definito per motivi pratici.
5.4.2. Il tipo stringa di caratteri
Il tipo stringa di caratteri si definisce come sequenza di caratteri. Per motivi
pratici la lunghezza della sequenza finita. possibile avere stringhe senza
caratteri, ossia con lunghezza nulla. Tali stringhe sono dette stringhe nulle o vuote.
Tra i valori del tipo stringa di caratteri si definisce un ordinamento se il tipo
carattere ordinato e il confronto tra due stringhe il risultato del confronto dei
caratteri in egual posizione. Si ha allora che BIANCO' segue 'BIANCA' ( maggiore
di), e 'caso' precede 'casolare' ( minore di). In particolare, per le stringhe che
presentano la medesima lunghezza l'ordinamento quello lessicografico: due
parole si confrontano carattere per carattere a partire da sinistra (carattere in prima
posizione) e l'ordinamento viene deciso dalla prima occorrenza di caratteri diversi
e si dice che la parola che ha il carattere pi piccolo precede l'altra. Per le stringhe
con lunghezza diversa si estende l'ordinamento lessicografico accodando alla
stringa pi corta il numero di spazi necessari a renderla lunga quanto l'altra. Si noti
170 Capitolo quinto

per che l'ordinamento tra le stringhe diverso da quello del dizionario per il quale
non si fa differenza tra lettere maiuscole e minuscole e sono assenti i caratteri
speciali e le cifre.
Qualche volta definita una funzione di accesso che consente di estrarre da
una stringa assegnata la sottosequenza che inizia in una posizione specificata ed
costituita da un numero fissato di caratteri, oppure termina in una data posizione.
Un'operazione interna al tipo stringa di caratteri (come gi visto applicabile a
tutte le sequenze) la concatenazione, che applicata a due sequenze, la prima di
lunghezza M, la seconda di lunghezza N, genera una sequenza di lunghezza M+N
avente come primi M simboli quelli della prima sequenza e come successivi N
simboli quelli della seconda sequenza.
Di solito si indica con &,//,+, ed ad esempio, se s1='CA' e s2='SA' allora si
ha che s1 + s2 'CASA'. Si ricordi che per definire una stringa sono necessari:
- l'attributo della stringa;
- il numero massimo di caratteri che la stringa pu contenere (solitamente
0 < K < MAX, con MAX che dipende dal linguaggio di programmazione).
Ad esempio:
type PAROLE = string[10]
type TELEFONO = string[12]

Per le stringhe di caratteri valgono considerazioni analoghe a quelle fatte per


il riempimento di un array. La lunghezza della stringa dipende dalla elaborazione
in corso e risulta sempre minore od uguale alla massima dimensione. I linguaggi di
programmazione per gestiscono in modi molto diversi la lunghezza della stringa.
In particolare alcuni consentono di utilizzare solo una parte di quella massima
dichiarata altri no. Allora si dice che una stringa ha una lunghezza variabile se
possibile usare solo una parte dei K caratteri previsti nella definizione. Sulle
stringhe gestite in questo modo definita la funzione LEN(x) che fornisce il numero
di caratteri presenti nella stringa (valore compreso in [0,K]). Si dice invece che una
stringa ha una lunghezza non variabile se vengono usati sempre tutti i K caratteri
previsti nella definizione.
Per comprendere la differenza fissiamo che s1 sia string[10] e s2 sia string[5] e
osserviamo il funzionamento della concatenazione s1 + s2 dopo aver effettuato le
seguenti assegnazioni:
s1:='abc' e s2:='efg'

1. caso variabile: i len(s2) caratteri di s2 vengono accodati ai len(s1) caratteri


di s1 dando la stringa 'abcefg'
2. caso non variabile: i 5 caratteri di s2 vengono accodati ai 10 caratteri di s1
fornendo la stringa 'abc efg '
Si noti che assegnare ad una stringa un'altra stringa di lunghezza minore della
sua dimensione non crea alcun problema nel caso variabile mentre in quello a
lunghezza fissa comporta che i restanti caratteri vengono solitamente riempiti con
il carattere spazio. Ad esempio l'assegnazione s1:='abc' assegna ad s1 definita come
string[10] la stringa 'abc' nel caso a lunghezza variabile e 'abc ' nell'altro caso.
Invece l'assegnazione ad una stringa di un'altra di dimensione maggiore non
presenta alcuna differenza nei due casi e si traduce in un troncamento dei caratteri
I dati 171

eccedenti. Ad esempio l'assegnazione ad s1 di 'abcdefghilmnopqrstuvz' corrisponde


all'assegnazione della sola stringa 'abcdefghil' (primi 10 caratteri).
Per il caso a lunghezza fissa bisogna per fare attenzione agli effetti combinati
della concatenazione e dell'assegnazione: difatti l'assegnazione s1:= s1 + s2 risulta
inutile in quanto per effetto della concatenazione vengono presi tutti i caratteri di s1
e composti con quelli di s2, ma per effetto della assegnazione la stringa ottenuta
verr troncata proprio dei caratteri di s2.
5.4.3. Il record
Il tipo strutturato record il prodotto cartesiano di informazioni dette campi: i
tipi dei campi possono essere omogenei o disomogenei. Per definire un record sono
necessari:
- l'attributo del record;
- e l'elenco degli attributi dei campi con relativi tipi.
Ad esempio:

type NOME = record of


NOME_PRIMO_CAMPO: TIPO_A;
NOME_SECONDO_CAMPO : TIPO_B;
:
NOME_I-esimo_CAMPO: TIPO_A;
:
NOME_N-esimo_CAMPO: TIPO_X
end;

type COORDINATE = record of


ASCISSA: real;
ORDINATA: real;
end;

type DATA = record of


GIORNO: integer;
MESE: integer;
ANNO: integer;
end;

La funzione di accesso del record consente la selezione di un campo. Si


realizza specificando il nome del record e quello del campo separati da un punto.

Ad esempio se A una variabile del tipo:

type ANAGRAFICA =
record of
NOME: string[40];
INDIRIZZO: string[30];
ETA: 1..100;
ESAMI_SOSTENUTI: integer
end
172 Capitolo quinto

allora per selezionare il campo NOME si deve scrivere A.NOME, mentre per ETA,
A.ETA e cos via.
Le operazioni sul record sono quelle definite sul tipo delle informazioni
componenti. Ad esempio:
A.NOME *4

non possibile, mentre:

A.ESAMI_SOSTENUTI +30

ovviamente possibile.
In alcuni linguaggi possibile l'assegnazione ad un record del valore di un
altro record dello stesso tipo. In questo caso il valore di tutti i campi del record a
secondo membro vengono assegnati ai campi con medesimo nome del record a
primo membro. Ad esempio, se dat1 e daT2 sono due record del tipo DATA, allora
l'assegnazione dat1:=dat2 corrisponde all'insieme delle assegnazioni:

dat1.giorno:=dat2.giorno
dat1.mese:=dat2.mese
dat1.anno:=dat2.anno

5.5. I puntatori
Una variabile detta puntatore se il suo valore individua la posizione di
un'altra informazione. Per posizione di una informazione si intende la posizione da
essa assunta o in memoria o all'interno di una struttura dati. In tal senso sono
puntatori i riferimenti ad un elemento di un array, di un carattere all'interno di una
stringa, e cos via.
Nei linguaggi attuali, nei quali possibile la creazione e la distruzione di
variabili dinamicamente, durante l'esecuzione del programma sotto il diretto
controllo del programmatore, i puntatori sono lunico strumento per poter operare
su tali variabili. Con comandi specifici (ad esempio new) si istanziano variabili
quando servono nel corso della elaborazione; con altri comandi (ad esempio
dispose) si recupera lo spazio di memoria occorso per lallocazione della variabile.
La istanziazione della variabile restituisce lindirizzo di memoria attraverso cui si
accede ad essa per tutte le operazioni consentite compatibili con il tipo di
appartenenza.
Per poter far uso di un tale meccanismo di allocazione dinamico, le variabili
devono essere opportunamente dichiarate per consentire non solo la gestione
dellindirizzo di memoria attraverso cui operare sulla variabile, ma anche la sua
effettiva occupazione in memoria. La definizione di una variabile puntatore si
effettua quindi indicando a quale tipo di variabile essa deve puntare come
lesempio seguente schematizza.

type tipo_puntato = record of


campo1: integer;
I dati 173

campo2: real;
end;
type puntatore =^tipo_puntato;

Con essa si definisce il tipo puntatore come riferimento al record di tipo


tipo_puntato. Allora la dichiarazione:

var punt : puntatore;

crea una variabile il cui contenuto sar l'indirizzo dellarea di memoria gestita
secondo le indicazioni di tipo della definizione e allocata dinamicamente. In altre
parole, l'inserimento all'interno del programma della seguente chiamata:

new(punt);

provoca l'allocazione in memoria di una variabile di tipo tipo_puntato (un


record quindi) e l'assegnazione alla variabile puntatore dell'indirizzo di allocazione.
Senza tale chiamata la variabile di tipo record, riportata nell'esempio, non pu
essere usata e solo dopo di essa si pu fare riferimento alla variabile creata tramite
la variabile puntatore. Per tali motivi si ha che:
- punt denota il valore del puntatore (ossia l'indirizzo di memoria dove il
record stato allocato per effetto della procedura new);
- punt^ denota invece la variabile puntata (quindi il record).

Cos la seguente assegnazione:

punt^.campo1 := 1000;

assegna il valore 1000 al primo campo del record.

Se infine si dichiara unaltra variabile dello stesso tipo puntatore:

var punt1: puntatore;

ed ad essa si assegna il valore del precedente puntatore:

punt1 := punt;

si ha che l'indirizzo di memoria associato a punt viene assegnato anche a punt1 in


modo che entrambi fanno riferimento alla stessa zona di memoria.
Con un meccanismo opposto al new, la procedura predefinita dispose
restituisce lo spazio di memoria associato al puntatore specificato nella chiamata
della procedura stessa. Cos:

dispose(punt)

rende disponibile per altre allocazioni l'area di memoria a cui fa riferimento punt.
174 Capitolo quinto

I linguaggi che dispongono di puntatori di questo tipo, ossia contenenti


direttamente indirizzi di memoria, devono fornire anche un valore che indichi che
il puntatore non punta a nulla. Solitamente tale costante predefinita e si indica
con NIL.

5.6. I file
Il file si definisce come una sequenza di elementi tutti dello stesso tipo. Si
possono cos avere file di interi, di caratteri, di record, di array, di reali, etc.
L'importanza di tale struttura che di essa non se ne deve indicare la dimensione
all'atto della definizione in quanto i suoi valori vengono allocati in una delle
memorie di massa disponibili nel sistema informatico. Tra laltro, mentre la
dimensione della memoria centrale da considerare definita e limitata, e quindi
sono limitati gli oggetti in essa inseribili, le memorie di massa hanno una capacit
cos grande da non rappresentare, solitamente, una limitazione al numero di
elementi gestibili. Comunque, pu accadere che durante l'aggiunta di informazioni
ad un file si generi un errore per la saturazione della memoria di massa non
essendo essa di fatto illimitata.
Poich le informazioni contenute nel file devono essere gestite nel rispetto del
modello di Von Neumann, al file viene fatto corrispondere un buffer in memoria
centrale capace di garantire il transito dei valori da e verso la memoria di massa.
Per operazioni di scrittura il buffer viene caricato del valore che successivamente
viene registrato sulla memoria di massa, per quelle di lettura si procede in modo
opposto, il valore viene letto dalla memoria di massa e quindi inserito nel buffer
dove pu essere poi elaborato.
Il file quindi composto da una sequenza di elementi tutti dello stesso tipo T
residenti sulla memoria di massa e da una ulteriore informazione di tipo T che
svolge le funzioni di buffer in memoria centrale. I file possono essere ad accesso
diretto o sequenziale. Nel primo caso si pu accedere direttamente ad un
particolare dato nel file nota la posizione; nel secondo caso laccesso al file
avviene in modo rigorosamente sequenziale (cio prelevando un valore dopo
l'altro), indipendentemente dal particolare supporto impiegato per la sua
memorizzazione.
5.6.1. I file sequenziali
Le operazioni definite su un file sequenziale di nome F sono:
- l'inserimento di un elemento PUT(F);
- l'estrazione di un elemento GET(F);
- l'operazione di riavvolgimento RESET(F) per predisporre il file alle
estrazioni;
- la cancellazione o azzeramento REWRITE(F) per predisporre il file alle
inserzioni
- e il predicato logico EOF(F) che segnala durante le estrazioni se il file
terminato (End Of File).
Il buffer viene inserito automaticamente all'atto della definizione, lo si indica
con F^ se F una variabile di tipo file ed di tipo T se il file composto da
elementi di tipo T. Il buffer l'unica informazione del file in memoria centrale che
I dati 175

consente di leggere o aggiungere componenti ad F permettendo il transito da e


verso la memoria ausiliaria.
In ogni momento il file pu essere visto come la concatenazione di una parte
destra Fd di una parte sinistra Fs (prendendo come riferimento l'organo di lettura e
scrittura):

F:=Fs+Fd

Figura 3: Parte destra e sinistra di un file

In tali condizioni EOF(F) assume il valore true se Fd vuoto, negli altri casi
false. Se EOF(F) falso, ossia la parte destra non vuota, si definisce il buffer
come:
F^:=first(Fd)

Nel caso di un file composto dalla sequenza di elementi (abcd) si ha che


l'esecuzione di un RESET(F) comporta l'inizializzazione del file (riavvolgimento) e il
posizionamento nel buffer del primo elemento secondo lo schema:

Fs :=<file vuoto>
Fd :=abcd (*intero file*)

e, quindi, per definizione:

F^:=first(Fd) ossia F^=a perch EOF(F) falso

L'esecuzione di un GET(F) porta invece nel buffer l'elemento del file


successivo a quello precedentemente prelevato per effetto di un RESET o di un altro
GET secondo lo schema:

se Fs:=ab e Fd:=cd allora la GET produce Fs:=abc e Fd:=d

e, quindi, per definizione


176 Capitolo quinto

F^:=first(Fd) ossia d (in quanto EOF(F) ancora falso).

L'esecuzione di un REWRITE(F) cancella gli elementi del file svuotandolo:

F=<file vuoto>

L'esecuzione di un PUT(F) accoda il contenuto del buffer agli elementi del file
secondo lo schema:

se F:=abcd e F^:=f allora put produce F:=F+F^, ottenendo F:=abcdf

solitamente il buffer F^ indefinito dopo un PUT.


Nei file sequenziali l'ordine in cui le operazioni possono susseguirsi molto
rigido. Dopo un reset sono possibili solo operazioni di get, mentre dopo un rewrite
solo quelle di put.
Si definisce generazione di un file l'insieme di operazioni necessarie alla
scrittura di un file su memoria di massa: esse sono un rewrite e una o pi
operazioni di put. Si definisce, invece, ispezione di un file l'insieme di operazioni
necessarie alla lettura di un file: esse sono un reset e tante operazioni di get fino a
che non si incontra la fine del file (eof diventa vero). Si osservi che:
- la definizione delle operazioni ci impone che l'accesso ad un elemento
possibile solo dopo l'accesso a tutti gli elementi che lo precedono;
- non possibile mischiare operazioni di put e get;
- durante l'ispezione del file le componenti vengono lette secondo la
disposizione sequenziale fissata durante la scrittura.
I linguaggi di programmazione mettono a disposizione procedure di lettura e
scrittura per i file pi semplici da usare. Sono procedure, ad esempio di read e di
write, in cui il buffer risulta nascosto e in cui si fa riferimento direttamente alla
variabile il cui valore deve essere letto o scritto su file. Ovviamente le variabili che
compaiono nelle istruzioni di read e write devono essere dello stesso tipo delle
informazioni che compongono il file.

Procedura Sequenza equivalente


read(F,var); var:=F^
get(F);
read(F,var1,var2,..,varN) read(F,var1);
read(F,var2);

read(F,varN);
write(F,var); F^:=var;
Put(F);
write(F,var1,var2,..,varN) write(F,var1);
write(F,var2);
............
write(F,varN);
Tabella 12 Operazioni di lettura e scrittura su file
I dati 177

Con tali operazioni, l'ispezione di un file con elaborazione dei valori si


presenta nel modo seguente:

(*M: posizionamento all'inizio del file *)


reset(f);
(*M: scorrimento fino alla fine di esso *)
while not eof(f)
do begin
(*M: leggo dal file *)
read(f,info);
elabora(info)
end

La generazione del file si presenta invece nella forma:

(*M: predisposizione del file alla scrittura *)


rewrite(f);
repeat
(*M: produci dati con una prefissata elaborazione*)
produci(info);
if info <> terminazione
then (*M: scrittura su file *)
write(f,info)
until info = terminazione
5.6.2. I file di caratteri o textfile
Un tipo di file molto comuni sono i file di caratteri, detti anche textfile. Fra
tutti i file, i textfile svolgono un ruolo molto importante in quanto, nella
maggioranza dei casi, i dati di ingresso e di uscita dei programmi sono costituiti da
textfile. Un processo di calcolo che interagisce con il mondo esterno pu essere
considerato come un processo di trasformazione di textfile.
Difatti, l'insieme di dati prelevati da una tastiera sono di fatto un textfile (detto
di input) cos come un textfile (detto di output) l'insieme dei risultati presentati
sul video o sul foglio di carta di una stampante. L'uso di alcuni caratteri di
controllo ASCII permette di organizzare i textfile in linee o righe. Ciascuna riga
contiene al suo interno le rappresentazioni (sequenze di caratteri) che servono
all'elaborazione nel caso dell'input o che da essa vengono generate nel caso
dell'output. In particolare, si conviene di usare il CR (Carriage Return) come
separatore di righi e lo spazio (Space) come separatore di informazioni.
Il prelievo da parte del processore di informazioni dal file di input prende il
nome di operazione di lettura mentre l'inserzione di informazioni in quello di
output viene indicata come operazione di scrittura.
Il passaggio dal tipo dell'informazione letta (o scritta) alla sequenza di
caratteri che la rappresentano nel file di input (o di output) prende il nome di
trasformazione di formato ed avviene durante l'elaborazione. Opportune
indicazioni guidano la trasformazione. Tali indicazioni possono essere di tipo
esplicite o implicito. Quelle esplicite sono fornite al processore dal programmatore
178 Capitolo quinto

mentre le implicite intervengono in assenza delle esplicite e sono definite nel


linguaggio di programmazione usato.
In definitiva i file di input e di output sono file particolari. Il file di input un
file che pu essere solo ispezionato e per tale motivo gi generato e resettato
all'esterno del processo di elaborazione ed ammette come unica operazione il get.
Identificheremo l'operazione di lettura del valore di una informazione dal file di
input con:

read(nome_variabile)

Essa corrisponde, detto INPUT il nome del file di input, alla sequenza di
operazioni:
nome_variabile:=INPUT^
get(INPUT)

ossia all'assegnazione alla variabile del contenuto del buffer associato al file
di input e ad un successivo get.
Il file di output un file che pu essere solo generato e per tale motivo
generato all'interno del processo di elaborazione ed ammette come unica
operazione il put. Identificheremo l'operazione di scrittura del valore di una
informazione nel file di output con:
write(nome_variabile)

Essa corrisponde, detto OUTPUT il nome del file di output, alla sequenza di
operazioni:
OUTPUT^:=nome_variabile
put(OUTPUT)

ossia all'assegnazione al buffer associato al file di output del valore della


variabile e ad un successivo put.
Comunque, non solo il mondo esterno (file INPUT per la tastiera e OUTPUT per
il video) organizzato come textfile. Anche altri file possono essere organizzati in
tale modo. Le informazioni che da essi vengono prelevate richiedono
trasformazioni di formato identiche a quelle viste a proposito dell'immissione dei
dati da tastiera, mentre quelle che in essi vengono registrate richiedono le stesse
trasformazioni di formato che governano la presentazione dei risultati al video.
Il vantaggio di organizzare i dati in textfile risiede nel fatto che la
rappresentazione in caratteri ne garantisce la comprensione da parte dell'uomo
anche all'esterno del programma che li genera o li ispeziona. In ogni caso, il lavoro
richiesto per la conversione di valori dalla loro rappresentazione interna (stringhe
di bit) nella forma di sequenze leggibili di caratteri per le operazioni di read e,
viceversa, per quelle di write, richiede del tempo di elaborazione. Se le
informazioni devono essere scritte su un file che lo stesso o un altro programma
deve rileggere, non c' alcuna evidente necessit di convertile dapprima in caratteri
e successivamente riconvertirle nel formato interno di memoria. Inoltre, la
conversione e riconversione oltre a far perdere del tempo pu, nel caso di
informazioni di tipo numerico, generare errori per la differenza di precisione tra la
rappresentazione esterna e quella interna: se ad esempio una variabile numerica
I dati 179

viene scritta sul file con un formato che tronca alcune sue cifre significative,
quando se ne rilegge successivamente il valore, lo si trover diverso da quello
iniziale.
Tutti i file di tipo non testo memorizzano i valori delle informazioni cos come
sono rappresentati in memoria centrale, quindi senza alcuna ulteriore elaborazione.
Essi dipendono fortemente dallambiente di programmazione che li genera e
pertanto richiedono un legame molto stretto tra la loro generazione e ispezione, nel
senso che non solo la successione delle informazioni lette deve corrispondere a
quella in cui le stesse informazioni sono state scritte ma anche che la lettura deve
avvenire nello stesso ambiente in cui sono stati generati. Nei casi in cui i file
vengono generati in un ambiente ed elaborati in un altro, si preferisce utilizzare per
essi il tipo textfile per garantire la portabilit dei dati.
5.6.3. La connessione e sconnessione dei file
La gestione delle memorie di massa affidata al Sistema Operativo. Molti
sono i modi di organizzare le memorie di massa sia dal punto di vista logico che da
quello fisico. In questa sede sufficiente ricordare che, da un punto di vista logico,
le memorie di massa sono organizzate in aggregati di informazioni tra loro
omogenee a cui viene dato il nome di file.
Il file system la componente del sistema operativo a cui affidato il compito di
organizzare e gestire i file. Le sue funzioni specifiche variano da computer a
computer, ma tipicamente includono:
- la creazione e la cancellazione dei file;
- la gestione degli accessi alle informazioni del file;
- la gestione e lorganizzazione dello spazio delle memorie di massa;
- la protezione dei file per impedire l'accesso da parte di persone non
autorizzate a farlo.
Poich su una memoria di massa possono risiedere pi file
contemporaneamente, il file system richiede che a ciascun file, all'atto della sua
creazione, venga assegnato un nome. Tale nome viene poi usato come suo
riferimento per effettuare una qualsiasi altra operazione di gestione come
l'aggiornamento, l'ispezione o la cancellazione. Due file diversi non possono avere
ovviamente lo stesso nome. Il file system gestisce per ogni file, oltre al nome,
anche le seguenti informazioni:
- l'allocazione del file sul supporto magnetico;
- la dimensione del file;
- la data di creazione o dell'ultimo aggiornamento del file;
- le informazioni di controllo sui diritti di accesso quali quelli che abilitano
operazioni di modifica del contenuto del file, la lettura del file o la sua
eventuale eliminazione.
L'informazione fondamentale che contraddistingue il file il nome
attribuitogli al momento della sua creazione. I file system dei vari sistemi operativi
prevedono sintassi molto diverse per la costruzione di tali nomi. Solitamente sono
stringhe di caratteri e cifre di lunghezza fissata attribuite al file in modo analogo a
quello in cui si sceglie un identificatore per una variabile: ossia in modo da
ricordarne il contenuto.
180 Capitolo quinto

Al nome pu essere aggiunta una estensione facoltativa: per esempio nella


stringa filename.est, filename il nome e est l'estensione. L'estensione
comincia con il punto (.), ed formata da 1, 2 o 3 caratteri.
Pi file possono essere raggruppati in cartelle o direttori. Se sulla memoria di
massa sono state organizzate pi cartelle, prevedendo anche che alcune di esse
siano interne ad altre, il nome del file da solo non basta ad identificarlo e si deve
specificare il percorso da seguire per raggiungerlo nella cartella in cui collocato.
Ad esempio \programmi\corso2007\c\ordina.c indica che il file ordina.c si trova
nella cartella c che interna a corso2007 che a sua volta interna a programmi.
Infine un sistema pu disporre di pi memorie di massa identificate da lettere
o da nomi. Se ad esempio il sistema dispone di una unit minidisco e di una unit
disco fisso, l'unit minidisco viene identificata dalla lettera A e il disco fisso dalla
lettera C.
Pertanto per individuare un file, si devono specificare:
- la lettera o il nome identificativi dell'unit,
- il percorso da seguire tra le cartelle per raggiungere quella che contiene il
file
- il nome di file
- e l'estensione, se esiste.

Linsieme dei quattro elementi detto specificazione del file. I due punti (:)
separano lidentificativo dellunit dal resto; le cartelle del percorso sono separate
tra di loro dal carattere \ e lestensione preceduta dal punto.
In un programma, prima di poter operare su un file si deve interagire con il
file system del sistema operativo fornendogli le indicazioni del file capaci di
individuarlo univocamente. La connessione permette all'interno di un programma
di richiedere al sistema operativo il file sul quale operare. Tutti i linguaggi
prevedono a questo scopo procedure predefinite per consentire la connessione tra
la variabile file e il nome da esso assunto nella memoria di massa gestita dal file
system del sistema operativo.
In modo molto semplice la connessione pu avvenire tramite una procedura
che associa alla variabile di tipo f il suo nome sulla memoria di massa. Ad esempio
con una procedura assign del tipo:

assign(F, c:\programmi\corso2007\ordina.c)

si attiva la connessione della variabile F con il file ordina.c residente nella


cartella corso2007, a sua volta interna alla cartella programmi presente sullunit
c:.
L'operazione di connessione deve ovviamente avvenire prima di un reset o di
un rewrite. A partire da essa il programma potr operare in lettura (reset) o scrittura
(rewrite) sul file che sulla memoria di massa ha il nome specificato.
In alcuni linguaggi alla connessione si accompagna anche lindicazione della
modalit di accesso. In essi, con procedure di tipo OPEN, si forniscono le
indicazioni di connessione per ispezione o per generazione come la tabella illustra.
I dati 181

Procedura Modalit Operazioni equivalenti


OPEN(F,nome_file,r) Ispezione Assign(F, nome_file)
Reset(F)
OPEN(F,nome_file,w) Generazione Assign(F, nome_file)
Rewrite(F)
Tabella 13 Procedura OPEN

In alcuni casi si pu anche attivare la scrittura in modalit di accodamento


(append) per aggiungere alla fine di un file esistente.
Cos come si stabilisce la connessione con un particolare file, si pu in ogni
momento sancire la sconnessione tra programma e file. Dopo che stata stabilita la
sconnessione con il file, non pi possibile effettuare operazioni su di esso. Solo
una ulteriore riconnessione ne permette l'uso. Per consentire la sconnessione
esistono procedure tipo close(F). Se non specificata esplicitamente, la sconnessione
avviene in modo automatico all'atto della terminazione del programma.
L'uso della connessione e della sconnessione consente di utilizzare le stesse
procedure di gestione dei file per file diversi all'interno di uno stesso programma.
5.6.4. I file ad accesso diretto (RANDOM)
Esistono numerosi problemi di gestione dei file per i quali l'accesso
sequenziale non adeguato. Si pensi alla gestione di un magazzino dove
l'operazione di registrazione degli articoli avviene in genere una sola volta ma la
modifica del numero di pezzi e del prezzo, per esempio, sono invece operazioni
che avvengono con una elevata frequenza interessando un solo elemento del file. In
questi casi serve una modalit di gestione dei file con la quale posizionarsi
velocemente sullelemento in una data posizione per poterlo modificare senza
dover seguire le procedure rigide di scorrimento tipiche dell'accesso sequenziale.
Oggi, tutti i linguaggi mettono a disposizione del programmatore file ad
accesso diretto (o anche casuale o random) nel senso che possibile operare su un
elemento in una posizione specificata senza dover processare tutti quelli che lo
precedono, come l'accesso sequenziale impone di fare. cos possibile leggere o
scrivere una qualsiasi delle componenti del file, anche se l'aggiunta di componenti
nuove deve avvenire sempre in coda al file stesso. In altre parole i file ad accesso
diretto possono essere visti come una estensione degli array su memoria di massa:
ad ogni elemento del file associata una posizione mediante la quale operare su di
esso con una particolare funzione di accesso. A differenza degli array non si deve
definire la dimensione massima.
Per la connessione dei file ad accesso diretto non richiesta lindicazione
della modalit di accesso. Dopo il posizionamento, mediante lindicazione della
posizione dellelemento su cui operare, si pu operare indifferentemente sia in
lettura con la procedura read che in scrittura con la procedura write.

5.7. Lastrazione sui dati


L'importanza di definire le strutture dati pila, coda e tabella risiede nel fatto
che parecchie applicazioni ne possono richiedere l'uso a prescindere dalla loro
effettiva disponibilit nei linguaggi di programmazione. Infatti, proprio per il gi
182 Capitolo quinto

discusso legame tra algoritmo e struttura dati in esso impiegata, importante poter
trattare ad un primo livello di formulazione della soluzione di un problema con
l'informazione astratta, definita cio tramite la struttura e le modalit di
funzionamento, rinviando, quindi, la definizione dettagliata del tipo con gli
strumenti messi a disposizione dal linguaggio dopo la verifica della correttezza
della soluzione stessa. In questo modo si otterranno soluzioni pi aderenti alla
realt del problema e quindi pi facilmente interpretabili e gestibili nel tempo.
In altri termini l'astrazione sui dati un utile metodo per posporre i dettagli di
implementazione in modo da risolvere i problemi di rappresentazione nella
maniera pi adeguata e quanto pi indipendente dall'algoritmo. L'uso di tale
metodo, peraltro, favorita dalla presenza in alcuni linguaggi pi moderni di
meccanismi appositi di definizione. Invece, nei linguaggi tradizionali, si deve
dapprima scegliere tra quelle disponibili la struttura dati che pi simile per
composizione e modalit d'uso a quella astratta e quindi renderla equivalente, da un
punto di vista funzionale, attraverso i meccanismi del linguaggio, quali le funzioni
o i sottoprogrammi.
5.7.1. Il tipo pila
La pila viene anche detta stack. E' una struttura che possiamo definire come
composta da oggetti tutti dello stesso tipo sui quali possibile operare in modo che
il primo oggetto che dalla struttura si pu estrarre l'ultimo che in essa stato
inserito. Per questa modalit di gestione la pila anche detta struttura LIFO dalle
parole inglesi Last In - First Out (ultimo entrato - primo uscente).
Le operazioni definite sulla pila sono:
- PUSH: per aggiungere un elemento alla pila,
- POP: per togliere alla pila l'elemento che stato aggiunto per ultimo,
- TOP: per osservare l'elemento che stato aggiunto per ultimo.
Inoltre sulla pila definito il predicato:
- EMPTY: che quando assume il valore TRUE indica che la pila vuota,
ossia non ha elementi.
Per motivi pratici, legati all'impossibilit di trattare tipi a cardinalit infinita,
viene introdotto anche il predicato:
- FULL: che con il valore TRUE indica quando la pila si riempita.
Come si pu notare, un tale tipo si presta a modellare l'organizzazione di
oggetti della vita quotidiana. Infatti, come una pila di piatti, di libri, di fogli esso
caratterizzato dal fatto che il primo oggetto prelevabile quello che si trova in testa
a tutti gli altri ed proprio quello che stato posato su di essi per ultimo.
Si noti infine che:
- POP e TOP sono possibili se la pila non vuota;
- PUSH possibile se la pila non piena.
5.7.2. Il tipo coda
La coda una struttura composta da oggetti tutti dello stesso tipo sui quali
possibile operare in modo che il primo oggetto estraibile dalla struttura il primo
che in essa stato inserito. Per questo modalit di gestione la coda anche detta
struttura FIFO dalle parole inglesi First In - First Out (primo entrato - primo
uscente).
I dati 183

Le operazioni definite sulla coda sono:


- PUSH: per aggiungere un elemento alla coda,
- POP: per togliere alla coda l'elemento che stato aggiunto per primo.
Inoltre sulla pila definito il predicato:
- EMPTY: che quando assume il valore TRUE indica che la coda
vuota, ossia non ha elementi.
Per motivi pratici, legati all'impossibilit di trattare tipi a cardinalit infinita,
viene introdotto anche il predicato:
- FULL: che con il valore TRUE indica quando la coda si
riempita.
Per comprendere questa organizzazione di oggetti possiamo pensare ad una
reale coda che si forma davanti ad uno sportello di un ufficio: la persona che
servita per prima proprio quella che arrivata prima nella coda e che si trova
quindi alla sua testa, e le persone che via via arrivano vanno a disporsi sempre
dopo l'ultimo della coda.

Si noti infine che:


- POP possibile se la coda non vuota;
- PUSH possibile se la coda non piena.
5.7.3. Il tipo tabella
La tabella una struttura costituita da un insieme finito di coppie di valori (a,b),
con a e b appartenenti a tipi diversi o anche uguali, tra loro corrispondenti secondo
l'applicazione F:

b:=F(a)

I tipi dei valori possono essere qualsiasi, sia atomici che strutturati. Inoltre il
primo elemento della coppia viene detto chiave della tabella per il fatto che il
mezzo per entrare nella struttura e prelevare il secondo elemento della coppia.
Le operazioni definite sulla tabella sono:
- INSERIMENTO: per aggiungere una coppia alla tabella;
- RICERCA: per estrarre, se esiste, l'elemento b corrispondente al valore della
chiave a specificata;
- CANCELLAZIONE: per eliminare la coppia che ha il primo elemento uguale
al valore della chiave specificata.
Inoltre sulla tabella sono definiti i predicati:
- EMPTY: che quando assume il valore TRUE indica che la tabella vuota,
ossia non ha elementi.
- FAIL: il cui valore TRUE indica il fallimento della ricerca sia per operazioni
di RICERCA che di CANCELLAZIONE, ossia indica che non esiste una
coppia con il valore della chiave specificata.
Per motivi pratici, legati all'impossibilit di trattare tipi a cardinalit infinita,
viene introdotto anche il predicato:
- FULL: che con il valore TRUE indica quando la tabella si riempita.
La tabella una struttura astratta di grande interesse poich permette di
trattare corrispondenze fra insiemi di qualsiasi natura. Ad esempio, si pu pensare
all'elenco telefonico che mette in corrispondenza un nominativo (la chiave) con un
184 Capitolo quinto

numero telefonico, all'indice di un libro (dove il titolo del paragrafo la chiave di


accesso alla pagina), alla rappresentazione di una funzione per punti, e cos via. Si
noti infine che:
- la RICERCA e la CANCELLAZIONE sono possibili se la tabella non vuota;
- l' INSERIMENTO possibile se la tabella non piena.
Capitolo sesto

Il linguaggio C

6.1. Introduzione
Il C un linguaggio di programmazione molto usato in diversi campi
applicativi. Realizzato nel 1972 da Dennis Ritchie, il linguaggio porta un nome che
deriva dal suo predecessore, il linguaggio B, progettato da Ken Thomson per
implementare il sistema operativo Unix. Ritchie e Thomson, successivamente,
riscrissero il sistema Unix interamente in C.
Sebbene il sistema operativo Unix, il compilatore C e quasi tutti i programmi
applicativi di Unix siano scritti in C, il linguaggio non legato ad alcun sistema
operativo o ad alcuna macchina particolare: viene comunque considerato da molti
come un linguaggio di programmazione di sistema per la sua utilit nella scrittura
dei sistemi operativi.
Il C un linguaggio di alto livello che possiede un ristretto insieme di
costrutti di controllo e di parole chiave ed un ricco insieme di operatori; esso
permette, inoltre, di programmare in modo modulare, usando funzioni e macro. Nel
contempo, il C viene anche considerato un linguaggio relativamente di basso
livello, in quanto prevede operazioni tipiche di un linguaggio macchina, come
lindirizzamento in memoria.
Per scelta di progetto il C non contiene istruzioni di ingresso/uscita (non
esistono istruzioni di READ e WRITE dedicate, e neppure istruzioni per laccesso ai
file) n istruzioni particolari per le operazioni matematiche; mancano anche
operazioni per trattare direttamente oggetti strutturati come stringhe di caratteri,
insiemi, liste ed array, ed infine non esistono operatori con i quali manipolare interi
array o intere stringhe. Il C affida limplementazione di tali tipologie di operazioni
a librerie esterne cos da avere un linguaggio compatto le cui funzionalit si
possono ampliare facilmente sia sviluppando ulteriori librerie che modificando
quelle standard.

6.2. Le caratteristiche generali del linguaggio C


Le caratteristiche principali del linguaggio C sono:
- presenza dei fondamentali costrutti di controllo di flusso:
o sequenza di istruzioni organizzate in blocchi;
o decisioni o costrutti selettivi (if, switch);
o cicli o costrutti iterativi (while, for, do).
186 Capitolo sesto

- disponibilit di operazioni su tipi fondamentali (come i caratteri, gli interi,


i reali in virgola mobile) e su tipi derivati, costruiti a partire dai tipi
fondamentali o da altri tipi derivati, (come larray, le funzioni, le strutture
e le unioni).
- gestione dei puntatori con una aritmetica sugli indirizzi.
- invocazione ricorsiva di una funzione, con chiamate nidificate.
- linguaggio case sensitive, nel senso che gli identificatori dipendono dal
modo in cui sono scritti in quanto lettere maiuscole e minuscole sono
considerate diverse.
Il linguaggio C un linguaggio strutturato con precise regole di visibilit
dei dati e del codice. Un programma C composto da un insieme di
sottoprogrammi, che possono essere visti come unit disgiunte, senza per la
possibilit di innesto (ovvero di dichiarare sottoprogammi allinterno di altri
sottoprogrammi in forma annidata). Le unit di programma sono tutte esterne le
une alle altre e sono dotate di propri oggetti locali; possibile tuttavia ricorrere ad
oggetti globali, esterni alle unit ma da esse visibili. Ogni unit costituita da una
sequenza di frasi terminate da punto e virgola che pu essere suddivisa in una
sezione dichiarativa, dove si dichiarano tutti gli oggetti necessari, ed in una sezione
esecutiva dove si trovano le istruzioni vere e proprie atte ad implementare
lalgoritmo associato allunit stessa.
6.2.1. Il vocabolario del linguaggio
Il vocabolario del linguaggio C costituito da sequenze di lunghezza finita di
caratteri trattate come singole entit logiche ( quindi l'insieme delle parole
costruite secondo le regole lessicali). In C ci sono sei classi di simboli:
- separatori ed identificatori,
- simboli speciali
- parole chiave,
- costanti,
- stringhe.
6.2.2. Separatori ed identificatori
Nel linguaggio le diverse entit lessicale sono separate tra loro mediante opportuni
separatori. I caratteri spazio ed ENTER (fine linea) sono considerati separatori
espliciti, mentre gli operatori (aritmetici e di relazione), il punto e virgola e
l'operatore dell'assegnazione (=) vengono implicitamente identificati come
separatori. Cos le frasi che seguono presentano due entit lessicali distinte:

alfa = 10
if contatore

mentre le frasi seguenti ne presentano soltanto una:

ifcontatore
whilecondizione
Il linguaggio C 187

Gli identificatori permettono di indicare i nomi di programmi, costanti,


variabili e funzioni. Un identificatore una stringa di caratteri che deve soddisfare
i seguenti vincoli:
- deve essere composta da lettere, cifre e dal carattere _;
- il primo carattere deve essere una lettera;
- deve essere costituito da un numero limitato di caratteri;
- non deve ovviamente contenere al suo interno lo spazio.

Figura 1 Carta sintattica per identificatori

Sono ad esempio identificatori diversi :


A
a
alpha
ALPHA
Alpha
Sol1
Pi_Greco
eq2Grado
Nella costruzione dellidentificatore si pu usare una delle lettere dellalfabeto
inglese ed una delle dieci cifre arabe. Per quanto riguarda le lettere, si possono
usare sia maiuscole che minuscole, con significato per diverso (alpha, ALPHA,
Alpha ad esempio sono tre identificatori diversi).
6.2.3. I simboli speciali
I simboli speciali sono o semplici caratteri o coppie adiacenti di essi ed indicano le
operazioni presenti nel linguaggio e tutta la punteggiatura richiesta dalla sintassi.
Essi sono:
+ - * /
(operatori aritmetici)

< > == <= >= ~=


(operatori di confronto)

, ; . : ..
(delimitatori e punteggiatura)
188 Capitolo sesto

( ) [ ] { }
(parentesi)

&& || !
(operatori logici)

// /* */
(commento)

Si vuole notare come il C distingua loperatore di assegnazione = da quello


di confronto logico ==.
6.2.4. Parole chiavi
Alcuni identificatori hanno un ben preciso e congelato significato nell'ambito del
linguaggio e pertanto prendono il nome di parole riservate o chiavi. Tali parole
sono riservate per usi particolari e non sono ridefinibili in altro modo dal
programmatore in quanto sono le chiavi che guidano nella costruzione delle frasi
del linguaggio. I seguenti identificatori sono esempi di parole chiavi.

int extern for


char register do
float typedef while
double static switch
struct goto case
union return default
long break
short continue
unsigned if
auto else
6.2.5. I delimitatori
Il linguaggio C usa il carattere punto e virgola (;) come delimitatore esplicito per
terminare tutte le frasi ad eccezione di quelle di commento.
6.2.6. Le frasi di commento
Come tutti gli altri linguaggi di programmazione anche il C consente di introdurre
frasi prive di valore esecutivo o dichiarativo al fine di migliorare la leggibilit e la
chiarezza del programma. Esse servono unicamente ad uno scambio di messaggi
tra le persone e prendono il nome di frasi di commento.
Le frasi di commento iniziano con i caratteri /* e terminano con i caratteri
*/; la presenza di una apertura e di una chiusura del commento permette di
distribuire la frase su pi righe. Ad esempio sono frasi si commento:

/*
questo un possibile
Commento del linguaggio
C
Il linguaggio C 189

*/
e
/************************************************
Nome programma: radice quadrata
Autore: Paolo Rossi
Versione: 1.0
Data: 12/19/2008
*************************************************/

possibile anche introdurre un commento in una unica riga, usando i caratteri


//, in questo caso considerato commento tutto quello che inizia con // e
termina con la fine del rigo (/n nella carta sintattica). I commenti non possono
essere nidificati.

int x_quadro; //definizione della radice quadrata


//segue implementazione algoritmo risolutivo

/* frase */

// frase /n

Figura 2 Carta sintattica per frasi di commento

6.2.7. Le costanti
Le costanti del linguaggio si dividono in costanti numeriche e costanti di tipo
carattere. Per ci che attiene le prime, i numeri trattati dal linguaggio sono di due
tipi: interi e reali. Un numero intero una sequenza di cifre eventualmente
preceduta da un segno. Un numero reale ha in aggiunta una parte decimale ed
eventualmente un fattore di scala. In particolare una costante reale in virgola
mobile si compone di una parte intera, un punto decimale, ed una parte decimale,
ad esempio 12.14. possibile inoltre usare il carattere e oppure E per
lesponente intero con segno come fattore di scala, come in 12.14 E-10. Sono
costanti intere:

10
300
-1000

Sono costanti reali:

3.400
10.20
190 Capitolo sesto

+1.99E+30
-30.008
-0.7E-10
9.02E3

Inoltre per le costanti intere, se la sequenza inizia con 0 (cifra zero), la


costante un numero ottale, altrimenti decimale. Una sequenza di cifre precedute
da 0x o 0X rappresenta invece un intero esadecimale. Una costante intera che
supera il pi grande intero rappresentabile dalla macchina, considerata long. Una
costante intera seguita da lettera l oppure L una costante long. Ad esempio:
012 rappresenta il numero ottale 12, mentre 012L rappresenta il numero ottale 12
di tipo long.

Figura 3 Carta sintattica per costanti numeriche

Una costante di tipo carattere racchiusa tra singoli apici. Il valore di una
costante carattere il valore numerico del carattere nel set di caratteri della
macchina.
Alcuni caratteri non grafici sono rappresentati come di seguito:
newline \n
tab orizzontale \t
backspace \b
carriage return \r
form feed \f
backslash \\
apice singolo \

Figura 4 Costanti di tipo carattere semplice


Il linguaggio C 191

6.2.8. Le stringhe
Le costanti stringa di caratteri sono sequenze di caratteri racchiuse da una
coppia di caratteri doppi apici ("), come in ''salve''. Il valore della stringa dato
dalla sequenza di caratteri esclusi i doppi apici che fungono da parentesi. Una
costante senza caratteri (una coppia di doppi apici) rappresenta la stringa a
lunghezza nulla. Tutte le stringhe, anche quando sono stringhe identiche, sono in
realt diverse. Il compilatore immette un byte nullo,\0, alla fine di ogni stringa
per individuarne la fine. Sono costanti stringhe di caratteri:
''ALFABETO''
''ciao''
''Minuscolo''

Figura 5 Carta sintattica per stringhe

6.3. Il programma e la gestione dei tipi in C


Un programma C un insieme di uno o pi sottoprogrammi o funzioni. Pi nel
dettaglio la struttura di un programma C prevede:
- un insieme di direttive di compilazione (inclusione di librerie esterne,
definizione costanti, etc)
- la dichiarazione di eventuali variabili globali (visibili a tutte le funzioni
del programma), di eventuali alias di tipi definiti dallutente e dei prototipi
delle funzioni
- la specifica di un insieme di funzioni f1(), f2(),,fN() ognuna costituita da
una sezione dichiarativa (variabili locali alla funzione) ed una esecutiva
(sequenza di istruzioni).
Lunica funzione che deve essere sempre presente allinterno di un
programma C chiamata main(), ed la prima funzione a cui viene ceduto il
controllo quando inizia lesecuzione di un programma. Di solito la funzione main()
si occupa del controllo generale delle varie attivit del programma attivando nel
giusto ordine le funzioni di cui il programma si compone. Di seguito riportata la
struttura generale di un programma C.

direttive di compilazione
dichiarazione di variabili globali
dichiarazione alias di tipi
dichiarazione prototipi di funzione

f1()
{
variabili locali
sequenza di istruzioni
}
192 Capitolo sesto

f2()
{
variabili locali
sequenza di istruzioni
}
.
.
.
fN-1()
{
variabili locali
sequenza di istruzioni
}

main()
{
variabili locali
sequenza di istruzioni
}

Un programma C quindi linsieme di una o pi funzioni, tra cui la main();


presenta un preambolo nel quale si elencano le direttive di compilazione, le
dichiarazioni di variabili globali, gli alias di tipi, i prototipi di funzioni.

Figura 7 Carta Sintattica per la rappresentazione di un programma

Una funzione C un blocco di frasi a cui viene assegnato una intestazione che
contiene la dichiarazione del tipo della funzione stessa, il nome e la lista dei
parametri di ingresso/uscita. Il blocco poi iniziato da una parentesi graffa aperta
ed chiuso da una parentesi graffa chiusa come mostrato di seguito.

<tipo della funzione> nome_funzione (parametri)


{
blocco
}

Figura 8 Carta Sintattica per la rappresentazione di un sottoprogramma o funzione

Ad un programma C infine associato un nome che coincide con il nome del


file del codice sorgente (con estensione .c). Il seguente esempio mostra un
Il linguaggio C 193

semplice programma C, di nome salve.c, che effettua la stampa di una frase a


video.

#include <stdio.h>

int main()
{
printf("Salve!\n");
return 0;
}

La funzione printf() scrive a video la sequenza di caratteri, racchiusa tra


virgolette, specificata tra le parentesi tonde. Come gi visto, una sequenza di
caratteri tra virgolette una stringa. Quella dell'esempio si chiude con i caratteri '\'
e 'n', che in coppia hanno, nel linguaggio C, il significato particolare di "vai a
capo". La funzione return serve a ritornare un valore (nel caso in oggetto 0) alla
fine dellesecuzione del programma main.
Infatti, avendo dichiarato che il valore di ritorno della funzione deve essere di
tipo intero, il compilatore si aspetta che la funzione main restituisca un valore
intero alla fine dellesecuzione.
Il programma, pur nella sua semplicit, permette di ricavare un certo numero
di informazioni molto utili sulla struttura generale di un programma in linguaggio
C. Ogni riga, contenente istruzioni o chiamate a funzioni o definizioni di dati, si
chiude con un punto e virgola (carattere che segnala al compilatore il termine
dellistruzione). La prima riga del preambolo una direttiva al compilatore
(#include): con essa si chiede linserimento del file stdio.h allinterno del
programma, a partire dalla riga in cui si trova la direttiva stessa. Nel file stdio.h ci
sono altre direttive e definizioni che servono al compilatore per tradurre
correttamente il programma. In particolare stdio.h contiene non solo la
definizione della funzione printf() utilizzata nel corpo del programma, ma di altre
funzioni di input ed output.
In generale tutti i programmi C includono alcune direttive di inclusione di file
.h, detti include file o header file, il cui contenuto necessario per un corretto
utilizzo delle funzioni di libreria. Il nome dell'include file , in questo caso,
racchiuso tra parentesi angolari (< e >): ci significa che il compilatore deve
ricercarlo solo nelle directory specificate nella configurazione del compilatore. Se
il nome viene invece racchiuso tra virgolette (ad esempio: "mialibreria.h"), il
compilatore lo cerca prima nella directory corrente, e poi in quelle indicate nella
configurazione. Da non dimenticare che le direttive del compilatore non sono mai
chiuse dal punto e virgola.
Tutto quello che si trova tra le due parentesi graffe costituisce invece il corpo
della funzione (function body) e definisce le azioni svolte dalla funzione stessa: pu
comporsi di definizioni di variabili, di istruzioni e di chiamate a funzione.
Come gi ricordato, tutti i programmi C hanno bisogno di una funzione
principale main che fa partire lesecuzione del programma. Un programma
termina quando:
- si raggiunge la fine del main;
- si effettua una chiamata ad una funzione particolare detta exit();
- il programma interrotto in qualche modo
194 Capitolo sesto

- il programma va in una condizione di errore detta anche crash.


6.3.1. Lintestazione di una funzione
L'intestazione di una funzione costituita dai seguenti elementi:
- il tipo della funzione corrispondente al valore da essa restituito alla sua
terminazione; se la funzione non restituisce valori al posto della
dichiarazione di tipo deve comparire void;
- il nome mnemonico ad essa assegnato;
- la lista di parametri di ingresso/uscita contenente la specifica (nome e
tipo) dei parametri formali mediante i quali la funzione capace
scambiare informazioni con gli altri sottoprogrammi.
Come si vedr in seguito, nella specifica dei parametri formali pu essere
usato o meno loperatore *, a seconda che il parametro deve essere scambiato
allatto dellattivazione della funzione per riferimento o per valore.
Sono ad esempio liste di parametri formali i seguenti esempi:
int a, int b
int a, int b, int *c
Nella specifica dei parametri che vanno passati per riferimento bisogna
utilizzare loperatore *. In realt in C lo scambio dei parametri avviene sempre per
copia e nel caso di passaggio per riferimento viene copiato lindirizzo anzich il
valore di una variabile. Di norma i parametri di ingresso di una funzione sono
passati per valore, mentre quelli di uscita o di ingresso/uscita per riferimento.

Figura 9 Carta Sintattica per lintestazione di un sottoprogramma

Sono esempi intestazioni di funzioni:


int main()
void somma (int a, int b, int *c)
int somma (int a, int b)
Si vuole fare notare come grazie allesistenza della dichiarazione void (vuoto)
in C esiste solo la dichiarazione di funzione e le procedure vengono viste come
particolari funzioni che non ritornano alcun valore.
6.3.2. Il blocco di una funzione
Il blocco una entit sintattica che contiene la parte elaborativa di una qualsiasi
unit di programma (programma principale, procedure e funzioni). Esso consiste di
una serie di frasi del linguaggio costituenti la specifica dellalgoritmo racchiuse tra
parentesi graffe.

specfica
{ }
algoritmo
Figura 10 Carta Sintattica per il blocco di un programma
Il linguaggio C 195

6.3.3. I tipi semplici


Il linguaggio C prevede tre dichiarazioni di tipo elementare per le variabili: uno per
le variabili di tipo alfanumerico, uno per le variabili di tipo numerico, ed uno per le
gestione delle variabili void.

Figura 10 Carta sintattica per i tipi elementari del linguaggio

Per ci che concerne le variabili alfanumeriche il tipo utilizzato dal C il tipo


char, cio carattere, corrispondente ad 1 byte. Esso pu assumere 256 valori
diversi, in quanto rappresentato su 8 bit. Si distinguono due tipi di char: il signed
char, con l'ottavo bit usato come indicatore di segno, e lunsigned char, che
utilizza invece tutti gli 8 bit per esprimere il valore, e pu dunque esclusivamente
assumere valori positivi.
Per quanto riguarda le variabili numeriche, il tipo di dato utilizzato per la
rappresentazione degli interi e corrispondente ad una word il tipo int. Anche il
tipo intero pu essere signed o unsigned. Il numero di bit costituenti una word
varia da macchina a macchina. Nellipotesi di una macchina con una word pari a
16 bit, lintero con segno assume valori che vanno da -32768 a 32767, mentre
quelli dell'intero senza segno variano da 0 a 65535.
Per evitare la differenza di rappresentazione tra macchina e macchina, lo
standard definisce anche un tipo particolare detto short int che occupa 16 bit:
spesso short int e int sono equivalenti. Per esprimere valori interi che variano in un
range maggiore, si pu usare il long int, che occupa 32 bit. Anche il long int pu
essere signed o unsigned. I tipi usati per rappresentare tipi interi sono anche detti
integral types.
Per quanto riguarda i tipi reali, il C permette di gestire numeri in virgola
mobile in floating point, a precisione singola e doppia mediante luso
rispettivamente delle parole chiave float e double. Il float occupa 32 bit secondo lo
standard IEEE 754, il double occupa 64 bit ed il long double 80 bit.
A causa della loro funzione le parole chiave signed, unsigned e long sono
anche indicate col nome di modificatori di tipo. La tabella seguente riassume le
caratteristiche dei tipi di dato sin qui descritti.
196 Capitolo sesto

TIPO BIT VALORI AMMESSI


character 8 da -128 a 127
unsigned character 8 da 0 a 255
short integer 16 da -32768 a 32767
unsigned short integer 16 da 0 a 65535
integer 16 da -32768 a 32767
unsigned integer 16 da 0 a 65535
long integer 32 da -2147483648 a 2147483647
unsigned long integer 32 da 0 a 4294967295
floating point 32 da 3.4*10-38 a 3.4*1038
double precision 64 da 1.7*10-308 a 1.7*10308
long double precision 80 da 3.4*10-4932 a 1.1*104932
Tabella 1: Valori ammessi per tipi numerici

Infine per la gestione di variabili booleane o logiche, pur non essendo previsto
nelle prime versioni del linguaggio, stato introdotto il tipo bool. Le variabili di
tipo bool possono assumere i soli due valori logici vero e falso (true e false).
6.3.4. Dichiarazione di variabili
In C necessario dichiarare una variabile prima di poterla utilizzare. La
dichiarazione delle variabili avviene dapprima specificando leventuale
modificatore di tipo, poi il tipo, e, quindi lidentificatore.

Figura 12 Carta sintattica per la dichiarazione di una variabile

Inoltre, in C, le variabili possono essere classificate, oltre che secondo il tipo


di dato, in base alla loro accessibilit e alla loro durata. In particolare, a seconda
del contesto in cui sono dichiarate, le variabili di un programma C assumono per
default determinate caratteristiche di accessibilit e durata; in molti casi, per,
queste possono essere modificate mediante l'utilizzo di apposite parole chiave, in
gergo note come classi di memorizzazione, applicabili alla dichiarazione delle
variabili stesse.
In termini generali, possiamo dire che la durata di una variabile si estende dal
momento in cui le viene effettivamente assegnata un'area di memoria fino a quello
in cui quellarea riutilizzata per altri scopi. Dal punto di vista dell'accessibilit ha
invece rilevanza se sia o no possibile leggere o modificare, da parti del programma
diverse da quella in cui la variabile stata dichiarata, il contenuto dell'area di
memoria riservata alla variabile stessa.
Il linguaggio C 197

Figura 13 Carta sintattica per la dichiarazione di una variabile

Le classi si memorizzazione delle variabili sono riportate di seguito.


- Automatic Qualsiasi variabile dichiarata all'interno di un blocco di
codice appartiene per default a tale classe. Non dunque necessario,
anche se possibile farlo, utilizzare la parola chiave auto; la durata e la
visibilit della variabile sono entrambe limitate al blocco di codice in cui
essa dichiarata.
- Register Dichiarando una variabile con la parola chiave register si forza
il compilatore ad allocarla direttamente in un registro della CPU, con
notevole incremento di efficienza nell'elaborazione del valore in essa
contenuto.
- Static Come nel caso delle variabili automatic, le variabili static sono
locali al blocco di codice in cui sono dichiarate ma hanno durata estesa a
tutto il tempo di esecuzione del programma. Esse, pertanto, esistono gi
prima che il blocco in cui sono dichiarate sia eseguito e continuano ad
esistere anche dopo il termine dell'esecuzione del medesimo. Ne segue
che i valori in esse contenuti sono persistenti; quindi se il blocco di codice
viene nuovamente eseguito esse si presentano con il valore posseduto al
termine dell'esecuzione precedente.
- External Le variabili external sono variabili dichiarate al di fuori delle
funzioni. Esse hanno durata estesa a tutto il tempo di esecuzione del
programma, ed in ci appaiono analoghe alle variabili static, ma
differiscono da queste ultime in quanto la loro accessibilit globale a
tutto il codice del programma. In altre parole, possibile leggere o
modificare il contenuto di una variabile external in qualsiasi funzione.
Infine il linguaggio C possiede il modificatore daccesso const utilizzato in
fase di assegnazione di una variabile per indicare che il valore della variabile stessa
non pu essere modificato durante lesecuzione del programma. Ad esempio:
const float versione=3.1;
ha leffetto di mantenere costante a 3.1 il valore della variabile reale versione.
La visibilit delle variabili, e pi in generale di un identificatore
opportunamente dichiarato, governata da regole precise che possono riassumersi
dicendo che quanto dichiarato allinterno di un blocco non usabile al suo esterno,
mentre vale che se un oggetto dichiarato allesterno di un blocco esso visibile
allinterno di tutti i blocchi che seguono lessicograficamente la dichiarazione.
Nella struttura del programma C, allora gli oggetti dichiarati nel preambolo sono
visibili a tutte le unit di programma e pertanto sono globali; gli oggetti dichiarati
nella sezione dichiarativa di una funzione sono locali ad essa; gli oggetti dichiarati
198 Capitolo sesto

allinterno di un blocco sono ad essi locali e visibili alle frasi che seguono la
dichiarazione stessa.
6.3.5. Alias di tipi
Il C non permette di definire un nuovo tipo allinterno di un programma: tuttavia
permette di introdurre un nome (pseudonimo o alias) che corrisponde ad uno dei
tipi definiti.
typedef nomeTipo nomeNuovoTipo;
Il meccanismo degli alias pu essere molto utile soprattutto per aumentare la
leggibilit di un programma e per evitare espressioni complesse.
6.3.6. Il tipo enumerativo
Tra i tipi fondamentali del linguaggio C va infine annoverato il cosiddetto tipo
enumerativo. Lenumerazione un insieme di costanti intere rappresentate da
identificatori. Le costanti sono dette anche costanti di enumerazione e sono delle
costanti simboliche i cui valori sono impostati automaticamente: iniziano da 0 e
sono incrementati di solito di 1. Un esempio di enumerazione il seguente:

enum GIORNI {LUN, MAR, MERC, GIOV, VEN, SAB, DOM }

creando un nuovo tipo GIORNI i cui identificatori sono associati con gli interi
compresi tra 0 e 6, ovvero:

enum GIORNI {LUN=0, MAR=1, MERC=2, GIOV=3, VEN=4, SAB=5, DOM=6 }

6.3.7. I tipi derivati


Come noto, in un dato linguaggio, a patire dai tipi fondamentali possibile
costruire nuovi tipi, detti tipi derivati. In C i tipi derivati sono vari: tra essi si
prenderanno in considerazione gli array, le strutture, le unioni ed i campi.
6.3.8. Il tipo array
La struttura array (o vettore) composta da un insieme di elementi tutti dello
stesso tipo e con un unico nome collettivo. Pu avere una o pi dimensioni fino ad
un massimo prefissato. Ad ogni elemento dell'array possibile accedere mediante
un indice (o un numero di indici uguale alle dimensioni stabilite) che ne individua
la posizione all'interno della struttura. Il numero di elementi dellarray definito
allatto della dichiarazione e resta inalterato durante il corso del programma.

Figura 14 Carte sintattiche per la costruzione di array


Il linguaggio C 199

La definizione di un array monodimensionale vet con cinque elementi di tipo


intero il seguente:
int vet[5];

Prima si dichiara il tipo (int), poi il nome dellarray (vet) e successivamente il


numero massimo degli elementi dellarray. Per accedere ad un singolo elemento di
un array, il linguaggio C mette a disposizione una funzione daccesso consistente
nel nome dellarray seguito dalla posizione dellelemento (o coppia di posizioni)
racchiusa tra parentesi quadre. La posizione anche detta indice di accesso. Nel
caso dellarray vet composto da 5 elementi lindice pu assumere i valori
0,1,2,3,4. Ad esempio le istruzioni:

vet[1]=70;
vet[3]=1;

assegnano al secondo elemento dellarray vet il valore 70 e al quarto elemento


dello stesso array il valore 1.

Figura 15 Carta sintattica per laccesso agli elementi di un array

Un esempio di definizione di array con pi dimensioni (matrice) il seguente:

int mat[10][15];
float matReal[15][15];

Laccesso agli elementi di un array a due dimensioni simile a quello di un


array ad una sola dimensione, bisogna per in tal caso specificare due indici:
lindice di riga e quello di colonna. Ad esempio listruzione:

mat[1][3]=3;

assegna il valore 3 allelemento della matrice che si torva in corrispondenza


della prima riga e della terza colonna.
6.3.9. Il tipo struct
Il linguaggio C mette a disposizione il tipo struct per la definizione dei tipi record.
La struttura record composta da un numero prefissato di componenti, anche di
tipo differente. Ogni componente, detto anche campo del record, ha un suo nome e
tipo. La definizione di un record prevede, allora, l'elencazione delle variabili, sia
semplici che a loro volta strutturate, costituenti i campi componenti. Le operazioni
consentite sul record sono quelle che si possono fare sui campi.
200 Capitolo sesto

Figura 16 Carta sintattica per il tipo struct

Nellesempio che segue si definiscono il tipo DATA e la variabile data_mese


di tipo record.

struct DATA
int giorno;
int mede;
int anno;
;
struct DATA data_mese;

In maniera pi sintetica si pu anche utilizzare la seguente definizione.


struct DATA
int giorno;
int mede;
int anno;
data_mese;
Laccesso ai valori dei singoli campi del record avviene indicando nome del
record e nome del campo separati da un punto:
nome_struct.nomecampo
ovvero se si vuole ad esempio accedere al giorno della data:
data_mese.giorno
6.3.10. Il tipo unione
Il concetto di unione deriva direttamente da quello di struttura, ma con una
importante differenza: i campi di una union, a differenza di quelli di una struct,
hanno lo stesso indirizzo di memoria e vanno ad occupare, quindi, tutte le
medesime locazioni di memoria. Questo implica che loccupazione di memoria di
una union coincide con quella del campo dellunione di dimensione maggiore. Ad
esempio:
union ghost
int a;
long b;
char c;
;
union ghost x;
ha una dimensione che coincide con quella della variabile b (di tipo long, in
alcune implementazioni come visto pari a 4 byte). Le unioni dunque sono da
preferire alle struct variabili quando servono variabili che possono assumere
diverse dimensioni a seconda delle circostanze.
6.3.11. I campi
I campi sono una particolare struttura C che consente di far riferimento
simbolicamente ai singoli bit di una variabile. Nell esempio seguente:
Il linguaggio C 201

struct
unsigned a:1;
insigned b:7;
variabileBit;

la variabile variabileBit occupa uno spazio in memoria pari alla somma dei bit
utilizzati da ogni campo della struttura. Cos su una word di 16 bit, il campo a
occupa 1 bit; b occupa 7 bit; i restanti 8 sono non utilizzati.
6.3.12. Stringhe di caratteri
Il C non prevede la presenza di un tipo stringa predefinito. Tuttavia, possibile
utilizzare un array di caratteri con alcune convenzioni. Larray:

char stringa[10];

dichiara un array di 10 caratteri, mentre la dichiarazione:

char sentenza[ ]= Salve mondo;

dichiara un array di caratteri in cui numero di elementi dato dalla quantit di


caratteri presenti nella stringa, pi uno, un carattere speciale che indica la fine della
stringa, detto carattere null (\0):

S a l v e M o n D o \0

Il carattere \0 il primo carattere del codice ASCII (NUL) e corrisponde al


codice 00000000. Le operazioni classiche sulle stringhe, quali la copia, la
concatenazione ed il confronto tra stringhe, sono implementate da opportune
funzioni standard di libreria string.h e verranno mostrate in seguito.
6.3.13. I Puntatori
La comprensione e luso corretto dei puntatori sono fondamentali per la creazione
di programmi C. Con essi si possono modificare gli argomenti delle funzioni
quando vengono chiamate ed inoltre consentono lallocazione dinamica della
memoria. Un puntatore una variabile che contiene un indirizzo di memoria: tale
indirizzo rappresenta la posizione in memoria di unaltra variabile. Quando una
variabile contiene lindirizzo di unaltra, la prima detta puntare alla seconda.
Poich una variabile possa essere usata come puntatore, bisogna che sia prima
dichiarata come tale, attraverso la dichiarazione:

tipo *var;

dove tipo un tipo base del linguaggio e var la variabile puntatore.


202 Capitolo sesto

6.4. Gli operatori del linguaggio


Di seguito viene riportata una carrellata degli operatori maggiormente diffusi nel
linguaggio C.
6.4.1. Operatori Aritmetici
Gli operatori aritmetici sono i classici operatori binari +,- ,*,/ e loperatore di
modulo %. La divisione tra interi tronca la parte frazionaria, mentre lespressione
x%y fornisce il resto della divisione di x per y. Loperatore di modulo pu essere
applicato solo a tipi integrali. Gli operatori + e hanno la stessa priorit, priorit
inferiore a * e / (che invece hanno identica priorit).
6.4.2. Operatori Relazionali
Gli operatori relazionali sono:
> >= < <=

mentre gli operatori di eguaglianza (e disuguaglianza) sono:


== !=

Gli operatori di relazione hanno priorit maggiore rispetto a quelli di eguaglianza


/disuguaglianza. Gli operatori relazionali hanno invece priorit minore rispetto agli
operatori aritmetici.
6.4.3. Operatori Logici
Gli operatori logici sono:
&& (and), || (or) e ! (not)
&& ha priorit maggiore di || ed entrambi hanno priorit inferiore agli operatori
relazionali e di uguaglianza. Si noti che non esistendo un tipo logico predefinito,
loperatore ! converte un operando non zero in un operando zero.
6.4.4. Operatori di incremento e decremento
Il C fornisce due operatori inusuali nei linguaggi ad alto livello, utili per
incrementare e per decrementare le variabili, ovvero loperatore ++ e loperatore --
, con notazione prefissa o postfissa, come in esempio:

x++
++x
x- -
- -x

Sia nella notazione prefissa che postfissa si ha come effetto quello di


incrementare (o decrementare) una variabile. Tuttavia ++x (- -x) incrementa
(decrementa) x prima di usarne il valore, mentre x++ (x- -) incrementa
(decrementa ) x dopo averne usato il valore.
Il linguaggio C 203

6.4.5. Operatori sui puntatori


Esistono due operatori per la manipolazione dei puntatori: & e *. Il primo un
operatore unario che restituisce lindirizzo di memoria delloperando cui
applicato. Ad esempio:

indirizzo_x=&x;

pone nella variabile indirizzo_x lindirizzo di memoria della variabile x. Il secondo


un operatore unario che restituisce il valore della variabile che si trova
allindirizzo indicato nella variabile che lo segue. Ad esempio:

valore_x=*indirizzo_x;

ha leffetto di porre nella variabile valore_x il valore della variabile che si trova in
memoria allindirizzo contenuto nella variabile indirizzo_x, ovvero il valore di x.
Il seguente esempio cerca di chiarire i concetti prima esposti.

int x;
int* indx=&x;
int valx=*indx;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma sui puntatori\n");
printf("Inserisci il numero x: ");
scanf("%d",&x);
printf("\nIl valore di x e': %d\n",x);
printf("\nL'indirizzo di memoria (in esadecimale) a cui si trova x e': %x\n",indx);
printf("\nIl valore di x mediante puntatore e': %d\n",x);

Luso dei puntatori risulta essenziale nello scambio di parametri allatto


dellattivazione di funzioni.
Se ad esempio si vuole realizzare una funzione che effettua la somma e la
differenza tra due numeri, allora i parametri, che alla fine dellelaborazione
dovranno contenere somma e differenza, dovranno essere passati per riferimento
attraverso lutilizzo delloperatore &, mentre nellintestazione e corpo della
funzione, essi dovranno essere gestiti attraverso loperatore * per accedere al valore
puntato. In particolare si ha per la funzione suddetta:

void sommadiff(int a, int b, int *d, int *s) {


*d=a-b;
*s=a+b;
}

mentre lattivazione della funzione avverr come segue:

int a,b,d,s;
sommadiff (a,b,&d,&s);

Lattivazione della funzione ha come effetto quello di passare una copia dei
valori delle variabili a ed b alla funzione (passaggio per valore) e quello di passare
204 Capitolo sesto

per le variabili d e s una copia dellindirizzo di memoria (passaggio per


riferimento) in cui esse si trovano per potere accedere al loro contenuto mediante
loperatore * allinterno della funzione.
Si vuole notare che il tipo array viene sempre passato per riferimento, e quindi
allatto dellattivazione di una funzione non viene utilizzato loperatore & per la
variabile ad esso relativo. Inoltre si ha che la sequenza:

char str[80], *p1;


p1=str;

ha leffetto di copiare nel puntatore p1 lindirizzo del primo elemento dellarray


str. Ci comporta che gli elementi di un array possono essere acceduti (in maniera
sequenziale ) anche mediante lutilizzo dei puntatori. Ad esempio:

str[4] e *(p1+4)

sono equivalenti in quanto ogni elemento del vettore occupa un solo byte di
memoria.
6.4.6. Operatori logici bit oriented
In C sono presenti operatori che consentono la manipolazione dei bit. Essi sono
elencati di seguito.

& AND bit a bit


| OR bit a bit
^ XOR
<< shift a sinistra
>> shift a destra
- complemento ad uno

6.5. La specifica dellalgoritmo in C


La specificazione delle azioni elaborative di un sottoprogramma in C si traduce in
un insieme di enunciati o statement composti. Lo statement composto formato da
una sequenza di statement semplici terminati dal carattere punto e virgola, mentre
gli statement semplici che compongono la specificazione dell'algoritmo denotano
le azioni elaborative vere e proprie che devono essere svolte dall'esecutore
macchina. Tali statement si possono classificare in:
- istruzioni di assegnazione
- richiamo di funzioni
- costrutti selettivi ( if else, switch case)
- costrutti iterativi (while, for)
6.5.1. Istruzioni di assegnazione
L'enunciato o istruzione di assegnazione la pi elementare forma di enunciato.
Esso prescrive che venga dapprima calcolato il valore dell'espressione che si trova
a destra del segno di =, e poi che tale valore venga poi assegnato alla variabile
Il linguaggio C 205

che si trova a sinistra dello stesso simbolo. La variabile e il valore dell'espressione


devono essere di norma dello stesso tipo con alcune eccezioni relativamente alle
variabili numeriche (e.g., se la variabile reale, allora il tipo dell'espressione pu
anche essere intero). Listruzione di assegnazione termina con il delimitatore punto
e virgola.

Figura 16 Carta sintattica per unistruzione di assegnazione

Unespressione, di cui per semplicit non riportata alcuna carta sintattica,


una formula o regola di calcolo che specifica sempre un valore detto risultato
dell'espressione. composta da operandi ed operatori. Gli operandi possono essere
variabili, costanti o valori restituiti da una funzione. Gli operatori coincidono con
quelli del linguaggio e sono classificati in monadici o unari e in diadici o binari a
seconda che prevedano uno o due operandi rispettivamente. Se in una espressione
sono presenti pi operandi, occorre ricordare la sequenza della loro esecuzione nel
caso in cui non sia esplicitata mediante l'introduzione nell'espressione delle
parentesi. Esempi di una istruzione di assegnazione sono:
x = 1;
x = x+1;
x = a+b;
In particolare, nel primo caso si assegna una costante numerica alla variabile
x, nel secondo caso si incrementa di 1 la variabile x, nel terzo caso ad x si assegna
la somma del valore di a con il valore di b. Si noti che in C listruzione del tipo:
Espressione1 = Espressione1 operando Espressione2
pu essere anche espressa con:
Espressione1 operando= Espressione2
Ad esempio, lespressione x = x+1 diventa:
x + = 1;
mentre lespressione y *= y+1 in realt la forma compatta di:
y = y * (y+1);
Una espressione particolare del C la cosiddetta espressione
condizionale, del tipo:
espressione1 ?espressione2 :espressione3
In questo tipo di espressione viene valutata lespressione1: se essa diversa
da zero (vera) allora viene valutata lespressione2, altrimenti viene valutata
lespressione3. Ad esempio lespressione:
z=(x>y)? x:y;
mette in z il valore maggiore tra x ed y.
6.5.2. Richiamo di funzioni
Il richiamo della funzione determina l'esecuzione della funzione indicata. Affinch
il richiamo sia corretto, si deve fornire una lista di parametri di I/O uguale, in
numero e tipo, a quella specificata nella dichiarazione della funzione. La
corrispondenza si stabilisce per ordine, nel senso che al primo parametro attuale
206 Capitolo sesto

associato il primo formale, e cos via. Per i sottoprogrammi di tipo funzioni


bisogna inoltre specificare la variabile in cui verr memorizzato il parametro
duscita.

Figura 18 Carta sintattica per richiamo di funzioni

La forma di richiamo per una funzione la seguente:

variabile=nome_fnzione(par_effettivo1,par_effettivo2,., par_effettivon);

mente per una procedura:

nome_procedura(par_effettivo1,par_effettivo2,., par_effettivon);

I parametri attuali devono essere forniti con rispetto del meccanismo di


sostituzione e del tipo dei parametri indicati nella dichiarazione della funzione o
della procedura. In particolare, se si fissato una sostituzione per valore, si
possono usare come parametri attuali variabili, costanti ed espressioni di un tipo
compatibile, secondo le regole viste a proposito dell'assegnazione di valore, con
quello del parametro formale (si pu ad esempio usare un parametro attuale di tipo
sia intero che reale nel caso di un parametro formale di tipo reale, mentre deve
essere assolutamente di tipo intero nel caso di parametro formale dichiarato intero).
Nel caso di sostituzione per riferimento, si devono impiegare solo variabili e i tipi
dei due parametri devono coincidere.
Esempi di istruzioni di richiamo di funzioni sono le seguenti:

x=somma(a,b);
somma(a,b,&c);
6.5.3. Costrutti selettivi
Gli enunciati selettivi permettono la selezione di azioni elaborative in funzione del
valore di un'espressione booleana e non: ossia si valuta l'espressione e si sceglie
l'istruzione successiva in funzione del valore trovato.
If-else
L'enunciato if-else (se - altrimenti) permette di effettuare la scelta tra due
alternative in funzione del valore di una espressione booleana. Se il valore
dell'espressione TRUE, si sceglie l'alternativa (insiemi di enunciati racchiusi tra
parentesi graffe) introdotta dopo lif, in caso contrario (insiemi di enunciati
Il linguaggio C 207

racchiusi tra parentesi graffe) quella aperta dall'else. In entrambi i casi, dopo
l'esecuzione del blocco selezionato, l'esecuzione stessa continua con l'enunciato
successivo all'if. anche possibile usare una notazione abbreviata nel caso in cui
non esista una delle due alternative, non specificando l'else dell'enunciato. Sono
esempi di if:

if (n>10) {
n=n+1;
}
else {
n=n-1;
}

if (n>10) n=0;

Si noti che, nel caso che lazione elaborativa dellif o dellelse sia composta
da un solo statement semplice, le parentesi graffe non sono obbligatorie. Inoltre si
pu notare come l'uso appropriato dell'incolonnamento (o anche indentazione)
delle strutture innestate l'una dentro l'altra migliori notevolmente la chiarezza del
programma in quanto evidenzia l'ordine di esecuzione dei vari blocchi. allora da
usare tale accorgimento anche quando la disposizione delle istruzioni sui righi non
importante, come nel nostro caso.

if espressione
( )
booleana

statement

statement
{ }
composto

else statement

statement
{ }
composto
Figura 19 Carta sintattica per if-else
Il linguaggio C permette anche di realizzare if annidati, ovvero costrutti di
selezione che appartengono al ramo if o al ramo else di unulteriore istruzione di
selezione. Nel caso di costrutti innestati il C dispone di una regola che assegna
ogni else allif pi vicino che non ne possiede gi uno.
Un esempio il seguente, dove lelse relativo al secondo if:
208 Capitolo sesto

if (x>0) {
if (y>0)
printf (x e y maggiori di 0);
else
printf(solo x maggiore di 0);
}

Switch-case
Listruzione switch permette di scegliere tra pi di due alternative (decisioni
multiple) verificando se il valore di una espressione uguale ad un valore tra quelli
specificati in una lista. In particolare consiste di un'espressione (di tipo numerico o
carattere), detta selettore, e di una lista di enunciati, ciascuno dei quali identificato
da uno o pi valori costanti appartenenti al tipo del selettore. L'enunciato scelto
quello identificato dalla costante che uguale al valore calcolato del selettore.
Solitamente la scansione degli identificatori, per cercare quello con valore uguale
al selettore, avviene in modo sequenziale. Per tale motivo si consiglia di disporre
per ultimi gli identificatori che hanno la minore probabilit di essere scelti. Un
esempio di switch il seguente:
switch(x)

case 0:
case 1:
n++;
break;
case 2:
n- -;
break;
default:
n *=2;

Si noti che listruzione break causa luscita dallo switch. Il caso chiamato
default viene eseguito quando non sono stati soddisfatti gli altri casi dello switch.
Un altro esempio il seguente:
SWITCH(numero_mese) {
CASE {1,3,5,7,8,10,12}
printf(mese di 31 giorni);
break;
CASE {4,6,9,11}
printf(mese di 30 giorni);
break;
CASE 2
printf(mese di 28 o 29 giorni);
break;
DEFAULT:
printf(mese non valido);
}
In questo caso viene verificata lappartenenza del valore della variabile dello
switch ad un tipo enumerativo. Si noti che la non introduzione del break porta a
confrontare il valore del selettore con tutti i casi anche quando uguale ad uno di
essi.
Il linguaggio C 209

Figura 20 Carta sintattica per costrutto SWITCH

6.5.4. Costrutti Iterativi


Gli enunciati iterativi permettono l'esecuzione di un blocco di istruzioni un certo
numero di volte. La terminazione della ripetizione avviene quando sono verificate
certe condizioni che sono calcolate internamente al blocco. Se il numero di
ripetizioni noto a priori, la struttura viene anche detta ciclica o enumerativa.
Il ciclo while
L'enunciato while composto da una espressione logica e da uno o pi enunciati
da ripetere in funzione del valore di tale espressione. L'esecuzione del while
comporta la valutazione dell'espressione e l'esecuzione degli enunciati nel caso in
cui il valore calcolato dell'espressione sia TRUE. Il ciclo ha termine quando
l'espressione assume il valore FALSE per cui, se l'espressione risulta subito falsa, gli
enunciati non vengono mai eseguiti. Un esempio di ciclo while :
while(x > 0)

a = a+x;
x- -;

Si osservi che una volta iniziato, il ciclo pu terminare solo se all'interno di


esso vi sono degli enunciati che modificano il valore di verit dell'espressione: cio
operano sulle variabili che ne fanno parte. comunque possibile uscire da un ciclo
210 Capitolo sesto

while in maniera incondizionata, cio, in maniera indipendente dal valore di verit


dellespressione, attraverso la parola chiave break.
while espressione
( )
booleana

statement
{ }
composto

statement

Figura 21 Carta sintattica per costrutto while

Il ciclo do-while
A differenza dei ciclo while, che verifica la condizione allinizio del ciclo (loop)
stesso, il costrutto do-while la verifica alla fine, con la conseguenza che esso viene
eseguito almeno una volta. In particolare, listruzione viene eseguita, poi viene
valutata lespressione: se vera, listruzione viene ancora eseguita e cos via. Il
ciclo termina quando listruzione diventa falsa.
do

statement
{ }
composto

statement

while espressione
( )
booleana
Figura 22 - Carta sintattica del costrutto do-while

Ad esempio, il seguente programma legge i numeri da tastiera finch si


introduce un numero con valore minore di zero.

do
scanf(%d,&n);
while (n>0)
Il linguaggio C 211

Il ciclo for
Il costrutto for un enunciato iterativo enumerativo o ciclico. Esso deve essere
usato ogni qualvolta il numero di ripetizioni noto a priori.

Figura 23- Carta sintattica per il costrutto for

Lo statement di inzializzazione coincide, nella sua forma pi semplice, con


unistruzione di assegnazione con la quale viene fornito il valore iniziale alla
variabile di controllo del ciclo. Lo statement di condizione rappresenta
unespressione booleana che serve a controllare la terminazione del ciclo, finch
TRUE il ciclo prosegue. Lo statement di aggiornamento definisce il modo in cui la
variabile di controllo cambia il suo valore ad ogni ripetizione del ciclo. Di norma
laggiornamento consiste in un incremento o decremento del valore della variabile
di controllo. Esempi di for sono:

for(int i=0; i<=100; i++)


printf(%d ,i);

for(int i=100; i>=0; i- -)

printf(%d ,i);
somma = somma+i;

Nel primo caso vengono visualizzati a video tutti gli interi compresi tra 0 e
100 (incremento), nel secondo caso gli stessi interi vengono visualizzati ma in
ordine inverso tra 100 e 0 (decremento) e ne viene effettuata la somma. In altri
termini, per il primo for, viene posta inizialmente la variabile di controllo i al
valore 0 e viene richiamata la funzione printf() per la visualizzazione a video di i,
dopodich, al ritorno dalla funzione, viene applicata la condizione di
aggiornamento (in questo caso di incremento) della variabile i e si verifica la
condizione (i<=100). Poich la condizione TRUE si ripete listruzione di
visualizzazione sul nuovo valore della variabile di controllo. Analogamente a
quanto gi descritto, il ciclo si ripete finch i non diventa maggiore di 100. Un
212 Capitolo sesto

discorso simile, ma con aggiornamento a decremento, vale per il secondo for.


Listruzione:

for( ; ;)

implementa di contro un ciclo infinito. Per una piena comprensione dei due
costrutti iterativi for e while, si presentano di seguito due costrutti equivalenti.

for(int i=0; i<=100; i++)


printf(%d ,i);

int i=0;
while (i<=100) {
printf(%d ,i);
i++;
}

6.6. Le librerie di funzioni


Come gi anticipato il C, per scelta di progetto, non supporta direttamente
istruzioni di ingresso/uscita, n istruzioni particolari per le operazioni matematiche;
non esistono nemmeno operazioni per trattare direttamente oggetti strutturati come
stringhe di caratteri, insiemi, liste ed array. Il C affida tali tipologie di operazioni a
librerie esterne di funzioni. per possibile servirsi delle funzioni di una
particolare libreria includendone il corrispettivo file header allinterno del
programma, come gi visto, mediante la direttiva di compilazione:

#include <file header della libreria>

Dopo linclusione possibile servirsi di tutte le funzioni della libreria nota


solo la loro interfaccia, ovvero noti i parametri di ingresso/uscita.
Ad esempio, se il seguente programma vuole utilizzare la funzione getch()
della libreria conio.h per attendere la digitazione di un carattere da tastiera, allora
il suo codice dovr avere la seguente forma:

#include <conio.h>
int main ()
{
getch();
return 0;
}

Un moderno compilatore C mette a disposizione una vasta gamma di librerie


contenenti:
- funzioni di uso generale (stdlib.h),
- gestione dellI/O (stdio.h),
- calcolo matematico (math.h),
- gestione di stringhe (string.h).
Il linguaggio C 213

Di seguito si mostreranno le funzioni principali delle librerie pi comunente


utilizzate, rimandando ad appositi manuali la descrizione approfondita delle varie
librerie del linguaggio.
6.6.1. La gestione dellI/O
Le funzioni comprese nel sistema di input/output del C possono essere raggruppate
in tre grandi categorie: I/O su console (tastiera e monitor), I/O su file bufferizzato e
I/O su file non bufferizzato (Unix-like). Per lutilizzo di tutte le funzioni suddette
richiesta linclusione del file header stdio.h. Tale libreria fornisce alcune
funzioni per le operazioni di lettura e scrittura dei valori delle variabili dai file
standard INPUT e OUTPUT.
In genere il file di INPUT rappresenta la tastiera del sistema di calcolo; quello
di OUTPUT il monitor. Essi possono essere visti come organizzati in un testo
costituito da sequenze di RIGHI separati tra loro dal carattere di fine rigo CR
(Carriage Return). La sequenza di righi terminata dal carattere di fine file.
All'interno di ogni rigo sono distribuite le rappresentazioni delle informazioni
opportunamente separate usando il carattere spazio.
Apertura file
In C la lettura da un file avviene aprendo un canale di comunicazione con la
memoria di massa attraverso la connessione del file. In altre parole un file deve
essere sempre connesso o aperto prima di prelevare dati da esso. Lapertura di un
file avviene attraverso la funzione fopen() della libreria stdio.h:
FILE* fopen (char* filename, char* permission)

Tale funzione apre un file il cui nome (path su disco del file) un insieme di
caratteri puntato dalla variabile filename, mentre la variabile permission
definisce la modalit di apertura del file (e.g., sola lettura, solo scrittura,
lettura/scrittura). La funzione suddetta restituisce poi un identificatore del file noto
anche con nome di puntatore a file, attraverso il quale il file viene referenziato. Se
per vari motivi il file non pu essere aperto viene restituito un puntatore nullo.
Di seguito riportato un esempio dellapertura in sola lettura di un file
pippo.txt contenente un array di numeri interi (i numeri si trovano su righi
differenti di testo separati tra loro dal carattere di fine rigo). La modalit di
apertura a solo lettura utilizza la stringa r, quella a sola scrittura lopzione w,
infine, quella in scrittura/lettura rw.

FILE *fid;
fid=fopen (c:\pippo,txt, r);
if (!fid) printf(FILE NON APERTO);

Di seguito riportato un esempio di apertura di un file in scrittura:

FILE *fid;
fid=fopen (c:\pippo,txt, w);
if (!fid) printf(FILE NON APERTO);
214 Capitolo sesto

Lettura da file
Dopo la connessione del file in modalit lettura, attraverso lidentificatore del file
possibile eseguire le operazioni di lettura che avvengono con lutilizzo della
funzione fscanf() della libreria stdio.h:

int fscanf(FILE*fid, char*format, var)

dove fid lidentificativo (puntatore) del file, format indica il tipo degli
elementi da leggere e var la variabile in cui si inseriscono gli elementi letti. La
funzione ritorna il numero di elementi effettivamente letti, se viene restituito EOF
significa che stata tentata la lettura dopo la fine del file.
La variabile format pu assumere i seguenti valori a seconda del tipo di dato
che si vuole leggere:

%d interi
%f,%g reali
%c caratteri
%s stringhe

Di seguito riportato un esempio di lettura del file dove memorizzato un


array di interi (sul primo rigo del file di testo c il riempimento del vettore):

FILE * fp;
register int i;
int vettore[100];
int riemp, ret;
if (!(fp=fopen("pippo.txt","r"))) {
printf("\n Il file non puo' essere caricato\n");
}
else {
ret=fscanf(fp,"%d",&riemp);
if (ret!=EOF) {
printf("\nNumero di elementi nel vettore: %d\n",riemp);
if (riemp>0) {
for (i=0; i<riemp; i++) fscanf(fp,"%d",vettore[i]);
}
}
else printf("\nfile vuoto!!!\n");
}

La lettura di informazioni da standard input (tastiere) avviene invece, come


gi descritto, attraverso la funzione scanf() (senza bisogno di aprire alcun file)
della libreria stdio.h:

int scanf(char*format, var)


Il linguaggio C 215

dove var rappresenta la variabile in cui verr memorizzato il valore immesso da


tastiera, mentre format ha lo stesso significato per la funzione fscanf. Di seguito e
riportato lesempio della lettura di un intero da tastiera:

int a;
scanf(%d, &a);
Scrittura su file
Dopo la connessione del file in modalit scrttura, attraverso lidentificatore del file
possibile eseguire le operazioni di lettura che avvengono con lutilizzo della
funzione fprintf() della libreria stdio.h:

int fscanf(FILE*fid, char*format, var)

dove fid lidentificativo del file, format indica il tipo degli elementi da scrivere e
var la variabile in cui si trovano gli elementi da scrivere su file. La funzione
ritorna il numero di elementi effettivamente scritti, se viene restituito un valore
negativo significa che si sono verificati problemi di scrittura su file. La variabile
format pu assumere gli stessi valori illustrati per la lettura dei file. Di seguito
riportato un esempio di scrittura su file di un array di interi (sul primo rigo del file
di testo viene inserito il riempimento del vettore):

register int i;
FILE*fp;
int count;
int tot=0;
int riemp=3;
int vettore[]= {1,2,3};
if (!(fp=fopen("pippo.txt","w"))) {
printf("\n Il file non puo' essere salvato\n");
}
else {
count=fprintf(fp,"%d\n",riemp);
tot=tot+count;
for (i=0; i<riemp; i++) {
count=fprintf(fp,"%d\n",vettore[i]);
tot=tot+count;
}
}
if (tot==riemp+1) printf(Scrittura avvenuta con successo);
La scrittura di informazioni su standard output (monitor) avviene invece,
come gi descritto, attraverso la funzione pritnf() della libreria stdio.h:
int printf(char*format, var)
dove var rappresenta la variabile il cui contenuto sar visualizzato a video, mentre
format ha lo stesso significato dellomonima variabile della funzione printf. Di
seguito e riportato lesempio di scrittura di un intero su monitor:

int a;
printf(%d, a);
216 Capitolo sesto

La gestione delle stringhe


Il C possiede un ampio insieme di funzioni per il trattamento delle stringhe e
dei caratteri. Si ricorda che una stringa coincide con un array di caratteri terminato
col carattere \0. Tutte le dichiarazioni richieste dalle funzioni per il trattamento
delle stringhe sono contenute nel file header string.h.
Di seguito si mostrer lutilizzo solo di alcune delle funzioni per la gestione
delle stringhe, rimandando ad appositi manuali una trattazione pi approfondita.
La funzione strcat() permette il concatenamento di due stringhe:

char *strcat(char *str1, char *str2)

Tale funzione concatena una copia della stringa str2 alla stringa str1,
concludendo la stringa str1 (che conterr la stringa risultante) con un carattere di
terminazione. Il primo carattere di str2 si sovrappone al terminatore originale di
str1, mentre la stringa str2 rimane inalterata. La funzione restituisce un puntatore
nullo. Di seguito riportato un esempio per la scrittura a video della
concatenazione delle stringhe ciao e come stai?.

char s1[]={c,i,a,o,.,.,., \0};


char s2[]={c,o,m,e, ,s,t,a,i,?, \0};
strcat(s1,s2);
printf(%s,s1);

La funzione strcpy() permette la copia di stringhe:

char *strcpy (char *str1, char *str2)

Tale funzione copia il contenuto della stringa str2 nella stringa str1,
restituendo un puntatore a str1. Di seguito riportato un esempio per la scrittura a
video della copia di una stringa.

char str[100];
strcpy(str,ciao);
printf(%s,str);

La funzione strcmp() permette di verificare luguaglianza tra stringhe:

int strcmp(char *str1, char *str2)

Tale funzione confronta secondo le regole lessicografiche due stringhe str1 e


str2 terminate da carattere nullo e restituisce un intero il cui valore determinato
sulla base delle seguenti regole:
- 0 le stringhe sono uguali;
- minore di 0 le stringhe sono diverse ed in pi str1 ha meno caratteri
di str2;
- maggiore di 0 le stringhe sono diverse e str1 ha pi caratteri di str2.
Il linguaggio C 217

Di seguito riportato un esempio per la verifica se due stringhe sono uguali.

char s1[100];
char s2[100];
scanf(%s,s1);
scanf(%s,s2);
if (strcmp(s1,s2)==0) printf(stringhe uguali);

La funzione strlen() permette di determinare la lunghezze di una stringa:

int strlen(char *str1)

Tale funzione conta il numero di caratteri da cui composta una stringa str1
che termina col carattere di terminazione, escludendo tale carattere dal conteggio.
Di seguito riportato un esempio di conteggio di caratteri di una stringa.
char s1[100];
scanf(%s,s1);
int len=strlen(s1);
printf(stringa lunga %d caratteri,len);

Infine, le due funzioni:

char*strlwr(char *str1)
char*strupr(char *str1)

convertono rispettivamente una stringa str1 in minuscolo e maiuscolo, restituendo


entrambe un puntatore alla nuova stringa.
Funzioni per il calcolo matematico
Il C possiede unampia gamma di funzioni matematiche presenti allinterno della
libreria math.h. Tali funzioni hanno come argomenti di ingresso variabili di tipo
double e restituiscono come argomenti di uscita ancora variabili di tipo double.
Le funzioni si possono dividere nelle seguenti categorie:
- funzioni trigonometriche
o double sin(double x)
per il calcolo del seno di un numero reale x
o double cos(double x)
per il calcolo del coseno di un numero reale x
o double tan(double x)
per il calcolo del tangente di un numero reale x
- funzioni iperboliche
o double sinh(double x)
per il calcolo del seno iperbolico di un numero reale x
o double cosh(double x)
per il calcolo del coseno iperbolico di un numero reale x
o double tanh(double x)
per il calcolo del tangente iperbolica di un numero reale
x
- funzioni esponenziali e logaritmiche
218 Capitolo sesto

o double exp(double x)
per il calcolo dellesponenziale di un numero reale x
o double log10(double x)
per il calcolo del logaritmo in base 10 di un numero
reale x
o double log2(double x)
per il calcolo del logaritmo naturale di un numero reale
x
- altre funzioni
o double sqrt (double x)
per il calcolo della radice quadrata di un numero reale x
o double fabs(double x)
per il calcolo del valore assoluto di un numero reale x
o double ceil (double x)
per il calcolo dellintero pi piccolo non inferiore ad un
numero reale x
o double floor(double x)
per il calcolo dellintero pi grande non superiore ad un
numero reale x
o double fmod(double x, double y)
per il calcolo del resto in modulo della divsione di x per
y
o double pow(double base, double exp)
per il calcolo di baseexp

6.7. Gli algoritmi di base in C


Si vogliono ora di seguito mostrare degli algoritmi base dellinformatica realizzati
con lausilio del linguaggio C.
6.7.1. Lo scambio di valore
Descrizione del problema : Scrivere una funzione che effettui lo scambio di
valore tra due informazioni di un tipo T. Esempio:
input: x=3, y=5
output: x=5, y=3

Descrizione dellalgoritmo : Se si associano alle due informazioni due contenitori


di liquidi, il problema diventa quello del loro trasferimento da un contenitore
allaltro senza che i liquidi si mischiano. Risulta allora evidente che non c modo
di effettuare tale trasferimento se non introducendo un terzo contenitore che
permette di svuotare uno degli altri due contenitori. Si pu cos travasare il liquido
il liquido dellaltro in quello che si svuotato e infine ritrasferire in esso il liquido
che stato spostato per primo nel terzo contenitore. Si comprende allora che per
scambiare due informazioni dello stesso tipo necessario introdurre una terza
variabile, ovviamente dello stesso tipo. Ad esempio date le tre informazioni (tra
parentesi quadre riportato il valore delle variabili):
x [3] y [5] z[]
si copia dapprima x in z:
Il linguaggio C 219

x [3] y [5] z[3]


poi y in x:
x [5] y [5] z[3]
ed infine z in y:
x [5] y [3] z[3]
utilizzando la sintassi del C, lalgoritmo assume la seguente forma:
z=x;
x=y;
y=z;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione scambia con le seguenti caratteristiche:
- Paramentri di input: [x,y] informazioni prima dello scambio
- Parametri di output: [x,y] informazioni dopo lo scambio
- Variabili locali: [z] informazione necessaria allo scambio

Implementazione
// FUNZIONE PER LO SCAMBIO DI VALORE
// La funzione void scambia(x,y)
// permette di scambiare il valore delle variabili x ed y

void scambia(float*x, float*y) {


// dichiarazione variabile locale di appoggio utilizzata per lo scambio
float z;

// effettua scambia per mezzo della variabile z


z=*x;
*x=*y;
*y=z;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
int x,y;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma che effettua lo scambio di valore tra 2 numeri\n");
printf("Inserisci il primo numero x: ");
scanf("%f",&x);
printf("Inserisci il secondo numero y: ");
scanf("%f",&y);
printf("\nIl valore di x prima dello scambio e': %f\n",x);
printf("\nIl valore di y prima dello scambio e': %f\n",y);
printf("\nElaborazione in corso....\n");
scambia(&x,&y);
system("Pause");
printf("\nIl valore di x dopo lo scambio e': %f\n",x);
printf("\nIl valore di y dopo lo scambio e': %f\n",y);
system("Pause");
return 0;
}
220 Capitolo sesto

6.7.2. Inserimento in un vettore


Descrizione del problema: Scrivere una funzione per linserimento
dellinformazione info nella posizione posiz di un vettore di n elementi di un certo
tipo T. Esempio:
input: n=5, v= [10 50 20 40 35], info=66, posiz=3
output: n=6, v=[10 50 66 20 40 35]

Descrizione dellalgoritmo: Si pu pensare al vettore come ad uno scaffale di libri


allineati verso sinistra. Per far posto ad un nuovo libro in una posizione assegnata,
bisogna spostare tutti i libri che si trovano in posizione successiva a quella data di
una posizione verso destra. Lo spostamento pu essere fatto un libro alla volta,
cominciando da quello in ultima posizione. Dopo linserimento, il numero di libri o
riempimento dello scaffale aumentato di una unit. Si fa lipotesi che lo scaffale
non sia mai pieno.
Nel caso in cui si debba inserire la lettera a nella seconda posizione di un
vettore di 4 elementi la procedura per linserimento riportata di seguito:
[x, y, z, f]
si effettua lo spostamento (shift) di tutti gli elementi del vettore, a partire
dallultimo fino a quello in seconda posizione, di un posto a destra:
[x, , y, z, f]
si copia il nuovo elemento nella seconda posizione e si incrementa di una unit il
numero di elementi allinterno del vettore:
[x, a, y, z, f]
Utilizzando la sintassi del C, lalgoritmo assume la seguente forma :
for (i=n-1;i>=posiz;i--) {
v[i+1]=v[i];
}
v[posiz]=info;
n=n+1;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione inserisci con le seguenti caratteristiche:
- Parametri di Input: [v,info,posiz,n] rispettivamente vettore, elemento da
inserire e rispettiva posizione, e riempimento del vettore
- Parametri di Output: [v,n] vettore e riempimento dopo linserimento
- Variabili locali: [i] contatore di ciclo

Implementazione
// FUNZIONE PER L'INSERIMENTO DI UN ELEMENTO IN UN VETTORE
// La funzione void inserisci(v,info,posiz,n)
// permette di inserire l'elemento info al posto posiz nel vettore v di riempimento n
// Vettore un alias di un tipo array di float

void inserisci(Vettore v, float info, int posiz, int* n) {

// contatore di ciclo
register int i;

// effettua l'inserimento mediante shift


Il linguaggio C 221

for (i=*n-1;i>=posiz;i--) {
v[i+1]=v[i];
}
v[posiz]=info;
// aggiorna il riempimento
*n=*n+1;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v;
register int j;
int posiz,n;
float info;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma di inserimento di un elemento in un vettore\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci elementi del Vettore (dopo ogni un numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%g",&v[j]);
}
printf("\nVettore v prima dell'inserimento\n");
printf("Vetore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%g,",v[j]);
else
printf("%g",v[j]);
}
printf("]\n");
printf("Inserisci l'elemento che vuoi inserire: ");
scanf("%f",&info);
posiz=-1;
while ((posiz<0) || (posiz>n-1)) {
printf("Inserisci la posizione dove inserirlo (>=0 <=%d): \n",n-1);
scanf("%d",&posiz);
};
printf("\nElaborazione in corso....\n");
inserisci(v,info,posiz,&n);
system("Pause");
printf("\nVettore v dopo l'inserimento\n");
printf("Vetore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%g,",v[j]);
else
printf("%g",v[j]);
}
222 Capitolo sesto

printf("]\n");
system("Pause");
return 0;
}

6.7.3. Eliminazione in un vettore


Descrizione del problema: Scrivere una funzione per leliminazione dellelemento
in una posizione posiz data di un vettore di n elementi di un certo tipo T. Esempio:
input: n=5, v= [22 50 30 16 10], posiz=2
output: n=4, v=[22 30 16 10]

Descrizione dellalgoritmo: Si pu pensare al vettore come ad uno scaffale di libri


allineati verso sinistra. Dopo avere tolto il libro dalla posizione assegnata, bisogna
spostare tutti quelli che si trovano alla sua destra di un posto verso sinistra per
recuperare lo spazio resosi disponibile. Lo spostamento viene fatto un libro alla
volta, cominciando da quello successivo al libro nella posizione assegnata e si
termina quando si arrivati allultimo libro. Dopo leliminazione, il numero di libri
o riempimento dello scaffale diminuito di una unit. Si fa lipotesi che lo scaffale
contenga almeno un elemento. Nel caso in cui si voglia eliminare lelemento in
seconda posizione di un vettore di 4 elementi, la procedura per leliminazione
riportata di seguito:
[x, y, z, f]
si effettua lo spostamento (shift) di tutti gli elementi del vettore, a partire da quello
in terza posizione fino allultimo, di un posto a sinistra:
[x, z, f]
si diminuisce di una unit il numero di elementi allinterno del vettore. Utilizzando
la sintassi del C, lalgoritmo assume la seguente forma :
for (i=posiz+1;i<n;i++) {
v[i-1]=v[i];
}
n=n-1;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione elimina con le seguenti caratteristiche:
- Parametri di Input: [v,posiz,n] vettore di partenza, posizione
dellelemento da eliminare e riempimento del vettore
- Parametri di Output: [v,n] vettore e suo riempimento dopo leliminazione
- Variabili locali: i contatore di ciclo

Implementazione
// FUNZIONE PER L'ELIMINAZIONE DI UN ELEMENTO IN UN VETTORE
// La funzione void elimina(v, posiz)
// permette di eliminare l'elemento al posto posiz nel vettore v di riempimento n
// Vettore un alias di un tipo array di float

void elimina(Vettore v, int posiz, int *n) {

// contatore di ciclo
register int i;
Il linguaggio C 223

// effettua l'eliminazione mediante shift


for (i=posiz+1;i<*n;i++) {
v[i-1]=v[i];
}
// aggiorna il riempimento
*n=*n-1;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v;
register int j;
int posiz,n;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma di eliminazione di un elemento da un vettore\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci gli elementi del Vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%g",&v[j]);
}
printf("\nVettore v prima dell'eliminazione\n");
printf("Vetore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%g,",v[j]);
else
printf("%g",v[j]);
}
printf("]\n");
posiz=-1;
while ((posiz<0) || (posiz>n-1)) {
printf("Inserisci posizione dellelemento da eliminare (>=0 <=%d): \n",n-1);
scanf("%d",&posiz);
};
printf("\nElaborazione in corso....\n");
elimina(v,posiz,&n);
system("Pause");
printf("\nVettore v dopo l'eliminazione\n");
printf("Vetore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%g,",v[j]);
else
printf("%g",v[j]);
}
printf("]\n");
system("Pause");
return 0;
224 Capitolo sesto

6.7.4. Eliminazione di una colonna da una matrice


Descrizione del problema: Scrivere una funzione per leliminazione
dellelemento in una data colonna col di una matrice di n righe e m colonne di
elementi di un certo tipo T. Esempio:
input: n=3, m=4, A= [10 22 33 50; 20 54 80 41; 30 10 23 31], col=2
output: n=3, m=3, A=[10 33 50; 20 80 41; 30 23 31]

Descrizione dellalgoritmo: Leliminazione di una colonna in una matrice si


effettua applicando lalgoritmo di eliminazione di un elemento da un vettore a tutte
le righe della matrice. Utilizzando la sintassi del C, lalgoritmo assume la seguente
forma:
for (i=0;i<n;i++) {
for (j=col+1;j<m;j++) {
A[i][j-1]=A[i][j];
}
}
m=m-1;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione eliminacol con le seguenti caratteristiche:
- Parametri di Input: [A,n,m,col], matrice, numero di righe, numero di
colonne ed indice della colonna da eliminare
- Parametri di Output: [A,m] matrice e numero di colonne dopo
leliminazione
- Variabili locali: i, j indici di riga e colonna

Implementazione
// FUNZIONE PER L'ELIMINAZIONE DI UNA COLONNA DA UNA MATRICE
// La funzione void eliminacol(A,n,m,col)
// permette di eliminare gli elementi della colonna col dalla matrice A
// Matrice un alias di un tipo array bidimensionale di int

void eliminacol(Matrice A, int n, int* m, int col) {

// contatori di ciclo
register int i,j;

// effettua l'eliminazione mediante shift


for (i=0;i<n;i++) {
for (j=col+1;j<*m;j++) {
A[i][j-1]=A[i][j];
}
}
// aggiorna il riempimento relativo alle colonne
*m=*m-1;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
Il linguaggio C 225

// Funzione main
int main () {
Matrice A;
register int k,z;
int n,m,col;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma che elimina una colonna da una matrice\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero di righe della matrice(>=0 <=50): \n");
scanf("%d",&n);
};
m=-1;
while ((m<0) || (m>MMAX-1)) {
printf("Inserisci il numero di colonne della matrice(>=0 <=50): \n");
scanf("%d",&m);
};
printf("Inserisci gli elementi della Matrice (dopo ogni elem premere INVIO)\n");
for (k=0; k<n; k++) {
for (z=0; z<m; z++) {
printf("elemento[%d,%d]=",k,z);
scanf("%d",&A[k][z]);
}
}
printf("\nMatrice A prima dell'eliminazione\n");
printf("A=\n|");

for (k=0; k<n; k++) {


for (z=0; z<m; z++) {
if (z<m-1) printf("%d ",A[k][z]);
else printf("%d|",A[k][z]);
}
if (k<n-1) printf("\n|");
else printf("\n");
}
col=-1;
while ((col<0) || (col>m-1)) {
printf("Inserisci l'indice di colonna da eliminare (>=0 <=%d): \n",m-1);
scanf("%d",&col);
};
printf("\nElaborazione in corso....\n");
eliminacol(A,n,&m,col);
system("Pause");
printf("\nMatrice A dopo l'eliminazione\n");
printf("A=\n|");
for (k=0; k<n; k++) {
for (z=0; z<m; z++) {
if (z<m-1) printf("%d ",A[k][z]);
else printf("%d|",A[k][z]);
}
if (k<n-1) printf("\n|");
else printf("\n");
}
system("Pause");
return 0;
}
226 Capitolo sesto

6.7.5. Eliminazione di una riga da una matrice


Descrizione del problema Scrivere una funzione per leliminazione dellelemento
in una data riga riga di una matrice di n righe e m colonne di elementi di un certo
tipo T. Esempio:
input: n=4, m=3, A= [10 22 33; 20 54 80; 30 10 23; 22 10 8], riga=2
output: n=3, m=3, A=[10 22 33; 30 19 23; 22 10 8]

Descrizione dellalgoritmo: Leliminazione di una colonna in una matrice si


effettua applicando lalgoritmo di eliminazione di un elemento da un vettore a tutte
le colonne della matrice. Utilizzando la sintassi del C, lalgoritmo assume la
seguente forma:
for (j=0;j<m;j++) {
for (i=riga+1;i<n;i++) {
A[i-1][j]=A[i][j];
}
}
n=n-1;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione eliminariga con le seguenti caratteristiche:
- Parametri di Input: [A,n,m,riga] matrice, numero di righe, numero di
colonne ed indice della riga da eliminare
- Parametri di Output: [A,n] matrice e numero di righe dopo leliminazione
- Variabili locali: i, j indici di riga e colonna

Implementazione

// FUNZIONE PER L'ELIMINAZIONE DI UNA RIGA DA UNA MATRICE


// La funzione void eliminacol(A,n,m,riga)
// permette di eliminare gli elementi di una data riga dalla matrice A
// Matrice un alias di un tipo array bidimensionale di int

void eliminariga(Matrice A, int* n, int m, int riga) {

// contatori di ciclo
register int i,j;

// effettua l'eliminazione mediante shift


for (j=0;j<m;j++) {
for (i=riga+1;i<*n;i++) {
A[i-1][j]=A[i][j];
}
}
// aggiorna il riempimento relativo alle colonne
*n=*n-1;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
Il linguaggio C 227

int main () {
Matrice A;
register int k,z;
int n,m,riga;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma di eliminazione di una riga da una matrice\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero di righe della matrice(>=0 <=50): \n");
scanf("%d",&n);
};
m=-1;
while ((m<0) || (m>MMAX-1)) {
printf("Inserisci il numero di colonne della matrice(>=0 <=50): \n");
scanf("%d",&m);
};
printf("Inserisci gli elementi della Matrice (dopo ogni elem premere INVIO)\n");

for (k=0; k<n; k++) {


for (z=0; z<m; z++) {
printf("elemento[%d,%d]=",k,z);
scanf("%d",&A[k][z]);
}
}
printf("\nMatrice A prima dell'eliminazione\n");
printf("A=\n|");
for (k=0; k<n; k++) {
for (z=0; z<m; z++) {
if (z<m-1) printf("%d ",A[k][z]);
else printf("%d|",A[k][z]);
}
if (k<n-1) printf("\n|");
else printf("\n");
}
riga=-1;
while ((riga<0) || (riga>m-1)) {
printf("Inserisci l'indice di riga da eliminare (>=0 <=%d): \n",m-1);
scanf("%d",&riga);
};
printf("\nElaborazione in corso....\n");
eliminacol(A,&n,m,riga);
system("Pause");
printf("\nMatrice A dopo l'eliminazione\n");
printf("A=\n|");
for (k=0; k<n; k++) {
for (z=0; z<m; z++) {
if (z<m-1) printf("%d ",A[k][z]);
else printf("%d|",A[k][z]);
}
if (k<n-1) printf("\n|");
else printf("\n");
}
system("Pause");
return 0;
}
228 Capitolo sesto

6.7.6. Ricerca sequenziale


Descrizione del problema: Scrivere una funzione per la ricerca dellinformazione
info in un vettore non ordinato avente n elementi di un certo tipo T. In particolare
la funzione deve produrre una indicazione sullesistenza dellinformazione nel
vettore e, nel caso esista, la posizione. Si fa lipotesi che nel caso in cui lelemento
non sia presente nel vettore la sua posizione -1. Esempio:
input: v= [9 5 6 8 7], info=8
output: msg=elemento presente, posiz=4

Descrizione dellalgoritmo: La ricerca di un oggetto in un insieme si effettua


fissando la strategia con la quale si possono effettuare i confronti delloggetto
cercato con quelli dellinsieme. Se non si ha una conoscenza dellinsieme, lunico
modo di procedere quello di prendere un oggetto alla volta e confrontarlo con
quello dato fino a quando non se ne trova uno uguale ad esso o stato visionato
lintero insieme. Tale tipo di ricerca detto sequenziale. La ricerca di
uninformazione in un vettore che contiene valori tra loro non ordinati procede in
maniera sequenziale. Si comincia a confrontare il primo elemento con quello
ricercato. Poi il secondo, poi il terzo e cos via fin quando il confronto non risulta
verificato. In questo modo si verifica lassenza dellelemento dopo averlo
confrontato con tutti gli elementi del vettore. Nel caso contrario, quando lo si
incontra, si ferma lindagine facendo lipotesi che nel vettore non esistano valori
tra di loro uguali. Facciamo ora un esempio. Sia assegnato il vettore:
v=[9 5 6 8 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore) e sia 4
il valore da ricercare. Allora lalgoritmo procede iterativamente nel seguente
modo:
passo confronto corrente trovato fine vettore
(posizione nel vettore)
1 4==9 no no
2 4==5 no no
3 4==6 no no
4 4==8 no no
5 4==9 no si

e la ricerca termina con lindicazione che 4 non presente nel vettore.


Cerchiamo quindi il valore 8:

passo confronto corrente trovato fine vettore


(posizione nel vettore)
1 8==9 no no
2 8==5 no no
3 8==6 no no
4 8==8 si no
Il linguaggio C 229

e la ricerca termina con lindicazione che il valore 8 presente allinterno del


vettore nella posizione 4. Utilizzando la sintassi del C, lalgoritmo assume la
seguente forma:

trovato=0;
i=0;
posiz=-1;
while (!trovato && i<n) {
if (v[i]==info) {
trovato=1;
posiz=i;
}
i++;
}

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione ricercaseq con le seguenti caratteristiche:
- Parametri di Input: [v,n,info] vettore dingresso, suo riempimento ed
informazione da ricercare
- Parametri di Output: [posiz] posizione dellelemento allinterno del vettore
- Variabili locali: [i,trovato,posiz] contatore di ciclo, variabile binaria che
indica se il confronto ha avuto successo e posizione dellelemento
allinterno del vettore

Implementazione
// FUNZIONE PER LA RICERCA DI UN ELEMENTO IN UN VETTORE
// La funzione int ricercaseq(v,n,info)
// permette di ricerca la posizione dellelemento info nel vettore v
// Vettore un alias di un tipo array monodimensionale di int

int ricercaseq(Vettore v, int n, int info) {

// contatore di ciclo, posizione dellelemento e variabile darresto


register int i=0;
int posiz=-1;
int trovato=0;

// effettua la ricerca sequenziale scorrendo gli elementi del vettore


while (!trovato && i<n) {
if (v[i]==info) {
trovato=1;
posiz=i;
}
i++;
}
// ritorna la posizione dellelemento
return posiz;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
230 Capitolo sesto

int main () {
Vettore v;
register int j;
int posiz,info,n;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma per la ricerca di un elemento da un vettore\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci gli elementi del Vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%d",&v[j]);
}
printf("\nVettore v prima della ricerca\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
printf("Inserisci l'elemento da ricercare: ");
scanf("%d",&info);
printf("\nElaborazione in corso....\n");
posiz=ricercaseq(v,n,info);
system("Pause");
printf("\n- Risultati ricerca -\n");
if (posiz!=-1) printf("L'elemento %d e' presente in posizione %d\n",info,posiz);
else printf("L'elemento % d non e presente nel vettore v\n",info);
system("Pause");
return 0;
}

6.7.7. Ricerca binaria


Descrizione del problema: Scrivere una funzione per la ricerca dellinformazione
info in un vettore non ordinato avente n elementi di un certo tipo T. In particolare
la funzione deve produrre una indicazione sullesistenza dellinformazione nel
vettore e, nel caso esista, la posizione. Si fa lipotesi che nel caso in cui lelemento
non sia presente nel vettore la sua posizione -1. Esempio:
input: v= [9 5 6 8 7], info=8
output: msg=elemento presente, posiz=4

Descrizione dellalgoritmo: La ricerca di una informazione in un elenco si pu


effettuare come visto nel caso precedente confrontando uno dopo laltro i valori
dellelenco con quello cercato fino a quando non si trova un elemento uguale o non
si analizzato lintero elenco. Il metodo sequenziale richiede nel caso peggiore n
confronti, dove n il riempimento del vettore. Se lelenco ordinato, si ricorre
allora ad una ricerca che ad ogni passo riduce linsieme in cui cercare mediante
unopportuna tecnica di dimezzamento. In questo modo il caso peggiore richiede al
Il linguaggio C 231

pi log2(n) confronti. Il metodo noto col nome di ricrca binaria si basa sui seguenti
passi:
- determinazione del punto medio dellinsieme in cui cercare;
- confronto dellelemento in questa posizione con quello da cercare;
- individuazione dellinsieme in cui continuare la ricerca se il passo 2 non
ha successo; esso risulta per vettore ordinato in senso crescente: il
sottoinsieme degli elementi in posizioni successive al punto medio se il
valore da cercare maggiore di quello del punto medio, altrimenti quello
caratterizzato da posizioni inferiori;
- ripetizioni dei passi precedenti finch il passo 2 non risulti verificato o
non sia possibile fissare un sottoinsieme in cui continuare la ricerca.
Facciamo ora un esempio. Sia assegnato il vettore:
v=[15 22 29 36 50 55]
(1 2 3 4 5 6)

(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore) e
sia 21 il valore da ricercare. Allora lalgoritmo procede iterativamente nel seguente
modo:

passo punto confronto prossimo fine trovato


medio corrente sottoinsieme di
ricerca
1 29 21<29 [15, 22] no no
2 15 21>15 [22] no no
3 22 21<22 [22, 15] si no

A questo punto la ricerca termina perch non esiste un sottoinsieme (lestremo


inferiore maggiore del superiore) in cui continuare la ricerca, con lindicazione
che 21 non presente nel vettore. Cerchiamo quindi il valore 50:

passo punto confronto prossimo fine trovato


medio corrente sottoinsieme di
ricerca
1 29 50>29 [36, 50, 55] no no
2 50 50==50 Vuoto si si
3 22 21<22 [22, 15] si no

e la ricerca termina con lindicazione che il valore 50 presente allinterno del


vettore nella posizione 5. Utilizzando la sintassi del C, lalgoritmo assume la
seguente forma:
posiz=-1;
trovato=0;
ei=0;
es=n-1;
while (!trovato && ei<es) {
medio=(ei+es)/2;
if (info==v[medio]) {
trovato=1;
posiz=medio;
232 Capitolo sesto

}
if (info<v[medio]) es=medio-1;
else ei=medio+1;
}

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione ricercabin con le seguenti caratteristiche:
- Parametri di Input: [v,n,info] vettore dingresso, suo riempimento ed
informazione da ricercare
- Parametri di Output: [posiz] posizione dellelemento allinterno del
vettore
- Variabili locali: [trovato,posiz,medio,ei,es] variabile binaria che indica se
il confronto ha avuto successo, posizione dellelemento allinterno del
vettore, punto, medio, estremo inferiore ed estemo superiore
dellintervallo di ricerca

Implementazione
// FUNZIONE PER LA RICERCA BINARIA DI UN ELEMENTO IN UN VETTORE
// La funzione int ricercaseq(v,n,info)
// permette di ricerca la posizione dellelemento info nel vettore v
// Vettore un alias di un tipo array monodimensionale di int

int ricercabin(Vettore v, int n, int info) {


// punto medio, etremi di ricerca, posizione dell'elemento e variabile d'arresto
int ei,es,medio;
int posiz=-1;
int trovato=0;
// inzializza l'intervallo di ricerca
ei=0;
es=n-1;
// effettua la ricerca binaria aggiornando gli intervalli di ricerca
while (!trovato && ei<es) {
medio=(ei+es)/2;
if (info==v[medio]) {
trovato=1;
posiz=medio;
}
if (info<v[medio]) es=medio;
else ei=medio;
}
// ritorna la posizione dell'elemento
return posiz;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v;
register int j;
int posiz,info,n;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma per la ricerca di un elemento da un vettore\n");
Il linguaggio C 233

n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci gli elementi del vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%d",&v[j]);
}
printf("\nVettore v prima della ricerca\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
printf("Inserisci l'elemento da ricercare: ");
scanf("%d",&info);
printf("\nElaborazione in corso....\n");
posiz=ricercabin(v,n,info);
system("Pause");
printf("\n- Risultati ricerca -\n");
if (posiz!=-1) printf("L'elemento %d e' presente in posizione %d\n",info,posiz);
else printf("L'elemento % d non e' presente nel vettore v\n",info);
system("Pause");
return 0;
}

6.7.8. La ricerca del valore massimo in un vettore


Descrizione del problema: Scrivere una funzione che determini il massimo di un
vettore v formato da n elementi di un certo tipo T. Esempio:
input: v=[10 55 20 11 30]
output: max=55

Descrizione dellalgoritmo: Lindividuazione del massimo in un insieme si


effettua osservando uno dopo laltro gli elementi che lo compongono e
memorizzando di volta in volta il valore pi grande. In particolare, si inizia
facendo lipotesi che il massimo sia il primo elemento del vettore e
successivamente lo si confronta con i restanti valori del vettore. Ogni volta che si
incontra un valore pi grande, si effettua laggiornamento del massimo. Facciamo
un esempio. Sia assegnato il vettore:

v=[3 5 6 8 7]
(1 2 3 4 5)

(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore). Allora
lalgoritmo procede iterativamente nel seguente modo:

massimo posizione confronto esito aggiornamento


234 Capitolo sesto

vettore (max<elemento confronto massimo


corrente del
vettore)
max=3 2 3<5 vero si
max=5 3 5<6 vero si
max=6 4 6<8 vero si
max=8 5 8<7 falso no

Utilizzando la sintassi del C, lalgoritmo assume la seguente forma :


max=v[0];
for (i=1;i<n;i++) {
if (v([i]>max) max=v[i];
}

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione max con le seguenti caratteristiche:
- Parametri di Input: [v,n] vettore dingresso e suo riempimento
- Parametri di Output: [max] variabile contenete il massimo del vettore
- Variabili locali: [i,max] contatore di ciclo e massimo corrente
Implementazione
// FUNZIONE PER LA RICERCA DEL MASSIMO DI UN VETTORE
// La funzione Elem max(v,n)
// permette di ricercare il massimo tra gli elementi di un vettore v
// Vettore un alias di un tipo array monodimensionale di int
// Elem un alias di un tipo intero rappresentante il tipo degli elemento del vettore

Elem max(Vettore v, int n) {

// contatore di ciclo e massimo corrente


register int i;
Elem max;
// inzializza il massimo
max=v[0];
// effettua la ricerca del massimo scorrendo gli elementi del vettore
for (i=1;i<n;i++) {
if (v[i]>max) max=v[i];
}
// ritorna il massimo
return max;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v;
register int j;
int n;
Elem massimo;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma per la ricerca del massimo vettore\n");
n=-1;
Il linguaggio C 235

while ((n<0) || (n>NMAX-1)) {


printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci gli elementi del vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%d",&v[j]);
}
printf("\nVettore v prima della ricerca\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
printf("\nElaborazione in corso....\n");
massimo=max(v,n);
system("Pause");
printf("\nIl massimo del vettore e' %d\n",massimo);
system("Pause");
return 0;
}

6.7.9. La posizione del valore minimo in un vettore


Descrizione del problema: Scrivere una funzione che determini la posizione del
valore minimo di un vettore formato da n elementi di un certo tipo T. Esempio:
input: v=[10 55 20 11 30]
output: posiz=1

Descrizione dellalgoritmo: Lindividuazione della posizione del minimo in un


insieme si effettua osservando uno dopo laltro gli elementi che lo compongono e
memorizzando di volta in volta la posizione dellelemento avente il valore pi
piccolo. In particolare, si inizia facendo lipotesi che la posizione del minimo sia
quella del primo elemento del vettore. Successivamente si confronta lelemento
nella presunta posizione di minimo con i restanti valori del vettore. Ogni volta che
si incontra un valore pi piccolo, si effettua laggiornamento della posizione in
modo che alla fine dei confronti si abbia la posizione del minimo. Si fa lipotesi
che nel vettore non esistano elementi uguali. Facciamo ora un esempio.
Sia assegnato il vettore:
v=[9 5 6 3 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore). Allora
lalgoritmo procede iterativamente nel seguente modo:
posiz. posizione confronto esito aggiornamento
minimo vettore (min>elemento confronto posizione
corrente del minimo
vettore)
posiz=1 2 9>5 Vero si
236 Capitolo sesto

posiz=2 3 5>6 Falso no


posiz=2 4 5>3 Vero si
posiz=4 5 3>7 Falso no

Utilizzando la sintassi del C, lalgoritmo assume la seguente forma:


posiz=0;
for (i=1;i<n;i++) {
if (v([i]<v[posiz]) posiz=i;
}

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione posmin con le seguenti caratteristiche:
- Parametri di Input: [v,n] vettore dingresso e suo riempimento
- Parametri di Output: [posiz] variabile contenete la posizione del minimo
del vettore
- Variabili locali: [i,posiz] contatore di ciclo e posizione del minimo
corrente

Implementazione
// FUNZIONE PER LA RICERCA DEL MASSIMO DI UN VETTORE
// La funzione int posmin(v,n)
// permette di ricercare la posizione del minimo tra gli elementi di un vettore v
// Vettore un alias di un tipo array monodimensionale di int

int posmin(Vettore v, int n) {

// contatore di ciclo e posizione del minimo correnye


register int i;
int posiz;
// inzializza la posizione del minimo
posiz=0;
// effettua la ricerca del massimo scorrendo gli elementi del vettore
for (i=1;i<n;i++) {
if (v[i]<v[posiz]) posiz=i;
}
// ritorna la posizione del minimo
return posiz;
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v;
register int j;
int n, posiz;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma per la ricerca della posizione del minimo\n");
n=-1;
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
Il linguaggio C 237

};
printf("Inserisci gli elementi del vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%d",&v[j]);
}
printf("\nVettore v prima della ricerca\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
printf("\nElaborazione in corso....\n");
posiz=posmin(v,n);
system("Pause");
printf("\nLa posizione del minimo del vettore e' %d\n",posiz);
system("Pause");
return 0;
}

6.7.10. Ordinamento di un vettore col metodo della selezione


Descrizione del problema: Scrivere una funzione per lordinamento in senso
crescente di un vettore di n elementi di un certo tipo. Esempio:
input: v=[30 10 50 12 22]
output: v=[10 12 22 30 50]

Descrizione dellalgoritmo: Ordinare un vettore in senso crescente significa


imporre che scelti due qualsiasi indici i e j, tali che i<j risulti v(i)<v(j). Un
meccanismo di ordinamento consiste nel dividere linsieme da ordinare in due
parti: una ordinata ed una disordinata. Si procede allora estraendo un elemento alla
volta dallinsieme disordinato e accodandolo a quello ordinato in modo che
lordinamento non venga alterato. Allinizio linsieme ordinato vuoto e
lalgoritmo termina quando contiene tutti gli elementi del vettore. Vi sono vari
modi di estrarre lelemento dallinsieme disordinato. Quello che di seguito
presentiamo seleziona ad ogni passo lelemento da accodare. In particolare
seleziona il minimo dallinsieme disordinato e lo accoda allinsieme ordinato. In tal
modo si viene ad ogni passo a scegliere il valore pi grandi di quelli che lo
precedono e contemporaneamente pi piccolo di quelli che lo seguono. Facciamo
ora un esempio.
Sia assegnato il vettore:

v=[9 2 1 4 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore). Allora
lalgoritmo procede iterativamente nel seguente modo:

Parte Parte posizione accodamento nuovo


238 Capitolo sesto

Ordinata Disordinata minimo intervallo di


(valore ricerca del
minimo) minimo
Vuota (1 2 3 4 5) 3(1) [1] [9 2 4 7]
(1) (2 3 4 5) 2(2) [1 2] [9 4 7]
(1 2) (3 4 5) 4(4) [1 2 4] [9 7]
(1 2 3) (4 5) 5(7) [1 2 4 7] [9]
(1 2 3 4) (5) 5(9) [1 2 4 7 9] vuoto

Si noti che lalgoritmo termina quando linsieme disordinato si riduce ad un


unico elemento. Inoltre poich si usa lo stesso vettore per la parte ordinata e
disordinata, laccodamento viene effettuato scambiando di posto il minimo ed il
valore che occupa la posizione di accodamento. Utilizzando la sintassi del C,
lalgoritmo assume la seguente forma :
for (i=0;i<n;i++) {
imin=i;
for (k=i+1;k<n;k++) {
if (v[k]<v[imin]) imin=k;
}
temp=v[i];
v[i]=v[imin];
v[imin]=temp;
}

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione ordina con le seguenti caratteristiche:
- Parametri di Input: [v,n] vettore dingresso e suo riempimento
- Parametri di Output: [v] vettore ordinato
- Variabili locali: [i,k,temp,imin] contatori di ciclo, variabile dappoggio
per gli scambi e posizione del minimo corrente della parte disordinata

Implementazione
// FUNZIONE PER L'ORDINAMENTO DI UN VETTORE
// La funzione void ordina(v,n) permette di ordinare in maniera crescente gli elementi del
// vettore v
// Vettore un alias di un tipo array monodimensionale di int

void ordina(Vettore v, int n) {


// contatori di ciclo
register int i,k;
// indice contenente la posizione del minimo della parte disordinata
// e variabile d'appoggio per gli scambi
int imin, temp;
// effettua l'ordinamento col metodo della selezione
for (i=0;i<n;i++) {
imin=i;
for (k=i+1;k<n;k++) {
if (v[k]<v[imin]) imin=k;
}
// effettua lo scambio tra l'elemento corrente ed il minimo della parte disord
temp=v[i];
Il linguaggio C 239

v[i]=v[imin];
v[imin]=temp;
}
}

Esempio duso: Per testare la funzione sviluppata pu essere utilizzato il seguente


main in cui inserita anche la gestione dellI/O.
// Funzione main
int main () {
Vettore v; register int j; int n=-1;
printf("Benvenuti al corso di Fondamenti di Informatica\n");
printf("Esempio di programma per lordinamento di un vettore\n");
while ((n<0) || (n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",&n);
};
printf("Inserisci gli elementi del vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<n; j++) {
printf("elemento[%d]=",j);
scanf("%d",&v[j]);
}
printf("\nVettore v prima dell'ordinamento\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
printf("\nElaborazione in corso....\n");
ordina(v,n);
system("Pause");
printf("\nVettore v dopo l'ordinamento\n");
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%d,",v[j]);
else
printf("%d",v[j]);
}
printf("]\n");
system("Pause");
return 0;
}

6.8. Esempi di programmi completi in C


Si vogliono ora di seguito mostrare degli esempi di programmi completi realizzati
con lausilio del linguaggio C.
240 Capitolo sesto

6.8.1. Gestione di un array


Descrizione del problema: Scrivere una libreria di funzioni che permettano la
gestione di un array di elementi di un dato tipo T. In particolare si vogliono
realizzare delle funzioni per:
- lordinamento dellarray
- la ricerca del massimo
- la ricerca sequenziale di un dato elemento nellarray
- linput da tastiera degli elementi dellarray
- loutput su video degli elementi di un array
- la gestione di un men per lattivazione delle funzioni

Descrizione dellalgoritmo: Per la realizzazione delle funzioni si sfruttano gli


algoritmi visti nella sezione precedente.

Descrizione delle funzioni: Per la realizzazione delle funzioni si utilizzano le


seguenti funzioni, di cui riportiamo per semplicit solo i parametri di
ingresso/uscita:
- ordina
o paramentri di input: [v,n] vettore e riempimento
o parametri di output: [v] vettore ordinato
- max
o paramentri di input: [v,n] vettore e riempimento
o parametri di output: [max] elemento massimo del vettore
- ricercaseq
o paramentri di input: [v,n,info] vettore, riempimento e elemento
da ricercare
o parametri di output: [posiz] posizione dellelemento ricercato
nellarray
- input_array
o paramentri di input: nessuno
o parametri di output [v] vettore e suo riempimento
- output_array
o paramentri di input: [v,n] vettore e riempimento
o parametri di output: nessuno
- menu
o parametri di input: nessuno
o parametri di output: nessuno

Implementazione ed esempio duso: Di seguito riportato limplementazione


dellintero programma con il codice relativo alle varie funzioni ed al main
utilizzato per testare il programma.
// Gestione array

// Preambolo del programma

// Direttive di compilazione
#include <stdio.h>
#include <stdlib.h>
Il linguaggio C 241

# define NMAX 50

// Alias di tipi
typedef float Vettore [NMAX];
typedef float Elem;

// prototipi funzioni
void ordina (Vettore v, int n);
int ricercaseq (const Vettore v, int n, Elem info);
Elem max (const Vettore v, int n);
void input_array (Vettore v, int* n);
void output_array (const Vettore v, int n);
void menu();

// FUNZIONE PER L'ORDINAMENTO DI UN VETTORE


// La funzione void ordina(v,n)
// permette di ordinare in maniera crescente gli elementi del vettore v

void ordina(Vettore v, int n) {


// contatori di ciclo
register int i,k;
// indice contenente la posizione del minimo della parte disordinata
// e variabile d'appoggio per gli scambi
int imin;
Elem temp;

// effettua l'ordinamento col metodo della selezione


for (i=0;i<n;i++) {
imin=i;
for (k=i+1;k<n;k++) {
if (v[k]<v[imin]) imin=k;
}
// effettua lo scambio tra l'elemento corrente ed il minimo della parte
disordinata
temp=v[i];
v[i]=v[imin];
v[imin]=temp;
}
}

// FUNZIONE PER LA RICERCA DI UN ELEMENTO IN UN VETTORE


// La funzione int ricercaseq(v,n,info)
// ritona la posizione dell'elemento info nel vettore v
// se l'elemento non presente viene ritornato -1

int ricercaseq(const Vettore v, int n, Elem info) {


// contatore di ciclo, posizione dell'elemento e variabile d'arresto
register int i=0;
int posiz=-1;
int trovato=0;
// effettua la ricerca sequenziale scorrendo gli elementi del vettore
while (!trovato && i<n) {
if (v[i]==info) {
trovato=1;
posiz=i;
242 Capitolo sesto

}
i++;
}
// ritorna la posizione dell'elemento
return posiz;
}

// FUNZIONE PER LA RICERCA DEL MASSIMO DI UN VETTORE


// La funzione Elem max(v,n)
// ritorna il massimo tra gli elementi di un vettore v

Elem max(const Vettore v, int n) {


// contatore di ciclo e massimo corrente
register int i;
Elem max;
// inzializza il massimo
max=v[0];
// effettua la ricerca del massimo scorrendo gli elementi del vettore
for (i=1;i<n;i++) {
if (v[i]>max) max=v[i];
}
// ritorna il massimo
return max;
}

// FUNZIONE PER L'INPUT DI UN VETTORE


// La funzione input_array(v,n)
// gestisce l'input da tastiera degli elementi di un vettore v

void input_array(Vettore v, int* n) {


register int j;
*n=-1;
while ((*n<0) || (*n>NMAX-1)) {
printf("Inserisci il numero delle componenti del tuo vettore(>=0 <=50): \n");
scanf("%d",n);
};
printf("Inserisci gli elementi del vettore (dopo ogni numero premere INVIO)\n");
for (j=0; j<*n; j++) {
printf("elemento[%d]=",j);
scanf("%g",&v[j]);
}
}

// FUNZIONE PER L'OUTPUT DI UN VETTORE


// La funzione output_array(v,n)
// gestisce l'output su monitor degli elementi di un vettore v

void output_array(const Vettore v, int n) {


register int j;
printf("Vettore = [");
for (j=0; j<n; j++) {
if (j<n-1)
printf("%g,",v[j]);
Il linguaggio C 243

else
printf("%g",v[j]);
}
printf("]\n");
}

// FUNZIONE PER LA GESTIONE DELL'ATTIVAZIONE DELLE FUNZIONI


// La funzione menu()
// gestisce l'attivazione delle funzioni mediante un men interattivo

void menu () {
Vettore v;
int n, posiz;
Elem massimo, info;
char opzione;
n=0;
while (opzione!='6') {
printf ("\n---PROGRAMMA PER LA GESTIONE DI UN ARRAY---\n");
printf ("[1] Inserimento elementi del Vettore\n");
printf ("[2] Visualizzione elementi del Vettore\n");
printf ("[3] Ricerca elemento nel Vettore\n");
printf ("[4] Visualizza elemento massimo nel Vettore\n");
printf ("[5] Ordina elementi del Vettore\n");
printf ("[6] Esci\n");
scanf("%s",&opzione);

switch (opzione) {
case '1':
input_array(v,&n);
break;
case '2':
if (n!=0) output_array (v,n);
else printf("\nVettore vuoto\n");
break;
case '3':
printf("\nInserisci l'elemento da ricercare: ");
scanf("%g",&info);
posiz=ricercaseq(v,n,info);
if (posiz!=-1)
printf("\nL'elemento %g e' in posizione %d\n",info,posiz);
else printf("\nL'elemento % g non e' presente nel vettore\n",info);
break;
case '4':
massimo=max(v,n);
printf("\nIl massimo del vettore e' %g\n",massimo);
break;
case '5':
ordina(v,n);
break;
case '6':
printf("Uscita programma...\n");
system("PAUSE");
default:
printf("\nOpzione non supportata\n");
}
244 Capitolo sesto

}
}

// MAIN

int main() {
menu();
return 0;
}

6.8.2. Gestione di un archivio


Descrizione del problema: Scrivere una libreria di funzioni che permettano la
gestione di un archivio di di impiegati. Dove un impiegato pu essere visto come
unistanza di un tipo strutturato caratterizzato dalle seguenti informazioni:
- matricola
- nome
- cognome
- dipartimento di afferenza
In particolare si vogliono realizzare delle funzioni per:
- il caricamento da file dellarchivio
- il salvataggio sul file dellarchivio
- linserimento di un nuovo impiegato in archivio
- la visualizzazione del contenuto dellarchivio
- la ricerca di un impiegato per cognome
- la modifica del dipartimento di afferenza di un dato impiegato
Descrizione dellalgoritmo: Gli algoritmi necessari alla realizzazione delle
funzioni si riconducono a quelle visti nella sezione precedente.
Descrizione delle funzioni: Si utilizzano le seguenti funzioni, di cui riportiamo per
semplicit solo i parametri di ingresso/uscita:
- carica_archivio
o paramentri di input [f]: nome del file su cui risiede larchivio
o parametri di output: [imp,n] archivio con impiegati
- salva_archivio
o paramentri di input [imp,f]: archivio corrente e nome del file su
cui deve risiedere larchivio
o parametri di output: nessuno
- inserisci_impiegato
o paramentri di input: [imp] archivio corrente
o parametri di output: [imp] archivio aggiornato
- visualizza_archivio
o paramentri di input [imp]: archivio corrente
o parametri di output: nessuno
- ricerca_impiegato
o paramentri di input: [imp,cogn] archivio corrente e cognome
dellimpiegato da ricercare
o parametri di output [trovato]: variabile binaria che indica la
presenza dellimpiegato in archivio
- modifica_impiegato
Il linguaggio C 245

o paramentri di input: [imp,cogn,dip] archivio corrente, cognome


dellimpiegato da ricercare e nome del nuovo dipartimento
o parametri di output [imp]: nuovo archivio

Implementazione ed esempio duso: Di seguito riportato limplementazione


dellintero programma con il codice relativo alle varie funzioni ed al main
utilizzato per testare il programma.
// Gestione Archivio
// Preambolo
// direttive di compilazione
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DIM_MAX 100
#define STR_MAX 100
//Alias di tipi
typedef char Stringa [STR_MAX];
typedef struct Impiegato {
int matricola;
Stringa Nome;
Stringa Cognome;
Stringa Dipartimento;
};
typedef Impiegato Impiegati [DIM_MAX];
// variabile globale contenente il riempimento dell'archivio
int num_impiegati=0;
// inserisce un nuovo impiegato in archivio
void inserisci_impiegato(Impiegati imp) {
int n=0;
register int i;
if (num_impiegati<100) {
do {
printf("Numero Impiegati presenti in archivio: %d\n",num_impiegati);
printf("Inserisci il numero di impiegati (>0 <=100): \n");
scanf("%d",&n);
} while ((n<1) || (n+num_impiegati>DIM_MAX));
printf("Inserisci gli Impiegati (premere INVIO)\n");
for (i=num_impiegati; i<num_impiegati+n; i++) {
printf("Inserire matricola dell'impiegato %d: ",i+1);
scanf("%d",&imp[i].matricola);
printf("Inserire nome dell'impiegato %d: ",i+1);
scanf("%s",imp[i].Nome);
printf("Inserire cognome dell'impiegato %d: ",i+1);
scanf("%s",imp[i].Cognome);
printf("Inserire dipartimento dell'impiegato %d: \n",i+1);
scanf("%s",imp[i].Dipartimento);
}
num_impiegati=n+num_impiegati;
} else printf("\nArchivio pieno!!!\n");
}
//stampa a video il contenuto dellarchivio
void visualizza_archivio(const Impiegati imp) {
register int i;
for (i=0; i<num_impiegati; i++) {
printf("Matricola dell'impiegato %d: %d\n",i+1, imp[i].matricola);
246 Capitolo sesto

printf("Nome dell'impiegato %d: %s\n",i+1,imp[i].Nome);


printf("Cognome dell'impiegato %d: %s\n",i+1,imp[i].Cognome);
printf("Dipartimento dell'impiegato %d: %s\n",i+1,imp[i].Dipartimento);
}
}

//ricerca se un impiegato presente in archivio


void ricerca_impiegato(Impiegati imp, Stringa cogn){
register int i,j;
int trovato=0;
for (i=0; i<num_impiegati; i++) {
if (strcmp(cogn,imp[i].Cognome)==0) {
trovato=1;
printf("Nome dell'impiegato %d: %s\n",i+1,imp[i].Nome);
printf("Cognome dell'impiegato %d: %s\n",i+1,imp[i].Cognome);
printf("Dipartimento dell'impiegato %d: %s\n",i+1,imp[i].Dipartimento);
}
}
if (!trovato)
printf("\n Impiegato non presente");
}

//modifica il dipartimento di un impiegato


void modifica_impiegato(Impiegati imp, Stringa cogn){
register int i,j;
int trovato=0;
i=0;
while (!trovato && i<num_impiegati) {
if (strcmp(cogn,imp[i].Cognome)==0)
trovato=true;
i++;
}
if (!trovato)
printf("\n Impiegato non presente");
else {
printf("Inserire nuovo Dipartimento dell'impiegato %d: \n",i);
scanf("%s",imp[i-1].Dipartimento);
}
}
// carica archivio da file
void carica_archivio (Impiegati imp, Stringa f) {
FILE * fp;
int ret;
register int i,j;
if (!(fp=fopen(f,"r"))) {
printf("\n L'archivio non puo' essere caricato\n");
}
else {
ret=fscanf(fp,"%d",&num_impiegati);
if (ret!=EOF) {
printf("\nNumero di impiegati presenti in archivio: %d\n",num_impiegati);
if (num_impiegati>0) {
for (i=0; i<num_impiegati; i++) {
fscanf(fp,"%d",&imp[i].matricola);
fscanf(fp,"%s",imp[i].Nome);
fscanf(fp,"%s",imp[i].Cognome);
Il linguaggio C 247

fscanf(fp,"%s",imp[i].Dipartimento);
}
}
}
else {
printf("\nArchivio vuoto!!!\n");
num_impiegati=0;
}
}
}
// salva archivio su file
void salva_archivio(const Impiegati imp, Stringa f) {
register int i,j;
FILE*fp;
if (!(fp=fopen(f,"w"))) {
printf("\n L'archivio non puo' essere salvato\n");
}
else {
fprintf(fp,"%d\n",num_impiegati);
for (i=0; i<num_impiegati; i++) {
fprintf(fp,"%d\n",imp[i].matricola);
fprintf(fp,"%s\n",imp[i].Nome);
fprintf(fp,"%s\n",imp[i].Cognome);
fprintf(fp,"%s\n",imp[i].Dipartimento);
}
}
}
// main
int main () {
Impiegati i;
char opzione;
Stringa cogn, file;
while (opzione!='7') {
printf ("\n-PROGRAMMA DI GESTIONE DI UN ARCHIVIO DI IMPIEGATI-\n");
printf ("[1] Inserisci Impiegati\n");
printf ("[2] Ricerca Impiegato\n");
printf ("[3] Modifica Impiegato\n");
printf ("[4] Visualizza Archivio\n");
printf ("[5] Carica Archivio\n");
printf ("[6] Salva Archivio\n");
printf ("[7] Esci\n");
scanf("%s",&opzione);
switch (opzione) {
case '1':
inserisci_impiegato(i);
break;
case '2':
printf("\nInserisci il cognome dell'impiegato che vuoi ricercare: ");
scanf("%s",cogn);
ricerca_impiegato(i,cogn);
break;
case '3':
printf("\nInserisci il cognome dell'impiegato che vuoi ricercare: ");
scanf("%s",cogn);
modifica_impiegato(i,cogn);
break;
248 Capitolo sesto

case '4':
visualizza_archivio(i);
break;
case '5':
printf("\nInserisci il nome del file-archivio: ");
scanf("%s",file);
carica_archivio(i,file);
break;
case '6':
printf("\nInserisci il nome del file su cui salvare l'archivio: ");
scanf("%s",file);
salva_archivio(i,file);
break;
case '7':
printf("Uscita programma...\n");
system("PAUSE");
return 0;
default:
printf("Opzione non supportata\n");
}
}
return 1;
}
Capitolo settimo

Il linguaggio dellambiente MATLAB

7.1. Caratteristiche del linguaggio


MATLAB un vero e proprio ambiente di progetto rivolto principalmente allo
sviluppo di programmi per lanalisi numerica. Tale ambiente utilizza un linguaggio
di programmazione con una sintassi simile a quella del C, e, cos come i linguaggi
di programmazione pi comuni, esso mette a disposizione del programmatore tutti
i pi noti tipi elementari di dato:
- dati di natura numerico:
o tipo intero,
o tipo reale,
- dati di natura alfanumerica:
o caratteri,
o stringhe.
In particolare linstanziazione di una variabile numerica avviene attraverso la
sintassi:
var=val
dove var e val rappresentano rispettivamente il nome ed il valore della variabile
numerica. Mentre linstanziazione di una variabile alfanumerica avviene attraverso
la sintassi:
var=val
dove var e val rappresentano rispettivamente il nome ed il valore della variabile
alfanumerica. Una variabile alfanumerica contraddistinta dalla presenza degli
apici, allinizio e alla fine del valore della variabile stessa.
Altra caratteristica fondamentale di MATLAB il concetto di funzione. Ogni
programma, sottoprogramma, procedura o funzione del linguaggio sempre
trattata come una funzione costituita o meno da un insieme di parametri di
ingresso-uscita. Ogni dichiarazione di funzione MATLAB preceduta dalla parola
chiave function.
Per quanto riguarda le istruzioni, il linguaggio MATLAB fornisce sia
enunciati o statement semplici che di controllo.
Quelli semplici sono:
- lassegnazione, che fornisce ad una variabile il valore che si ottiene
calcolando il risultato di unespressione composta in generale di costanti,
variabili, operatori e funzioni; essa si indica (se var la variabile che
riceve il valore ed E lespressione che lo fornisce) con un sintassi del
tipo: var=E
250 Capitolo settimo

- lattivazione di funzioni, eventualmente con il passaggio dei dati da


elaborare e con la ricezione di uno pi risultati. Si noti che MATLAB,
come del resto altri linguaggi, mette a disposizione un insieme molto
ampio di funzioni predefinite quali ad esempio quelle per il calcolo
numerico oppure quelle per la lettura e la scrittura di dati sui supporti di
ingresso e uscita.
Gli enunciati di controllo si dividono al loro volta in:
- enunciati composti, che si ottengono disponendo in sequenza enunciati
semplici, di selezione e di iterazione;
- enunciati di selezione;
- enunciati di iterazione.
Come anticipato il linguaggio MATLAB prevede la costruzione di programmi
con la struttura di funzioni composte da un unico blocco di istruzioni, costituente la
sezione esecutiva. A differenza di altri linguaggi, manca nel corpo di una funzione
MATLAB la sezione dichiarativa in quanto tutte le variabili, come vedremo, sono
automaticamente trattate e riconosciute o come set di reali o di caratteri. Una
funzione pu richiamare o essere richiamata da altre funzioni e pu essere o meno
caratterizzata dalla presenza di parametri di ingresso e di uscita.
In figura 1 riportato un esempio di programma MATLAB che richiama due
funzioni. La funzione A un esempio di funzione avente solo parametri di
ingresso, mentre la funzione B un esempio di funzione avente parametri sia di
ingresso che di uscita. Il programma principale esso stesso una funzione senza
parametri. Tutte le variabili usate allinterno di una funzione MATLAB sono ad
essa locali, ossia hanno una visibilit limitata alla sola funzione in cui sono usate.
In altri termini una variabile definita allinterno della funzione A non pu essere
usata nella funzione B e viceversa.
function nome_programma
enunciato 1 del programma
.
funzioneA (lista_parametri_ingresso)
.
[lista_paramteri_ucita] = funzioneB(lista_parametri_ingresso)
.
enunciato N del programma

function funzioneA(lista_parametri_ingresso)
enunciato 1 della funzioneA
..
enunciato N1 della funzioneA

function [lista_paramteri_ucita] = funzioneB(lista_parametri_ingresso)


enunciato 1 della funzioneB
..
enunciato N2 della funzioneB
Figura 1 Esempio di programma Matlab

7.1.1. Il vocabolario del linguaggio


Il vocabolario del linguaggio costituito da sequenze di lunghezza finita di
caratteri trattate come singole entit logiche ( quindi l'insieme delle parole
Il linguaggio dellambiente MATLAB 251

costruite secondo le regole lessicali). Tali entit sono raggruppate in cinque classi
differenti per finalit e caratteristiche. Le 5 classi sono:
- separatori;
- identificatori e parole riservate;
- simboli speciali (operatori, delimitatori, frasi di commento);
- numeri interi e decimali;
- sequenze di caratteri racchiuse tra apici;
Si noti che le terza e la quarta classe contengono le costanti (numeriche e
alfanumeriche) gestite dal linguaggio.
7.1.2. I separatori
Ciascuna entit lessicale separata dalla successiva mediante opportuni separatori.
I caratteri spazio ed ENTER (fine linea) sono considerati separatori espliciti,
mentre gli operatori (aritmetici e di relazione), il punto e virgola e l'operatore
dell'assegnazione (=) vengono implicitamente identificati come separatori. Cos le
frasi che seguono presentano due entit lessicali distinte:

alfa = 10
if contatore

mentre le frasi seguenti ne presentano soltanto una:


ifcontatore
whilecondizione

7.1.3. Gli identificatori e le parole chiavi


Gli identificatori permettono di indicare i nomi di programmi, costanti, variabili e
funzioni. Un identificatore una stringa di caratteri che deve soddisfare i seguenti
vincoli:
- deve essere composta da lettere, cifre e dal carattere _;
- il primo carattere deve essere una lettera;
- deve essere costituito da un numero limitato di caratteri;
- non deve ovviamente contenere al suo interno lo spazio.
In figura 2 riportata la carta sintattica per la costruzione di un identificatore.

Figura 2 Carta sintattica per identificatori


252 Capitolo settimo

Esempi di identificatori sono:

A
a
ALFA
Alfa
SOL1
PI_greco
equaz_2_grado

Lesempio sottolinea il fatto che MATLAB case sensitive ovvero fa


differenza tra lettere maiuscole e minuscole per cui ALFA e Alfa sono considerati
distinti.
Alcuni identificatori hanno un ben preciso e congelato significato nell'ambito
del linguaggio e pertanto prendono il nome di parole riservate o chiavi. Tali parole
sono riservate per usi particolari e non sono ridefinibili in altro modo dal
programmatore in quanto sono le chiavi che guidano nella costruzione delle frasi
del linguaggio. Esempi di parole chiavi del linguaggio sono: if, function, while,
else, end.
Accanto agli identificatori riservati, esiste un insieme di identificatori con
significato ormai standard, che costituiscono l'ambiente di lavoro del linguaggio. In
MATLAB ne esistono tantissimi, la maggior parte di questi fa riferimento a
funzioni matematiche. Alcuni esempi sono: abs, max, min, sin, cos, sqrt, mean,
etc
7.1.4. I simboli speciali
I simboli speciali sono o semplici caratteri o coppie adiacenti di essi ed
indicano le operazioni predefinite presenti nel linguaggio e tutta la punteggiatura
richiesta dalla sintassi. Essi sono i seguenti:

+ - * /
(operatori aritmetici)
< > == <= >= ~=
(operatori di confronto)
, ; . : ..
(delimitatori e punteggiatura)
( ) [ ] { }
(parentesi)
& | ~ ()
operatori logici)
%
(commenti)
Di seguito descritto luso dei vari simboli speciali.
Operatori Aritmetici
Gli operatori aritmetici sono i classici operatori binari +,- ,*,/ e loperatore
di modulo %. La divisione tra interi tronca la parte frazionaria, mentre
lespressione x%y fornisce il resto della divisione di x per y. Loperatore di
modulo pu essere applicato solo a tipi integrali. Gli operatori + e hanno la stessa
priorit, priorit inferiore a * e / (che invece hanno identica priorit).
Il linguaggio dellambiente MATLAB 253

Operatori Relazionali
Gli operatori relazionali sono:
> >= < <=

mentre gli operatori di eguaglianza (e disuguaglianza) sono:


== ~=

Gli operatori di relazione hanno priorit maggiore rispetto a quelli di eguaglianza


/disuguaglianza. Gli operatori relazionali hanno invece priorit minore rispetto agli
operatori aritmetici.
Operatori Logici
Gli operatori logici sono:
& (and), | (or) e ~ (not)

& ha priorit maggiore di | ed entrambi hanno priorit inferiore agli operatori


relazionali e di uguaglianza. Si noti che non esistendo un tipo logico predefinito,
loperatore ~ converte un operando non zero in un operando zero.
I delimitatori
Il linguaggio MATLAB non ha dei delimitatori canonici per delimitare le frasi del
programma. Lunico carattere che ha una funzione di questo tipo il carattere ;
(punto e virgola). Tale carattere viene utilizzato come termine di ogni frase del
linguaggio. Se non lo si inserisce al termine della frase, allora viene prodotta in
automatico la stampa del valore delle variabili calcolate nella istruzione; se invece
si chiude la frase con il punto e virgola tale stampa viene disabilitata.
7.1.5. Le frasi di commento
Come tutti gli altri linguaggi di programmazione anche MATLAB
consente di introdurre nel programma frasi prive di ogni valore esecutivo o
dichiarativo che consentono di migliorare la leggibilit e la chiarezza del
programma. Esse servono unicamente ad uno scambio di messaggi tra le persone.
Tali frasi prendono il nome di frasi di commento. Nel linguaggio una frase che
inizia con il simbolo speciale % un commento come mostrato in figura 3.

% la variabile alfa deve avere valore negativo


% i>=10 implica una condizione di errore

Figura 3 Carta sintattica per frasi di commento


254 Capitolo settimo

7.1.6. Le costanti numeriche


I numeri trattati dal linguaggio sono di due tipi, interi e reali. Un numero
intero una sequenza di cifre eventualmente preceduta da un segno. Un numero
reale ha una parte decimale ed eventualmente un fattore di scala.
Sono costanti intere:
10
300
-1000

Sono costanti reali:


3.400
10.20
+1.99E+30
-30.008
-0.7E-10
9.02E3
In figura 4 riportata la carta sintattica per la generazione di costanti
numeriche.

Figura 4 Carta sintattica per costanti numeriche

7.1.7. Le costanti stringhe di caratteri


Le costanti stringa di caratteri sono sequenze di caratteri racchiuse da una
coppia di caratteri ' (apici). Il valore della stringa dato dalla sequenza di caratteri
esclusi gli apici che fungono da parentesi (vedi carta sintattica in figura 5). Una
costante senza caratteri (una coppia di apici) rappresenta la stringa a lunghezza
nulla.
Sono costanti stringhe di caratteri:
'ALFABETO'
'ciao'
'Minuscolo'
Il linguaggio dellambiente MATLAB 255

Figura 5 Carta sintattica per stringhe

7.2. La struttura del programma


Da un punto di vista testuale, il programma visto come un insieme di frasi a
cui viene costituito da una intestazione che ne riassume molto brevemente il
significato ed un blocco che pu essere visto come una entit sintattica che
contiene la parte elaborativa del programma. Ogni intestazione sempre preceduta
dalla parola chiave function.

Figura 6 Programma in MATLAB

7.2.1. La dichiarazione e gestione dei tipi


Come gi anticipato in MATLAB non esiste il concetto di dichiarazione
esplicita di tipo. Ogni variabile appartiene, in maniera implicita, ad uno dei tipi
elementari messi a disposizione dal linguaggio. A differenza dei classici linguaggi
di programmazione, il linguaggio MATLAB utilizza due soli tipi elementari di
dato, o meglio, due sole classi elementari di oggetti:
- double array (array bidimensionale di numeri reali);
- char array (array bidimensionale di caratteri).
La classe double array permette la gestione di tutti dati di tipo numerico come
interi, reali a singola precisione e reali a doppia precisione. Di contro la classe char
array permette la gestione di tutti i dati di tipo alfanumerico come caratteri e
stringhe. Un oggetto di tali classi ha una struttura simile a quella di una matrice.
Risulter evidente che attraverso tali classi base di oggetti possibile simulare tutti
i tipi classici di un linguaggio di programmazione.
double
variabili array
numeriche

char
variabili array
alfanumeriche
Figura 7 Carta sintattica per i tipi di MATLAB

Tipi Semplici: il tipo intero


Il tipo intero contiene il sottoinsieme dei numeri interi compresi nell'intervallo [-
MAXINT, MAXINT] con MAXINT valore costante predefinito. Il valore di MAXINT
256 Capitolo settimo

dipende dalla rappresentazione interna dei numeri interi ed quindi dipendente dal
particolare sistema di calcolo. Sulle variabili di tipo intero sono definite le
operazioni di somma, sottrazione, divisione e moltiplicazione pi moltissime altre
funzioni tra cui ricordiamo: la funzione resto in modulo MOD, la funzione valore
assoluto ABS, la funzione segno SIGN e cos via.
Tipi Semplici: il tipo reale
Il tipo reale contiene un intervallo di estremi predefiniti dell'insieme dei numeri
reali. Sui valori del tipo reale sono definite le operazioni di somma, sottrazione,
divisione e di moltiplicazione, pi un insieme ampio di funzioni pi avanzate. Sono
inoltre definite le due funzioni di conversione da reale a intero floor(x), ceil(x) e
round(x). La prima restituisce la parte intera di x; la seconda restituisce la parte
intera di x+1; la terza calcola l'intero mediante un arrotondamento. Esempio:
floor (0.6) = 0
ceil (0.6) = 1
round(0.6) = 1

Tipi Semplici: il tipo char


Le costanti che compongono il tipo char formano un insieme finito e ordinato di
caratteri. L'ordinamento pu variare a seconda del sistema di calcolo e dipende dal
codice usato per la rappresentazione in memoria. Solitamente viene impiegato il
codice ASCII a sette bit, per cui l'ordinamento viene stabilito dalla posizione del
carattere all'interno della tabella introdotta dall'ASCII. Un carattere denotato da
uno dei simboli di tale tabella racchiuso tra apici (ad esempio 'm').
Tipi Semplici: il tipo booleano
In MATLAB non esiste il tipo booleano, ma questo pu essere simulato con una
variabile intera che pu assumere due soli valori (0 e 1): uno corrispondente a
FALSE, laltro a TRUE. Sui valori logici sono definite le operazioni di NOT (~),
AND (&) ed OR (!).
Tipi Strutturati: il tipo array
La struttura array composta da un insieme di elementi tutti dello stesso tipo e con
un unico nome collettivo. Pu avere una o pi dimensioni fino ad un massimo
prefissato. Ad ogni elemento dell'array possibile accedere mediante un indice (o
un numero di indici uguale alle dimensioni stabilite) che ne individua la posizione
all'interno della struttura.
In MATLAB il numero di elementi dell'array non definito a priori e pu
cambiare nel corso del programma. Un array monodimensionale di interi o reali
coincide con un oggetto della classe double array di dimensione 1xN, con N pari al
numero di elementi contenuti nellarray. Un array monodimensionale di caratteri
coincide con un oggetto della classe char array di dimensione 1xN, con N pari al
numero di elementi contenuti nellarray. Gli elementi del vettore vanno racchiusi
tra parentesi quadre e separati da uno spazio bianco o da una virgola.
a=[1 2 3];
b=[7,2,8,6];
Il linguaggio dellambiente MATLAB 257

Nel primo caso si creato il vettore a di tre elementi con valori 1, 2 e 3; nel
secondo caso si creato il vettore b con quattro elementi 7, 2, 8 e 6.
Un array bidimensionale (matrice) di interi o reali coincide con un oggetto
della classe double array di dimensione MxN, con M pari al numero di righe della
matrice e N pari al numero di colonne. Un matrice di caratteri coincide con un
oggetto della classe char array di dimensione MxN, con M pari al numero di righe
della matrice e N pari al numero di colonne. Gli elementi della matrice vanno
racchiusi tra parentesi quadre, gli elementi delle righe sono separati da uno spazio
bianco o da una virgola, mentre ogni riga separata dalla successiva mediante il
carattere punto e virgola ;. Con:

a=[1 2 3 4; 5 6 7 8; 9 10 11 12];

si crea una matrice di tre righe e quattro colonne i cui elementi hanno i valori
indicati.
1 2 3 4
a 5 6 7 8
9 10 11 12
La selezione di uno dei componenti dell'array si effettua facendo seguire al
nome dell'array il valore dell'indice, o degli indici separati da virgola nel caso di
array a pi dimensioni, racchiusi tra una coppia di parentesi tonde.
Sono esempi di funzioni di accesso:

a(3,(I*J+2))
a(I,J)
a(3)
Nel caso di array con informazioni strutturate, si devono comporre le varie
funzioni di accesso. Le operazioni consentite sugli array sono quelle che si possono
fare sui componenti l'array stesso.
In MATLAB anche i tipi semplici sono visti come casi particolari di quelli
strutturati. In MATLAB le variabili intere, reali e caratteri sono gestite mediante un
oggetto della classe double array di dimensione 1x1, mentre i caratteri mediante
un oggetto della classe char array di dimensione 1x1, come si pu vedere di
seguito.

a=1;
Name Size Class
a 1x1 double array
a=1.5;
Name Size Class
a 1x1 double array
a=a;
Name Size Class
a 1x1 char array
258 Capitolo settimo

Le carte sintattiche di seguito mostrano come costruire array in MATLAB e


come accedere agli elementi in essi contenuti.

identificatore = [ reale ]

carattere

identificatore = [ carattere ]

Figura 8 Carta sintattica per la costruzione di array monodimensionali

Figura 9 Carta sintattica per per la costruzione di array bidimensionali

identificatore ( indice )

indice ;

Figura 10 Carta sintattica laccesso agli elementi di array

Tipi Strutturati: il tipo record


La struttura record composta da un numero prefissato di componenti, anche di
tipo differente. Ogni componente, detto anche campo del record, ha un suo nome e
tipo. La definizione di un record prevede, allora, l'elencazione delle variabili, sia
semplici che a loro volta strutturate, costituenti i campi componenti. Le operazioni
consentite sul record sono quelle che si possono fare sui campi.
In MATLAB la definizione di un record avviene definendo il nome del record
e ponendo tra parentesi graffe le variabili costituenti i campi del record separate da
Il linguaggio dellambiente MATLAB 259

virgole. Il valore delle variabili deve essere noto allatto della definizione del
record. MATLAB tratta i record come oggetti della classe non elementare cell
array (array di celle). Una cella (campo del record) pu essere a sua volta o di tipo
char arry o di tipo double array.

Figura 11 Carta sintattica per la costruzione di record

Nellesempio successivo mostrata la definizione del record agenda.

Nominativo='Angelo Chianese';
Indirizzo='via Claudio 121';
citta='Napoli';
tel=39081777777;
agenda={Nominativo,Indirizzo,citta,tel}

L'accesso ad un campo si effettua specificando il nome del record e lindice


del campo compreso tra parentesi graffe. Se un campo un'informazione
strutturata, allora si deve per esso applicare la funzione di accesso caratteristica del
tipo di appartenenza.

agenda{1}
agenda{3}

Tipi Strutturati: il tipo intervallo


Il tipo intervallo si definisce come sottoinsieme di un tipo predefinito. MATLAB
tratta solo intervalli di natura numerica. Per definire un intervallo devono essere in
generale specificati lestremo iniziale (ei), quello finale (ef) ed un passo (p): in tale
caso si generano tutti i valori che si ottengono calcolando x = x + p con valore
iniziale di x uguale a ei e valore finale uguale a ef. Non obbligatorio specificare
il passo: nel caso venga omesso assume automaticamente il valore unitario. La
sintassi per la generazione di un intervallo la seguente:
t=[ei:passo:ef]

Con il tipo intervallo si introduce di fatto un array (vedi carta sintattica in


figura 12) con tanti valori quanti sono quelli determinati dalla dichiarazione di
intervallo. Esempi sono in tabella 1.

Istruzione Intervallo generato


t=[1:10] 1 2 3 4 5 6 7 8 9 10
t=[0:0.1:1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Tabella 1 Esempi di intervalli
260 Capitolo settimo

array
identificatore = [ ]
subrange

intero o intero o intero o


: :
reale reale reale

Figura 12 Carta sintattica per la costruzione di un intervallo

Tipi Strutturati: il tipo file


Un file una sequenza di componenti tutti dello stesso tipo che risiede in modo
permanente sui supporti di massa.Un file pu essere visto come un dato strutturato
utilizzabile per la registrazione di un qualsiasi numero di elementi. In MATLAB
non esiste un tipo file, come vedremo in seguito, le operazioni di I/O da e verso file
sono ottenute aprendo dei veri e propri canali di comunicazione tra il programma e
la memoria di massa.
7.2.2. La dichiarazione di funzione
MATLAB, come gi anticipato, utilizza il concetto di funzione per la creazione di
programmi e sottoprogrammi. La dichiarazione di funzione si compone di due
parti, l'intestazione e il blocco di enunciati. L'intestazione composta dalla parola
chiave function, l'identificatore della funzione e due liste: la prima contenente gli
eventuali parametri di uscita separati da virgola e racchiusi in parentesi quadre, la
seconda contenente gli eventuali parametri di ingresso separati da virgola e
racchiusi in parentesi tonde. Tali liste possono essere omesse nel caso di mancanza
dei parametri di ingresso o uscita. Di seguito riportato un esempio di intestazione
di funzione a n uscite e a m ingressi.
function [out1,out2,..outn]=nome_funzione(in1,in2,in3,,inm)

Figura 13 Carta sintattica per lintestazione di una funzione


Una funzione, come qualsiasi elaborazione, comanda l'esecuzione di
operazioni che, a partire da un insieme di dati iniziali, fornisce un insieme di
risultati. Dati iniziali e risultati sono i parametri della funzione e sono anche detti
argomenti della funzione. Si conviene che:
Il linguaggio dellambiente MATLAB 261

- i parametri attuali sono forniti all'atto del richiamo e rappresentano i dati


effettivamente elaborati;
- i parametri formali sono quelli usati all'interno della procedura per poterla
scrivere.
Al momento del richiamo i parametri formali vengono sostituiti da quelli
attuali. Per tale motivo il tipo dei parametri attuali deve corrispondere a quello
dichiarato dei parametri formali. Le due liste di parametri della dichiarazione di
funzione comprendono l'elenco dei parametri formali. Il linguaggio prevede due
meccanismi di sostituzione, per valore e per riferimento o variabile. La sostituzione
per valore prevede la valutazione del parametro attuale e l'assegnazione di tale
valore a quello formale. La sostituzione per variabile o riferimento fa s che i
parametri formali coincidano con quelli attuali. Difatti, all'atto della chiamata,
viene fornito al parametro formale l'indirizzo di memoria del parametro attuale in
modo che tutte le operazioni sui parametri formali avvengono di fatto su quelli
attuali. Per questo motivo i parametri attuali risentono delle elaborazioni fatte dalla
procedura o funzione a differenza di quanto avviene per i parametri valore. In
MATLAB i parametri di ingresso sono passati per valore quelli di uscita per
riferimento. Il blocco contiene invece la specifica dellalgoritmo.
7.2.3. La specifica dellalgoritmo
La specificazione delle azioni elaborative del programma si traduce in un
enunciato o statement composto. Lo statement composto formato da una
sequenza di statement. Gli statement possono essere o meno separati dal carattere
punto e virgola. Gli statement semplici che compongono la specificazione
dell'algoritmo denotano azioni elaborative che devono essere svolte dall'esecutore
macchina.
Gli statement sono:
- assegnazione,
- if else,
- while,
- switch case,
- for,
- richiamo funzione.
7.2.4. Assegnazione
L'enunciato di assegnazione la pi elementare forma di enunciato. Esso
prescrive che venga dapprima calcolato il valore dell'espressione che si trova a
destra del =, e che tale valore venga poi assegnato alla variabile che si trova a
sinistra dello stesso simbolo. La variabile e il valore dell'espressione devono essere
dello stesso tipo con l'eccezione che, se la variabile reale, allora il tipo
dell'espressione pu anche essere intero.
Una espressione una formula o regola di calcolo che specifica sempre un
valore detto risultato dell'espressione. composta da operandi ed operatori. Gli
operandi possono essere variabili, costanti o valori restituiti da una funzione. Gli
operatori sono classificati in monadici o unari e in diadici o binari a seconda che
prevedano uno o due operandi rispettivamente. Se in una espressione sono presenti
pi operandi, occorre specificare la priorit della loro esecuzione nel caso in cui
262 Capitolo settimo

non sia esplicitata mediante l'introduzione nell'espressione delle parentesi. In


particolare, il linguaggio prevede quattro classi di operatori a ciascuna delle quali
assegnata una precedenza nel senso che, in mancanza di parentesi, deve essere
svolta prima l'operazione con operatore con precedenza maggiore.
Gli operatori in ordine di precedenza decrescente sono:
- l'operatore di negazione logica;
- gli operatori detti moltiplicativi;
- gli operatori detti additivi;
- gli operatori di relazione.
Ciascun operatore applicabile solo a particolari tipi di operandi e il risultato
della operazione risulter del tipo stabilito dal linguaggio. Sono assegnazioni:

alfa = 3.569
circonferenza = 2 * PI_GRECO * raggio
area_rettangolo = base * altezza
i=i-1

Figura 14 Carta sintattica per lenunciato di assegnazione

7.2.5. Richiamo di funzione


Il richiamo della funzione determina l'esecuzione della funzione indicata. Affinch
il richiamo sia corretto, si deve fornire una lista di parametri uguale, in numero e
tipo, a quella specificata nella dichiarazione della funzione. La corrispondenza si
stabilisce per ordine, nel senso che al primo parametro attuale associato il primo
formale, e cos via.

[parametri di uscita attuali]=nome_funzione(parametri di ingresso attuali)

I parametri attuali devono essere forniti con rispetto del meccanismo di


sostituzione e del tipo dei parametri indicati nella dichiarazione della procedura. In
particolare, se si fissato una sostituzione per valore, si possono usare come
parametri attuali variabili, costanti ed espressioni di un tipo compatibile, secondo
le regole viste a proposito dell'assegnazione di valore, con quello del parametro
formale (si pu ad esempio usare un parametro attaule di tipo sia intero che reale
nel caso di un parametro formale di tipo reale, mentre deve essere assolutamente di
tipo intero nel caso di parametro formale dichiarato intero). Nel caso di
sostituzione per riferimento, si devono impiegare solo variabili e i tipi dei due
parametri devono coincidere.
Il linguaggio dellambiente MATLAB 263

Figura 15 Carta sintattica per lenunciato di richiamo di funzione

Funzioni predefinite
Il linguaggio mette a disposizione un ampio set di funzioni predefinite applicabili a
tipi semplici e strutturati, per lo pi di natura matematica. Tali funzioni possono
essere introdotte all'interno di un programma, alcuni esempi sono:

cos(x)
sqrt(x)
mean(v)
max(v)
det(A)

Di particolare interesse sono le funzioni di conversione tra caratteri e reali e tra


reali e caratteri:

char(126) = ~
double(a) = 97

Funzioni per lI/O


Il linguaggio fornisce alcune funzioni per le operazioni di lettura e scrittura dei
valori delle variabili dai file INPUT e OUTPUT. In genere il file di INPUT
rappresenta la tastiera del sistema di calcolo; quello di OUTPUT il monitor. Essi
possono essere visti come organizzati in un testo costituito da sequenze di RIGHI
separati tra loro dal carattere di fine rigo CR (Carriage Return). La sequenza di
righi terminata dal carattere di fine file. All'interno di ogni rigo sono distribuite le
rappresentazioni delle informazioni opportunamente separate usando il carattere
spazio. L'introduzione degli spazi pu avvenire sia in maniera esplicita che
implicita. In maniera esplicita il numero di caratteri di spazio viene specificato
direttamente nelle istruzioni di lettura/scrittura. Nell'altro modo si assegna alla
rappresentazione del valore delle variabili, mediante opportune dichiarazioni di
formato, un numero di caratteri maggiore di quello necessario. Per tali motivi le
procedure di lettura devono provvedere al riconoscimento, interpretazione e
trasformazione delle sequenze di caratteri nei formati interni degli interi e reali;
quelle di scrittura, alla trasformazione inversa di questi tipi in sequenze di caratteri
264 Capitolo settimo

durante le operazioni di scrittura. Invece non sono richieste trasformazioni per la


lettura e scrittura delle variabili di tipo carattere.
Lettura da file di INPUT
In MATLAB la lettura da un file avviene aprendo un canale di comunicazione con
la memoria di massa attraverso il concetto di apertura di un file. Un file deve
essere aperto prima di essere utilizzato. Lapertura di un file avviene attraverso la
funzione:
[fid,message]=fopen (filename, permission)

dove fid lidentificativo del file, message il messagio associato allapertura del
file, filename il nome del file (path su disco del file) e permission la modalit
con cui si apre il file (in questo caso lettura).
Dopo lapertura, con lidentificatore del file possibile eseguire le operazioni
di lettura che avvengono con lutilizzo della funzione:

[A] = fscanf(fid, format)

dove fid lidentificativo del file, format indica il tipo degli elementi da leggere ed
A la matrice in cui si inseriscono gli elementi letti. La variabile format pu
assumere i seguenti valori a seconda del tipo di dato che si vuole leggere:

%d interi
%f, %g reali
%c caratteri
%s stringhe
Di seguito riportato un esempio di lettura da file:
[fid,message]=fopen ('c:\file.txt','r);
[v_input]=fscanf(fid,'%s')
v_input = ciao

La lettura di informazioni da standard input (tastiera) avviene attraverso la


funzione:

var_input=input(msg,[s])

dove var_input rappresenta la variabile in cui verr memorizzato il valore immesso


da tastiera e msg un messaggio visualizzato a video. Il parametro s va
specificato solo per le variabili di tipo stringa.

var_input=input(Inserisci un numero:)
var_input=input(Inserisci una stringa:,s)

Scrittura su file di OUTPUT


Anche la scrittura su file avviene aprendo un canale di comunicazione con la
memoria di massa Un file deve essere aperto prima di essere utilizzato.
Il linguaggio dellambiente MATLAB 265

Analogamente alloperazione di lettura lapertura di un file avviene attraverso la


funzione:
[fid,message]=fopen (filename, permission)

dove fid lidentificativo del file, message il messagio associato allapertura del
file, filename il nome del file (path su disco del file) e permission la modalit
con cui si apre il file (in questo caso scrittura). A questo punto attraverso
lidentificatore del file possibile eseguire le operazioni di scrittura che avvengono
con lutilizzo della funzione:

[count] = fprintf (fid, format,A)

dove fid lidentificativo del file, format indica il tipo degli elementi da scrivere,
A la matrice in cui sono presenti gli elementi da scrivere e count conta il numero
di elementi effettivamente scritti su file. La variabile format assume gli stessi
valori previsti nella lettura. Di seguito riportato un esempio di scrittura su file:

[fid,message]=fopen ('c:\file.txt','w');
stringa=ciao;
[count]=fprintf(fid,stringa,'%s')
count = 4
[fid,message]=fopen ('c:\file.txt','r');
[v_input]=fscanf(fid,'%s')
v_input = ciao

La scrittura di informazioni su standard output (monitor) avviene attraverso la


funzione stessa fprintf senza specificare lidentificativo del file:

fprintf (%s,Messaggio visualizzato a video)

7.2.6. Gli enunciati di selezione


Gli enunciati selettivi permettono la selezione di azioni elaborative in funzione del
valore di una espressione booleana e non: ossia si valuta l'espressione e si sceglie
l'istruzione successiva in funzione del valore trovato.
Il costrutto IF-ELSE
L'enunciato IF-ELSE (se - altrimenti) permette di effettuare la scelta tra due
alternative in funzione del valore di una espressione booleana. Se il valore
dell'espressione TRUE, si sceglie l'alternativa introdotta dopo lIF (linsieme di
enunciati compresi tra lif e lelse), in caso contrario quella aperta dall'ELSE
(linsieme di enunciati compresi tra lelse e lend). In entrambi i casi, dopo
l'esecuzione del blocco selezionato, l'esecuzione stessa continua con l'enunciato
successivo all'IF. anche possibile usare una notazione abbreviata nel caso in cui
non esista una delle due alternative, non specificando l'ELSE dell'enunciato. Nel
liguagio MATLAB ogni costrutto if-else va terminato con la parola chiave end.
Sono esempi di IF:
266 Capitolo settimo

if (n>10)
n=n+1;
else
n=n-1;
end

if (n>10)
n=0;
end;
n=n-1;

Si noti, infine, come l'uso appropriato dell'incolonnamento (o anche


indentazione) delle strutture innestate l'una dentro l'altra migliori notevolmente la
chiarezza del programma in quanto evidenzia l'ordine di esecuzione dei vari
blocchi.

Figura 16 Carta sintattica per luso del costrutto if-else

Il costrutto switch-case
L'enunciato switch-case permette di scegliere nel caso in cui le alternative siano
pi di due. Esso consiste di un'espressione (di tipo numerico o carattere), detta
selettore, e di una lista di enunciati, ciascuno dei quali identificato da uno o pi
valori costanti appartenenti al tipo del selettore preceduti dalla parola case.
L'enunciato scelto quello identificato dalla costante che uguale al valore
calcolato del selettore.
Una volta eseguito lenunciato scelto si esce dalla struttura switch. La
scansione dei valori costanti, per cercare quello con valore uguale al selettore,
avviene in modo sequenziale per cui vanno disposti per ultimi gli enunciati che
hanno la minore probabilit di essere scelti. Qualora il valore calcolato dal selettore
Il linguaggio dellambiente MATLAB 267

non uguale ai valori costanti indicati viene eseguito lenunciato preceduto dalla
parola chiave otherwise se presente, altrimenti si esce dallo struttura. Sono esempi
di switch-case:

SWITCH(colore_semaforo)
CASE rosso
msg=stop;
CASE verde
msg=vai;
CASE giallo
msg=attenzione;
OTHERWISE
msg=semaforo rotto;
END

SWITCH(numero mese)
CASE {1,3,5,7,8,10,12}
msg=mese di 31 giorni;
CASE {4,6,9,11}
msg=mese di 30 giorni;
CASE 2
msg=mese di 28 o 29 giorni;
OTHERWISE
msg=mese non valido;
END

Infine, la struttura switch si presta in maniera brillante per far corrispondere


insiemi di valori di tipo diverso. L'esempio che segue illustra l'utilit dello switch
per creare la corrispondenza tra i valori numerici delle cifre (variabile valcifra) e il
relativo carattere ASCII (variabile carcifra).

SWITCH(valcifra)
CASE 0 carcifra='0';
CASE 1 carcifra='1';
CASE 2 carcifra='2';
CASE 3 carcifra='3';
CASE 4 carcifra='4';
CASE 5 carcifra='5';
CASE 6 carcifra='6';
CASE 7 carcifra='7';
CASE 8 carcifra='8';
CASE 9 carcifra='9';
END
268 Capitolo settimo

Figura 17 Carta sintattica per luso del costrutto switch-case

7.2.7. Le strutture iterativa

Il while
Gli enunciati iterativi permettono l'esecuzione di un blocco di istruzioni un certo
numero di volte. La terminazione della ripetizione avviene quando sono verificate
certe condizioni che sono calcolate internamente al blocco. Se il numero di
ripetizioni noto a priori, la struttura viene anche detta ciclica o enumerativa.
L'enunciato while composto da una espressione logica e da uno o pi
enunciati da ripetere in funzione del valore di tale espressione. L'esecuzione del
while comporta la valutazione dell'espressione e l'esecuzione degli enunciati
compresi tra le parole while ed end nel caso in cui il valore calcolato
dell'espressione sia TRUE. Il ciclo ha cos termine quando l'espressione assume il
valore FALSE per cui, se l'espressione risulta falsa alla prima esecuzione del while,
tali enunciati non vengono mai eseguiti. Si osservi che una volta iniziato, il ciclo
pu terminare solo se all'interno di esso vi sono degli enunciati che modificano il
valore di verit dell'espressione: cio operano sulle variabili che ne fanno parte.
un esempio di while:

somma=0;
while (n<=20)
somma=somma+vettore(n);
n=n+1;
end
Il linguaggio dellambiente MATLAB 269

possibile uscire da un ciclo WHILE in maniera incondizionata, cio, in


maniera indipendente dal valore di verit dellespressione, attraverso la parola
chiave BREAK.

while espressione
( )
booleana

statement
end
composto

statement

Figura 18 Carta sintattica per luso del costrutto while

Il for
Il for un enunciato iterativo enumerativo, detto anche ciclico, che deve essere
usato ogni qualvolta il numero di ripetizioni noto a priori. Si presenta nel
seguente modo:
for t = Tin : Tfin
S
end

dove t viene detta contatore di ciclo e Tin e Tfin rappresentano il campo di


variabilit di t e quindi il numero di volte che S viene ripetuto. La variabile
contatore di ciclo e le variabili Tin ed Tfin possono appartenere ad uno dei tipi di cui
nota l'enumerazione. I valori di Tin ed Tfin sono calcolati all'inizio del ciclo e si ha
che il blocco S eseguito se e solo se, Tin risulta minore o uguale di Tfin, altrimenti
si procede in sequenza con l'istruzione successiva al for. Il numero di volte che il
blocco S viene ripetuto viene calcolato prima del ciclo ed uguale a:

(double(Tin)-double(Tfin)+1)

Il valore di t non deve essere mai alterato dagli enunciati che compongono S
(se ci fosse consentito, si verrebbe a contraddire il presupposto che il numero di
ripetizioni noto a priori). Inoltre, eventuali modifiche di Tin ed Tfin interne ad S
non alterano il numero di iterazioni del blocco S stesso.
In MATLAB possibile, cos come avviene per la generazione degli,
intervalli specificare anche il passo di iterazione, in tale caso il costrutto assume la
seguente forma:

for t = Tin :p: Tfin


S
end
270 Capitolo settimo

dove p rapprenda il passo di iterazione (se non viene specificato di default


posto al valore 1). Quando il passo assume valore negativo e Tin > Tfin possibile
generare iterazioni in modo decrescente. Ad esempio attraverso listruzione:

for t = 10 :-1:1
S
end

si esegue listruzione S comunque 10 volte con il contatore del ciclo che parte
da 10 ed arriva ad 1 in modalit decrescente.

Figura 19 Carta sintattica per luso del costrutto for

7.3. Gli algoritmi di base in MATLAB


Si vogliono ora di seguito mostrare degli algoritmi base dellinformatica realizzati
con lausilio del linguaggio MATLAB.
7.3.1. Lo scambio di valore
Descrizione del problema
Scrivere una funzione che effettui lo scambio di valore tra due informazioni di un
tipo T. Esempio:
input: x=3, y=5
output: x=5, y=3

Descrizione dellalgoritmo
Se si associano alle due informazioni due contenitori di liquidi, il problema diventa
quello del loro trasferimento da un contenitore allaltro senza che i liquidi si
mischiano. Risulta allora evidente che non c modo di effettuare tale trasferimento
se non introducendo un terzo contenitore che permette di svuotare uno degli altri
due contenitori. Si pu cos travasare il liquido il liquido dellaltro in quello che si
svuotato e infine ritrasferire in esso il liquido che stato spostato per primo nel
terzo contenitore. Si comprende allora che per scambiare due informazioni dello
stesso tipo necessario introdurre una terza variabile, ovviamente dello stesso tipo.
Ad esempio date le tre informazioni:
x [3] y [5] z[]
si copia dapprima x in z:
x [3] y [5] z[3]
Il linguaggio dellambiente MATLAB 271

poi y in x:
x [5] y [5] z[3]
ed infine z in y:
x [5] y [3] z[3]
lalgoritmo assume la seguente forma :

z=x;
x=y;
y=z;

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione scambia con le
seguenti caratteristiche:
- Paramentri di input: [x,y] informazioni prima dello scambio
- Parametri di output: [x,y] informazioni dopo lo scambio
- Variabili locali: [z] informazione necessaria allo scambio

Implementazione
% FUNZIONE PER LO SCAMBIO DI VALORE
% La funzione [x,y]=scambia(x,y)
% permette di scambiare il valore delle variabili x ed y.
% Esempio:
% x=3, y=5
% [x,y]=scambia(x,y)
% x=5, y=3

function [x,y]=scambia(x,y) % Intestazione funzione


% effettua scambia per mezzo di una terza variabile
z=x;
x=y;
y=z;

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help scambia
FUNZIONE PER LO SCAMBIO DI VALORE
La funzione [x,y]=scambia(x,y)
permette di scambiare il valore delle variabili x ed y.
Esempio:
x=3, y=5
[x,y]=scambia(x,y)
x=5, y=3
x=9;
y=19;
[x,y]=scambia(x,y)
x = 19
y=9

Si nota come tutta la documentazione che precede lintestazione nel codice


pu essere utilizzata come help della funzione.
272 Capitolo settimo

7.3.2. Linserimento in un vettore


Descrizione del problema
Scrivere una funzione per linserimento dellinformazione info nella posizione
posiz di un vettore di n elementi di un certo tipo. Esempio:
input: n=5, v= [10 50 20 40 35], info=66, posiz=3
output: n=6, v=[10 50 66 20 40 35]

Descrizione dellalgoritmo
Si pu pensare al vettore come ad uno scaffale di libri allineati verso sinistra. Per
far posto ad un nuovo libro in una posizione assegnata, bisogna spostare tutti i libri
che si trovano in posizione successiva a quella data di una posizione verso destra.
Lo spostamento pu essere fatto un libro alla volta, cominciando da quello in
ultima posizione. Dopo linserimento, il numero di libri o riempimento dello
scaffale aumentato di una unit. Si fa lipotesi che lo scaffale non sia mai pieno.
Nel caso in cui si debba inserire la lettera a nella seconda posizione di un vettore di
4 elementi la procedura per linserimento riportata di seguito:
[x, y, z, f]
si effettua lo spostamento (shift) di tutti gli elementi del vettore,a partire
dallultimo fino a quello in seconda posizione, di un posto a destra:
[x, , y, z, f]
si copia il nuovo elemento nella seconda posizione e si incrementa di una unit il
numero di elementi allinterno del vettore:
[x, a, y, z, f]
utilizzando la sintassi di Matlab, lalgoritmo assume la seguente forma :
for i=n:-1:posiz
v(i+1)=v(i);
end;
v(posiz)=info;
n=n+1;

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione inserimento con le
seguenti caratteristiche:
- Parametri di Input: [v, n, info, posiz] rispettivamente vettore, riempimento
del vettore, elemento da inserire e rispettiva posizione,
- Parametri di Output: [v, n] vettore e riempimento dopo linserimento
- Variabili locali: [i] contatore di ciclo

Implementazione
% FUNZIONE PER L'INSERIMENTO IN UN VETTORE
% La funzione [v,n]=inserimento(v,n,info,posiz)
% permette di inserire nel vettore v di n elementi l'elemento info
% alla posizione posiz.
% Esempio:
% v=[1 2 4 5], n=4, info=3, posiz=3
% [v,n]=inserimento(v,n,info,posiz)
% v=[1 2 3 4 5], n=5

function [v,n]=inserimento(v,n,info,posiz)
Il linguaggio dellambiente MATLAB 273

% sposta gli elementi del vettore di un posto a destra a partire dallultimo fino
% a quello in posizione posiz
for i=n:-1:posiz
v(i+1)=v(i);
end;
% inserisci il nuovo elemento nella posizione specificata
v(posiz)=info;
% aumenta di una unit il numero di elementi nel vettore
n=n+1;

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help inserimento
FUNZIONE PER L'INSERIMENTO IN UN VETTORE
La funzione [v,n]=inserimento(v,n,info,posiz)
permette di inserire nel vettore v di n elementi l'elemento info
alla posizione posiz.
Esempio:
v=[1 2 4 5], n=4, info=3, posiz=3
[v,n]=inserimento(v,n,info,posiz)
v=[1 2 3 4 5], n=5
v=[10 50 20 40 35];
n=5;
info=66;
posiz=3;
[v,n]=inserimento(v,n,info,posiz)
v =10 50 66 40 35
n=6

7.3.3. Leliminazione in un vettore


Descrizione del problema
Scrivere una funzione per leliminazione dellelemento in una posizione posiz data
di un vettore di n elementi di un certo tipo. Esempio:
input: n=5, v= [22 50 30 16 10], posiz=2
output: n=4, v=[22 30 16 10]

Descrizione dellalgoritmo
Si pu pensare al vettore come ad uno scaffale di libri allineati verso sinistra. Dopo
avere tolto il libro dalla posizione assegnata, bisogna spostare tutti quelli che si
trovano alla sua destra di un posto verso sinistra per recuperare lo spazio resosi
disponibile. Lo spostamento viene fatto un libro alla volta, cominciando da quello
successivo al libro nella posizione assegnata e si termina quando si arrivati
allultimo libro. Dopo leliminazione, il numero di libri o riempimento dello
scaffale diminuito di una unit. Si fa lipotesi che lo scaffale contenga almeno un
elemento. Nel caso in cui si l elemento in seconda posizione di un vettore di 4
elementi la procedura per leliminazione riportata di seguito:
[x, y, z, f]
si effettua lo spostamento (shift) di tutti gli elementi del vettore, a partire da quello
in terza posizione fino allultimo, di un posto a sinistra:
[x, z, f]
274 Capitolo settimo

si diminuisce di una unit il numero di elementi allinterno del vettore.


Utilizzando la sintassi di Matlab, lalgoritmo assume la seguente forma:
for i=posiz+1:1:n
v(i-1)=v(i);
end;
n=n-1;

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione eliminazione con
le seguenti caratteristiche:
- Parametri di Input: [v, n, posiz] vettore di partenza, riempimento del
vettore e posizione dellelemento da eliminare
- Parametri di Output: [v,n] vettore e suo riempimento dopo leliminazione
- Variabili locali: i contatore di ciclo

Implementazione
% FUNZIONE PER L'ELIMINAZIONE IN UN VETTORE
% La funzione [v,n]=eliminazione(v,n,posiz)
% permette di eliminare dal vettore v di n elementi l'elemento
% alla posizione posiz.
% Esempio:
% v=[1 2 4 3], n=4, posiz=3
% [v,n]=eliminazione(v,n,posiz)
% v=[1 2 3], n=3

function [v,n]=eliminazione(v,n,posiz)
% sposta gli elementi del vettore di un posto a sinistra a partire
% da quello successivo alla posizione posiz fino all'ultimo
for i=posiz+1:1:n
v(i-1)=v(i);
end;
% diminuisce di una unit il numero di elementi nel vettore
n=n-1;
% aggiorna il vettore in maniera da considerare solo i primi n elementi
v=v(1:n);

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help eliminazione
FUNZIONE PER L'ELIMINAZIONE IN UN VETTORE
La funzione [v1,n]=eliminazione(v,n,posiz)
permette di eliminare dal vettore v di n elementi l'elemento
alla posizione posiz.
Esempio:
v=[1 2 4 3], n=4, posiz=3
[v,n]=eliminazione(v,n,posiz)
v=[1 2 3], n=3
v=[22 50 30 16 10];
n=5;
posiz=2;
Il linguaggio dellambiente MATLAB 275

[v,n]=eliminazione(v,n,posiz)
v = 22 30 16 10
n=4

7.3.4. Leliminazione di una colonna da una matrice


Descrizione del problema
Scrivere una funzione per leliminazione di un data colonna di una matrice di N
righe ed M colonne di un certo tipo. Esempio:
input: N=3, M=4, A= [10 22 33 50; 20 54 80 41; 30 10 23 31], col=2
output: N=3, M=3, A=[10 33 50; 20 80 41; 30 23 31]

Descrizione dellalgoritmo
Leliminazione di una colonna in una matrice si effettua applicando lalgoritmo di
eliminazione di un elemento da un vettore a tutte le righe della matrice. Utilizzando
la sintassi di Matlab, lalgoritmo assume la seguente forma:
for j=col+1:1:M
for i=1:N
A(i,j-1)=A(i,j);
end;
end;

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione elimina_colonna
con le seguenti caratteristiche:
- Parametri di Input: [A,N,M,colonna], matrice, numero di righe, numero di
colonne ed indice della colonna da eliminare
- Parametri di Output: [A,m] matrice e numero di colonne dopo
leliminazione
- Variabili locali: i, j indici di riga e colonna

Implementazione
% FUNZIONE PER L'ELIMINAZIONE DI UNA COLONNA IN UNA MATRICE
% La funzione [A]=elimina_colonna(A,N,M,col)
% permette di eliminare la colonna col dalla matrice A di N righe e M colonne.
% Esempio:
% A=[1 2 3; 4 5 6], N=2, M=3, col=3
% [A]=elimina_riga(A,N,M,col)
% A=[1 2; 4 5]

function [A]=elimina_colonna(A,N,M,col)
% applica a tutte le righe della matrice l'algoritmo per l'eliminazione
% di un elemento nella posizione col assegnata
for j=col+1:1:M
for i=1:N
A(i,j-1)=A(i,j);
end;
end;
% diminuisce di una unit il numero di colonne
M=M-1;
% aggiorna la matrice
A=A(1:N,1:M);
276 Capitolo settimo

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help elimina_colonna
FUNZIONE PER L'ELIMINAZIONE DI UNA COLONNA IN UNA MATRICE
La funzione [A]=elimina_colonna(A,N,M,col)
permette di eliminare la colonna col dalla matrice A di N righe e M colonne.
Esempio:
A=[1 2 3; 4 5 6], N=2, M=3, col=3
[A]=elimina_riga(A,N,M,col)
A=[1 2; 4 5]
A=[10 22 33 50; 20 54 80 41; 30 10 23 31];
N=3;
M=4;
col=2;
[A]=elimina_colonna(A,N,M,col)
A=
10 33 50
20 80 41
30 23 31

7.3.5. Leliminazione di una riga da una matrice


Descrizione del problema
Scrivere una funzione per leliminazione di un data riga di una matrice di N righe
ed M colonne di un certo tipo. Esempio:
input: N=3, M=4, A= [10 22 33 50; 20 54 80 41; 30 10 23 31], riga=1
output: N=2, M=4, A=[20 80 54 41; 30 10 23 31]

Descrizione dellalgoritmo
Leliminazione di una riga in una matrice si effettua applicando lalgoritmo di
eliminazione di un elemento da un vettore a tutte le colonne della matrice.
Utilizzando la sintassi di Matlab, lalgoritmo assume la seguente forma :
for i=riga+1:1:N
for j=1:M
A(i-1,j)=A(i,j);
end;
end;

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione elimina_riga con
le seguenti caratteristiche:
- Parametri di Input: [A, N, M, riga] matrice, numero di righe, numero di
colonne ed indice della riga da eliminare
- Parametri di Output: [A,n] matrice e numero di righe dopo leliminazione
- Variabili locali: i, j indici di riga e colonna

Implementazione
% FUNZIONE PER L'ELIMINAZIONE DI UNA RIGA IN UNA MATRICE
% La funzione [A]=elimina_riga(A,N,M,riga)
% permette di eliminare la riga assegnata dalla matrice A di N righe e M colonne.
% Esempio:
Il linguaggio dellambiente MATLAB 277

% A=[1 2 3; 4 5 6], N=2, M=3, riga=1


% [A]=elimina_riga(A,N,M,riga)
% A=[4 5 6]

function [A]=elimina_riga(A,N,M,riga)
% applica a tutte le colonne della matrice l'algoritmo per l'eliminazione
% di un elemento nella posizione riga assegnata
for i=riga+1:1:N
for j=1:M
A(i-1,j)=A(i,j);
end;
end;
% diminuisce di una unit il numero di righe
N=N-1;
% aggiorna la matrice
A=A(1:N,1:M);

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help elimina_riga
FUNZIONE PER L'ELIMINAZIONE DI UNA RIGA IN UNA MATRICE
La funzione [A]=elimina_riga(A,N,M,riga)
permette di eliminare la riga assegnata dalla matrice A di N righe e M colonne.
Esempio:
A=[1 2 3; 4 5 6], N=2, M=3, riga=1
[A]=elimina_riga(A,N,M,riga)
A=[4 5 6]
A=[10 22 33 50; 20 54 80 41; 30 10 23 31];
N=3;
M=4;
riga=1;
[A]=elimina_riga(A,N,M,riga)
A=
20 54 80 41
30 10 23 31

7.3.6. La ricerca sequenziale


Descrizione del problema
Scrivere una funzione per la ricerca dellinformazione info in un vettore non
ordinato avente n elementi di un certo tipo. In particolare la funzione deve produrre
una indicazione sullesistenza dellinformazione nel vettore e, nel caso esista, la
posizione. Si fa lipotesi che nel caso in cui lelemento non sia presente nel vettore
la sua posizione 0.
Esempio:
input: v= [9 5 6 8 7], info=8
output: msg=elemento presente, posiz=4

Descrizione dellalgoritmo
La ricerca di un oggetto in un insieme si effettua fissando la strategia con la quale
si possono effettuare i confronti delloggetto cercato con quelli dellinsieme. Se
non si ha una conoscenza dellinsieme, lunico modo di procedere quello di
278 Capitolo settimo

prendere un oggetto alla volta e confrontarlo con quello dato fino a quando non se
ne trova uno uguale ad esso o stato visionato lintero insieme. Tale tipo di ricerca
detto sequenziale. La ricerca di uninformazione in un vettore che contiene valori
tra loro non ordinati procede in maniera sequenziale. Si comincia a confrontare il
primo elemento con quello ricercato. Poi il secondo, poi il terzo e cos via fin
quando il confronto non risulta verificato. In questo modo si verifica lassenza
dellelemento dopo averlo confrontato con tutti gli elementi del vettore. Nel caso
contrario, quando lo s incontra, si ferma lindagine facendo lipotesi che nel vettore
non esistano valori tra di loro uguali. Facciamo ora un esempio. Sia assegnato il
vettore:
v=[9 5 6 8 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore) e sia 4
il valore da ricercare. Allora lalgoritmo procede iterativamente nel seguente
modo:
passo confronto corrente trovato fine vettore
(posizione nel vettore)
1 4==9 no no
2 4==5 no no
3 4==6 no no
4 4==8 no no
5 4==9 no si
e la ricerca termina con lindicazione che 4 non presente nel vettore. Cerchiamo
quindi il valore 8:

passo confronto corrente trovato fine vettore


(posizione nel vettore)
1 8==9 no no
2 8==5 no no
3 8==6 no no
4 8==8 si no

e la ricerca termina con lindicazione che il valore 8 presente allinterno del


vettore nella posizione 4. Utilizzando la sintassi di Matlab, lalgoritmo assume la
seguente forma:
trovato=0;
i=0;
posiz=0;
while (!trovato & i<n)
if (v[i]==info)
trovato=1;
posiz=i;
msg='elemento presente';
end
i++;
end
if trovato==0
msg='elemento non presente';
end
Il linguaggio dellambiente MATLAB 279

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione ricercaseq con le
seguenti caratteristiche:
- Parametri di Input: [v, info] vettore dingresso ed informazione da
ricercare
- Parametri di Output: [msg, posiz] variabile contenete il messaggio
sullesito della ricerca e posizione dellelemento allinterno del vettore
- Variabili locali: [i, trovato, n] contatore di ciclo, variabile binaria che
indica se il confronto ha avuto successo o meno e riempimento del vettore
- Funzioni richiamate: length per il calcolo del riempimento del vettore.

Implementazione
% FUNZIONE PER LA RICERCA SEQUENZIALE DI UN ELEMENTO IN UN VETTORE
% La funzione [msg,posiz]=ricercaseq(v,info)
% permette di cercare l'elemento info nel vettore v.
% Se la ricerca ha successo viene restituita la posizione posiz
% dell'elemento nel vettore.
% msg una variabile che segnala l'esito della ricerca.
% Esempio:
% v=[1 2 8 9 5 6], info=8
% [msg,posiz]=ricercaseq(v,info)
% msg= 'elemento presente', posiz=3

function [msg,posiz]=ricercaseq(v,info)
% inizializzazione variabili locali
% variabile binaria che indica il successo del confronto
% (0 indica che l'elemento non stato ancora trovato,
% 1 il successo del confronto)
trovato=0;
% riempimento del vettore
n=length(v);
% cerca iterativamente l'elemento nel vettore confrontandolo con i suoi elementi
% dal primo all'ultimo
i=0;
posiz=0;
while (!trovato & i<n)
if (v[i]==info)
trovato=1;
posiz=i;
msg='elemento presente';
end
i++;
end
if trovato==0
msg='elemento non presente';
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB ed il confronto con la funzione find predefinita
nel linguaggio.
280 Capitolo settimo

help ricercaseq
FUNZIONE PER LA RICERCA SEQUENZIALE DI UN ELEMENTO IN UN VETTORE
La funzione [msg,posiz]=ricercaseq(v,info)
permette di cercare l'elemento info nel vettore v.
Se la ricerca ha successo viene restituita la posizione posiz
dell'elemento nel vettore.
msg una variabile che segnala l'esito della ricerca.
Esempio:
v=[1 2 8 9 5 6], info=8
[msg,posiz]=ricercaseq(v,info)
msg= 'elemento presente', posiz=3
v=[9 5 6 8 7];
info=8;
[msg,posiz]=ricercaseq(v,info)

msg = elemento presente


posiz = 4

posiz=find(v==8)
posiz =4

7.3.7. La ricerca binaria


Descrizione del problema
Scrivere una funzione per la ricerca dellinformazione info in un vettore ordinato in
senso crescente avente n elementi di un certo tipo. In particolare la funzione deve
produrre una indicazione sullesistenza dellinformazione nel vettore e, nel caso
esista, la posizione. Si fa lipotesi che nel caso in cui lelemento non sia presente
nel vettore la sua posizione 0. Esempio:
input: v=[10 12 15 33 40 55], info=33
output: msg=elemento presente, posiz=4

Descrizione dellalgoritmo
La ricerca di una informazione in un elenco si pu effettuare come visto nel caso
precedente confrontando uno dopo laltro i valori dellelenco con quello cercato
fino a quando non si trova un elemento uguale o non si analizzato lintero elenco.
Il metodo sequenziale richiede nel caso peggiore n confronti, dove n il
riempimento del vettore. Se lelenco ordinato, si ricorre allora ad una ricerca che
ad ogni passo riduce linsieme in cui cercare mediante unopportuna tecnica di
dimezzamento. In questo modo il caso peggiore richiede al pi log2(n) confronti. Il
metodo noto col nome di ricerca binaria si basa sui seguenti passi:
1. determinazione del punto medio dellinsieme in cui cercare;
2. confronto dellelemento in questa posizione con quello da cercare;
3. individuazione dellinsieme in cui continuare la ricerca se il passo 2 non
ha successo; esso risulta per vettore ordinato in senso crescente: il
sottoinsieme degli elementi in posizioni successive al punto medio se il
valore da cercare maggiore di quello del punto medio, altrimenti quello
caratterizzato da posizioni inferiori;
4. ripetizioni dei passi precedenti finch il passo 2 non risulti verificato o
non sia possibile fissare un sottoinsieme in cui continuare la ricerca.
Facciamo ora un esempio. Sia assegnato il vettore:
Il linguaggio dellambiente MATLAB 281

v=[15 22 29 36 50 55]
(1 2 3 4 5 6)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore) e sia 21
il valore da ricercare. Allora lalgoritmo procede iterativamente nel seguente
modo:
passo punto confronto prossimo fine trovato
medio corrente sottoinsieme
di ricerca
1 29 21<29 [15, 22] no no
2 15 21>15 [22] no no
3 22 21<22 [22, 15] si no

A questo punto la ricerca termina perch non esiste un sottoinsieme (lestremo


inferiore maggiore del superiore) in cui continuare la ricerca, con lindicazione
che 21 non presente nel vettore. Cerchiamo quindi il valore 50:
passo punto confronto prossimo fine trovato
medio corrente sottoinsieme
di ricerca
1 29 50>29 [36, 50, 55] no no
2 50 50==50 Vuoto si si
3 22 21<22 [22, 15] si no

e la ricerca termina con lindicazione che il valore 50 presente allinterno del


vettore nella posizione 5. Utilizzando la sintassi di Matlab, lalgoritmo assume la
seguente forma:
posiz=0;
trovato=0;
ei=1;
es=n;
while (!trovato & ei<es+1)
medio=floor((ei+es)/2);
if (info==v(medio))
trovato=1;
end;
if (info<v(medio))
es=medio-1;
else ei=medio+1;
end;
end;

Descrizione delle funzioni: Per la realizzazione dellalgoritmo si utilizza una sola


funzione ricercabin con le seguenti caratteristiche:
- Parametri di Input: [v, info] vettore dingresso ed informazione da
ricercare
- Parametri di Output: [msg, posiz] variabile contenete il messaggio
sullesito della ricerca e posizione dellelemento allinterno del vettore
- Variabili locali: [i,trovato,n,ei,es,medio] contatore di ciclo, variabile
binaria che indica se il confronto ha avuto successo o meno, riempimento
282 Capitolo settimo

del vettore, estremo inferiore, estremo superiore e punto medio del


sottoinsieme di ricerca
- Funzioni richiamate: length per il calcolo del riempimento del vettore

Implementazione
% FUNZIONE PER LA RICERCA BINARIA DI UN ELEMENTO IN UN VETTORE
% La funzione [msg,posiz]=ricercabin(v,info)
% permette di cercare l'elemento info nel vettore v.
% Se la ricerca ha successo viene restituita la posizione posiz
% dell'elemento nel vettore.
% msg una variabile che segnala l'esito della ricerca.
% Esempio:
% v=[1 2 8 9 5 6], info=8
% [msg,posiz]=ricercabin(v,info)
% msg= 'elemento presente', posiz=3
% Nota: la ricerca applicabile solo se il vettore d'ingresso ordinato
function [msg,posiz]=ricercabin(v,info)
% inizializza le varibili locali
% posizione dell'elemento all'interno del vettore
% (se l'elemento non viene trovato la sua posizione nulla)
posiz=0;
% variabile binaria che indica il successo del confronto
% (0 indica che l'elemento non stato ancora trovato,
% 1 il successo del confronto)
trovato=0;
% estremi superiore e inferiore dei sottoinsieme di ricerca
% (inizialmente il sottoinsime di ricerca coincide con l'intero vettore)
ei=1;
es=length(v);
% inizio ricerca
% la condizione di continuazione della ricerca che l'estremo inferiore del
% sottoinsieme corrente di ricerca sia minore di quello superiore e che lelemento
% non sia stato ancora trovato
while (!trovato & ei<es+1)
% calcolo del punto medio
medio=floor((ei+es)/2);
% se l'elmento viene trovato pone ad 1 la variabile trovato
% e arresta la ricerca
if (info==v(medio))
trovato=1;
end;
% se l'elmento non viene trovato aggiorna gli estremi del sottoinsieme di ricerca
% a seconda che l'info da ricercare sia minore o maggiore del punto medio
if (info<v(medio))
es=medio-1;
else ei=medio+1;
end;
end;
% a secona dell'esito della ricerca aggiorna la variabile msg
if (trovato==1)
msg='elemento presente';
posiz=medio;
else
msg='elemento non presente';
end;
Il linguaggio dellambiente MATLAB 283

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help ricercabin
FUNZIONE PER LA RICERCA BINARIA DI UN ELEMENTO IN UN VETTORE
La funzione [msg,posiz]=ricercabin(v,info)
permette di cercare l'elemento info nel vettore v.
Se la ricerca ha successo viene restituita la posizione posiz
dell'elemento nel vettore.
msg una variabile che segnala l'esito della ricerca.
Esempio:
v=[1 2 8 9 5 6], info=8
[msg,posiz]=ricercabin(v,info)
msg= 'elemento presente', posiz=3
Nota: la ricerca applicabile solo se il vettore d'ingresso ordinato
v=[15 22 29 36 50 55];
info=21;
[msg,posiz]=ricercabin(v,info)
msg = elemento non presente
posiz = 0
info=50;
[msg,posiz]=ricercabin(v,info)
msg = elemento presente
posiz = 5

7.3.8. Il valore massimo in un vettore


Descrizione del problema
Scrivere una funzione che determini il massimo di un vettore formato da n
elementi di un certo tipo. Esempio:
input: v=[10 55 20 11 30]
output: max=55

Descrizione dellalgoritmo
Lindividuazione del massimo in un insieme si effettua osservando uno dopo
laltro gli elementi che lo compongono e memorizzando di volta in volta il valore
pi grande. In particolare, si inizia facendo lipotesi che il massimo sia il primo
elemento del vettore e successivamente lo si confronta con i restanti valori del
vettore. Ogni volta che si incontra un valore pi grande, si effettua laggiornamento
del massimo. Facciamo ora un esempio. Sia assegnato il vettore:
v=[3 5 6 8 7]
(1 2 3 4 5)

(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore).
Allora lalgoritmo procede iterativamente nel seguente modo:

massimo posizione confronto esito aggiornamento


vettore (max<elemento confronto massimo
corrente del
vettore)
max=3 2 3<5 Vero si
284 Capitolo settimo

max=5 3 5<6 Vero si


max=6 4 6<8 vero si
max=8 5 8<7 falso no

Utilizzando la sintassi del nostro PDL, lalgoritmo assume la seguente forma:


max=v(1);
for i=2:n
if (v(i)>max)
max=v(i);
end
end

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione massimo con le
seguenti caratteristiche:
- Parametri di Input: [v] vettore dingresso
- Parametri di Output: [max] variabile contenete il massimo del vettore
- Variabili locali: [i, n] contatore di ciclo e riempimento del vettore
- Funzioni richiamate: length per il calcolo del riempimento del vettore

Implementazione
% FUNZIONE PER IL CALCOLO DEL MASSIMO DI UN VETTORE
% La funzione [max]=massimo(v)
% permette di calcolare l'elemento massimo max del vettore v.
% Esempio:
% v=[2 4 8 7 5]
% [max]=massimo(v)
% max=8
function [max]=massimo(v)
% calcolo riempimento vettore
n=length(v);
% inizializza il massimo al primo elemento del vettore
max=v(1);
% iterativamente scorre il vettore e verifica se ci sia qualche
% elemento maggiore del massimo
for i=2:n
% se l'elmento corrente maggiore del massimo aggiorna il massimo
if (v(i)>max)
max=v(i);
end
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help massimo
FUNZIONE PER IL CALCOLO DELA MASSIMO DI UN VETTORE
La funzione [max]=massimo(v)
permette di calcolare l'elemento massimo max del vettore v.
Esempio:
v=[2 4 8 7 5]
[max]=massimo(v)
Il linguaggio dellambiente MATLAB 285

max=8
v=[3 5 6 8 7];
[max]=massimo(v)
max = 8

7.3.9. La posizione del valore minimo di un vettore


Descrizione del problema
Scrivere una funzione che determini la posizione del valore minimo di un vettore
formato da n elementi di un certo tipo. Esempio:
input: v=[10 55 20 11 30]
output: posiz=1

Descrizione dellalgoritmo
Lindividuazione della posizione del minimo in un insieme si effettua osservando
uno dopo laltro gli elementi che lo compongono e memorizzando di volta in volta
la posizione dellelemento avente il valore pi piccolo. In particolare, si inizia
facendo lipotesi che la posizione del minimo sia quella del primo elemento del
vettore. Successivamente si confronta lelemento nella presunta posizione di
minimo con i restanti valori del vettore. Ogni volta che si incontra un valore pi
piccolo, si effettua laggiornamento della posizione in modo che alla fine dei
confronti si abbia la posizione del minimo. Si fa lipotesi che nel vettore non
esistano elementi uguali. Facciamo ora un esempio. Sia assegnato il vettore:
v=[9 5 6 3 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore).
Allora lalgoritmo procede iterativamente nel seguente modo:

posiz. posizione confronto esito aggiornamento


minimo vettore (min>elemento confronto posizione
corrente del minimo
vettore)
posiz=1 2 9>5 vero si
posiz=2 3 5>6 falso no
posiz=2 4 5>3 vero si
posiz=4 5 3>7 falso no

Utilizzando la sintassi di Matlab, lalgoritmo assume la seguente forma :


posiz=1;
for i=2:n
if (v(posiz)>v(i))
posiz=i;
end
end

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione posmin
con le seguenti caratteristiche:
- Parametri di Input: [v] vettore dingresso
286 Capitolo settimo

- Parametri di Output: [posiz] variabile contenete il massimo del vettore


- Variabili locali: [i, n] contatore di ciclo e riempimento del vettore
- Funzioni richiamate: length per il calcolo del riempimento del vettore

Implementazione
% FUNZIONE PER IL CALCOLO DELLA POSIZIONE DEL MINIMO DI UN VETTORE
% La funzione [posiz]=posmin(v)
% permette di calcolare la posizione dell'elemento minimo posiz del vettore v.
% Esempio:
% v=[2 4 8 7 5]
% [posiz]=posmin(v)
% posiz=1
function [posiz]=posmin(v)
% calcolo riempimento vettore
n=length(v);
% inizializza la posizione del minimo alla prima nel vettore
posiz=1;
% iterativamente scorre il vettore e verifica se ci sia qualche elemento
% minore di quello nella presunta posizione di minimo
for i=2:n
% se l'elmento corrente minore aggiorna la posizione
if (v(posiz)>v(i))
posiz=i;
end
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help posmin
FUNZIONE PER IL CALCOLO DELLA POSIZIONE DEL MINIMO DI UN VETTORE
La funzione [posiz]=posmin(v)
permette di calcolare la posizione dell'elemento minimo posiz del vettore v.
Esempio:
v=[2 4 8 7 5]
[posiz]=posmin(v)
posiz=1
v=[9 5 6 3 7];
[posiz]=posmin(v)
posiz = 4

7.3.10. Minimo e massimo in una matrice


Descrizione del problema
Scrivere una funzione che determini il valore minimo e massimo di una matrice
formata da n x m elementi di un certo tipo. Esempio:
input: A=[1 2 3 4; 8 7 6 5]
output: max=8, min=1

Descrizione dellalgoritmo
Lindividuazione del minimo e del massimo in un insieme si effettua osservando
uno dopo laltro gli elementi che lo compongono e memorizzando di volta in volta
la posizione i valori dellelemento avente il valore pi piccolo e pi grande. In
Il linguaggio dellambiente MATLAB 287

particolare, si inizia facendo lipotesi che il primo elemento della matrice sia
contemporaneamente il massimo ed il minimo e successivamente lo si confronta
con i restanti valori della matrice. Ogni volta che si incontra un valore pi piccolo
o pi grande, si effettua laggiornamento del minimo e del massimo. Utilizzando la
sintassi di Matlab, lalgoritmo assume la seguente forma :
min=A(1,1);
max=min;
for i=1:n
for j=1:m
if (A(i,j)>max)
max=A(i,j);
else
if (A(i,j)<min)
min=A(i,j);
end
end
end
end

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione minmax con le
seguenti caratteristiche:
- Parametri di Input: [A] matrice dingresso
- Parametri di Output: [min, max] variabili contenete il minimo e massimo
della matrice
- Variabili locali: [i,j,n,m] indice di riga, indice di colonna, numero di righe
e numero di colonne della matrice
- Funzioni richiamate: size per il calcolo del numero di righe di colonne
della matrice

Implementazione
% FUNZIONE PER IL CALCOLO DEL MINIMO e MASSIMO DI UNA MATRICE
% La funzione [min,max]=minmax(A)
% permette di calcolare il minimo e massimo (min e max) di una matrice A.
% Esempio: A=[1 2;3 4]
% [min,max]=minmax(A)
% min=1, max=4

function [min,max]=minmax(A)
% calcolo dimensioni matrice
[n,m]=size(A);
% inizializza il massimo e il minimo al primo elmento della matrice
min=A(1,1);
max=min;
% iterativamente scorre la matrice e verifica se ci sia qualche
% elemento minore o maggiore
% di quello minimo o massimo presunto
for i=1:n
for j=1:m
% se l'elmento corrente maggiore del massimo aggiorna il massimo
if (A(i,j)>max)
max=A(i,j);
else
288 Capitolo settimo

% se l'elmento corrente minore del minimo aggiorna il minimo


if (A(i,j)<min)
min=A(i,j);
end
end
end
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help minmax
FUNZIONE PER IL CALCOLO DEL MINIMO e MASSIMO DI UNA MATRICE
La funzione [min,max]=minmax(A)
permette di calcolare il minimo e massimo (min e max) di una matrice A.
Esempio:
A=[1 2;3 4]
[min,max]=minmax(A)
min=1, max=4

A=[1 2 3 4;8 7 6 5];


[min,max]=minmax(A)
min = 1, max = 8

7.3.11. Ordinamento di un vettore col metodo della selezione


Descrizione del problema
Scrivere una funzione per lordinamento in senso crescente di un vettore di n
elementi di un certo tipo. Esempio:
input: v=[30 10 50 12 22]
output: v=[10 12 22 30 50]

Descrizione dellalgoritmo
Ordinare un vettore in senso crescente significa imporre che scelti due qualsiasi
indici i e j, tali che i<j risulti v(i)<v(j). Un meccanismo di ordinamento consiste nel
dividere linsieme da ordinare in due parti: una ordinata ed una disordinata. Si
procede allora estraendo un elemento alla volta dallinsieme disordinato e
accodandolo a quello ordinato in modo che lordinamento non venga alterato.
Allinizio linsieme ordinato vuoto e lalgoritmo termina quando contiene tutti gli
elementi del vettore. Vi sono vari modi di estrarre lelemento dallinsieme
disordinato. Quello che di seguito presentiamo seleziona ad ogni passo lelemento
da accodare. In particolare seleziona il minimo dallinsieme disordinato e lo accoda
allinsieme ordinato. In tal modo si viene ad ogni passo a scegliere il valore pi
grandi di quelli che lo precedono e contemporaneamente pi piccolo di quelli che
lo seguono. Facciamo ora un esempio. Sia assegnato il vettore:
v=[9 2 1 4 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore).
Allora lalgoritmo procede iterativamente nel seguente modo:

Parte Parte posizione accodamento nuovo


Il linguaggio dellambiente MATLAB 289

Ordinata Disordinata minimo intervallo di


(valore ricerca del
minimo) minimo
Vuota (1 2 3 4 5) 3(1) [1] [9 2 4 7]
(1) (2 3 4 5) 2(2) [1 2] [9 4 7]
(1 2) (3 4 5) 4(4) [1 2 4] [9 7]
(1 2 3) (4 5) 5(7) [1 2 4 7] [9]
(1 2 3 4) (5) 5(9) [1 2 4 7 9] vuoto

Si noti che lalgoritmo termina quando linsieme disordinato si riduce ad un


unico elemento. Inoltre poich si usa lo stesso vettore per la parte ordinata e
disordinata, laccodamento viene effettuato scambiando di posto il minimo ed il
valore che occupa la posizione di accodamento. Utilizzando la sintassi di Matlab,
lalgoritmo assume la seguente forma :

for i=1:n-1
imin=i;
for j=i+1:n
if (v(j)<v(imin))
imin=j;
end
end
temp=v(i);
v(i)=v(imin);
v(imin)=temp;
end

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione ordina con le
seguenti caratteristiche:
- Parametri di Input: [v] vettore dingresso
- Parametri di Output: [v] vettore ordinato
- Variabili locali: [i,n,imin,temp] contatore di ciclo, riempimento del
vettore, indice del minimo corrente dellinsieme disordinato e variabile
dappoggio per effettuare lo scambio ai fini dell accodamento
- Funzioni richiamate: length per il calcolo del riempimento del vettore

Implementazione
% FUNZIONE PER L'ORDINAMENTO DI UN VETTORE
% La funzione [v]=selectsort(v)
% permette di ordinare in senso crescente il vettore v.
% Esempio: v=[4 1 3 2 5]
% [v]=selectsort(v)
% v=[1 2 3 4 5]

function [v]=selectsort(v)

% calcolo riempimento vettore


n=length(v);
% doppio ciclo per l'ordinamento
for i=1:n-1
290 Capitolo settimo

imin=i;
% determina il minimo per la parte disordinata
for j=i+1:n
if (v(j)<v(imin))
imin=j;
end
end
% effettua l'accodamento scambiando di posto l'elemento minimo e il valore
% che occupa la posizione di accodamento
temp=v(i);
v(i)=v(imin);
v(imin)=temp;
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.

help selectsort
FUNZIONE PER L'ORDINAMENTO DI UN VETTORE
La funzione [v]=selectsort(v)
permette di ordinare in senso crescente il vettore v.
Esempio:
v=[4 1 3 2 5]
[v]=selectsort(v)
v=[1 2 3 4 5]
v=[9 2 1 4 7];
[v]=selectsort(v)
v=1 2 4 7 9

7.3.12. Ordinamento di un vettore col metodo del gorgogliamento


Descrizione del problema
Scrivere una funzione per lordinamento in senso crescente di un vettore di n
elementi di un certo tipo. Esempio:
input: v=[30 10 50 12 22]
output: v=[10 12 22 30 50]

Descrizione dellalgoritmo
Ordinare un vettore in senso crescente significa imporre che scelti due qualsiasi
indici i e j, tali che i<j risulti v(i)<v(j). Un meccanismo di ordinamento consiste nel
dividere linsieme da ordinare in due parti: una ordinata ed una disordinata. Si
procede allora estraendo un elemento alla volta dallinsieme disordinato e
accodandolo a quello ordinato in modo che lordinamento non venga alterato.
Allinizio linsieme ordinato vuoto e lalgoritmo termina quando contiene tutti gli
elementi del vettore. Vi sono vari modi di estrarre lelemento dallinsieme
disordinato. Quello che di seguito presentiamo fa in modo che il minimo
dellinsieme disordinato gorgogli in prima posizione cos come una bolla daria
sale dal fondo alla superficie. In questo modo si viene ad ogni passo a scegliere il
valore pi grandi di quelli che lo precedono e contemporaneamente pi piccolo di
quelli che lo seguono. Il gorgogliamento viene eseguito confrontando a due a due
gli elementi dellinsieme disordinato ed effettuando lo scambio di posizione
Il linguaggio dellambiente MATLAB 291

quando le condizioni di ordinamento non sono rispettate. Se dopo uno scorrimento


non si eseguono scambi si deduce che il vettore ordinato e lalgoritmo pu
terminare. Facciamo ora un esempio. Sia assegnato il vettore:
v=[9 2 1 4 7]
(1 2 3 4 5)
(tra le parentesi tonde sono indicate le posizioni degli elementi nel vettore).
Allora lalgoritmo procede iterativamente nel seguente modo:
Parte Parte Confronto gorgogliamento
Ordinata Disordinata
Vuota (1 2 3 4 5) 4<7(4,5) [9 2 1 4 7]
1<4 (3,4) [9 2 1 4 7]
2>1(2,3) -> scambio [9 1 2 4 7]
9>1(1,2) -> scambio [1] [9 2 4 7]
(1) (2 3 4 5) 4<7(4,5) [1] [9 2 4 7]
2<4 (3,4) [1] [9 2 4 7]
9>2 (2,3) -> [1 2 ] [9 4 7]
scambio
(1 2) (3 4 5) 4<7(4,5) [1 2] [9 4 7]
9>4 (3,4) -> [1 2 4] [9 7]
scambio
(1 2 3) (4 5) 9>7 (4,5) -> [1 2 4 7] [9]
scambio
(1 2 3 4) (5) Nessuno [1 2 4 7 9]

Si noti che lalgoritmo termina quando linsieme disordinato si riduce ad un


unico elemento. Inoltre se si applica lalgoritmo ad un vettore gi ordinato si ha
che non vengono effettuati scambi e quindi questa condizione pu essere utile per
arrestare lalgoritmo stesso. Utilizzando la sintassi di Matlab, lalgoritmo assume la
seguente forma:

scambio=1;
i=1;
while (i<n & scambio==1)
scambio=0;
for j=i+1:n
if (v(j)<v(i))
temp=v(i);
v(i)=v(j);
v(j)=temp;
scambio=1;
end
end
i=i+1;
end

Descrizione delle funzioni


Per la realizzazione dellalgoritmo si utilizza una sola funzione ordina con le
seguenti caratteristiche:
- Parametri di Input: [v] vettore dingresso
- Parametri di Output: [v] vettore ordinato
292 Capitolo settimo

- Variabili locali: [i,n,scambio,temp] contatore di ciclo, riempimento del


vettore, variabile binaria che indica se avvenuto qualche scambio
nelliterazione corrente e variabile dappoggio per effettuare lo scambio ai
fini dellaccodamento nellinsieme ordinato
- Funzioni richiamate: length per il calcolo del riempimento del vettore

Implementazione
% FUNZIONE PER L'ORDINAMENTO DI UN VETTORE
% La funzione [v]=bubblesort(v)
% permette di ordinare in senso crescente il vettore v.
% Esempio:
% v=[4 1 3 2 5]
% [v]=bubblesort(v)
% v=[1 2 3 4 5]
function [v]=bubblesort(v)
% variabili locali
% calcolo del riempimento
n=length(v);
% variabile locale che segnala se nell'iterazione corrente ci sono stati scambi
scambio=1;
% contatore di ciclo
i=1;
% ciclo di ordinamento
while (i<n & scambio==1)
scambio=0;
for j=i+1:n
% spostamento del valore minimo verso la parte ordinata
if (v(j)<v(i))
temp=v(i);
v(i)=v(j);
v(j)=temp;
scambio=1;
end
end
i=i+1;
end

Esempio duso
Si riporta un esempio duso del programma mediante la shell (interprete dei
comandi) dellambiente MATLAB.
help bubblesort
FUNZIONE PER L'ORDINAMENTO DI UN VETTORE
La funzione [v]=bubblesort(v)
permette di ordinare in senso crescente il vettore v.
Esempio:
v=[4 1 3 2 5]
[v]=bubblesort(v)
v=[1 2 3 4 5]
v=[9 2 1 4 7];
[v]=bubblesort(v)
v=1 2 4 7 9
Il linguaggio dellambiente MATLAB 293

7.4. Esercizi completi


Si vogliono ora di seguito mostrare ulteriori esempi di progetti di programmi
realizzati in Matlab. Per semplicit si riporta per ogni esercizio la sola descrizione
del problema e limplementazione del programma risolutivo.
Esercizio 1
Dato un vettore di numeri reali scrivere una funzione che:
1. Determini la somma degli elementi del vettore.
2. Determini la media degli elementi del vettore.
3. Determini il minimo degli elementi del vettore.
4. Determini il massimo degli elementi del vettore.
function [somma,media,minimo,massimo]=esercizio1(v)
n=length(v);
somma=v(1);
massimo=somma;
minimo=somma;
for i=2:n
if (v(i)<minimo)
minimo=v(i);
end
if (v(i)>massimo)
massimo=v(i);
end
somma=somma+v(i);
end
media=somma/n;

Esercizio 2
Data una matrice di numeri reali scrivere una funzione che:
1. Memorizzi, nel caso la matrice sia quadrata, in un vettore di uscita gli
elementi della diagonale.
2. Calcoli, nel caso di matrice quadrata, la media degli elementi della
diagonale.
3. Segnali errore nel caso in cui la matrice sia non quadrata.
function [msg,media]=esercizio2(A)
[n,m]=size(A);
if (n==m)
media=0;
for i=1:n
media=media+A(i,i);
end
media=media/n;
msg='';
else
msg='error: matrix must be square';
media='NaN';
end
294 Capitolo settimo

Esercizio 3
Dato un vettore di numeri reali ordinato e due suoi elementi a e b, tali che a<=b,
scrivere una funzione che memorizzi in un vettore di uscita tutti gli elementi del
vettore di in ingresso compresi tra a e b. Esempio.: v_in=[1,3,6,8,70,555], a=6,
b=70, v_out=[70].
function [vout]=esercizio3(vin,a,b)
n=length(vin);
if (a<b)
indice1=1;
indice2=1;
for i=1:n
if (vin(i)==a)
indice1=i;
break;
end
end
for j=1:n
if (vin(j)==b)
indice2=j;
break;
end
end
vout=vin(indice1+1:1:indice2-1);
else
vout='NaN';
end

Esercizio 4
Dato un vettore di caratteri (stringa) scrivere una funzione che:
1. Memorizzi in un vettore di uscita la stringa dingresso invertita.
2. Calcoli il tipo di lettera (a,b,c,d,e,f,) e il numero di caratteri presenti
nella stringa dingresso.
Esempio: v_in=hello, v_out=olleh, ris=a 0, b 0,,e 1, , h 1,, l 2, , o 1,
, z 0
function [vout]=esercizio4(vin)
n=length(vin);
alfabeto=['a','b','c','d','e','f','g','h','i','l','m','n','o','p','q','r','s','t','u','v','z'];
for i=1:n
vout(n+1-i)=vin(i);
end
% la funzione zeros crea 1 array di interi della stessa dimensione del vettore
% alfabeto ed inizializzati a 0
cont=zeros(1,length(alfabeto));
for i=1:n
for j=1:length(alfabeto)
if (vin(i)==alfabeto(j))
cont(j)=cont(j)+1;
break;
end
end
end
for i=1:length(alfabeto)
Il linguaggio dellambiente MATLAB 295

fprintf('%c ',alfabeto(i));
fprintf('%d\n',cont(i));
end

Esercizio 5
Dato un vettore di numeri reali scrivere una funzione che:
1. Effettui lo shift (spostamento) a destra con linserimento di uno zero in
testa degli elementi del vettore di ingresso (in questo caso si perde
lelemento di coda). Esempio.: v_in=[1,2,3,4], v_out=[0,1,2,3]
2. Effettui lo shift (spostamento) circolare a destra con linserimento
dellelemento di coda in testa. Esempio.: v_in=[1,2,3,4], v_out=[4,1,2,3]
function [v_out1, v_out2]=esercizio5(v_in)
n=length(v_in);
for i=2:n
v_out1(i)=v_in(i-1);
v_out2(i)=v_in(i-1);
end;
v_out1(1)=0;
v_out2(1)=v_in(n);

Esercizio 6
Dato un vettore di numeri reali scrivere una funzione che:
1. Effettui lo shift (spostamento) a sinistra con linserimento di uno zero in
coda degli elementi del vettore di ingresso (in questo caso si perde
lelemento di testa). Esempio.: v_in=[1,2,3,4], v_out=[2,3,4,0]
2. Effettui lo shift (spostamento) circolare a sinistra con linserimento
dellelemento di testa in coda. Esempio.: v_in=[1,2,3,4], v_out=[2,3,4,1]
function [v_out1, v_out2]=esercizio6(v_in)
n=length(v_in);
for i=1:n-1
v_out1(i)=v_in(i+1);
v_out2(i)=v_in(i+1);
end;
v_out1(n)=0;
v_out2(n)=v_in(1);

Esercizio 7
Dato un vettore di numeri interi scrivere una funzione che:
1. Memorizzi in primo vettore di uscita solo i numeri pari.
2. Memorizzi in un secondo vettore di uscita solo i numeri dispari.
Esempio.: v_in=[1 2 33 11 8], v_out1=[2 8], vout2=[1 33 11]
function [pari,dispari]=esercizio7(v)
n=length(v);
indice_pari=1;
indice_dispari=1;
for i=1:n
% la funzione mod(x,y) restituisce il resto in modulo della divisione di x per y
if mod(v(i),2)==0
296 Capitolo settimo

pari(indice_pari)=v(i);
indice_pari=indice_pari+1;
else
dispari(indice_dispari)=v(i);
indice_dispari=indice_dispari+1;
end
end

Esercizio 8
Dato una matrice di numeri reali scrivere una funzione che:
1. Memorizzi in un primo vettore di uscita, una dietro laltra, le righe pari.
2. Memorizzi in un secondo vettore di uscita, una dietro laltra, le righe
dispari.
Es.: A=[1 2 3;4 5 6;7 8 9], v1=[4 5 6], v2=[1 2 3 7 8 9]
function [v1,v2]=esercizio8(A)
[n,m]=size(A);
i1=1;
i2=1;
for i=1:n
if mod(i,2)==0
for j=1:m
v1(i1)=A(i,j);
i1=i1+1;
end
else
for j=1:m
v2(i2)=A(i,j);
i2=i2+1;
end
end
end
Il linguaggio dellambiente MATLAB 297

Esercizio 9
Sia assegnato un vettore di numeri reali su un file di ingresso, scrivere una
funzione che:
1. Legga e memorizzi in un vettore gli elementi dal file dingresso.
2. Effettui lordinamento del vettore utilizzando una funzione esterna.
3. Scriva su un file duscita il vettore ordinato.
In questo caso si utilizzano due funzioni, una per lordinamento e una per
linput/output da file.
function [v]=selectsort(v)
n=length(v);
for i=1:n-1
imin=i;
for j=i+1:n
if (v(j)<v(imin))
imin=j;
end
end
temp=v(i);
v(i)=v(imin);
v(imin)=temp;
end

function esercizio9(pathin,pathout)
fid1=fopen(pathin,'r');
v=fscanf(fid1,'%g');
v=selectsort(v);
fclose(fid1);
fid2=fopen(pathout,'w');
fprintf(fid2,'%g ',v);
fclose(fid2);
Nota: per lordinamento si usata la funzione selectsort vista in precedenza.
Esercizio 10
Sia assegnato un vettore sparso (contente molti elementi nulli) di numeri reali su
un file di ingresso, scrivere una funzione che:
1. Legga e memorizzi su un vettore gli elementi da file dingresso.
2. A partire dal vettore ottenuto costruisca un vettore di uscita avente come
elementi solo quelli non nulli (split).

function [vout]=esercizio10(pathin)
fid1=fopen(pathin,'r');
v=fscanf(fid1,'%g');
n=length(v);
j=1;
for i=1:n
if v(i)~=0
vout(j)=v(i);
j=j+1;
end
end
298 Capitolo settimo

Esercizio 11
Scrivere un programma per il calcolo della media degli esami sostenuti e del voto
maggiore.In questo caso si utilizzano tre funzioni, una per il calcolo del massimo
di un vettore, una per il calcolo della media e una per la gestione dellinput/output.

function [max]=massimo_esami(v_input)
max=v_input(1);
n=length (v_input);
for i=2:n
if (max<v_input(i))
max=v_input(i);
end
end
function [media]=media_esami(v_input)
n=length(v_input);
media=0;
for i=1:n
media=media+v_input(i);
end
media=media/n;

function esercizio11
fprintf('\nProgramma per la creazione di statistche sugli esami sostenuti\n');
fprintf('\nSezione per la raccolta dei dati anagrafici\n');
nome=input('Inserire nome:','s');
cognome=input('Inserire cognome:','s');
matr=input('Inserire matricola:','s');
fprintf('\nSezione per la raccolta dei dati relativi agli esami sostenuti\n');
num_esami=input('Inserire numero di esami sostenuti:');
for i=1:num_esami
fprintf('Inserire votazione relativa esame ');
fprintf('%d',i);
voto_esami(i)=input(':');
end
media=media_esami(voto_esami);
voto_massimo=massimo_esami(voto_esami);
fprintf('\nSezione relativa alle statistiche calcolate\n');
fprintf('\nLa media dei tuoi esami : ');
fprintf('%d',media);
fprintf('\nLa tua votazione migliore : ');
fprintf('%d',voto_massimo);
Capitolo ottavo

La traduzione dei programmi

8.1. Introduzione
La realizzazione di un programma un'attivit complessa che va dalla scelta di un
algoritmo alla sua implementazione in un linguaggio di programmazione. Per il
programmatore il linguaggio di programmazione si configura come una macchina
virtuale che analizza il testo del programma e lo rende eseguibile secondo delle
regole fissate dal linguaggio stesso.
In realt, la traduzione del testo del programma - detto anche testo sorgente o
origine - in operazioni eseguibili sulla macchina reale, avviene secondo due
modalit diverse:
- mediante una preventiva traduzione del testo origine nel linguaggio della
macchina reale e successiva esecuzione del programma tradotto in
linguaggio macchina;
- od attraverso una contestuale interpretazione del testo origine e sua
esecuzione.
In generale un traduttore trasforma un testo espresso in un certo linguaggio A
in quello di un linguaggio B, detto oggetto o target: A un linguaggio simbolico, B
un linguaggio prossimo a quello della macchina, ma non necessariamente
coincidente con esso. Tradizionalmente, bench nei vari casi il processo di
traduzione sia concettualmente lo stesso, i traduttori assumono nomi diversi
secondo il tipo di linguaggio sorgente e del linguaggio oggetto. In particolare, si
distinguono i seguenti traduttori.
- i compilatori che sono i traduttori pi diffusi e utilizzati. Il linguaggio
sorgente un linguaggio ad alto livello (ad esempio C, C++, Pascal,
FORTRAN ), mentre il linguaggio oggetto un linguaggio prossimo a
quello macchina.
- i pre-compilatori che traducono da linguaggio sorgente a linguaggio
sorgente permettendo di estendere a basso costo le caratteristiche di un
linguaggio esistente per il quale sia disponibile un traduttore. In tal caso, il
processo di traduzione avviene in due fasi distinte: una prima traduzione,
ad opera del pre-compilatore, in un linguaggio sorgente in cui i costrutti
estesi sono ricondotti a sequenze elementari, e una seconda fase di
traduzione, ad opera del compilatore, di questa forma espansa in
linguaggio oggetto.
300 Capitolo ottavo

- gli assemblatori o assembler, che, invece, permettono di effettuare una


traduzione da un linguaggio assemblativo simbolico al linguaggio
macchina.

8.2. Il processo di traduzione


Un programma, dal momento in cui ideato al momento in cui pu essere
eseguito, deve subire un insieme di trasformazioni, come mostrato in figura 1.

Figura 1: Dalla scrittura del programma sorgente allesecuzione

A ciascuna trasformazione corrisponde una certa applicazione che la effettua.


Lapplicazione che permette di editare il testo di un programma, di visionarlo ed
eventualmente di modificarlo detto editor. Un editor offre un insieme di
funzionalit per aiutare lutente nelle scrittura del testo sorgente. In particolare, un
editor deve in ogni modo garantire linserimento, la cancellazione, la visione, la
ricerca e la modifica di parti del testo. Il testo sorgente prodotto dalleditor
memorizzato in forma permanente (ad esempio su un disco).
Il compilatore di contro, come gi visto, lapplicazione che permette la
traduzione da linguaggio sorgente a linguaggio oggetto. Il processo di
compilazione produce un file oggetto. Il compilatore tuttavia non in grado di
mettere assieme le diverse componenti di un programma. Si osservi, ad esempio, il
semplice programma C che stampa a video il messaggio Salve mondo.

#include <stdio.h>
main()
{
printf(salve, mondo \n);
}

Il prototipo della funzione printf definita nel file header stdio.h, che una
delle librerie messe a disposizione dal linguaggio per svincolare il programmatore
dalla conoscenza dellinsieme di operazioni, sicuramente non banali, per la
scrittura di una stringa su video.
Quando il compilatore incontra il nome della funzione printf, si limita a
prevedere per essa un richiamo, senza per essere in grado di stabilire dove dovr
La traduzione dei programmi 301

essere trasferito il controllo durante lesecuzione. Un compilatore non quindi in


grado di risolvere:
- laggregazione di componenti software scritti in momenti diversi da
persone diverse ed eventualmente in linguaggi diversi;
- il collegamento tra la definizione di una procedura/funzione di libreria e il
suo richiamo.
Tali funzionalit vengono assolte da una applicazione da attivare
successivamente alla fase di compilazione, detta linker o collegatore. Il linker
riceve in ingresso un programma oggetto, un insieme di comandi che gli indicano
come deve procedere e i riferimenti alle librerie da cui estrarre moduli software che
devono essere collegati per produrre un unico programma eseguibile.
Solo a valle dellintervento del clinker il programma finalmente pronto per
lesecuzione e viene detto eseguibile. Per essere eseguito deve per essere caricato
in memoria centrale. Tale operazione affidata ad unaltra applicazione detta
caricatore o loader che legge da disco limmagine di memoria del programma,
decide dove posizionarlo in memoria e infine gli trasferisce il controllo.
8.2.1. La compilazione
Il processo di traduzione tanto pi complesso quanto pi il linguaggio da
tradurre vicino al linguaggio naturale. Peraltro, la possibilit di esprimere
lalgoritmo in un linguaggio vicino al linguaggio naturale piuttosto che a quello
della macchina, facilita il compito del programmatore: ed questo il motivo per il
quale i linguaggi di alto livello hanno raggiunto una grande diffusione. Ma quanto
pi il linguaggio ad alto livello si avvicina a quello naturale tanto pi si allontana
dal linguaggio macchina, facendo aumentare il gap semantico tra il programma
sorgente e quello oggetto. Il compito di colmare tale gap affidato al compilatore
che nel tempo ha sempre pi assunto un ruolo centrale nello sviluppo dei
programmi.
Il processo di compilazione evolve attraverso una sequenza di fasi di solito
classificate in fasi di analisi e di sintesi. Le fasi di analisi sono rivolte ad analizzare
il testo del programma in base alle regole del linguaggio definite dalla grammatica,
mentre la fase di sintesi produce il codice oggetto sulla base delle informazioni
raccolte durante la fase di analisi, nel caso in cui il programma corretto
grammaticalmente.
Nel dettaglio, lo scopo della fase di analisi :
- riconoscere le frasi appartenenti al linguaggio e interpretarne il
significato; e nel caso in cui il riconoscimento fallisca, rilevare gli errori
ossia le violazioni delle regole grammaticali;
- costruire un insieme di informazioni sulle variabili e sulle procedure
usate, sui tipi definiti dallutente e sullo spazio necessario per contenere i
dati.
Per comprendere il funzionamento della fase di analisi occorre richiamare gli
aspetti costitutivi ed essenziali di un linguaggio. Elemento fondamentale di ogni
linguaggio lalfabeto. Lalfabeto definito come un insieme di simboli che
chiameremo caratteri. Laggregazione dei caratteri dellalfabeto permette di
costruire le parole. Le parole possono essere a loro volta aggregate in frasi del
linguaggio. Naturalmente, non tutte le aggregazioni dei caratteri dellalfabeto
permettono di costruire parole valide, e non tutte le aggregazioni di parole
302 Capitolo ottavo

permettono di costruire frasi corrette, ed infine non tutte le frasi corrette hanno un
significato valido.
Le regole di costruzione delle parole a partire dallalfabeto sono dette regole
lessicali. Il modo con cui le parole sono concatenate tra loro per costruire frasi
corrette nel linguaggio costituisce la sintassi del linguaggio, mentre il significato
da attribuire alla frase riguarda la semantica del linguaggio. Linsieme delle regole
lessicali e sintattiche costituisce la grammatica del linguaggio. Le regole della
grammatica di un linguaggio vengono illustrate attraverso opportuni
metalinguaggi, come la BNF (Backus Naur Form) o le carte sintattiche.
La figura 2 mostra come le regole della grammatica del linguaggio
condizionano le fasi in cui si articola il processo di traduzione.

Analisi
Analisi Lessicale

Costruzione di Analisi Sintattica Gestione degli


tabelle interne errori

Analisi Semantica

Figura 2 - La fase di analisi del compilatore

La prima fase costituita dallanalisi lessicale o scanning. Lo scanning


dapprima verifica le regole di costruzione delle parole, estraendo i cosiddetti token
(parole chiave, identificatori, costanti, operatori, etc.). Ai token vengono anche
associate delle informazioni. Successivamente trasforma il testo sorgente in una
sequenza di token. Ad esempio per listruzione:

x=100;

vengono riconosciuti come validi i tre token (x, =, 100). Mentre ai token
corrispondenti ai simboli chiave del linguaggio non viene aggiunta altro che la loro
classificazione, per quanto attiene x e 100, si aggiungono informazioni quali il
fatto che 100 una costante intera e x un identificatore associato ad un tipo, che
tale identificatore ha una certa visibilit associata al luogo in cui la variabile stata
dichiarata. Lo scanning, infine, costruisce una rappresentazione dellistruzione del
tipo: identificatore, operatore di assegnamento, costante, punto e virgola.
Linsieme delle informazioni ricavate dallo scanning, saranno utili per la fase
di sintesi del codice e verranno perci conservate in apposite tabelle gestite dal
compilatore. Le tabelle sono generate durante la fase di scanning, ma vengono
arricchite anche nel corso della fase di analisi.
La fase successiva a quella di scanning la fase di analisi sintattica o parsing.
Lanalizzatore sintattico, o parser, raggruppa i token in strutture sintattiche
La traduzione dei programmi 303

rappresentate graficamente dagli alberi sintattici. Questi ultimi sono alberi i cui
nodi sono gli operatori del linguaggio e le foglie gli operandi. Ad esempio
listruzione:
x = (a + b) * c

rappresentabile dal seguente albero sintattico:

= *
x
c
+

a b
viene trasformata dal parser in una forma pi generale indipendente dalla
specifica frase utilizzando la descrizione dei token con le annesse informazioni
estratte e collocate nelle tabelle interne, ottenendo lalbero di seguito.

= *
identificator
+ identificator

identificator identificator

La rappresentazione in alberi sintattici consente di avere la classificazione


delle singole frasi che compongono il testo del programma nella radice dellalbero
che le rappresenta.
Lo scopo dellanalizzatore semantico quello di stabilire se una frase ha
qualche significato ed, in caso affermativo, capire quale. Questa affermazione nel
caso dei linguaggi di programmazione ha implicazioni molto precise perch non
tutte le violazioni delle regole semantiche possono essere gestite dal compilatore.
A titolo di esempio, costituiscono violazioni semantiche a tempo di compilazione
(o compilation time), le operazioni tra operandi di tipo non compatibile (esempio: a
= b, con a di tipo carattere e b di tipo reale), operandi illegali per il tipo di oggetti a
cui sono applicati, luso di oggetti non dichiarati, il richiamo di funzioni con un
numero di parametri diverso da quello della dichiarazione. Molte altre violazioni
semantiche si verificano solo durante lesecuzione del programma tradotto. Ad
esempio sono violazioni semantiche a tempo di esecuzione (o run time) i tentativi
di accesso a file non aperti in precedenza, violazioni degli intervalli di definizione
per gli indici dellarray, tentativi di accedere oltre la fine di un file, accessi a
variabili dinamiche attraverso puntatori non validi e cos via.
Le informazioni estratte nella fase di analisi vengono conservate per poter poi
procedere alla sintesi del codice. In particolare per quanto riguarda le variabili
304 Capitolo ottavo

dichiarate nel testo di un programma, necessario associare ad esse il nome e il


tipo per riservare lo spazio destinato a contenerne il valore durante lesecuzione,
lindirizzo di memoria in cui collocare il valore e le modalit di accesso (scope),
che saranno diverse a seconda che si tratti di una variabile globale, locale, di un
parametro o di una funzione. Informazioni che vengono strutturate in una tabella
dei simboli a cui si accede mediante il nome dellidentificatore.
Identificatore Classificazione Tipo Occupazione Scope Indirizzo
100 costante intero 1 byte locale
X variabile reale 4 byte locale
A variabile reale 4 byte globale
B variabile intero 2 byte locale
C variabile intero 2 byte locale
Tabella 1 Tabella dei simboli

Solo dopo aver terminato la fase di analisi senza aver rilevato errori il
compilatore pu avviare la fase di sintesi con la generazione del codice in
linguaggio macchina effettivamente eseguibile da una macchina reale. Sono
disponibili gli alberi sintattici con la classificazione delle diverse componenti del
programma e le informazioni riportate nella tabella dei simboli.
Lapproccio pi semplice della fase di sintesi quello di scandire i diversi
alberi e le tabelle e di procedere con una generazione delle singole istruzioni in
linguaggio macchina senza tener conto di possibili ottimizzazioni legate alla
struttura del calcolatore . Ad esempio, dato il blocco:

x = a+b ;
y = a+b ;

il codice prodotto nella macchina in tale situazione diventa:


ADD a,b
STORE x
ADD a,b
STORE y

che inaccettabile dal punto di vista dellefficienza. Si noti infatti che il risultato
della prima somma (uguale alla seconda) permane nellaccumulatore senza essere
modificato dalla operazione di store in x.
Situazione che il compilatore scopre anche analizzando i due alberi sintattici
rappresentativi delle due istruzioni di assegnazione. In tale caso il compilatore
procede alla ottimizzazione del codice eliminando la seconda ed inutile operazione
di ADD come il codice che segue dimostra.
ADD a,b
STOREA x
STOREA y

che corrisponde allassegnamento multiplo:

x = y =a + b;
La traduzione dei programmi 305

del tutto equivalente, dal punto di vista semantico, al testo originale.


Il generatore di codice deve quindi in generale non solo rispettare la semantica
del testo originale, ma anche gestire efficientemente le risorse della macchina
reale per ottenere un programma con prestazioni ottimali. Ridurre la quantit di
codice garantendo le stesse funzionalit comporta lesecuzione di un numero
minore di istruzioni con una riduzione dei tempi complessivi. Di solito, alla
ottimizzazione del codice si accompagna anche una riduzione delloccupazione in
memoria, come lesempio precedente dimostra. Si potrebbe operare anche
lottimizzazione delloccupazione di memoria da parte delle strutture dati. Ma a
differenza del codice, lottimizzazione dellarea dati potrebbe provocare un
aumento dei tempi di accesso alle strutture stesse, rendendo i due obiettivi
(riduzione di spazio di memoria e velocit di esecuzione) conflittuali tra di loro. La
complessit della fase terminale di un compilatore risiede pertanto nellindividuare
il compromesso ottimale nel rapporto spazio/velocit. La qualit di un compilatore
risiede pertanto nella sua capacit di produrre un codice ottimizzato.
Per ottenere lottimizzazione del codice, i compilatori di solito operano in due
passi: in una prima fase si genera un codice intermedio, non orientato ad alcuna
macchina reale. Si genera, cio, del codice di livello molto basso, ma ancora
largamente indipendente dalla CPU per la quale verr generato il codice finale.
Tale tipo di codice, in genere, ignora lesistenza dei registri di macchina, la loro
natura, il loro numero e le reali modalit di indirizzamento della memoria. In una
seconda fase, il codice intermedio viene tradotto nel codice macchina ottimizzato
per un determinato processore. La forma intermedia prodotta, infatti, ha in genere
delle caratteristiche che permettono di effettuare le ottimizzazioni necessarie.
8.2.2. Il collegamento
Un programma pu essere composto da un numero arbitrario di unit di
compilazione, eventualmente provenienti da linguaggi sorgente diversi. Il
collegamento si rende quindi necessario per aggregare tutte le componenti e
costruire ununica unit eseguibile.
Il ruolo del linker centrale in ambienti di sviluppo software di grandi dimensioni quale
quello prodotto in ambiente industriale, dove i progetti raggiungono dimensioni di diversi
anni uomo. In questi casi il progetto pu essere completato in tempi pi rapidi solo con la
suddivisione delle attivit da svolgere in un certo numero di gruppi di progetto,
provvedendo in una fase successiva alla integrazione dei diversi moduli oggetto attraverso
il loro collegamento.
Il Linker o Collegatore fonde gli spazi di indirizzi separati dei moduli oggetto in una
unica dimensione lineare. Per aggregare in un unico file eseguibile le diverse unit di
compilazione prodotte, occorre che il compilatore generi delle informazioni opportune nel
modulo oggetto, come, ad esempio, quelle mostrata in figura 3.
Identificazione
Tabella dei Simboli Esportati
Tabella dei Simboli Importati
Istruzioni macchina
Dizionario di rilocazione
Fine modulo
Figura 3 - Un esempio di modulo oggetto
306 Capitolo ottavo

La prima parte del modulo oggetto contiene il nome del modulo, pi altre
informazioni necessarie al linker come le lunghezze delle varie strutture dati del
modulo ed eventualmente la data di compilazione. La seconda parte del modulo
oggetto una lista di simboli interni al modulo a cui possono far riferimento altri
moduli (simboli esportati). La terza parte contiene una lista di simboli usati nel
modulo, ma definiti in altri moduli (simboli importati). La quarta parte del modulo
contiene il codice compilato e le costanti: cio la parte che verr caricata in
memoria per essere eseguita. La quinta parte il dizionario di rilocazione dove
vengono forniti gli indirizzi base e le costanti di spiazzamento relative. La sesta ed
ultima parte contiene una indicazione di fine modulo, a volte un controllo per
rilevare eventuali errori di lettura del modulo e lindirizzo da cui iniziare
lesecuzione.
Molti linker richiedono due passi. Nel primo passo il linker legge tutti i
moduli oggetto e costruisce una tabella dei nomi e delle lunghezze dei moduli oltre
ad una tabella dei simboli globali costituita dai riferimenti esterni. Nel passo due i
moduli oggetto vengono scanditi di nuovo, si calcolano i nuovi indirizzi di
memoria (rilocazione) e si collegano. Pi nel dettaglio, lalgoritmo del linker si
compone dei seguenti passi.
- Costruzione di una tabella con tutti i moduli oggetto con indicazione della
loro dimensione.
- Assegnazione di un indirizzo di caricamento ad ogni modulo riportato in
tabella.
- completamento delle istruzioni che contengono un indirizzo di memoria
con la definizione delleffettivo indirizzo di memoria. Per agevolare tale
lavoro il compilatore non fissa allinterno dei singoli moduli degli
indirizzi definitivi, ma assume che lallocazione in memoria per ogni
modulo compilato avvenga a partire dallindirizzo zero. Cos lindirizzo
fissato dal collegatore, detto anche costante di rilocazione, uguale al
primo indirizzo occupato dal modulo, deve essere sommato a tutti gli
indirizzi presenti nelle istruzioni perch si completi il piano effettivo di
allocazione in memoria.
- Risoluzione dei richiami di dati e procedure esterne ad un modulo. Il
compilatore infatti, in presenza di richiami a moduli esterni non completa
la traduzione perch non pu conoscere dove tali moduli verranno
allocati. Solo il collegatore, che provvede alla disposizione in memoria di
tutti i moduli aggregare, pu quindi il completare la definizione degli
indirizzi nel caso di istruzioni che fanno riferimento ad identificatori non
locali, quali ad esempio i richiami di sottoprogrammi e funzioni.

In figura seguente viene mostrato il linking di tre moduli oggetto A,B,C (nella
figura con JSR si indica il salto a sottoprogramma e con RTS il ritorno al
programma chiamante).
La traduzione dei programmi 307

-- INIZIO MODULO A -- INIZIO PROGRAMMA


-- ESEGUIBILE MAIN
110 JSR B 110 JSR B
111 111
. .
299 END 299 END
-- FINE MODULO A -- FINE PROGRAMMA
-- ESEGUIBILE MAIN

-- INIZIO SUBROUTINE B -- INIZIO SUBROUTINE B


300

200 JSR C
201 500 JSR C
. 501
400 RTS .
-- FINE SUBROUTINE B 700 RTS
-- FINE SUBROUTINE B
-- INIZIO SUBROUTINE C
-- INIZIO SUBROUTINE C
701
200 RTS
-- FINE SUBROUTINE C
.
901 RTS
-- FINE SUBROUTINE C

Figura 4 - Linking di tre moduli A, B, C.

La tabella costruita nel passo 1 mostrata nella tabella 2.

Nome Etichetta Lunghezza Valore


A 300 0
B 401 300
C 201 701
Tabella 2 - Tabella dei moduli oggetto

8.2.3. Il caricamento
Il caricatore ha il compito di disporre nei registri di memoria sia il codice che i dati
del programma da eseguire e di provvedere alla sua attivazione.
Quando i calcolatori erano utilizzati da un solo utente per volta, il problema
del caricamento e dellattivazione di un programma era di facile soluzione: i
programmi erano tradotti in una forma oggetto detta binario assoluto, una forma
che era limmagine esatta del programma da eseguire. In essa tutti i riferimenti
interni e gli indirizzi di caricamento erano definiti dai traduttori e dal linker. Per
poter essere eseguito, il codice binario assoluto deve essere caricato nelle posizioni
esatte per cui stato definito: loperazione di caricamento si riduce quindi alla
308 Capitolo ottavo

scrittura in memoria, ad un indirizzo prefissato, del file eseguibile, mentre


lesecuzione ha inizio caricando il registro contatore di programma PC con
lindirizzo della prima istruzione eseguibile.
Tuttavia, con lavvento della multiprogrammazione, questo tipo di
caricamento ha perso di significato: non possibile, infatti, prevedere a priori da
parte del linker lesatta porzione di memoria libera per il caricamento.
necessario, quindi, ricorrere ad una forma di rappresentazione dei programmi pi
flessibile. Una via percorsa quella del codice binario rilocabile. Anche in questo
caso tutti i riferimenti a codice e dati sono fatti dai traduttori e dal linker; tuttavia
non si tratta di indirizzi assoluti, cio indirizzi che corrispondono uno a uno con gli
indirizzi della memoria fisica, ma di indirizzi relativi ad unorigine con indirizzo
zero. In fase di caricamento il caricatore pu rilocare gli indirizzi spiazzandoli di
una certa quantit rispetto allorigine: ad ogni indirizzo verr sommato, a opera del
caricatore, un certo valore iniziale, detto base di rilocazione.

-- INIZIO PROGRAMMA

100
101 JSR 200
102
..
300 END
-- FINE PROGAMMA

base di rilocazione B=1000

-- INIZIO PROGRAMMA
1000

1100
1101 JSR 1200
1102
..
1300 END
-- FINE PROGAMMA
Figura 5: Rilocazione di un codice con base di rilocazione B=1000

Una tecnica interessante che in questa sede viene solamente accennata


quella che usata dai caricatori a classi di rilocazione. In questo caso, si fa uso di
cosiddette marche di rilocazione - ovvero di informazioni ausiliarie prodotte dal
linker attraverso le quali possibile marcare esplicitamente le istruzioni che
possono essere modificate per potere allocare segmenti diversi di codice non
contiguamente ma in zone di memoria differenti, accessibili mediante diverse basi
di rilocazione. Cos facendo simpone una condizione meno restrittiva al
caricamento del programma, potendo usare frammenti liberi non contigui di
memoria e ottimizzando lo sfruttamento della stessa.
8.2.4. Gli interpreti
Un linguaggio interpretato differisce in maniera sostanziale da uno compilato.
Un interprete essenzialmente un esecutore che definisce una macchina astratta
La traduzione dei programmi 309

attraverso il linguaggio che riconosce: con il meccanismo dellinterpretazione il


linguaggio sorgente di alto livello assume il ruolo di linguaggio macchina del
sistema virtuale fatto dalla macchina effettiva che esegue linterprete stesso.

Figura 6- Un interprete esegue un programma


scritto in un linguaggio ad alto livello

I vantaggi degli interpreti rispetto ai traduttori sono la loro indipendenza dalla


macchina reale e dal sistema operativo che li ospitano. Un interprete, infatti,
costituisce un sistema chiuso: esso esegue un certo codice e non deve generare
alcun eseguibile per una macchina reale. Non esistendo vincoli imposti dalla
macchina reale, il modello di macchina astratta pu cos essere liberato da tutti i
dettagli che caratterizzano un processore ed il sistema operativo che gira su di esso.
Uno stesso programma, allora, pu essere eseguito su macchine diverse: per questo
quasi tutti i programmi che girano su reti di computer eterogenee - come internet -
sono scritti in Java, che un linguaggio interpretato.
Lo svantaggio di un programma scritto in un linguaggio interpretato che
esso pi lento rispetto ai programmi compilati, in quanto il calcolatore esegue
sempre il programma interprete che a sua volte esegue il programma utente, con
evidente spreco di memoria e di risorse. In altri termini, mentre nel caso della
compilazione i tempi di compilazione e di esecuzione sono separati, nel caso
dellinterprete gli stessi tempi si sommano. Ogni volta che un programma
interpretato viene eseguito, esso viene anche tradotto. Nel caso della compilazione
ci non accade.

8.3. La verifica della correttezza dei programmi


Lo sviluppo del software una attivit complessa, e come tale soggetta ad
errori derivanti sia da una analisi inesatta da una implementare non corretta dei
requisiti richiesti al programma. I primi sono estremamente dannosi, in quanto si
ripercuotono su tutte le successive fasi (di progettazione e di implementazione)
310 Capitolo ottavo

sino a quando non emergono dallincapacit del sistema a fare quanto richiesto. I
secondi vengono introdotti durante la progettazione o la codifica e diverse possono
esserne la causa: scarsa conoscenza del linguaggio, assunzioni non verificate,
complessit del progetto, e molte volte semplice distrazione.
Le attivit di testing rivestono un ruolo importante nello sviluppo del software
in quanto provvedono a verificare la correttezza dei programmi. importante
sottolineare che la rilevazione degli errori deve avvenire quanto prima possibile per
evitare che tutto quanto sviluppato in condizioni non corrette risulti inutile.
Le tecniche di testing, intese come ricerca degli errori, includono metodi di
prevenzione che portano a verificare i sistemi a partire dalla fase di progettazione.
Inoltre importante che durante la fase di analisi si provveda alla definizione di
piani di test da attuare successivamente a programma terminato e in esecuzione.
Nei modelli dei cicli di sviluppo del software, il testing viene spesso considerato
come quella fase che segue lo sviluppo per sancire se il prodotto pronto per
andare in esercizio. In realt il testing unattivit complessa che accompagna un
programma in tutta la sua vita e nei gradi progetti improntati alla qualit i suoi
costi possono superare anche il 30% di quelli complessivi dellintero progetto. Con
il testing si pu rilevare la presenza di malfunzionamenti, ma non pu dimostrare
che il prodotto privo di errori soprattutto in progetti di grandi dimensioni e
complessit. In generale non esiste un software privo di difetti e il testing
unattivit che non si pu mai considerare definitivamente conclusa. Dal punto di
vista pratico, a seconda della importanza dellapplicazione software, va individuata
la soglia di convenienza tra la completezza dei test da effettuare e i costi da
sostenere.
importante comunque che i casi di test siano definiti sin dalla fase di
progettazione e durante lo sviluppo dei programmi al fine di evidenziare difetti,
errori, e malfunzionamenti. Il difetto (detto anche Fault) un elemento del
software, oppure di una componente della documentazione relativa al prodotto
software, che non risponde ai requisiti. Un solo difetto pu generare diverse
disfunzioni. Lerrore la causa che genera il difetto. Il malfunzionamento (o anche
Failure) invece leffetto dellerrore, quindi la conseguenza di un difetto, che si
manifesta durante lutilizzo del prodotto software. Lobiettivo della fase di test
quello di eliminare la maggior parte possibile di difetti prima che il prodotto
software venga utilizzato, in modo da evitare qualsiasi malfunzionamento
prevedibile.
Le attivit di testing devono verificare se e in quali condizioni un programma
non fa ci che dovrebbe fare o fa quanto non dovrebbe fare. Un malfunzionamento
pu essere di tipo funzionale se non genera i risultati attesi; non funzionale se fa un
cattivo uso di risorse e presenta problemi di prestazioni non adeguate, scarsa
sicurezza; oppure ha una usabilit limitata in quanto la sua interfaccia utente non
ne consente un facile uso. anche possibile classificare i malfunzionamenti in base
allo gravit delle conseguenze sullutilizzo del prodotto software:
- grave se lintero sistema non pu essere utilizzato;
- rilevante se alcune funzionalit critiche del sistema sono indisponibili
per gli utenti;
- media se solo alcune funzionalit non critiche del sistema non possono
essere usate;
La traduzione dei programmi 311

- lieve se pur in presenza di funzionalit non usabili comunque possibili


lutilizzo del prodotto.
La verifica di un programma pu essere di tipo statico o dinamico. di tipo
statico se viene effettuata senza eseguire il programma verificando le regole di
codifica, la documentazione di progetto, la struttura del programma. di tipo
dinamico se effettuata eseguendo il codice e osservandone il comportamento
durante lesecuzione dei casi previsti da un piano di test. Tra le pi importanti
verifiche dinamiche, si ricordano:
- i test di singole unit (Unit Test) hanno lobiettivo di individuare gli errori
nel singolo modulo software;
- i test di integrazione (Integration Test) con i quali si provano i
collegamenti tra diverse unit hanno lobiettivo di individuare gli errori
nel software quando tutti i moduli che compongono un sottosistema o
lintero sistema vengono fatti lavorare insieme;
- i test dellintero sistema (System Test) hanno lobiettivo di garantire che il
prodotto software nel suo complesso soddisfi completamente i requisiti
iniziali;
- i test prestazionali (Performance Test) per verificare se il sistema produce
i risultati utilizzando al meglio le risorse; una risorsa importante , ad
esempio, il tempo, per cui un sistema efficiente se produce risultati in
tempo utile al suo utilizzatore;
- i test di stress che pongono il sistema in condizioni estreme di utilizzo per
controllare se capace di sostenere il carico che ne deriva e capire cos i
limiti di applicabilit;
- i test di usabilit per misurare il grado di facilit con cui lutente usa le
diverse funzioni: lusabilit tiene conto della progettazione delle
interfacce con le quali lapplicazione interagisce con il mondo esterno. Un
problema vivo nella progettazione delle interfacce la loro rispondenza a
requisiti che misurano la capacit di uso delle applicazioni da parte di
tutti, anche di chi portatore di alcuni handicap, e che vengono indicate
con il termine di accessibilit.
Le verifiche possono aver luogo in due condizioni contrapposte a seconda che
il verificatore conosca o meno la logica e la struttura interna del software. Nel
primo caso, detto anche white-box, il verificatore pu predisporre i casi di prova in
modo da poter provare il pi possibile:
- le istruzioni: in modo da eseguire almeno una volta tutte le parti del
codice che stato scritto;
- le decisioni: in modo da eseguire almeno una volta tutti i cammini
linearmente indipendenti che derivano dai nodi decisionali (if then else e
case) presenti nel codice.
Nel secondo caso, detto anche black-box, il verificatore conosce solo la logica
del software che deve testare, ma ne ignora del tutto la struttura interna. Il testing si
effettua confrontando l'analisi degli output generati dal sistema o da suoi
componenti, con i risultati previsti come risposta ad input predefiniti. In tale
situazione i casi di prova vanno costruiti prendendo in considerazione tutte le
possibili combinazioni tra dati di ingresso e risultati in uscita, scegliendo in modo
significativo i valori di prova.
312 Capitolo ottavo

Con attivit di debugging si indica invece linsieme di tecniche da applicare


per leliminazione degli errori. Vale la pena ribadire che una cattiva progettazione
se allinizio fa percepire una riduzione dei tempi di sviluppo implica solitamente
dei tempi pi lunghi di debugging. Nella stesura di un programma si possono
commettere tre principali tipi di errori, comunemente chiamati bug:
- Errori di sintassi: errori dovuti al non rispetto delle regole grammaticali
imposte dal linguaggio di programmazione adottato. Sono gli errori pi
facili da individuare e da correggere poich non possibile eseguire il
programma finch la loro presenza non completamente rimossa. Un
esempio comune consiste nella mancata chiusura di un costrutto if else o
nell'uso errato dei costrutti di iterazione, o ancora nella scrittura di parole
chiave in modo scorretto.
- Errori logici: ossia gli errori dovuti ad una errata progettazione
dellalgoritmo. Sono i pi complessi da individuare in quanto l'esecuzione
procede regolarmente senza per fornire il risultato desiderato. Il saper
prevenire errori logici una capacit che si acquisisce nel tempo e
rappresenta una delle caratteristiche fondamentali di un buon
programmatore. Solo una buona fase di analisi consente di evitare la
costruzione di programmi sbagliati.
- Errori di esecuzione: ossia quelli che intervengono quando il contesto in
cui il programma opera diverso da quello progettato. Sono errori di
esecuzione la divisione di un numero per 0, l'accesso ad una posizione di
un array non presente, il tentativo di connessione ad un file che non esiste.
In presenza di un errore di esecuzione il programma viene terminato
prematuramente con linvio di un messaggio mostrato a video e
corrispondente allerrore verificatosi.
Nello specifico della scrittura di programmi il debugging consente la ricerca e
la correzione di errori con particolare riferimento alla correzione degli errori logici
presenti nella struttura dellalgoritmo: errori che si manifestano con un
comportamento anomalo del programma rispetto a quello atteso. Gli errori di tipo
logico, al contrario di quelli sintattici, non sono rilevabili in fase di compilazione
del programma e ci rende spesso pi difficoltosa la loro localizzazione e
correzione.
Sebbene sia possibile svolgere l'attivit di debugging senza alcun supporto da
parte dell'ambiente di programmazione, osservando cio il comportamento del
programma ed esaminando manualmente il suo codice alla ricerca degli errori,
molti ambienti di programmazione moderni offrono specifiche funzionalit volte a
semplificare tale opera quali il tracciamento (Tracing), i punti di arresto
(Breakpoint) e lanalisi dei valori delle variabili (Watchpoint).
Lanalisi dei valori delle variabili consente al programmatore di visionare lo
stato dellesecuzione. Losservazione dei valori assunti per effetto delle istruzioni
eseguite importante per comprendere non solo la correttezza delle attivit svolte
ma soprattutto se ci che deve essere ancora eseguito avverr secondo precise e
previste condizioni.
Con il tracciamento il programma viene eseguito a scatti, una istruzione alla
volta. Lambiente al termine dellesecuzione di una istruzione si ferma aspettando
che il programmatore attivi lesecuzione dellistruzione successiva. Ad ogni arresto
La traduzione dei programmi 313

il programmatore pu osservare lo stato dellesecuzione individuando cos la


genesi dellerrore.
Eseguire passo passo il programma per non solo faticoso ma in alcuni casi
non utile in quanto leffetto di alcune istruzioni non incide sulle cause degli errori.
I punti di arresto consentono cos di far interrompere lesecuzione del programma
in alcuni dei suoi punti pi critici per controllare lo stato dellesecuzione.
La determinazione dei punti di arresto uno degli aspetti pi critici del
debugging. Perch siano efficaci per la determinazione delle cause di errore,
devono essere previsti sin dalla fase di progettazione del programma mediante
ladozione delle asserzioni con le quali il programmatore esegue continuamente
assunzioni sullo stato dellesecuzione: come ad esempio parametri che devono
assumere valori precisi, precondizioni che devono essere verificate prima di
svolgere unazione, condizioni invarianti allinterno di un loop, post-condizioni
che devono verificarsi dopo lesecuzione di un processo di calcolo. Luso delle
asserzioni uno dei cardini della programmazione professionale in consente infatti
di scrivere codice che si verifica pi facilmente.

8.4. Gli ambienti integrati


Lesecuzione di un programma richiede la scrittura (editing) dei testi sorgenti delle
diverse parti del programma e il completamento delle fasi di compilazione,
collegamento e caricamento in memoria. La comparsa di un solo errore che si
verifichi durante il ciclo di editing, compilazione, collegamento, caricamento ed
esecuzione costringe il programmatore a ritornare nella fase di editing per
immettere le correzioni del caso nel sorgente ed a rieffettuare un nuovo ciclo di
compilazione, collegamento, caricamento ed esecuzione.
Per ridurre i tempi di produzione dei programmi sono nati nel tempo ambienti
di programmazione integrati con i quali che semplificano la generazione dei
programmi eseguibili a partire dalla loro forma sorgente. L'editor, il compilatore, il
collegatore ed il caricatore fanno parte di un unico ambiente operativo e sono
strettamente interconnessi (ovvero integrati) tra loro. I vantaggi di tali ambienti
sono elencati di seguito.
- Una semplice interazione con l'utente: tutti i comandi sono selezionati
mediante men guidati. Non pi necessario ricordare sequenze di
comandi spesso criptiche e foriere di errori.
- La riduzione dei tempi di sviluppo: tutti gli strumenti sono integrati in un
unico software e sono progettati in modo da lavorare sinergicamente e
perci con maggiore efficienza.
- Una maggiore semplicit nelle operazioni di correzione degli errori
(debugging): l'integrazione delle funzionalit di editing con quelle di
compilazione, collegamento ed esecuzione consente di non abbandonare
la fase di editing e quindi di rilevare e correggere l'errore quando si
verifica.
8.4.1. Lambiente DEV-C++
La creazione di programmi C viene semplificata con lutilizzo di appositi ambienti
di sviluppo o Integrated Development Environment (IDE), che forniscono al
314 Capitolo ottavo

programmatore uninterfaccia di facile utilizzo per la rapida scrittura ed il


successivo testing dei programmi.
DEV-C++ un esempio di IDE, ossia un ambiente di sviluppo per programmi
scritti in linguaggio C o C++ con le seguenti caratteristiche:
- usa Mingw, una versione del famoso compilatore C GCC (GNU
Compiler Collection);
- crea eseguibili Win32, ossia dei file .exe per macchine con sistemi
operativi Windows;
- un free software scaricabile gratuitamente dalla rete;
- scritto in Delphi, che un altro linguaggio di programmazione.
Esso si presenta al programmatore attraverso una schermata simile a quella
mostrata in figura 7.

Figura 7 Schermata di avvio di DEV-C++

In DEV-C++ si distinguono le seguenti componenti principali:


- una finestra di editing per la scrittura dei programmi;
- una barra dei men dalla quale si accede ai comandi per la compilazione
ed esecuzione dei programmi;
- un finestra per lorganizzazione dei file contenenti i diversi programmi;
tale finestra utile per organizzare i file nel caso di sviluppo di progetti,
ovvero di programmi composti da componenti distribuiti su pi file;
- un finestra contente gli output di compilazione nella quale compaino le
segnalazioni degli errori rilevati durante la compilazione.
Un programma C per poter essere eseguito richiede che vengano attivate le
fasi di:
- editing: il programma viene scritto nel linguaggio C attraverso un editor
testuale;
La traduzione dei programmi 315

- compilazione: il codice sorgente del programma viene tradotto in codice


oggetto attraverso luso di un apposito compilatore, eventuali errori
sintattici nella scrittura del programma sono risolti in questa fase;
- linking ed esecuzione: eventuali funzioni di librerie esterne (gi
compilate) vengono collegate o linkate al codice oggetto allatto del
caricamento del programma in memoria, il quale successivamente pu
essere eseguito;
- debugging e testing: il programma viene testato rispetto a dei casi di test
ed in caso di comportamento anomalo si utilizzano meccanismi di
debugging per correggere gli errori funzionali.
La prima fase dello sviluppo di un programma la scrittura del codice
sorgente. Si utilizza la finestra di editing (dal men File selzionare Nuovo->File
sorgente). La successiva fase quella di compilazione, atta a produrre il codice
oggetto necessario allesecuzione. Essa avviene utilizzando il comando di
compilazione nella barra dei men come mostrato in figura 8.

Figura 8 Compilazione attraverso DEV-C++


Gli errori rilevati durante la compilazione sono segnalati nella finestra degli
output di compilazione. Ad ogni errore viene associata una diagnostica che il
programmatore deve interpretare per comprendere la causa dellerrore stesso. Per
rimuovere la causa dellerrore il programmatore deve modificare il testo sorgente
prima di riavviare la compilazione (figura 9).
Il compilatore DEV segnala tutti gli errori presenti nel programma legati ad
una violazione delle regole grammaticali del linguaggio: alcuni di essi sono reali
ma atri possono presentarsi a causa dei primi: se, ad esempio viene rilevato un
errore in un if, anche le frasi successive che compongono lintera struttura (lelse)
vengono riportate come errate. Alcuni errori non sono gravi e il compilatore li
segnala di tipo warning: per essi la compilazione procede comunque ed il
compilatore a introdurre una correzione in modo automatico. importante che tutti
gli errori rilevati vengano per rimossi, in quanto la correzione automatica
introdotta dai warning potrebbe alterare la logica del programma.
316 Capitolo ottavo

Le successive fasi di linking ed esecuzione avvengono attraverso il comando


di esecuzione disponibile sempre nella barra dei men (figura 10). Durante
lesecuzione si aprir una finestra DOS che dar modo al programmatore di
visualizzare i risultati dellesecuzione del programma.
Non possibile eseguire un programma se prima non lo si compilato. Perch
un programma sia compilato non devono essere segnalati errori dal compilatore ad
eccezione di quelli di tipo warning.
Gli errori logici non rilevabili a tempo di compilazione, che compaiono quindi
solo durante lesecuzione, sono individuabili e gestibili attraverso il meccanismo
del debugging del codice sorgente.
La verifica della correttezza funzionale del codice avviene inserendo
allinterno del programma C dei punti di debug o breakpoints con un clic del
mouse sulla barra nera del editor del DEV. Quando si inserisce un breakpoint e si
esegue un programma con lopzione di debug (attraverso il comando dalla barra
dei men), lesecuzione si arresta al punto di debug prefissato; procedendo poi con
lopzione Step Successivo possibile eseguire ed esaminare il codice linea per
linea per lindividuazione di eventuali errori e della loro posizione allinterno del
codice stesso.

Figura 9 Gestione errori di compilazione


La traduzione dei programmi 317

Figura 10 Esecuzione di programmi attraverso DEV-C++

La tecnica del debugging risulta molto utile quando una funzione non viene
eseguita correttamente e, da una prima analisi visiva, non si riesce a determinate il
punto in cui presente lerrore. Inserendo i breakpoint risulta inoltre possibile
stabilire quali sono le parti di codice corrette e quali non lo sono (figura 11 ed 12).

Figura 11 Programma con comportamento anomalo


318 Capitolo ottavo

Figura 12 Debug di un programma

In DEV-C++ il debug permette inoltre di controllare laggiornamento delle


variabili durante il ciclo di esecuzione. Tale controllo (attivabile mediante
laggiunta di osservazioni, vedi figura 13) serve a stabilire se durante
lesecuzione del programma le variabili si aggiornano correttamente.

Figura 13 Controllo aggiornamento di variabili


La traduzione dei programmi 319

Nellesempio mostrato si pu vedere che la variabile che non si aggiorna


correttamente la variabile b a causa di uno scorretto uso della funzione scanf.
Un programma compilato con un compilatore C viene allocato in quattro aree
di memoria distinte:
- unarea codice contente il codice oggetto del programma;
- unarea globale contente tutte le variabili globali del programma;
- unarea heap contente le variabili allocate in maniera dinamica;
- e unarea stack che viene usata durante lesecuzione del programma per
memorizzare lindirizzo di rientro delle funzioni, gli argomenti passati
alle funzioni, le variabili locali.
8.4.2. Lambiente MATLAB
MATLAB mette a disposizione una vasta gamma di funzioni per la
risoluzione di problemi di natura matematica, ponendosi, agli occhi dellutente,
come un potente ambiente per il calcolo scientifico.
MATLAB, nella cosiddetta modalit interattiva di calcolatrice scientifica, si
presenta allutente attraverso linterfaccia grafica in figura 14 chiamata Command
Window.

Figura 14 Command Window

Tale interfaccia costituisce una vera e propria finestra di comandi in cui


possibile specificare, sottoforma di funzione, le azioni che MATLAB deve
intraprendere. Un primo esempio banale, per capire la modalit di funzionamento
della calcolatrice MATLAB, la somma tra due numeri mostrata nella figura 15.
Come si pu notare la somma avviene, come in una normale calcolatrice,
utilizzando il tasto (funzione) + e il tasto <enter>, che rappresenta linvio del
comando; il risultato della somma viene memorizzato in una particolare variabile
ans, che MATLAB utilizza per conservare il risultato delloperazione corrente.
320 Capitolo ottavo

Figura 15 Esempio duso della Command Window

Per potere sfruttare tutte le potenzialit della calcolatrice MATLAB bisogna


conoscere innanzitutto tutte le funzioni da essa messe a disposizione. Per avere
unidea della libreria di funzioni che si possono utilizzare, basta conoscere il
comando di utilit help, il quale rende disponibile un vero e proprio manuale in
linea per lutilizzo di MATLAB. Per rendere pi semplice lutilizzo del manuale da
parte dellutente le funzioni sono classificate per argomento.
Quando si digita nella finestra dei comandi help senza argomenti compare la
serie di argomenti o topics a cui si pu fare riferimento. Digitando poi help
nome_argomento possibile accedere alla lista di funzioni MATLAB relative
allargomento. Digitando infine help nome_funzione compare la descrizione della
modalit di utilizzo della funzione. Un esempio di utilizzo dellhelp MATLAB per
risalire alla modalit duso della funzione abs (valore assoluto) potrebbe essere il
seguente:

help
help elfun
help abs
ABS Absolute value.
ABS(X) is the absolute value of the elements of X. When
X is complex, ABS(X) is the complex modulus (magnitude) of
the elements of X.
See also SIGN, ANGLE, UNWRAP

Come si pu notare dallesempio lhelp relativo ad una funzione termina con


un elenco di tutte le funzioni ad essa correlate, in modo da rendere semplice ed
immediata la ricerca.
Poich lelemento base dellambiente MATLAB la matrice, tutti i dati
vengono immessi sottoforma di matrici (reali o caratteri). Le matrici possono
essere fornite in 3 modi diversi:
1. da tastiera come lista di elementi,
2. caricate da file-esterni di dati,
3. generate da funzioni .
La traduzione dei programmi 321

importante sottolineare che MATLAB distingue le lettere maiuscole da


quelle minuscole. In particolare limmissione di un dato da tastiera avviene
utilizzando una sintassi del tipo:
nome_variabile=valore[;] <enter>
e la presenza del carattere ; (opzionale) consente di memorizzare linformazione
senza visualizzarla.
Tutti i dati sono memorizzati sotto forma di matrice e gestiti nellambiente in
una area che prende il nome di WORKSPACE (spazio di lavoro). Le variabili
utilizzate rimangono in tale spazio di memoria per tutta una sessione di lavoro ed
possibile visualizzarne il valore sia durante lesecuzione del programma che alla
sua terminazione con i comandi who e whose.
La funzione who mostra tutte la variabili allocate, mentre la funzione whose
mostra oltre al nome delle variabili anche il tipo, la dimensione e la quantit di
memoria occupata.

a=1;
v=[1 2 3];
who
Your variables are:
a v
whos
Name Size Bytes Class
a 1x1 8 double array
v 1x3 24 double array
Grand total is 4 elements using 32 bytes

Il comando di utilit per cancellare delle variabili dalla memoria il clear;


clear senza argomenti cancella tutte le variabili, clear nome_varaibile elimina la
variabile con il nome specificato. Unaltra funzione utile quando si opera in
modalit calcolatrice la funzione clc che serve a pulire lo schermo.
Vediamo ora degli esempi duso di MATLAB in modalit calcolatrice per la
risoluzione si semplici problemi matematici.

Esempio 1 - Trovare la trasposta di una data matrice A


Per il calcolo della trasposta si utilizza il carattere (funzione) (apice). La sequenza
di comandi usata per risolvere il problema potrebbe essere la seguente:

A=[1 2 3 4;5 6 7 8]
A=
1 2 3 4
5 6 7 8
A=A'
A=
1 5
2 6
3 7
4 8
322 Capitolo ottavo

Esempio 2 - Risolvere il sistema di equazioni lineari descritto da Ax=b con A


matrice dei coefficienti (quadrata) e b vettore dei termini noti
La soluzione del sistema data da x=A-1b; per questo problema sono disponibili
due funzioni: la prima inv permette il calcolo dellinversa di una matrice, la
seconda \ (funzione di divisione a sinistra) permette la risoluzione diretta del
sistema suddetto. Delle sequenze di comandi utili per risolvere il problema
potrebbero essere le seguenti:

A=[1 2;3 4]
A=
1 2
3 4
b=[1;1]

b=
1
1
x1=inv(A)*b
x1 =
-1
1
x2=A\b
x2 =
-1
1

Esempio 3 - Riportare landamento della funzione sen(x) nellintervallo


[0,6.28]con passo 0.1.
Per determinare landamento di una funzione bisogna prima rappresentare
lintervallo delle ascisse, poi calcolare il vettore delle ordinate, ed, infine tracciarne
il grafico. La funzione utilizzata per graficare funzioni la funzione plot. Essa ha
come parametri di ingresso il vettore delle ascisse e quello delle ordinate della
funzione da graficare. Infine per il calcolo del seno di un numero si utilizza la
classica funzione sin. Una sequenza d comandi utile per risolvere il problema
potrebbe essere la seguente:

x=[0:0.1:6.28];
y=sin(x);
plot(x,y)
La traduzione dei programmi 323

0.8

0.6

0.4

0.2

-0.2

-0.4

-0.6

-0.8

-1
0 1 2 3 4 5 6 7

Figura 16 Plot di una funzione

Esempio 4 - Trovare il determinante di una data matrice A.


Per il calcolo del determinante si utilizza la funzione det. La sequenza di comandi
usata per risolvere il problema potrebbe essere la seguente:

A=[1 2;3 4]
A=
1 2
3 4
det(A)
ans =
-2

Esempio 5 - Trovare le radici di un dato polinomio p.


Per il calcolo delle radici di un polinomio si utilizza la funzione roots. Essa ha
come parametro di ingresso un vettore contenente i coefficienti del polinomio.La
sequenza di comandi usata per risolvere il problema con p(s)=2s2-4s+1 potrebbe
essere la seguente:

p=[2 -4 1]
p=
2 -4 1
roots(p)
ans =
1.7071
0.2929

Esempio 6 - Calcolare lintegrale definito tra a e b di una data funzione f(x).


Per il calcolo dellintegrale di una funzione si utilizza la funzione quad. Essa ha
come parametri di ingresso la funzione f e gli estremi di integrazione. La sequenza
di comandi usata per risolvere il problema con f(x)=log(x), a=1 e b=10 potrebbe
essere la seguente:

quad('log',1,10)
ans = 14.0257
324 Capitolo ottavo

MATLAB si presenta anche come ambiente per la produzione di programmi


con il quale ampliare la gi vasta libreria di funzioni disponibile. A tale scopo
MATLAB offre allutente un editor per lo sviluppo di programmi, chiamato M-file
editor, che si presenta allutente con linterfaccia mostrata in figura.

Figura 17 M-file editor

Con leditor possibile sviluppare programmi, o meglio funzioni, sfruttando i


costrutti e le propriet del linguaggio di MATLAB. Un primo semplice esempio di
funzione MATLAB potrebbe essere quello del calcolo della somma tra tre numeri
reali, il cui codice da scrivere :
function [d]=somma(a,b,c)
d=a+b+c;

Al termine della scrittura, la funzione deve essere salvata con il suo stesso
nome in modo tale da poter da essere poi richiamata nella finestra dei comandi, o
allinterno di altre funzioni. Nellesempio la funzione presenta tre variabili
dingresso a,b,c ed una di uscita d e i valori ai parametri di ingresso possono essere
dalla Command Window assegnati nel modo seguente:
[ris]=somma(1,2,3)
ris = 6

I valori dei parametri possono essere passati sia direttamente che per mezzo di
altre variabili; inoltre, si osservi che, quando viene richiamata una funzione, non
necessario che il nome delle variabili di ingresso e uscita coincidano con quelli
utilizzati per la scrittura della funzione, ci che importante che siano per ordine
e tipo coincidenti con esse.
Facendo riferimento allesempio seguente s1, s2 e s3 vengono associate ad
a,b,c.

s1=1;
s2=2;
s3=3;
La traduzione dei programmi 325

[ris]=somma(s1,s2,s3)
ris = 6

Quando non ci sono parametri di ingresso da passare mediante la finestra di


comandi, anche lopzione Run, presente nella voce del men Tools delleditor,
consente di attivare una funzione.
Gli errori relativi al codice di una funzione vengono riportati nella finestra dei
comandi durante la sua esecuzione. Ad esempio se in una funzione di nome somma
si inserisce:
a=iput('Inserisci il secondo numero: ');

si riceve il seguente messaggio durante la sua esecuzione:

??? Undefined function or variable 'iput'.

Error in ==> C:\MATLABR11\work\somma.m


On line 3 ==> a=iput('Inserisci il secondo numero: ');

MATLAB d informazione relativamente alla tipologia e posizione di tutti gli


errori allinterno del codice e quindi rende possibile una loro rapida correzione.
Nellesempio viene segnalato che la funzione iput risulta non definita.
La verifica della correttezza non solo sintattica, ma anche funzionale, del
codice pu invece avvenire inserendo allinterno della funzione dei punti di debug
attraverso lopzione Set/Clear Breakpoints presente nella voce del men Debug
delleditor. Quando si inserisce un breakpoint e si esegue una funzione,
lesecuzione si arresta al punto di debug; procedendo poi con lopzione Single step
possibile esaminare il codice linea per linea per lindividuazione di eventuali
errori e della loro posizione.
La tecnica del debugging risulta molto utile quando una funzione non viene
eseguita correttamente e, da una prima analisi, non si riesce a determinate il punto
in cui si genera lerrore. Inserendo i breakpoint risulta inoltre possibile stabilire
quali sono le parti di codice corrette e quali non lo sono. Ad esempio si scriva la
seguente funzione di somma:

function somma
a=input('Inserisci il primo numero: ');
b=input('Inserisci il secondo numero: ');
c=input('Inserisci il terzo numero: ');
d=a+b;
fprintf('La somma %g',d)

palesemente errata in quanto non calcola la somma delle tre variabili a, b, e c


ma solo delle prime due. In tal caso la funzione, pur risultando sintatticamente
corretta, non ritorna il giusto risultato:

somma
Inserisci il primo numero: 1
Inserisci il secondo numero: 2
Inserisci il terzo numero: 3
La somma 3
326 Capitolo ottavo

Per capire il non corretto funzionamento della funzione si potrebbe inserire un


breakpoint sullistruzione di somma come mostrato in figura 18.

Figura 18 Debugging con Matlab

Eseguendo la funzione si nota come la sua esecuzione si arresta prima


dellistruzione indicata. Spostando ora il cursore del mouse sulle variabili a, b e c,
si pu osservare che queste contengono effettivamente il valore digitato e quindi
lerrore non presente nella parte di codice relativa allinserimento dati.
Procedendo poi con lopzione Single Step viene eseguita la sola istruzione alterata
consentendo di comprendere la causa dellerrore.
Un secondo semplice esempio di funzione potrebbe essere quella del calcolo
della somma degli elementi di un vettore, funzione, per altro, gi presente nella
libreria MATLAB (sum). Essa si compone di un ciclo iterativo in cui ad ogni passo
k viene calcolata la somma dei primi k elementi del vettore. Una prima versione di
codice, in cui si prevede che il vettore dingresso sia passato dalla finestra dei
comandi, risulta la seguente:

function [somma]=sommav1(v)
n=length(v);
somma=0;
for i=1:n
somma=somma+v(i);
end;

In questo caso occorre prelevare la dimensione del vettore mediante la


funzione length. Lesempio duso della funzione mostrato in seguito:
La traduzione dei programmi 327

v=[1 2 3 4 5 6 7 8 9 10];
s=sommav1(v)
s=
55

In una seconda versione, in cui si prevede linserimento del riempimento e


degli elementi del vettore durante lesecuzione della funzione, il codice potrebbe
essere il seguente:

function sommav2
somma=0;
n=input('Inserisci la dimensione del vettore: ');
for i=1:n
fprintf('Inserisci l''elemento %d-esimo: ',i);
v(i)=input('');
somma=somma+v(i);
end
fprintf('\nLa somma : %g',somma);

In tal caso la lettura degli elementi preceduta da quella del riempimento al


fine di dimensionare il ciclo for di inserimento. Un esempio duso della funzione
mostrato in seguito:

sommav2
Inserisci la dimensione del vettore: 3
Inserisci l'elemento 1-esimo: 1
Inserisci l'elemento 2-esimo: 2
Inserisci l'elemento 3-esimo: 3
La somma : 6

In una terza versione, in cui si prevede il solo inserimento degli elementi ma


non il riempimento, il codice potrebbe essere il seguente:

function sommav3
somma=0;
k=1;
risp='s';
while (risp=='s')
fprintf('Inserisci l''elemento %d-esimo del vettore: ',k);
v(k)=input('');
somma=somma+v(k);
risp=input('Altro elemento? (s)i o premere un zltro tasto per uscire: ','s');
k=k+1;
end
fprintf('\nLa somma : %g',somma);

In tal caso dopo linserimento di un dato elemento viene chiesto, attraverso un


ciclo while, allutente se continuare o meno con ulteriori inserimenti. Un esempio
duso delle funzione mostrato in seguito:
328 Capitolo ottavo

sommav3
Inserisci l'elemento 1-esimo del vettore: 2
Altro elemento? (s)i o premere un qualsiasi tasto per uscire: s
Inserisci l'elemento 2-esimo del vettore: 3
Altro elemento? (s)i o premere un qualsiasi tasto per uscire: s
Inserisci l'elemento 3-esimo del vettore: 4
Altro elemento? (s)i o premere un qualsiasi tasto per uscire: n
La somma : 9

In una quarta ed ultima versione, in cui si prevede linserimento degli


elementi ed un numero particolare (tappo) di fine riempimento, il codice potrebbe
essere il seguente:

function sommav4
somma=0;
k=1;
fine=0;
while (fine~=1)
fprintf('Inserisci l''elemento %d-esimo del vettore(-1 per terminare): ',k);
v(k)=input('');
if (v(k)~=-1)
somma=somma+v(k);
k=k+1;
else
fine=1;
end
end
fprintf('\nLa somma : %g',somma);

In tal caso la scelta del tappo a -1 limita il programma al funzionamento solo


nel caso di numeri positivi. Un esempio duso delle funzione mostrato in seguito:

sommav4
Inserisci l'elemento 1-esimo del vettore(-1 per terminare): 1
Inserisci l'elemento 2-esimo del vettore(-1 per terminare): 2
Inserisci l'elemento 3-esimo del vettore(-1 per terminare): 3
Inserisci l'elemento 4-esimo del vettore(-1 per terminare): -1
La somma : 6

Un terzo semplice esempio di funzione MATLAB potrebbe essere quello del


calcolo della somma degli elementi della diagonale principale di una matrice
quadrata di numeri interi, funzione gi presente nella libreria MATLAB (trace).
Lestrazione degli elementi della diagonale pu essere fatta attraverso un
unico ciclo iterativo, essendo questi caratterizzati dal fatto di avere lindice di riga
uguale a quello di colonna.
Una prima versione del codice da scrivere, in cui la matrice passata dalla
finestra dei comandi, potrebbe essere per il nostro esempio la seguente:
La traduzione dei programmi 329

function [somma]=diagv1(A)
[n,m]=size(A);
somma=0;
for i=1:n
somma=somma+A(i,i);
end

Analogamente al caso monodimensionale necessario conoscere la


dimensioni di riga e di colonna della matrice, ottenibili attraverso la funzione size.
Un esempio duso della funzione mostrato di seguito:

A=[1 10;20 30]


A=
1 10
20 30
s=diagv1(A)
s=
31

Una seconda versione del codice da scrivere, in cui le dimensioni di riga e


colonna e gli elementi della matrice sono richiesti durante lesecuzione della
funzione, potrebbe essere la seguente:

function diagv2
n=input('Inserire ordine Matrice: ');
for i=1:n
for j=1:n
fprintf('Inserire elemento di posto(%d,%d): ',i,j);
A(i,j)=input('');
end
end
fprintf('Matrice letta:');
A
somma=0;
for i=1:n
somma=somma+A(i,i);
end
fprintf('La somma %d',somma);

In tal caso la lettura degli elementi preceduta da quella delle dimensioni di


riga e colonna al fine di dimensionare i cicli for di inserimento. Un esempio duso
della funzione mostrato in seguito:

diagv2
Inserire ordine Matrice: 3
Inserire elemento di posto(1,1): 1
Inserire elemento di posto(1,2): 2
Inserire elemento di posto(1,3): 3
Inserire elemento di posto(2,1): 4
Inserire elemento di posto(2,2): 5
Inserire elemento di posto(2,3): 6
Inserire elemento di posto(3,1): 7
Inserire elemento di posto(3,2): 8
330 Capitolo ottavo

Inserire elemento di posto(3,3): 9


Matrice letta:
A=
1 2 3
4 5 6
7 8 9
La somma 15
Capitolo nono

La programmazione orientata agli oggetti

9.1. I limiti del paradigma procedurale


Gli ultimi anni hanno visto una chiara e netta evoluzione dei modelli di
programmazione da un approccio orientato a procedure e funzioni, e, quindi alla
programmazione dal punto di vista del calcolatore, a modelli denominati di Object
Oriented Programming (OOP) che, partendo dal punto di vista dellutente,
suddividono lapplicazione in concetti rendendo il codice pi comprensibile e
semplice da mantenere.
Il modello classico di programmazione conosciuto come paradigma
procedurale si basa su una filosofia top-down di tipo divide et impera: in tale
tipologia di approccio, un problema complesso viene suddiviso in problemi pi
semplici in modo che siano facilmente risolvibili mediante procedure e funzioni.
Nella pratica lapplicazione di tecniche top-down permette di ottenere programmi
non costituiti da un unico blocco monolitico di istruzioni, ma programmi composti
da moduli funzionali, ciascuno dei quali realizza un singolo e ben preciso compito.
Una tale impostazione, in cui lattenzione del programmatore rivolta al problema,
risulta un valido aiuto per lattivit di programmazione, in quanto rispetta la
limitazione degli esseri umani che, solitamente, sono in grado di esaminare un solo
aspetto di un problema alla volta. Inoltre, il processo di raffinamento iterativo
produce una gerarchia di sottoproblemi di complessit via, via decrescente. Tale
approccio stato formalizzato in molti modi ed ben supportato da molti linguaggi
che forniscono al programmatore un ambiente in cui sono facilmente definibili
procedure e funzioni.
Allinterno di unapplicazione procedurale i dati vengono condivisi dalla varie
procedure e funzioni mediante luso di variabili globali, passaggio di parametri e
ritorno di valori. Un esempio di applicazione procedurale riportata in figura 1.
Lapplicazione in questione consente la gestione di cartelle cliniche relative a
pazienti di una struttura ospedaliera. Come si pu osservare, il problema suddetto
stato risolto suddividendolo in pi sottoproblemi, e utilizzando varie procedure,
alcune, pi di alto livello, si occupano della gestione dei dati del paziente
(mediante variabile globale) ed linterfacciamento con gli utenti dellapplicazione;
altre, di pi basso livello, si occupano della gestione dei file fisici su memoria di
massa che contengono le informazioni dei pazienti in maniera persistente. Ogni
volta che bisogna accedere al file system per gestire i file dei pazienti si utilizza
una delle tre procedure: Salva su file(), Elimina file(), Leggi da file().
332 Capitolo nono

Figura 1 Diagramma delle componenti di unapplicazione procedurale

Dal momento che di solito le procedure non sono auto-documentanti (self-


documenting), ossia non rappresentano entit ben definite, se un programmatore
deve modificare lapplicazione aggiungendo la procedura di aggiornamento dei
dati di un paziente, questi, non conoscendo a fondo il codice dellapplicazione,
potrebbe utilizzare la routine Aggiorna Cartella Clinica(), senza chiamare la
procedura di Ricerca Cartella Clinica(), dimenticando cos laggiornamento dei dati
globali su cui lavorano le procedure di gestione dei file, e, producendo di
conseguenza nel programma effetti indesiderati, difficilmente gestibili. Per tale
motivo, le applicazioni basate sul modello procedurale sono in generale difficili da
aggiornare e manutenere, nonch da controllare con i classici meccanismi di
debugging. I bug possono presentarsi in qualunque punto del codice causando
una propagazione incontrollata dellerrore.

9.2. Introduzione al paradigma object oriented


La programmazione Object-Oriented nasce storicamente dallincapacit dei
linguaggi procedurali (e.g, Pascal, C) di gestire in maniera efficiente programmi
complessi, soprattutto in termini di difficolt di manutenzione (e.g., correzione
errori e apporto di modifiche), come visto nellesempio del paragrafo precedente.
A tale proposito, una possibile soluzione al problema della gestione delle
cartelle cliniche potrebbe essere quella di raggruppare (in gergo incapsulare) in
La programmazione orientata agli oggetti 333

appositi moduli software tutta la logica di gestione dei dati dei pazienti, ed in un
altri la logica di gestione dei file, costringendo i programmatori ad usare tali
moduli per lo sviluppo di nuove procedure che lavorano sui dati in questione.
Su tale presupposto si basa il paradigma Object Oriented, che, a differenza
del paradigma procedurale, accentra lattenzione verso i dati. Lapplicazione viene
suddivisa in un insieme di oggetti in grado di interagire tra di loro e codificati in
modo tale che la macchina sia in grado di comprenderli.
La programmazione orientata agli oggetti rappresenta quindi un nuovo modo
di pensare alla risoluzione dei problemi per mezzo di un calcolatore: invece di
modellare il problema adattandolo alla logica del calcolatore, lapproccio OO
adatta il calcolatore al problema .
I problemi vengono dunque analizzati individuando delle entit indipendenti
che sono in relazione con altre. Tali entit non sono scelte perch facilmente
traducibili nella logica di programmazione, ma in quanto esistono dei vincoli fisici
o concettuali che le separano dal resto del problema e sono rappresentate come
oggetti di un programma. La scelta degli oggetti non va effettuata dunque
adattando il problema alla logica della programmazione, ma guardando al
problema in termini semplici.
Il paradigma object oriented formalizza la tecnica di incapsulare e
raggruppare parti di un programma in oggetti software che rappresentano concetti
ben definiti sia a livello di utente che a livello applicativo. Tali oggetti sono poi
riuniti per formare unapplicazione.
Nellesempio precedente, si pu osservare come lapplicazione di gestione
delle cartelle cliniche dei pazienti si accentri su tre concetti principali: Cartella
Clinica, Gestore Cartelle e Gestore di file. I concetti suddetti rappresentano
dellentit, classi di oggetti, del mondo reale che hanno caratteristiche comuni: ad
esempio tutte le cartelle cliniche avranno come informazioni il nome e cognome
del paziente, la sua tessera sanitaria, il suo gruppo sanguigno, una descrizione di
tutte le attivit sanitarie svolte sul paziente, una descrizione del suo stato di salute,
etcSu tali oggetti sono poi definite una serie di azioni o funzionalit come
quella dellaggiornamento e recupero dei dati di un paziente, eseguite, ad esempio,
dal personale medico ogni qualvolta il paziente si ricovera presso la struttura
ospedaliera. Allo stesso modo possibile pensare al gestore di cartella come
unentit (ad esempio un impiegato della reception della struttura) che si occupa di
gestire (aggiornare, recuperare, creare, etc) le cartelle cliniche, mentre un
Gestore di File rappresenta unentit (ad esempio un impiegato dellufficio
archivi) preposta allarchiviazione delle cartelle.
Lindividuazione degli oggetti e delle azioni su di essi non per sufficiente
alla realizzazione dellapplicazione, il secondo passo quello di definire
linterazione tra gli oggetti. necessario, ad esempio, stabilire come un medico, un
impiegato della reception ed uno dellufficio archivi devono comunicare qualora si
deve aggiornare la cartella clinica di un paziente al momento del ricovero. La cosa
pi ovvia che il gestore della reception, allatto del ricovero del paziente, recuperi
la cartella clinica con laiuto delladdetto agli archivi e la consegni al chirurgo, il
quale dopo loperazione aggiorna lo stato di salute del paziente. Allatto della
dimissione del paziente, limpiegato della reception provveder a conservare la
cartella aggiornata consegnandola alladdetto allarchiviazione.
334 Capitolo nono

In altri termini, il programmatore in un approccio di tipo object oriented inizia


con lanalizzare tutti i singoli aspetti concettuali che compongono un programma.
Questi concetti costituiscono gli oggetti dellapplicazione ed hanno nomi legati a
ci che rappresentano. Una volta che le classi di oggetti sono identificati, il
programmatore decide di quali attributi (caratteristiche) e funzionalit dotare le
entit. Lanalisi infine dovr includere le modalit di interazione tra gli oggetti.
Proprio grazie a queste interazioni sar possibile riunire gli oggetti per formare una
applicazione.
Programmare in un linguaggio orientato agli oggetti significa quindi creare
nuovi tipi di dato chiamati classi e associare ad essi delle operazioni, dette metodi,
che indicano alle classi come trattare i messaggi ad esse inviati. Lutente definisce
poi delle variabili del tipo creato, dette oggetti o istanze, e interagisce con tali
oggetti.
Il concetto di programmazione ad oggetti si pu riassumere nel seguente
modo: si invia un messaggio ad un oggetto e si lascia che esso lo gestisca. Essa
nasconde i dati e la complessit di un programma e pone al centro dellattenzione
i tipi di dato e le operazioni: non sono i dati ma i messaggi a muoversi nel sistema,
Non si invocano funzioni sui dati, ma si inviano messaggi agli oggetti.
A differenza di procedure e funzioni, gli oggetti sono auto-documentanti.
Una applicazione pu essere scritta a partire da poche informazioni ed in particolar
modo il funzionamento interno delle funzionalit degli oggetti completamente
nascosto al programmatore.
Riferendoci sempre allesempio precedente, lapplicazione complessiva
risulter costituita da 3 classi: Cartella Clinica, Gestore Cartelle e Gestore file. La
prima avr come attributi o variabili membro i dati anagrafici del paziente, il
codice di tessera sanitaria, una descrizione di tutte le attivit sanitarie svolte sul
paziente, e una descrizione dello stato attuale di salute; di contro, i metodi definiti
su oggetti di tipo Cartella Clinica sono essenzialmente quelli che permettono
laggiornamento delle variabili membro. Sulla seconda classe, Gestore Cartella,
sono definiti tutti i metodi per linserimento, aggiornamento, ricerca e
cancellazione di cartelle. Infine, sulla terza classe, Gestore file, sono definiti i
metodi per larchiviazione su file di cartelle.
La figura 2 schematizza il diagramma delle classi per lapplicazione in
questione. La comunicazione ed interazione tra gli oggetti avviene mediante
linvocazione dei metodi e scambi di messaggio. Ad esempio se il Gestore Cartelle
vuole creare una nuova cartella e archiviarla, dovr richiamare (istanziare) prima
un oggetto di tipo Cartella Clinica e utilizzare i vari metodi di set della classe, e,
successivamente richiamare un oggetto di tipo Gestore File con il metodo di
salvataggio, esplicitando nel messaggio di richiamo del metodo tutte le
informazioni relative alla cartella clinica da archiviare. da notare, in questo caso,
come laggiunta di nuove funzionalit di gestione delle cartelle (ad esempio la
stampa dellelenco di tutte le cartelle dei pazienti) non provochi problemi nel
codice (tutta la logica di gestione dei dati delle cartelle incapsulata nella classe
Cartella Clinica ed solo attraverso essa che possibile accedere ai dati di un
paziente), ma solo laggiunta di un metodo nella classe Gestore Cartella.
La programmazione orientata agli oggetti 335

Figura 2 Diagramma delle classi i di unapplicazione OO


9.2.1. La nascita della programmazione ad oggetti
I primi concetti relativi al Object Oriented Programming (OOP) si ritrovano
nel vecchio linguaggio Simula-67, creato in Scandinavia nel 1967. Simula fu creato
per rendere semplice il compito della simulazione, e, dal mondo della simulazione,
provengono le idee portanti del paradigma ad oggetti. La simulazione di sistemi
reali, infatti, tratta una quantit di entit separate ed autonome chiamate oggetti,
che comunicano tra di loro scambiandosi dei messaggi. Fu naturale rendersi conto
che nello stesso modo si poteva impostare la soluzione di molti altri problemi di
natura completamente diversa: nacquero cos i primi linguaggi interamente ad
oggetti, nei quali cominciano a comparire i concetti di ereditariet e delle propriet
ad essa collegate. Smaltalk sicuramente il pi completo ed il pi puro dei primi
linguaggi object oriented, anche se la programmazione Object Oriented deve il suo
successo a linguaggi pi semplici ed efficienti come C++ (ottenuto per estensione
del C) e Java, oramai largamente usati nel mondo universitario, ma anche nel
mondo delle industrie del software.
In figura 3 mostrata levoluzione dei linguaggi di programmazione a partire

da quelli imperativi e procedurali ai linguaggi orientati agli oggetti concorrenti.


Figura 3 Evoluzione dei linguaggi di programmazione

Nel paradigma di programmazione imperativo un programma specifica


linsieme delle azioni che devono essere eseguite in sequenza per calcolare i
336 Capitolo nono

risultati a partire dai dati, in quello procedurale un programma visto come un


insieme di procedure o funzioni, mentre nella nuova visione del paradigma ad
oggetti, un programma un insieme di oggetti software che cooperano per
produrre risultati.

9.3. I fondamenti della programmazione ad oggetti


Come gi ampiamente discusso, la caratteristica fondamentale della OOP,
rispetto ai paradigmi di programmazione precedenti, che essa permette di
focalizzare lattenzione sui concetti invece di pensare al codice (alle
procedure) che servono ad implementare quei concetti, come accade per i linguaggi
convenzionali. Scrivere un programma significa allora concentrarsi anzitutto sulla
individuazione dei concetti e sul modo in cui essi sono in relazione tra di loro.
I concetti chiave dellOOP sono tre: gli oggetti, le classi e lereditariet. Da
ci discendono due caratteristiche molto potenti, quali il polimorfismo ed il binding
dinamico, come vedremo dettagliatamente nel seguito.
9.3.1. Oggetti e classi
La programmazione orientata agli oggetti si basa sul seguente punto di vista:
il mondo fatto di oggetti, e, dato che un programma una rappresentazione (un
modello) nel calcolatore di una certa realt di interesse, allora anche il programma
sar composto di oggetti, detti oggetti software (o anche solo oggetti).
Nella programmazione orientata agli oggetti, lenfasi posta non tanto sulle
azioni che devono essere svolte quanto sugli oggetti che compiono/subiscono tali
azioni. Gli oggetti cooperano e comunicano tra loro mediante messaggi. Pi nel
dettaglio, da un lato, abbiamo a che fare con gli oggetti della realt fisica: ad
esempio, nella modellazione di elementi geometrici, sono oggetti punti, linee,
angoli, solidi; nella modellazione di un zoo, sono oggetti i differenti animali, le
gabbie, il cibo, e cos via. Dallaltro canto, un programma non ha a che fare
direttamente con oggetti reali, ma con una loro appropriata rappresentazione che
pu a sua volta essere chiamata oggetto.
La programmazione Object Oriented utilizza il concetto di oggetto in
entrambi i sensi: al livello di analisi e progetto, un oggetto coincide con un oggetto
reale, mentre a livello implementativo un oggetto una rappresentazione
appropriata di un oggetto reale.
Si consideri ad esempio un oggetto reale quale una autoradio. Essa
contraddistinta da un nome (attraverso il quale possibile referenziarla) e da una
marca e modello. Un oggetto di tipo autoradio sapr inoltre compiere determinate
azioni quali, accendersi, spegnersi, cambiare canale, regolare volume, sintonizzarsi
un nuovo canale, etc,e, si trova in ogni istante in un certo stato, specificato da un
insieme di propriet. Per esempio, pu essere accesa e sintonizzata su un dato
canale con il volume al massimo o al minimo (le propriet hanno un nome, un
insieme di valori ammissibili e un valore corrente). Linsieme delle operazioni che
una radio in grado di compiere costituisce il comportamento delloggetto.
Si possono poi utilizzare alcuni comandi presenti sul volante della macchina
per far eseguire allautoradio delle operazioni, nella terminologia della
programmazione ad oggetti, la richiesta dellesecuzione di unoperazione viene
La programmazione orientata agli oggetti 337

fatta mediante linvio di un messaggio ad un oggetto. Un altro aspetto notevole di


una radio che per utilizzarla non necessario conoscerne il funzionamento
interno, ma sufficiente avere una descrizione delle operazioni che in grado di
eseguire (come si trovano ad esempio nel manuale duso). La descrizione di
ciascuna operazione data specificando il formato del messaggio (e.g.,, premere
un tasto) e il significato (e.g., la pressione del tasto provoca il cambiamento di
canale). Le precedenti caratteristiche si ritrovano anche negli oggetti software. Un
oggetto software:
- ha un nome che permette di referenziarlo univocamente,
- ha un comportamento in quanto capace di eseguire determinate
operazioni,
- ha uno stato che caratterizzato da un insieme di propriet,
- soddisfa uninterfaccia che una descrizione delle operazioni che pu
eseguire,
- ha unimplementazione: ossia un insieme di istruzioni che specificano nel
dettaglio come le operazioni sono eseguite.

Figura 4 Oggetto di tipo autoradio

Un oggetto caratterizzato quindi da un nome, dei dati o propriet e dei


metodi od operazioni. Loggetto software autoradio nella pratica un modello di
unautoradio, che esiste solo, virtualmente, nel calcolatore. Solo gli aspetti di
unautoradio reale che sono ritenuti rilevanti per lapplicazione sono mantenuti (ad
esempio, le diverse modalit di funzionamento dellautoradio, come lettore CD o
MP3 non sono considerate), inoltre, i suoi dati sono modificabili esclusivamente
attraverso i metodi, la cui implementazione celata allutente (incapsulamento).
In figura 4 riportata una rappresentazione di un oggetto software di tipo
autoradio.
In generale, per usare un oggetto software sufficiente conoscerne solo
linterfaccia (il manuale duso, o in altri termini, la descrizione delle operazioni).
Nella terminologia della programmazione ad oggetti, lo stato di un oggetto
determinato dai suoi dati, e il comportamento dai suoi metodi. Una propriet
importante degli oggetti , come gi anticipato, lincapsulamento dei dati, che
permette di nascondere la rappresentazione dei dati e limplementazione delle
operazioni sui dati. Ci offre diversi vantaggi:
- modularit che implica che un oggetto pu essere gestito
indipendentemente dagli altri
338 Capitolo nono

- scomponibilit in quanto possibile costruire oggetti complessi a partire


da oggetti semplici
- riusabilit perch gli oggetti possono essere riutilizzati
- Il meccanismo di separazione tra linterfaccia di un oggetto e la sua
implementazione anche noto con termine di information hiding.
Lunica modalit a disposizione dei programmatori per lattivazione dei
metodi definito su un dato oggetto lo scambio di messaggi. Ci implica che lo
stato di un oggetto manipolabile solo dai metodi definiti sulloggetto stesso (vedi
figura 5) . Un messaggio composto da tre elementi:
- ricevitore: loggetto cui indirizzato il messaggio
- selettore: il metodo che si vuole eseguire
- parametri: eventuali parametri del metodo.

Figura 5 Schematizzazione di oggetti

In seguito alla ricezione di un messaggio, un oggetto verifica che vi sia


unoperazione avente lo stesso profilo, ed esegue il metodo corrispondente. Ad
esempio se si vuole aumentare di 1 il volume dellautoradio, allora il telecomando
potrebbe inviare un messaggio caratterizzato dalla tripla: (Autoradio, Aumenta
Volume(), 1).
Altri esempi di oggetti sono ancora un conto bancario, caratterizzato dagli
attributi, numero conto corrente, intestatario, ABI, CAB, CIN, nome filiale, e, dai
metodi apri conto, chiudi conto, preleva, deposita; oppure un magazzino
caratterizzato dagli attributi, nome, descrizione, locazione e lista prodotti, e, dai
metodi inserisci prodotto e rimuovi prodotto, cerca prodotto, stampa
inventario prodotti.
Ogni oggetto pu essere quindi visto come unentit dotata di caratteristiche
(attributi) e funzionalit o servizi (metodi), il cui stato modificabile solo mediante
uno scambio di messaggi con altri oggetti del dominio applicativo. Il confinamento
di informazioni e funzionalit in oggetti permette poi livelli maggiori di astrazione
e semplifica la gestione di sistemi complessi.
Un altro concetto fondamentale nella programmazione orientata agli oggetti
quello di classe. Una classe pu essere vista come una descrizione, sia
strutturale che comportamentale, di un insieme di oggetti simili. Una classe una
sorta di modello o prototipo che definisce un tipo di oggetto (attributi e metodi
simili ad un insieme di oggetti), e, ancora, una classe il progetto di una famiglia
di oggetti software. Tutti gli oggetti appartenenti a una classe hanno: la stessa
struttura (attributi), un comportamento simile (operazioni) ed una semantica
comune.
La programmazione orientata agli oggetti 339

In genere una classe identifica un tipo di dato astratto, ovvero un tipo non
predefinito nel linguaggio, ma costruito ad hoc dal programmatore, e gestito
come un tipo primitivo del linguaggio (la sua rappresentazione pu essere
modificata solo mediante gli operatori definiti sul tipo attraverso il meccanismo
dellincapsulamento). Esempi di classi sono: linsieme delle autoradio prodotte da
varie case costruttrici, linsieme dei conto correnti di uno o pi istituti bancari,
linsieme delle cartelle cliniche dei pazienti afferenti ad una data struttura
ospedaliera, etc
Riferendoci allesempio dellautoradio, cos come si possono costruire molte
autoradio diverse sulla base di un unico progetto (e.g., modelli differenti di una
stessa marca), analogamente, si possono costruire molti oggetti descritti da una
stessa classe.
Nella programmazione orientata agli oggetti comune avere molti oggetti
dello stesso tipo con caratteristiche simili. Il processo di creazione di un oggetto a
partire da una classe detto istanziazione, e, un oggetto descritto da una certa
classe detto unistanza di quella classe; istanze diverse di una stessa classe sono
da considerarsi distinte, in particolare, ciascuna istanza possiede e manipola un
proprio stato. Le classi, invece, non hanno uno stato, cos come non ha senso dire
che il progetto di un autoradio spento o acceso.
Il lavoro del programmatore consiste nellindividuazione delle varie tipologie
di oggetti software necessarie per un programma e nella definizioni della classi, per
ciascuna tipologia di oggetto. La progettazione di una classe prevede la definizione
degli attributi e delle operazioni comuni agli oggetti descritti dalla classe, la
progettazione dellinterfaccia con la definizione dei metodi accessibili
pubblicamente, e limplementazione di ciascun metodo.
Una classe deve rappresentare un unico concetto e soddisfare i seguenti
requisiti:
- coesione - gli attributi e i metodi devono essere strettamente correlati al
concetto rappresentato dalla classe
- coerenza - la descrizione delle operazioni deve seguire uno schema
coerente.
opportuno che un oggetto rappresenti un concetto ben definito e che
rimanga in uno stato consistente per tutto il tempo che viene utilizzato, dalla sua
creazione alla sua distruzione. Inoltre in un insieme di classi preferibile avere un
basso livello di accoppiamento, cio di dipendenza tra le classi. Uneccezione
costituita, come vedremo, dal meccanismo dellereditariet.
9.3.2. Oggetti software e classi come implementazioni di tipi di
dato astratto
Da un punto di vista implementativo un dato oggetto pu essere visto come
una sorta di dato strutturato, ad esempio un record Pascal o una struttura C, su cui
agiscono un insieme di metodi che permettono di aggiornare i campi elementari del
dato.
Un oggetto quindi assimilabile ad una struttura che occupa uno spazio di
memoria durante lesecuzione del programma, ed composto da un certo numero
di campi. In figura 6 sono mostrati degli oggetti che descrivono in modo parziale
personaggi di film fantasy.
340 Capitolo nono

Un oggetto spesso include riferimenti ad altri oggetti. Nel caso dei personaggi
di un film, il riferimento sicuramente al film stesso. Un riferimento pu contenere
un oggetto come suo valore (vedi figura 7).
Programmare con il paradigma OO significa creare un gran numero di oggetti
in maniera dinamica, seguendo un pattern che non semplice predire a priori.
Come gi discusso nel paragrafo precedente, nel paradigma OO, invece che
descrivere un unico oggetto, si descrive quanto vi di comune ad una intera
categoria di oggetti, attraverso il concetto di classe.
Da un punto visto implementativo, quindi, una classe simile ad un tipo
record od ad un tipo struttura.
Di seguito viene riportata una possibile definizione in un linguaggio simile al
C, per la classe Personaggio, che descrive i personaggi di film fantasy (ssi suppone
lesistenza del tipo String per la gestione di stringhe di caratteri).

Class Personaggio {
String Nome;
String Razza;
String Classe;
Film NomeFilm;
}

Nome, Razza, Classe e NomeFilm rappresentano gli attributi o variabili


membro della classe; NomeFilm inoltre il riferimento ad un oggetto appartenente
alla classe Film (con attributi Nome, Regista, Nazione) che descrive invece i film.

Class Film {
String Nome;
String Regista;
String Nazione;
}

Figura 6 Oggetti come record


La programmazione orientata agli oggetti 341

da notare che ogni classe descrive un insieme di oggetti potenzialmente


infinito. Quindi un oggetto listanza di una classe, la quale pu essere vista
come il tipo di un oggetto. Si noti inoltre che, mentre il concetto di oggetto esprime
un concetto a tempo di run-time (un oggetto creato durante lesecuzione di un
programma), quello di classe invece un concetto statico a livello di compilazione:
a tempo di esecuzione esistono solo oggetti; a tempo di compilazione solo classi.

Figura 7 Relazioni tra oggetti

Oltre che dagli attributi, una classe caratterizzata da operazioni o metodi che
modificano il valore dei suoi attributi. Prendiamo ad esempio in considerazione la
classe che descrive i numeri complessi:

class Complex{
float Re;
float Im;
}

e siano c1 ed c2 due oggetti della classe Complex

Complex c1, c2;

Per operare su di essi si possono definire delle procedure che permettono di


accedere alla parte reale e alla parte immaginaria e di calcolare il modulo del
numero complesso. Tali procedure caratterizzano il tipo Complex, e costituiscono a
tutti gli effetti parte delle descrizione delloggetto complesso, quindi della sua
342 Capitolo nono

classe. Tenendo conto dei metodi associati ad una classe, la definizione del tipo
Complex si modificher allora come nel seguito:

class Complex{
float Re;
float Im;
public:
float getReal();
float getImg();
void setReal(float reale);
void setImg(float immaginario);
float getModule();
}

Dove lidentificatore public indica che i metodi di getReal, getImg, setReal,


setImg e getModule, sono metodi pubblici che possono essere utilizzati da
qualsiasi altro oggetto esterno. Gli attributi, al contrario, non sono modificabili da
oggetti esterni.
In realt concetti di classe ed oggetto intuitivamente ricalcano quello che in
informatica teorica viene chiamato Tipo di Dato Astratto (Abstract Data Type,
ADT). Come gi ricordato, un tipo di dato astratto un tipo di dato definito
dallutente, e, quindi non predefinito nel linguaggio, che per viene gestito come
un tipo primitivo, ovvero la sua rappresentazione pu essere modificata solo
mediante gli operatoti definiti sul tipo. Una classe quindi limplementazione di
un ADT.
Un ADT descrive una classe di strutture dati non attraverso la sua
implementazione, ma attraverso un elenco di servizi disponibili sulla struttura
dati, e attraverso alcune propriet che formalmente descrivono e specificano questi
servizi. Un ADT, in altre parole, una descrizione precisa, non ambigua, e
completa di una classe di dati, senza alcuna descrizione della sua possibile
rappresentazione fisica.
Possiamo dire allora che un ADT una classe di strutture dati descritte
attraverso una vista esterna: servizi disponibili e propriet di questi servizi.
Un esempio classico quello dello Stack. Uno stack caratterizzato da alcuni
servizi verso lesterno e da alcune propriet che ne definiscono la struttura; la pi
importante delle quali la strategia con cui si accede agli elementi dello stack che
la cosiddetta LIFO (Last In First Out). Il tipo Stack, definito su un insieme di
oggetti T, deve poter offrire quindi allesterno operazioni per la creazione dello
stack (CreaUnoStack), per linserimento e prelievo di un elemento dallo stack
(push e pop) e per verificare se lo stack vuoto (Vuoto):

CreaUnoStack();
push (T elem);
T pop ();
Vuoto();

operazioni che devono soddisfare le seguenti precondizioni o assiomi:


La programmazione orientata agli oggetti 343

- possibile effettuare unoperazione di pop se e solo se lo Stack non


vuoto;
- appena creato lo Stack, questultimo vuoto;
- effettuando unoperazione di push, lo Stack non vuoto;
- se si esegue unoperazione di pop dopo aver fatto una di push, lo Stack
rimane nello stato di partenza;
- un oggetto inserito, viene inserito sempre in testa.
Nel caso pi generale, un classe dotata di tre tipi di metodi:
- Costruttori
- Metodi di Accesso
- Metodi di trasformazione
Di fatto, nel caso precedente dello stack, il metodo creaUnoStack istanzia un
possibile stack, ed dunque un costruttore di tipo; il metodo Vuoto invece un
metodo che restituisce una informazione relativa allo stack, dunque un metodo di
accesso alle stack. I metodi push e pop, invece, sono dei metodi che trasformano lo
stato dello stack, e sono dunque dei metodi di trasformazione. Il metodo Vuoto,
inoltre, potrebbe essere messo a disposizione dellutente del tipo, oppure
semplicemente usato per verificare la presenza di elementi nellesecuzione delle
operazioni di pop. In questo ultimo caso, diciamo che il metodo privato alla
classe, ovvero quando usabile solo dai metodi della classe stessa e non
dallesterno.
Si nota, dunque, che il tipo di dato astratto nasconde allesterno
linformazione (information hiding): lunico modo per manipolare i dati che essa
gestisce, luso dei metodi. Come implementato lo stack, ovvero la struttura dati
che ne permette la realizzazione, non interessa allutente finale: lo stack pu essere
realizzato tramite array di elementi di tipo T o tramite liste a puntatori, ed il tutto
deve essere trasparente allutente finale. Ogni utente deve poi poter continuare ad
usare le operazioni di push e pop in modo del tutto indifferente dalla loro
implementazione: non interessa quindi il come fatto, ma cosa si possa fare
con un ADT.
In un certo senso, come se linsieme dei servizi offerti dallADT ad un
utente, ovvero la sua interfaccia, costituisca una sorta di contratto tra il
programmatore e lutilizzatore dellADT.
Di seguito riportata una possibile implementazione completa della classe
Stack per la gestione di pile di caratteri.

// Definizione della classe Stack


Class Stack {
// struttura dati utilizzata per limplementazione dello stack
char elem_array [DIMMAX] ;
//riferimento alla testa dello stack ed elemento di testa dello stck
int top;
char top_elem;
// Definizione dei metodi per la gestione dello stack
public:
// Metodo Costruttore
void CreaUnoStack();
// Operazioni di pup e push
344 Capitolo nono

void push (char elem);


void pop();
private:
// Metodo di verifica se lo stack vuoto
int Vuoto();
};
// Implementazione dei metodi
// Metodo costruttore: produce l'inizializzazione dello stack
void Stack::CreaUnoStack () {
top=-1 ; // resetta il riferimento alla testa dello stack
};
// Metodo push: inserisce un elemento in testa allo stack
void Stack::push ( char elem ) {
top=top+1 ;
elem_array[top]=elem ;

};
// Metodo pop: elimina l'elemento di testa dallo stack
char Stack::pop () {
if (!Vuoto()) {
top_elem=elem_array[top] ;
top=top-1 ;

}
else top_elem=;
return top_elem;
};
// Metodo Vuoto: controlla se lo stack vuoto (ritornando il valore 1)
int Stack::Vuoto () {
if ( top==-1 ) return 0 ;
else return 1 ;
};
9.3.3. Il meccanismo dellereditariet
Lereditariet sicuramente una delle caratteristiche pi importanti dei
linguaggi orientati agli oggetti. Come visto, il concetto di classe e di oggetto
ricalcano quanto teoricamente previsto negli ADT o in alcuni linguaggi basati sugli
oggetti (object based).
Un linguaggio segue il paradigma di programmazione orientato agli oggetti se
e solo se object based ed implementa un meccanismo linguistico noto con il
termine di ereditariet o inheritance .
Il concetto di ereditariet alla base della riusabilit e dellestensibilit dei
sistemi software. Il mondo reale, daltro canto, permette di definire tipi di oggetto a
partire da tipi di oggetto gi noti, per estensione, specializzazione o combinazione
di questi.
Lereditariet il processo di creazione di una nuova classe con le
caratteristiche di una classe esistente e con altre caratteristiche peculiari. Pi nel
dettaglio, essa rappresenta il meccanismo attraverso il quale possibile riusare
La programmazione orientata agli oggetti 345

(ereditare) le caratteristiche (attributi e metodi) di una classe, detta superclasse, da


parte di altre classi dette sottoclassi.
Ogni sottoclasse eredita la struttura ed il comportamento dalla superclasse
e viene specializzata rispetto alle caratteristiche di questultima attraverso la
definizione delle proprie caratteristiche specifiche che consiste nellaggiunta di
nuovi attributi e metodi , e/o, ridefinizione dei metodi esistenti. Inoltre, la modifica
delle caratteristiche della superclasse influenzano direttamente tutte le sottoclassi.
In altri termini lereditariet un potente meccanismo di strutturazione dei
programmi che consente di definire nuove classi a partire da quelli esistenti,
ponendosi come obiettivi principali il riuso e lestensibilit del codice.
Si prenda, ad esempio, in considerazione il mondo geometrico, ed in
particolare una classe ben definita detta Poligono. Un poligono, come mostrato di
seguito, definito dai suoi vertici e da alcuni metodi per il calcolo, ad esempio, del
perimetro o dellarea.

Class Poligono {
Vertex v1,,vn;
public:
float area();
float perimetro();
}

Se si deve definire un rettangolo vi sono due possibili alternative: si definisce


la classe Rettangolo da zero, rimplementandone struttura dati e metodi, oppure si
prende in considerazione il fatto che un rettangolo un tipo di poligono, per cui
valgono tutte le propriet gi definite per il poligono pi altre propriet
caratteristiche del rettangolo stesso. Il meccanismo che permette di ottenere tale
gerarchia di classi , per lappunto, lereditariet. Il Poligono verr detto
superclasse o genitore del rettangolo (parent oppure ancestor), mentre il
Rettangolo detto sottoclasse o figlio (descendant) del poligono.
Si deve dunque esprimere che una classe Rettangolo eredita dalla classe
Poligono i suoi dati ed i suoi metodi con una sintassi del tipo:

class Rettangolo inherits from Poligono{


public:
float diagonale( );
}

Il che vuol dire che anche area e perimetro sono metodi della classe
Rettangolo, ed anche i vertici v1,,vn (eventualmente per n=4) sono dati della
classe stessa. In aggiunta la classe Rettangolo prevede il metodo per il calcolo
della diagonale.
In altre parole, lereditariet permette di riutilizzare i servizi offerti da una
classe padre: se Y ereditata da X, allora tutti i servizi di X sono automaticamente
disponibili in Y, senza ulteriori definizioni, restando inteso che Y pu aggiungere
nuove caratteristiche (dati e servizi) per i prorpri scopi specifici.
Si noti che lereditariet a volte vista come una estensione ed altre volte
come una specializzazione. Dire che un rettangolo discende da poligono, equivale a
346 Capitolo nono

dire che un rettangolo un poligono. Nelle reti semantiche, questo tipo di relazione
anche detta relazione di tipo is_a. Daltro canto, considerando i servizi offerti dal
rettangolo, possiamo dire che essi sono sicuramente i servizi offerti dal poligono
con i pi i metodi particolare del rettangolo: in questo senso un rettangolo anche
una estensione della classe poligono. Un ultima considerazione riguarda la
possibilit di prevedere nei linguaggi orientati agli oggetti la cosiddetta ereditariet
multipla, che permette ad una classe di discendere da pi classi
contemporaneamente.
Lereditariet favorisce la progettazione e lo sviluppo di un sistema software
in modo completamente differente da quello tradizionale: invece di riprogettare ed
implementare tutto da zero, lidea quella di costruire nuovi programmi su quanto
gi fatto, estendendone le caratteristiche.
Per concludere il paragrafo, si vuole infine fare osservare come, nella
progettazione OO, lereditariet non lunica forma di relazione tra oggetti. In
pratica esistono varie tipologie di relazioni, le pi comuni sono:
- generalizzazione/specializzazione ottenute attraverso il meccanismo di
ereditariet;
- composizione/aggregazione che indicano che un dato oggetto di una data
classe costituito da uno o pi oggetti di unaltra classe;
- associazione che indica che ad un dato oggetto di una data classe
associato uno o pi oggetti di unaltra classe.
Infine un ulteriore potente meccanismo della programmazione OO quello
della redefinition o overloading: alcuni metodi offerti da X possono essere
ridefiniti in Y in maniera pi appropriata. La ridefinizione permette di cambiare
limplementazione di un metodo da parte della classe figlia, senza alterazione della
semantica.
9.3.4. Polimorfismo e binding dinamico
Con il termine polimorfismo si intende in generale la capacit di assumere
forme differenti. Nella programmazione orientata agli oggetti, si intende la capacit
di un oggetto di essere istanza di classi differenti. Siano ad esempio date le
dichiarazioni:

Poligono p; Rectangle r;

Allora la seguente assegnazione corretta:

p=r;
essendo ovviamente p ed r i riferimenti agli oggetti. Ci discende dal fatto che
r, essendo rettangolo, un poligono. E invece scorretta lassegnazione:

r=p;

in quanto un poligono non un rettangolo. Lidea di oggetti che assumono


forma differente risulter chiaro dallesempio seguente. Sia data la seguente
gerarchia di classi ottenuta attraverso il meccanismo di ereditariet:
La programmazione orientata agli oggetti 347

// Esempio perpolimorfismo
class Animale{
public:
void RiproduciVerso();
};
class Mammifero inherits from Animale;
class Quadrupede inherits from Mammifero;
class Cane inherits from Quadrupede;
class Gatto inherits from Quadrupete;

Cane pluto;
Gatto tom;

Loggetto tom (cos come loggetto pluto) a sua volta un oggetto di tipo
quadrupede, un oggetto di tipo mammifero ed un di tipo oggetto animale. come
dire che i gatti (ed i cani) sono degli animali mammiferi.
Consideriamo, tuttavia, il metodo pubblico della classe animale
RiproduciVerso che evidentemente deve poter esprimere il verso di un animale (se
emette suoni). Si supponga che la classe Cane e la classe Gatto ridefiniscano il
metodo, nel seguente modo:

Cane::RiproduciVerso(){
printf( Bau Bau Bau);
}

Gatto::RiproduciVerso(){
printf( Miao Miao);
}

Si consideri ora il seguente frammento di codice (si nota che con la sintassi
nome_oggetto->nome_metodo si attiva il metodo selezionato della classe a cui
appartiene loggetto):

a=pluto;
a->RiproduciVerso();
a=tom;
a->RiproduciVerso();

La prima esecuzione del metodo RiproduciVerso stamper a video Bau Bau


Bau, mentre la seconda esecuzione far stampare a video Miao Miao. Loggetto
animale dapprima un cane, per cui verr applicato il metodo
Cane::RiproduciVerso(), quindi un gatto (per effetto del polimorfismo), e dovr
essere logicamente applicato il metodo Gatto::RiproduciVerso().
Questa regola nota anche con il termine di collegamento dinamico o
dynamic binding ed afferma che la forma dinamica delloggetto a determinare
quale versione del metodo deve essere applicato ad un oggetto polimorfo.
Polimorfismo e binding dinamico, entrambi direttamente discendenti dal
348 Capitolo nono

meccanismo dellereditariet, sono le propriet pi importanti dei sistemi Object


Oriented.
9.3.5. Note di progetto
Come si pu intuire alla fine di questa breve trattazione, programmare ad
oggetti non velocizza lesecuzione dei programmi e non ottimizza luso della
memoria. allora lecito domandarsi: perch programmare a oggetti? La risposta
che programmare ad oggetti facilita, come visto e discusso ampiamente nei
precedenti paragrafi, la progettazione, lo sviluppo e il mantenimento di sistemi
software molto complessi, cosa che invece non accade con un approccio di tipo
procedurale.
Ricapitolando, si visto come le caratteristiche principali del paradigma
object oriented sono:
- astrazione dei dati: possibile creare nuovi tipi di dato per adattare
lambiente di programmazione alle proprie esigenze;
- ereditariet: una volta definito un tipo, si possono specificare altri tipi
basati su di esso;
- polimorfismo: possibile rendere i tipi derivati estensibili rispetto ai
tipi base.
Attraverso tali caratteristiche la programmazione ad oggetti consente di:
- ridurre la dipendenza del codice di alto livello dalla rappresentazione dei
dati (laccesso ai dati mediato da uninterfaccia);
- riutilizzare del codice di alto livello;
- sviluppare moduli indipendenti luno dallaltro.
Vengono cos a scomparire i difetti derivanti da un software non manutenibile
(ad esempio ottenuto con un approccio procedurale) come:
- la rigidit (i.e., non pu essere cambiato con facilit e non pu essere
stimato limpatto di una modifica),
- la fragilit (i.e., una modifica singola causa una cascata di modifiche
successive ed i bachi sorgono in aree concettualmente separate dalle aree
dove sono avvenute le modifiche),
- la non riusabilit (i.e, esistono molte interdipendenze, quindi non
possibile estrarre parti che potrebbero essere comuni).
Capitolo decimo

Introduzione ai Sistemi Operativi

10.1. Introduzione
Un Sistema Operativo una componente fondamentale di un sistema di
calcolo e cercare di delineare brevemente le sue caratteristiche fondamentali una
attivit complessa. Per questo, invece di iniziare con definizioni rigorose,
cercheremo di far anzitutto comprendere il motivo per cui sono sorti i sistemi
operativi sulla scena dell'informatica, mostrando di volta in volta le problematiche
che essi sono chiamati a risolvere.
Si consideri un sistema di calcolo secondo il modello di von Neumann: i
processi elaborativi, intesi come programmi o parti di programma in esecuzione
vengono eseguiti di fatto dalla CPU con velocit diverse. Ad esempio un processo
di stampa dei risultati viene eseguito con una velocit differente rispetto ad un
processo di calcolo per la lentezza dei dispositivi (alcuni meccanici) della
stampante. Pi precisamente, prendiamo in esame un sistema come quello in
figura 1 ed un programma che effettui la somma ed il prodotto di due numeri:
inizialmente i valori devono essere prelevati da tastiera e, dopo aver effettuato gli
opportuni calcoli, i risultati devono essere visualizzati sul monitor.

Figura 1 Esempio di sistema con i due canali input standard ed output standard
350 Capitolo decimo

La CPU non solo deve eseguire le istruzioni di calcolo ma, interfacciandosi


con i dispostivi di I/O, anche quelle di ingresso e uscita dei dati con processi
diversi che devono essere sincronizzati, come mostrato di seguito.

input(dato1);
input(dato2);
somma:=dato1+dato2;
output(somma);
prodotto=dato1xdato2;
output(prodotto);

Individuiamo banalmente tre processi: input da tastiera, calcolo e stampa; se


plausibile che essi presentano tempi di elaborazione differenti, altres
impensabile che la somma dei numeri sia eseguita prima dellinput dei dati, o che
loutput avvenga dopo la produzione dei risultati.
In altre parole, necessario introdurre dei meccanismi di sincronizzazione tra
i tre processi: possibile fare le operazioni sono quando i dati di ingresso sono
pronti, ed possibile effettuare una stampa solo quando i risultati sono stati
prodotti. Un sistema semplice per effettuare la sincronizzazione dei sistemi
periferici consiste nellattribuire ad ogni sistema di gestione della periferica (detto
anche canale) un registro di stato, in cui un particolare bit, detto bit di flag, indica
se la periferica ha completato lultima operazione richiesta.

Figura 2 Diagrammi di flusso per la sincronizzazione

Nel caso del canale di gestione della tastiera, tale bit 1 quando stato
premuto e rilasciato un carattere nel buffer di lettura, ed 0 quando tale carattere
prelevato dalla CPU. Analogamente per il monitor, il bit uguale ad 1 indica che la
periferica ha terminato loperazione di stampa ed pronta a ricevere un altro
carattere nel buffer (si suppone che la periferica sia in grado di stampare un solo
carattere per volta), il bit viene poi posto a 0 dalla CPU dopo linvio del dato.
In un sistema cos gestito, la CPU per effettuare le istruzioni di input ed
output interroga ciclicamente i registri di stato delle periferiche, aspettando che
abbiano termine eventi esterni non dipendenti da essa, quali linserimento di un
Introduzione ai sistemi operativi 351

dato da parte di un operatore: solo quando i bit di flag sono uguali ad uno, pu dirsi
completata l'operazione di lettura, ovvero:
- nel caso della tastiera prelevando il dato dal buffer dati e ponendo il bit a
0;
- nel caso del monitor inviando il dato nel buffer dati e ponendo il bit a 0.
Quelle finora descritte prendono il nome operazioni di lettura e scrittura a
controllo di programma.

Figura 3 Diagrammi di flusso per la sincronizzazione

La strategia di sincronizzazione presentata, a causa delle differenti velocit di


elaborazione tra le istruzioni di calcolo interno (dellordine dei nanosecondi) e le
istruzioni di input/output (dellordine dei millisecondi perch richiedono il
colloquio con i dispositivi di I/O) portano ad un uso non intelligente della risorsa
CPU che, nel caso di programmi con molte operazioni di I/O, passa la gran parte
del proprio tempo ad interrogare lo stato delle periferiche.
I tempi complessivi di elaborazione sono dati dalla somma dei tempi necessari
alla terminazione dei singoli processi e comprendono quindi tempi che non
dipendono dalle capacit della CPU. Nel caso delle operazioni di input, ad
esempio, tali tempi dipendono dalle capacit delloperatore o dalla tempestivit
con la quale inserisce i valori.

Figura 4 Tempi di elaborazione


352 Capitolo decimo

Quanto precedentemente descritto mostra come, anche per un esempio molto


semplice, esiste la necessit di utilizzare al meglio il tempo della CPU, evitando di
introdurre inutili tempi di attesa a scapito della velocit e dellefficienza che si
richiede a sistemi complessi e, per certe applicazioni, con tempi di risposta
stringenti e critici. Ci ha fatto nascere lesigenza di introdurre programmi capaci
di amministrare in modo pi razionale tutte le risorse di un calcolatore, CPU
compresa. Tali programmi sono appunto i sistemi operativi.

10.2. Caratteristiche di un Sistema Operativo


Esistono nella relativa letteratura specializzata molte definizioni di che cosa
un sistema operativo e di quale sono le sue funzionalit, anche per il fatto che i
sistemi operativi hanno avuto unevoluzione storica connessa al parallelo sviluppo
dellhardware dei calcolatori e alle crescenti esigenze degli utilizzatori.
Seconda una definizione di tipo generale, un sistema operativo un insieme
di programmi (spesso di grande complessit) che implementano le funzioni
essenziali per la gestione di un sistema di elaborazione e realizzano
uninterfaccia facile da usare tra lhardware della macchina e gli utilizzatori.
Da un punto di vista di tipo top-down un sistema operativo pu essere quindi
visto come una macchina estesa che si pone tra lhardware della macchina e gli
utilizzatori finali (programmatori ed utenti), offrendo a questi ultimi
uninterfaccia gradevole ed amichevole. Tale aspetto pone laccento su tutti i
problemi di interfaccia utente e di semplicit duso che sono molto attuali per chi
progetta e realizza sistemi operativi. Basti pensare alle interfacce grafiche degli
attuali sistemi operativi quali Windows, Linux e MacOS che permettono agli utenti
di interagire con la macchina attraverso semplici click del mouse.
Da un punto di vista bottom-up, invece un sistema operativo risulta un
gestore delle risorse hardware e software di un sistema di elaborazione quali la
CPU, la memoria, i dischi, i dispositivi di I/O, programmi, etc In questo caso
lattenzione posta sullattivit di supervisore che il sistema operativo deve
esercitare nei confronti degli altri programmi eseguiti sulla macchina e di gestore
delle risorse hardware di un calcolatore.
Si pu dire che un sistema operativo consente di creare un ambiente di lavoro
virtuale su di una macchina, ponendosi tra la macchina nuda (lhardware) ed il
mondo delle applicazioni. La virtualizzazione delle risorse presenta ai suoi utenti
una macchina astratta caratterizzata dalle sue capacit e non dalla sua struttura. E
le funzionalit principali che devono essere offerte sono:
- offrire un ambiente di lavoro amichevole;
- assegnare a programmi ed utenti le risorse hardware e software disponibili
ottimizzandone lutilizzo;
- controllare lesecuzione dei programmi ed in particolare luso della CPU,
della memoria e dei dispositivi di I/O.
Le applicazioni che vengono solitamente usate dallutente possono prendere
vita soltanto allinterno dellambiente generato dal sistema operativo. Esso ha il
compito fondamentale di controllare e coordinare lutilizzo dellhardware della
macchina per conto degli utenti e delle applicazioni.
In altri termini, un sistema operativo un insieme di programmi che si
interpone tra lhardware di un calcolatore e chi lo deve utilizzare. Tali programmi
Introduzione ai sistemi operativi 353

si pongono lobiettivo di consentire al calcolatore di svolgere le proprie funzioni


con la massima efficienza possibile. Lefficienza di un sistema di elaborazione
delle informazioni, intesa come capacit del sistema di soddisfare al meglio le
esigenze degli utilizzatori, pu essere misurata in vari modi.
Tra le necessit principali che hanno guidato la comparsa prima, e
levoluzione poi dei sistemi operativi, c quella di rendere massimo il lavoro
compiuto dal calcolatore in termini di programmi eseguiti nellunit di tempo,
indicato col termine throughput; nel contempo, si vuole limitare il tempo che
intercorre per ogni programma tra lintroduzione dei dati di ingresso e la
presentazione dei risultati dellelaborazione, di solito indicata con il termine tourn
around time.
Si noti che tali caratteristiche sono in palese contrasto tra loro in quanto bassi
tempi di tourn around time prevedono un uso esclusivo delle risorse di un sistema
da parte dei singoli programmi, condizione che va in contraddizione con laumento
del throughput. Affinch un programma presenti il pi basso tourn around time,
infatti, deve trovare sempre disponibili sia la CPU che le periferiche di input ed
output: ci costringerebbe la CPU a dedicarsi completamente ad un programma
quando potrebbe, invece, eseguirne degli altri mentre il primo fermo in attesa che
operazioni di ingresso ed uscita arrivino a terminazione.
Per consentire alla CPU di non preoccuparsi della gestione dellinput e
delloutput il modello di Von Neumann stato nel tempo modificato fornendo alle
periferiche unautonomia di funzionamento e la capacit di segnalare la
terminazione delle proprie attivit. Ogni periferica viene dotata di un processore
dedicato il cui compito quello di gestire le operazioni di ingresso ed uscita
liberando la CPU da tale compito. Il processore dedicato opera in parallelo con la
CPU e segnala che ha terminato il compito affidatogli inviando una richiesta di
interruzione. La CPU, dal canto suo, dopo aver attivato il processore dedicato, pu
dedicarsi ad altro fino a che non viene interrotto. La figura seguente confronta il
comportamento di un sistema senza processori dedicati (detti anche canali) con uno
che li possiede.

Figura 5 Confronto tra tempi di elaborzione


354 Capitolo decimo

Si nota un miglioramento complessivo del sistema perch vengono utilizzati i


tempi morti dei canali, anche se il tourn around time dei singoli programmi
peggiora.
Inoltre per rendere il calcolatore facilmente usabile e condivisibile da pi
utenti, cos come se si vogliono prevenire situazione di guasti, necessario
concedere tempo di esecuzione e risorse ai programmi del sistema operativo,
sottraendoli ad altri programmi in esecuzione. Si introduce cos una condizione di
sovraccarico gestionale o overhead che di norma tanto pi grande quanto pi
complesso e sofisticato il sistema operativo. Basti pensare ad esempio al sistema
operativo Windows Vista che per un corretto funzionamento richiede quasi un
Giga di memoria centrale.
10.2.1. Levoluzione storica dei Sistemi Operativi
I sistemi operativi, analogamente allhardware dei calcolatori, hanno subito
nel corso della storia una serie di cambiamenti che hanno portato alla nascita degli
attuali sistemi. Levoluzione dei sistemi operativi classificabile in otto
generazioni, dove ogni generazione si distingue dalla precedente per una precisa
evoluzione tecnologica.
1. Anni 40: Assenza dei Sistemi Operativi
2. Anni 50: Monitor e Sistemi Operativi Batch
3. Anni 60: Sistemi Operativi Multiprogrammati
4. Anni 60-70: Sistemi Operativi General Purposes
5. Anni 70: Sistemi Time Sharing
6. Anni 80: Sistemi Operativi per Personal Computer e Sistemi Operativi
Transazionali
7. Anni 90-00: Sistemi Operativi Real-Time, Sistemi Operativi con
supporto per multiprocessore e Sistemi Operativi Distribuiti
8. Anni 00 ad oggi: Sistemi Operativi per dispositivi mobili (palmari,
cellulari, etc..)
Nel periodo che va dalla nascita dei calcolatori agli anni 50 i sistemi operativi
sono praticamente inesistenti: gli utilizzatori scrivono programmi direttamente in
linguaggio macchina e si fanno carico anche del caricamento in memoria e
dellavvio dei programmi. Ogni programma viene caricato singolarmente,
solitamente usando schede perforate, e quindi fatto eseguire fino al suo
completamento o fino a che, per qualche motivo, non si ferma. A questo punto
loperatore pu eseguire la stampa dei risultati oppure, in caso di terminazione
anomala, il dump (stampa) dei registi della memoria per esaminare la causa
dellerrore. La CPU rimane inattiva durante tutte i periodi relativi alla gestione
delle operazioni di I/O e tra lesecuzione di un programma ed un altro.
Negli anni 50 la General Motors produce il primo sistema operativo per il
proprio calcolatore, lIBM 701. Tale sistema operativo, cos come altri della stessa
generazione, era una sorta di monitor che si occupava di caricare i programmi in
memoria e di controllare lesecuzione dello stesso, azzerando poi la macchina tra
unesecuzione e laltra di programmi. I programmi erano fatti in modo da restituire
il controllo, alla fine della propria esecuzione, al sistema operativo che si occupava
di azzerare (anche detto resettare) lo stato della macchina e di iniziare a leggere il
Introduzione ai sistemi operativi 355

programma successivo. Lobiettivo era quello di limitare i tempi morti della CPU,
riducendo lazione delluomo nellesecuzione dei programmi.
Unulteriore ottimizzazione introdotta dai sistemi operativi di questa
generazione quella di raggruppare pi programmi in un singolo gruppo o lotto
(batch), caricandoli tutti, prima dellesecuzione, su una periferica pi veloce del
lettore di schede, ad esempio su nastro magnetico. Il caricamento su nastro viene
fatto fuori linea da un apposito dispositivo, mentre il controllo della esecuzione ed
il passaggio da un programma allaltro avviene utilizzando un apposito linguaggio
di controllo detto Job Control Language (JCL). Inoltre, i suddetti sistemi operativi
mettono a disposizione dei programmatori delle primitive per linput e output sui
dispositivi standard (schede, nastro, stampante, etc) in modo da svincolare questi
ultimi dalla natura delle periferiche di input/ouput.
Con la gestione a lotti si superano i tempi morti legati allinizio e
terminazione dei programmi, permane per ancora il problema della inattivit della
CPU durante le operazioni di I/O. La successiva generazione di sistemi operativi
introduce il concetto di multiprogrammazione che consiste nel caricare in memoria
centrale pi programmi facendo in modo che condividano la CPU. Tale
caratteristica resa possibile grazie allintroduzione di due importanti innovazioni:
- i processori di I/O, ovvero processori pi semplici della CPU, dotati di un
insieme proprio di istruzioni e registri, ed in grado di gestire la
comunicazione con i dispositivi di I/O;
- le interruzioni, ovvero segnali generati dai controllori dei dispositivi di
I/O in grado, arrivando alla CPU, di interrompere il suo normale ciclo di
esecuzione.
Attraverso lintroduzione dei processori di I/O e del meccanismo delle
interruzioni possibile sovrapporre le operazioni di input ed output con quelle di
calcolo, eliminando i tempi morti della CPU dovuti allattesa del completamento
delle operazioni stesse di I/O. Se la CPU sta eseguendo un programma ed esso
richiede unoperazione di I/O, il programma corrente viene sospeso e loperazioni
di I/O delegata al processore di I/O del dispositivo. Intanto, la CPU pu eseguire
un altro programma, mentre uninterruzione segnaler il termine delloperazione di
I/O e la ripresa del programma precedentemente sospeso. Con una tale gestione il
sistema operativo diventa lamministratore delle risorse del calcolatore: i vari
programmi che coesistono nella memoria centrale devono dividersi luso delle
periferiche, della memoria e della CPU.
La successiva generazione di sistemi operativi porta allottimizzazione della
tecnica della multiprogrammazione, prevedendo sia il caricamento in memoria di
quelli idonei allesecuzione, mediante la tecnica dello swapping (ogni programma
viene spostato dalla memoria di massa alla memoria centrale solo quando serve),
che il caricamento in memoria non di un intero programma ma di sole specifiche
parti (quelle che con pi probabilit serviranno in un dato istante secondo il
principio di localit dei dati e delle istruzioni), aumentando cos il numero di
programmi che possibile caricare contemporaneamente nella memoria centrale
(grado di multiprogrammazione). Con la memoria virtuale viene inoltre estesa la
capacit della memoria centrale con quella delle memorie di massa, ed un
programma pu avere una dimensione potenzialmente infinita. Infatti con la
divisione del programma in parti vengono portate in memoria solo quelle che
devono essere eseguite mentre le restanti restano a disposizione sulla memoria di
356 Capitolo decimo

massa. Il sistema operativo trasferisce le porzioni in memoria centrale quando non


servono (swap out) e preleva dalla memoria di massa quelle che devono essere
eseguite (swap in).
I sistemi operativi time-sharing della quinta generazione nascono con
lesigenza di consentire a pi utilizzatori di avere accesso diretto e contemporaneo
ai loro programmi e dati durante lesecuzione, si parla infatti di sistemi multiutente
o conversazional/interattivii.
Il problema dei sistemi della precedente generazione risiedeva nel fatto che
programmi con molto calcolo interno potevano monopolizzare luso della CPU,
causando lunghi tempi di attesa per gli altri programmi. Affinch ci non accada
possibile assegnare degli intervalli di tempo della CPU, detti anche quanti di tempo
o time slice, ad ogni programma, dopodich terminato tale tempo il programma in
esecuzione deve abbandonare la CPU (anche se non ha richiesto alcuna operazione
di I/O) e cedere il posto al programma successivo secondo prestabilite politiche di
schedulazione. Poich un programma potrebbe richiedere molte time slice prima di
terminare, si ha che, rispetto ai sistemi multiprogrammati non time-sharing, il tourn
around time peggiora ma migliora il throughput complessivo.
Nella generazione successiva i sistemi operativi hanno unarchitettura interna
pressoch invariata e lattenzione viene posta sulle interfacce dutilizzo al fine di
facilitare luso dei primi personal computer agli utenti inesperti. Nascono cos i
primi sistemi operativi user-fiendly che nelle successive generazioni porteranno
alla comparsa degli attuali sistemi operativi Windows, Linux e MacOS con
interfacce di utilizzo completamente grafiche.
Si assiste quindi alla nascita di sistemi operativi le cui funzionalit sono
rivolte alla tipologia di applicazioni per cui sono progettati. Nascono cos i sistemi
operativi transazionali (si pensi ai sistemi operativi per gli sportelli del bancomat),
ovvero sistemi interattivi destinati ad eseguire transazioni ovvero sequenze di
operazioni elementari logicamente legate, dove lutente interroga ed aggiorna
archivi di dati. Un altro esempio costituito dai sistemi operativi real-time, ovvero
sistemi di tipo che gestiscono programmi che interagiscono con lambiente esterno
attraverso periferiche e che garantiscono tempi di risposta utili per le applicazioni e
lambiente esterno stesso (si pensa ai sistemi per il controllo di un reattore nucleare
o dei radar).
Negli anni 90 levoluzione dellhardware e la diffusione della rete internet
porta alla replicazione di alcune componenti del modello di Von Neumann (es.
schede madri multiprocessore) ed alla distribuzione delle risorse di calcolo (es.
stampanti, file system) nella rete, e ci comporta la nascita dei sistemi operativi
con supporto multiprocessore e distribuiti, ovvero di sistemi in grado di gestire pi
processori e risorse multiple che non sono pi localizzate su una macchina, ma si
trovano distribuite sia fisicamente che logicamente.
Lultima generazione (2008) dei sistemi operativi vede infine un
adeguamento delle loro caratteristiche ai dispositivi mobili, come palmari e
cellulari. In tali sistemi si prediligono caratteristiche come interfacce grafiche
evolute e risparmio energetico.
10.2.2. Alcuni esempi di Sistemi Operativi
Nel seguito si riporta una breve descrizione dei sistemi operativi pi
conosciuti ad oggi (2008), per quanto riguarda il mondo dei personal computer, che
Introduzione ai sistemi operativi 357

sono stati pietre miliari nel mondo dellinformativa e che, almeno per quanto
riguarda i pi recenti, probabilmente saranno ancora sulla scena nei prossimi anni.
DOS
Dal punto di vista storico, non si pu non partire dal Disk Operating System,
o DOS. Il DOS pi famoso certamente MS-DOS della Microsoft, ma giusto
ricordare anche il DR-DOS della Digital Research, (peraltro compatibile con MS-
DOS) e il PC-DOS della IBM (su licenza della Microsoft). MS-DOS stato
progettato e sviluppato per lavorare con i microprocessori (8088-8086) Intel
montati dalla IBM sui primi personal computer agli inizi degli anni Ottanta. Di
MS-DOS sono state commercializzate diverse versioni, lultima delle quali la 7.0.
MS-DOS nato ed rimasto un sistema operativo monoutente.
UNIX e LINUX
UNIX/Linux un sistema operativo multiutente e multitasking (in grado
quindi di gestire contemporaneamente diversi programmi che possono essere
visualizzati sullo schermo). Esistono differenti versioni di UNIX, ognuna con
diverse caratteristiche a seconda del produttore. UNIX il sistema operativo pi
aperto e portatile tra quelli esistenti perch, semplicemente apportando, se
necessarie, alcune modifiche, in grado di gestire piattaforme diverse (dal
mainframe al PC), nonch di essere utilizzato su computer basati su
microprocessori con diverse tecnologie costruttive.
LINUX la versione freeware molto potente di UNIX, che scaricabile
gratuitamente da Internet o acquistabile, a prezzo simbolico, su CD-ROM. Linux
un prodotto realizzato a livello universitario. Linterfaccia grafica si chiama X
Window. Il sistema costantemente aggiornato da sviluppatori delle pi rinomate
universit del mondo (il codice sorgente infatti pubblico) e pu costituire una
valida soluzione che non ha niente da invidiare alle implementazioni commerciali
di UNIX.
OS/2
OS/2 frutto di unintesa tra Microsoft e IBM, per le piattaforme basate sui
processori INTEL e compatibili. La prima versione risale al 1987. Fu il primo
sistema operativo multitasking e multiutente. Due anni pi tardi usc la versione
1.3, lultima sviluppata congiuntamente da IBM e Microsoft. OS/2 forniva le
prestazioni di un vero sistema operativo a 32 bit anche a piattaforme Intel.
WINDOWS
Windows nasce come un ambiente grafico per il DOS, al quale si appoggiava
per svolgere molte delle sue funzioni interne: era a tutti gli effetti una specie di
guscio intorno al DOS del quale ha bisogno per poter essere eseguito. Prodotto
dalla Microsoft negli anni Ottanta, riesce ad imporsi sul mercato solo con la
versione 3.1, dieci anni dopo. La versione successiva alla 3.1 Windows 3.11 for
Workgroup, particolarmente adatta alla connessione in rete. A partire da tale
versione, Windows diventa uno standard mondiale per computer con
microprocessori Intel compatibili. L'evoluzione a Windows 95 (dallanno di
commercializzazione) porta ad un radicale cambiamento e la versione successiva
358 Capitolo decimo

(Windows 98) ha aggiunto multimedialit, grafica molto curata ed un modo di


operare estremamente intuitivo. Nasce inoltre anche una versione multitasking e
multitutente, detto Windows NT (New Technology), che funzionava su
piattaforme Intel compatibili, Alpha e alcuni RISC. Il successore di Windows NT
Windows 2000, conosciuto anche con i nomi in codice Cairo e Windows NT 5. Al
pari del suo predecessore, Windows 2000 pensato per essere usato in ambito
professionale e come server grazie alle elevate prestazioni, stabilit e sicurezza.
Nel 2000, Microsoft presenta Windows ME (Millennium Edition), un progetto che
serve come ripiego temporaneo tra Windows 98 e il nuovo Windows XP.
L'unificazione delle linee Windows NT/2000 e Windows 3.1/95/98/ME viene
raggiunto con Windows XP, rilasciato nel 2001. Windows XP usa il kernel di
Windows NT. Nel 2003, Microsoft rilascia Windows Server 2003, un
aggiornamento del sistema operativo per server che incorpora molte delle
caratteristiche di Windows XP con migliorate componenti server e strumenti di
amministrazione.
Allo stato (2008), la versione pi recente di Windows Windows Vista, che
contiene molte nuove funzioni rispetto a XP, e diverse migliorie, come la nuova
interfaccia grafica (Graphical User Interface, GUI) chiamata Windows Aero.
Windows Vista si presenta come un sistema operativo che garantisce meglio
l'utilizzatore dal punto di vista della sicurezza e vulnerabilit rispetto ai virus
informatici, malware ed ai problemi legati ad errori di sistema.
Mac OS
Parallelamente alla linea Microsoft, la Apple Computer ha proposto sul
mercato il Mac OS, acronimo di Macintosh Operating System, a tutti gli effetti il
primo sistema operativo ad utilizzare con successo un'interfaccia grafica. Il sistema
funzionava essenzialmente sui processori CISC Motorola della serie 68000,
utilizzati nei Macintosh per molti anni. Nel 1994 vennero lanciati i Power
Macintosh basati sui processori RISC PowerPC, sviluppata da un consorzio
comprendente Apple, IBM e Motorola, ed il sistema operativo venne gradualmente
convertito in codice PowerPC. A partire dalla versione Mac OS 10, denominata
Mac OS X, la Apple rivoluziona il suo sistema operativo, completamente riscritto e
basato su piattaforma Unix. A fine giugno 2005 viene adottata la CPU Intel per le
macchine Apple, appositamente modificati per far funzionare il Mac OS X. La
versione attuale (2008) la Mac OS X 10.5, o Leopard.

10.3. Larchitettura dei Sistemi Operativi


I moderni sistemi operativi presentano unarchitettura a livelli, detta anche a
buccia di cipolla.
Introduzione ai sistemi operativi 359

hardware

Kernel

Gestore Memoria

Gestore periferiche

Gestore file system

Programmi di utilit

Shell e programmi utente

Figura 6 Architettura di un sistema operativo

Ogni strato o livello del sistema operativo costituisce una macchina virtuale:
cio una macchina definita da ci che capace di fare e non da come fatta. Ogni
macchina virtuale si avvale delle macchine sottostanti per funzionare e una tale
impostazione modulare favorisce lo sviluppo del sistema operativo consentendo di
modificare solo alcuni livelli senza toccare tutti gli altri. Solo lo strato hardware
costituisce una macchina reale (Modello di Von Neumann). I livelli, da quello pi
vicino allhardware a quello pi a contatto con gli utenti e le applicazioni, sono:
1) il nucleo o kernel che gestisce i processi e la sincronizzazione tra i
processi. Alloca la CPU ai processi tramite un opportuno schedulatore
(scheduler) e gestisce le interruzioni;
2) il gestore della memoria che effettua la corrispondenza tra indirizzi logici
e fisici dei programmi e alloca la memoria ai programmi che ne fanno
richiesta. Si occupa infine del caricamento e scaricamento delle
informazioni dalla e verso la memoria di massa (swapping) e della
protezione delle aree di memoria;
3) il gestore delle periferiche che fornisce le primitive che implementano le
operazioni di I/O sui dispositivi e gestisce parzialmente i
malfunzionamenti;
4) il file system che gestisce lorganizzazione logica e fisica delle
informazioni nella memoria di massa (i file), e ne controlla gli accessi (per
leggere, scrivere, o modificare i file);
360 Capitolo decimo

5) linterprete dei comandi che forma un guscio (shell) attraverso cui lutente
e le applicazioni interagiscono con il sistema operativo;
6) i programmi di utilit, ossia programmi di sistema per il supporto allo
sviluppo dei programmi, quali editor di testi, fogli elettronici, database,
etc
Al primo livello, la macchina kernel presuppone che ogni processo disponga
virtualmente di un proprio processore. Al secondo livello la macchina gestore della
memoria pu essere schematizzata invece come una macchina in cui ogni processo
possiede virtualmente una propria CPU e una propria memoria. Analogamente al
terzo livello la macchina gestore delle periferiche assegna a ciascun processo la sua
CPU, la sua memoria ed un insieme di periferiche. La macchina del quarto livello
permette ad ogni processo di vedere ed utilizzare un proprio file system. Infine, ai
livelli successivi la macchina rimane sostanzialmente la stessa e ci sono solo
servizi come i programmi di utilit, la shell ed i programmi utenti.
10.3.1. La gestione dei processi
Un processo non altro che un programma, o una sua parte, eseguita dalla
CPU: si pu pensare ad un processo come ad una sequenza di istruzioni, con un
inizio ed una fine determinate, che fa parte di un programma pi grande. In un
sistema multiprogrammato pi processi risiedono in memoria e procedono nella
esecuzione con tecniche di gestione differenti.
In un tale ambiente i diversi processi vengono detti concorrenti perch si
contendono il possesso delle stesse risorse (CPU, memoria, input ed output) e il
sistema operativo deve provvedere a risolvere le problematiche di cooperazione,
competizione e interferenza tra essi esistenti.
La competizione una forma di interazione tra i processi prevedibile, ma non
desiderata, perch ne rallenta lesecuzione. Viceversa la cooperazione una forma
di interazione prevista e desiderata, fra processi tra loro logicamente imparentati
nel senso che hanno obiettivi comuni. Un esempio di cooperazione quello tra
processi concorrenti che si scambiano messaggi di sincronizzazione per proseguire
nella esecuzione. Un esempio di competizione , invece, quello tra pi processi che
vogliono usare una stessa risorsa comune (come una stampante). Il sistema
operativo deve poter gestire la possibilit (non desiderata) che vi possano essere
altri processi concorrenti che, richiedendo luso della stessa stampante, scatenino
conflitti, non certi, ma possibili, capaci di bloccare il sistema. Quanto
allinterferenza, essa si verifica in presenza di interazioni tra processi che la natura
del problema non mostra in modo esplicito come ad esempio accade quando un
processo P ha bisogno di effettuare una stampa, ma prima che ci avvenga, un
secondo processo Q altera senza alcuna necessit lo stato della stampante
bloccandola. Linterferenza pu essere anche provocata da erronee soluzioni a
problemi di cooperazione e competizione. Il sistema operativo pu occuparsi solo
delle interferenze macroscopiche, mentre la maggioranza delle interferenze deve
essere gestite a monte nel progetto dei diversi programmi.
Affinch un sistema operativo possa gestire i processi, deve esistere per ogni
processo unarea dati non accessibile al processo ma associata ad esso, contenente
un insieme di informazioni indispensabili dette descrittore del processo. Un
processo non pu esistere se non esiste il suo descrittore. Un processo nasce nel
momento in cui viene allocato il suo descrittore, e quindi un attimo prima che
Introduzione ai sistemi operativi 361

venga eseguita la sua prima istruzione. Per tale ragione si pu affermare che un
processo prende vita ancor prima di cominciare ad essere eseguito.
Il descrittore un record, ovvero un insieme di campi contenenti tutte le
informazioni necessarie allesecuzione di un dato processo. Tra i principali campi
si trovano il nome o identificatore del processo ed il suo stato. Un ulteriore campo
contiene linsieme dei valori dei registri del processore nel momento in cui
questultimo perde temporaneamente lusufrutto della CPU, ossia nel momento in
cui passa dallo stato running allo stato waiting o di ready (come vedremo di
seguito). Altri campi sono utilizzati per memorizzazione informazioni quali la
priorit, i dispositivi di I/O utilizzati, il tipo di relazione (parantela) con altri
processi, e cos via.
La componente del sistema operativo dedicata a svolgere la gestione dei
processi il cosiddetto nucleo o kernel. Il kernel deve presentare le seguenti
funzionalit:
- Creazione di processi: che permette la generazione di nuovi processi
allinterno di un sistema operativo. Un esempio sono le primitive di fork
che consentono ad un dato processo in esecuzione di creare un altro
processo, detto figlio, a cui delegare determinate operazioni (ad esempio
stampa dei risultati elaborativi), e, quelle di join, che consentono al
processo padre di sincronizzarsi con la terminazione dei figli (ovvero
attesa della stampa prima di proseguire con le successive elaborazioni).
- Sincronizzazione di processi: che consente di risolvere i citati problemi di
cooperazione, competizione ed interferenza. A tale proposito i sistemi
operativi seguono due modelli fondamentali, i modelli a memoria comune
ed a scambio di messaggi. Nel primo modello si hanno pi processi che
accedono a risorse comuni (hardware/software), le quali si trovano in
ununica memoria condivisa. I problemi pi diffusi in tale modello sono
quelli relativi alla competizione, mentre gli stratagemmi utilizzati per
risolverli si basano sul concetto di semaforo, ovvero sullutilizzo di
apposite strutture dati gestite da procedure che regolano laccesso alle
risorse (e.g. un processo pu interagire con una risorsa, se e solo se,
interrogando il semaforo con le sue procedure si accorge che questo
verde ovvero che la risorsa libera e non impegnata da altri processi).
Nel secondo modello, invece, esistono pi processi dotati di risorse locali
(e quindi visibili ad un singolo processo) e lunica forma di
comunicazione consentita quella basata sullo scambio di messaggi. A
tale proposito apposite primitive di send (manda) e receive (ricevi)
vengono messe a disposizione per realizzare la cooperazione tra i
processi.
- Scheduling dei processi: che consente di scegliere (schedulare) quali
processi devono essere assegnati alla CPU. Lo schedulatore dei processi
interviene ogni qual volta un processo deve essere assegnato alla CPU ed
ha lo scopo di ottimizzare uno o pi dei parametri caratteristici di un
sistema operativo: throughput, tourn around time, tempo di attesa e
tempo di risposta dei vari processi. Classici algoritmi di scheduling sono
quelli che si basano su una strategia di accesso a code di tipo FIFO (First-
In-First-Out), dove il primo processo ad arrivare in coda il primo ad
essere servito, oppure quelli basati su code a priorit dove esistono pi
362 Capitolo decimo

code di processi che vengono servite sulla base della priorit o importanza
dei processi in esse contenuti, o infine, algoritmi di tipo SJF (Short Job
First), in cui ad essere serviti sono i processi che durano di meno. A
secondo poi dellutilizzo o meno del time-sharing, un processo verr
eseguito solo per un time-slice di tempo o per intero.
In un sistema cos strutturato, i processi (programmi in esecuzione nel
sistema) possono trovarsi negli stati di:
c) running - in quanto sono in esecuzione avendo ottenuto il possesso della
CPU;
d) ready - nel senso che sono pronti per lesecuzione ed attendono solo che
gli venga concessa la CPU;
e) waiting perch sono in attesa di qualche evento, come la fine di
unoperazione di I/O, che li far diventare prima ready e poi, quando sar
possibile, running.

Figura 7 Diagramma degli stati di un processo

Lo schedulatore ha il compito di selezionare tra i processi che si trovano in


uno specifico stato, quello che deve essere gestito per primo. A tal fine ad ogni
processo associato oltre allo stato anche una priorit che ne determina lordine di
schedulazione. Un processo nello stato di running passa in un altro stato se:
arrivato alla sua naturale terminazione o se un errore grave ne ha
decretato una terminazione prematura;
ha avviato una operazione di input ed output e deve pertanto aspettare
che il canale attivato segnali il completamento delloperazione richiesta
con una richiesta di interruzione; in tale caso il processo passa nello
stato di waiting;
ha terminato il quanto di tempo assegnato se il sistema gestito secondo
la modalit del time-sharing; in tale caso il processo passa nello stato di
ready.
Un processo nello stato di waiting pu solo passare nello stato di ready
quando loperazione di input/output richiesta terminata. Infine un processo nello
stato di ready passa nello stato di running quando ha acquisito il diritto per farlo.
La tecnica del time-sharing garantisce che tutti i processi procedano con le
stesse garanzie evitando che la CPU possa essere monopolizzata da uno solo di
Introduzione ai sistemi operativi 363

essi. Si pensi ad un processo costituto da lunghi calcoli iterativi seguiti da


operazioni di input/output: un tale processo lascerebbe il possesso della CPU solo
dopo molto tempo costringendo tutti gli altri ad aspettane la terminazione. Con i
quanti di tempo tutti i processi vengono eseguiti poco alla volta ma procedono tutti
assieme. Tutte le risorse del sistema vengono equamente distribuite tra tutti i
processi. Si comprende che quanto pi sono i processi da eseguire tanto pi
lutente costretto ad aspettare che il sistema gli fornisca i risultati desiderati.
Una tecnica diversa quella del tempo reale o real time. In tali sistemi le
risposte devono essere fornite in un tempo utile allambiente circostante. Tipici
sistemi real-time sono i sistemi di controllo nei quali le risposte devono regolare il
funzionamento di dispositivo (una caldaia, un motore) secondo dei tempi
prestabiliti: si comprende che se il segnale di controllo non arriva in tempo utile il
dispositivo si porta in una condizione di errore (lo scoppio della caldaia, la fusione
del motore). Nei sistemi real time i processi devono mantenere le risorse fino a
quando non producono i risultati desiderati e quindi terminano.
Nei sistemi moderni le due tecniche convivono. Ai processi di tipo real time
vengono assegnate priorit molto alte per far s che lo schedulatore li selezioni
prima di tutti gli altri processi.
10.3.2. La gestione della memoria
Il gestore della memoria il componente del sistema operativo che si occupa
dellallocazione e deallocazione dei processi in memoria centrale. Si trova ad un
livello superiore al kernel in quanto un processo che non allocato in memoria non
pu essere eseguito. La memoria e la CPU sono pertanto le due risorse
fondamentali che un processo deve possedere per poter essere eseguito. Un sistema
monoprogrammato se un solo processo alla volta viene allocato in memoria;
invece multiprogrammato se pi processi vengono disposti in memoria anche se
uno solo di essi viene eseguito. Poich pu capitare che lo spazio di memoria arrivi
a saturazione, il gestore di memoria deve attuare delle tecniche per assegnarla solo
a quei processi che possono essere eseguiti. Con il meccanismo dello swapping si
attua il trasferimento di processi dalla memoria centrale a quella di massa (swap-
out) quando essi sono in uno stato di waiting, e, viceversa, il trasferimento di
processi da memoria di massa in memoria centrale (swap-in) di quelli che sono
tornati ready. Lo scopo dello swapping di lavorare con un numero di processi
attivi maggiore di quello che potrebbe essere consentito con le dimensioni effettive
della memoria, aumentando il grado complessivo di multiprogrammazione.
Le tecniche che sono state studiate fino ad oggi per la gestione della memoria
possono essere raggruppate in due grandi classi:
5) le tecniche basate su paginazione e segmentazione che richiedono che il
codice e i dati di un processo siano integralmente contenuti nella memoria
centrale;
6) le tecniche basate su memoria virtuale, che richiedono che il codice e i
dati di un processo siano solo in parte contenuti in memoria centrale.
La paginazione consiste nel suddividere la memoria fisica in blocchi di
dimensioni fissate, detti frame, e la memoria logica dei processi in blocchi di
uguale dimensione chiamati appunto pagine. Quando un processo deve essere
eseguito vengono caricate nei frame le pagine. Il mapping tra gli indirizzi logici del
processo e quelli fisici di memoria avviene a tempo di esecuzione (dinamicamente)
364 Capitolo decimo

mediante un hardware dedicato detto Memory Management Unit (MMU), che


utilizzando unapposita tabella converte gli indirizzi logici di pagina del processo
in indirizzi fisici di frame.
Nella segmentazione, invece, la memoria suddivisa in partizioni a lunghezza
variabili dette segmenti. Analogamente allo spazio fisico di memoria, anche lo
spazio logico dei processi viene suddiviso in segmenti ed inoltre la corrispondenza
tra indirizzi logici e fisici avviene come nel caso della paginazione attraverso una
MMU.
Infine la memoria virtuale pu essere applicata sia nellambito di una
memoria paginata, che in quello di una memoria segmentata e si basa sullassunto
che un dato processo per essere eseguito non deve risiedere per forza tutto in
memoria centrale. La memoria (segmentata o paginata che sia), necessaria alla
esecuzione di tutti i processi, non coincide pi con la sola memoria centrale ma
risulta essere fisicamente allocata sulla memoria di massa, e solo una sua parte
rimane in memoria centrale. Se durante lesecuzione di un processo accade che lo
stesso abbia bisogno di accedere ad una particolare sua pagina non residente nella
memoria centrale ma sul disco (condizione detta di page fault), il sistema operativo
deve prevedere un meccanismo automatico che effettui l'arresto del processo,
l'ingresso della pagina mancante in memoria e la ripresa del processo, il tutto in
maniera completamente trasparente rispetto all'utente. Se nella memoria centrale
esiste una pagina libera, la nuova pagina potr occuparla, altrimenti bisogner
effettuare lo swap-out di alcune delle pagine preesistenti. La gestione del page fault
realizzata tramite un apposito algoritmo di sostituzione che seleziona la pagina
vittima da swappare su disco e carica la pagina richiesta in memoria: tale
algoritmo deve garantire buone prestazioni individuando nel modo pi opportuno
la pagina vittima sulla base di opportuni criteri (ad esempio, viene scelta la pagina
meno usata di recente).
10.3.3. Il file system
Il file system gestisce essenzialmente la collocazione dei file sulla memoria di
massa e tutte le informazioni necessarie per consentire lesecuzione delle
operazioni su di essi.
Il file system permette di ottenere unastrazione della memoria di massa
organizzandola in insiemi di directory e file: mentre le directory contengono
informazioni riguardanti i file, i file contengono i dati veri e propri (contenuti in
appositi blocchi fisici del disco). In realt un file system vede sia le directory che i
file come un insieme di file. In particolare le directory sono file che contengono un
array di record in cui ogni record il descrittore di un file. Le informazioni pi
comunemente memorizzate in un campo del descrittore di file sono:
- nome del file (nome simbolico del file);
- tipo di file (solo in S.O. che gestiscono il tipo, cio essenzialmente file
eseguibili e non);
- locazione (dispositivo e allocazione sul dispositivo);
- posizione corrente (puntatore alla posizione corrente di lettura/scrittura
del blocco)
- protezione (informazioni per il controllo dellaccesso);
- contatore di utilizzo (numero di utenti che allo stato condividono il file);
- ora e data (ora, data e identificatore di processo);
Introduzione ai sistemi operativi 365

- identificatore di processo (relativamente ad operazioni quali: creazione,


ultima modifica e ultimo utilizzo del file).
Per ci che concerne le operazioni, le operazioni fondamentali che vengono
fatte a livello di directory sono la creazione e la cancellazione di un file, oppure
lapertura o la chiusura o visualizzazione dei dati relative ad un file.
Creare o aggiornare un file significa aggiungere un descrittore di file
allinterno di un file directory; cancellare un file significa eliminarlo, visualizzare
significa accedere o ricercare dei dati. Tali operazioni presuppongono una visita
dei descrittori di file, ed in particolare la creazione deve fare una operazione di
visita totale, mentre la visualizzazione e la cancellazione presuppongono una visita
parziale.
Se si vuole lavorare su di un file, le operazioni fondamentali diventano:
apertura di un file, chiusura di un file, creazione di un file(scrittura), lettura di un
file, reset di un file. Mentre i metodi di accesso ai file supportati da un sistema
operativo sono: accesso sequenziale, accesso diretto ed accesso mediante un indice
(cio mediante un tabella di corrispondenza chiave e posizione).
Per ci che concerne infine lallocazione dei file su disco, tre possono essere
le modalit:
- allocazione contigua che comporta che un file sia memorizzato in blocchi
contigui del disco e nel descrittore del file si trova lindirizzo del blocco
iniziale ed il numeri di blocchi occupati;
- allocazione linkata che porta un file ad essere memorizzato in blocchi non
contigui di memoria e nel descrittore di file si ha ancora il blocco di inizio
del file cos come nella allocazione contigua, per invece di avere il
numero di blocchi consecutivi, i vari blocchi sono linkati mediante
puntatori che sono contenuti nei blocchi stessi (si tratta quindi di una lista
a puntatori i cui elementi sono i blocchi del disco). Per percorrere il file
basta quindi entrare nel primo blocco e poi utilizzare i vari puntatori che
si trovano in posizione standard nei blocchi.
- allocazione indicizzata con la quale un file memorizzato in blocchi non
contigui di memoria e nel descrittore di file si ha lindirizzo di un blocco
particolare, detto indice, che contiene la posizione sul disco (puntatori) di
tutti i blocchi costituenti il file.
10.3.4. Linterprete dei comandi: la shell
In un sistema operativo, la shell rappresenta la componente che permette agli
utenti di comunicare con il sistema. Essa crea un ambiente di lavoro attraverso il
quale possibile impartire comandi al sistema. La shell un vero e proprio
interprete di linguaggio che prende anche il nome di Job Control Langauge (JCL)
in quanto serve a controllare il lavoro del sistema operativo. I comandi pi noti
sono quelli che richiedono che i programmi vengano prima caricati in memoria e
poi eseguiti. Esistono molti tipi di shell, che si dividono principalmente in shell
testuali e grafiche.
Una shell testuale un programma con una interfaccia a linea di comando,
che viene eseguito da un terminale testuale. L'utente digita un comando, ovvero
richiede l'esecuzione di un programma, e il programma eseguito pu interagire con
l'utente e/o stampare dati sul terminale. Una delle pi note shell testuali quella dei
sistemi operativi DOS caratterizzata dal suo prompt dei comandi C:>, ben noto a
366 Capitolo decimo

quanti hanno familiarit con i personal computer della prima generazione. In


ambiente Unix, esistono diverse shell, una tra le pi famose sicuramente la Bash
(Bourne-Again Shell), ma ne esistono altre come la Korn Shell e la C Shell, con un
insieme di funzionalit e caratteristiche di base in comune.
L'evoluzione grafica delle shell rappresentata dalle Graphic User Interface,
che attraverso luso di icone e finestre permettono di svolgete le varie operazioni
possibili con un clic del mouse, rendendo il sistema user-friendly. Sebbene le shell
grafiche siano un passo avanti per l'interazione uomo-macchina, il loro punto di
debolezza rappresentato dallalto consumo delle risorse di calcolo del computer
che si contrappone alla potenza e velocit d'uso di quelle testuali. Le Shell grafiche
pi conosciute sono GNOME e KDE (sotto ambiente UNIX) ed EXPLORER (sotto
ambiente Windows).
Capitolo undicesimo

Le reti di comunicazione

11.1. I sistemi di comunicazione


Alla base della trasmissione dellinformazione il concetto di messaggio inteso,
informalmente, come una informazione che viene trasferita da un entit detta
sorgente ad una o pi entit dette destinatario.
Un sistema di comunicazione, come mostrato in figura 1, in generale
formato da cinque elementi fondamentali:
- una sorgente che genera messaggi;
- un sistema di codifica che trasforma un messaggio della sorgente in una
sequenza di segnali;
- un canale trasmissivo (ad esempio un doppino telefonico, fibre ottiche,
letere) usato per trasferire segnali dalla sorgente alla destinazione;
- un decodificatore che esegue di solito le operazioni inverse di un
codificatore, ossia trasforma i segnali in messaggi;
- un destinatario che riceve i messaggi.
Si noti che linsieme costituito da codificatore, canale e decodificatore anche
detto sistema di trasmissione dellinformazione. Inoltre codificatore e
decodificatore sono a volte chiamati trasmettitore e ricevitore rispettivamente.
Si consideri ad esempio una tipica comunicazione telefonica su telefono fisso:
un essere umano parla emettendo un sequenza di suoni (i simboli in formato
acustico che costituiscono il messaggio da trasmettere), quindi un opportuno
codificatore trasforma il segnale acustico in un segnale elettrico; tale segnale viene
trasmesso su un canale, costituito da cavi telefonici e da un insieme di interruttori
che trasportano il segnale al decodificatore del destinatario; a questo punto il
segnale elettrico viene trasformato nuovamente in segnale acustico consegnando
in questo modo il messaggio al destinatario.
Si noti che i canali di comunicazione hanno una capacit limitata, misurata in
bit al secondo. Tale misura rappresenta il numero di bit che il canale di
comunicazione in grado di trasmettere nellunit di tempo.
Lo studio sistematico dei sistemi di comunicazione una attivit vasta e
complessa che esula dagli scopi di questo testo. Nel seguito mostreremo i concetti
fondamentali ed introduttivi della problematica, rimandando a testi specializzati di
networking, di telecomunicazioni e telematica per una trattazione esaustiva e
sistematica.
368 Capitolo undicesimo

Figura 1 - Sistema di Comunicazione

11.1.1. Codici e codifica


Un messaggio prodotto da una sorgente pu essere modellato come una sequenza
di lunghezza finita di simboli appartenenti ad un insieme prefissato, detto alfabeto
della sorgente. In altre parole, stiamo pensando ad una applicazione (matematica)
detta codifica che, data una informazione i, la associa ad una opportuna parola
codice, wc composta da simboli dellalfabeto sorgente, ovvero:

i I wc C (1)

con I e C insiemi di cardinalit finita. Si noti che le caratteristiche principali di


un messaggio sono il formalismo scelto per rappresentarlo ed il significato del
messaggio, caratteristiche indipendenti luna dallaltra (il formalismo di
rappresentazione non dipende dal significato del messaggio).
Una codifica si dice non ambigua se lapplicazione (1) iniettiva, ovvero ogni
coppia di informazioni distinte di I sono trasformate in coppie di parole distinte wc.
Detto card(I) la cardinalit, ovvero il numero di elementi dellinsieme I, e card(C)
la cardinalit di C, una codifica si dice:
- non ridondante se card(I) = card(C);
- ridondante se card(C) > card(I) .
Si noti che se card(C) < card(I), allora si ha una codifica ambigua. Nel nostro
caso, distinguiamo tra:
- codice sorgente: ovvero il codice con il quale sono rappresentati i
messaggi emessi dalla sorgente;
- codice canale: ovvero il codice col quale sono rappresentati i messaggi
trasmessi lungo il canale;
- codice destinatario: ovvero il codice del destinatario, che a volte
puessere diverso da quello della sorgente.
Le reti di comunicazione 369

Si prenda ad esempio il codice Morse. Si tratta del primo esempio di codice


esplicitamente pensato per trasmissioni su canali di comunicazione. Il codice fu
ideato nel 1844 da Samuel F.B. Morse per luso del telegrafo elettrico, anchesso
frutto della sua inventiva.
La prima linea telegrafica sperimentale fu la tratta Washington - Baltimora,
inaugurata con linvio in tempo reale degli impulsi elettrici che corrispondevano
alla frase biblica Cos ha permesso Dio, passata alla storia come il primo
messaggio telegrafico in alfabeto Morse.
Lalfabeto Morse una combinazione di punti e linee che rappresentano
numeri e lettere dellalfabeto, dove la durata di una linea equivale a quella di tre
punti: per trasmettere i messaggi codificati ci si pu servire di segnalazioni
luminose, acustiche o elettriche, che permettono di codificare le due durate
(lunga e breve) dei segnali. Tuttora rappresenta un codice internazionale di segnali
usato nei sistemi di radiotelegrafia di tutti i paesi, eccetto Stati Uniti e Canada, e
ovunque nel mondo per le comunicazioni in navigazione marittima.
Il codice base formato da 36 simboli (26 caratteri e 10 cifre), come in figura
2, codificati in sequenze di punti e linee. Si noti che la codifica ambigua, in
quanto non consente sempre al decodificatore di associare ad un messaggio un
unico significato se non si dispone di una sincronizzazione tra un carattere ed il
successivo (ad esempio una pausa).

Figura 2 - Esempio di Codifica: il codice Morse

11.1.2. Il problema degli errori


I canali di trasmissione sono di solito costituiti da circuiti elettronici che possono,
durante la trasmissione, dare luogo ad una serie di disturbi, cui viene dato il nome
di rumore. Di solito si distinguono due tipi fondamentali di rumore:
- rumore bianco: si tratta di un disturbo sempre presente nei dispositivi
elettronici ( in gran parte generato dal moto degli elettroni) e pu essere
facilmente mitigato attraverso opportuni dispositivi elettronici detti filtri;
- rumore impulsivo: si tratta di un disturbo dovuto a cause imprevedibili che
possono verificarsi durante la trasmissione (caduta di tensione, effetti
parassiti delle linee elettriche e cos via). Il rumore impulsivo genera
errori casuali e altera in modo imprevedibile i bit trasmessi.
Solitamente, per ridurre gli effetti dei disturbi (soprattutto quelli
imprevedibili), sono state definite tecniche di trasmissione dei messaggi che
permettano nel contempo di rilevare la presenza di errori e, sotto opportune
ipotesi, di correggerli.
370 Capitolo undicesimo

La considerazione intuitiva alla base delle tecniche di correzione di errore la


seguente: se il dato ricevuto dal destinatario attraverso il canale diverso da quello
che vi era stato immesso, allora si verificato un errore di trasmissione. In
particolare, un errore singolo se stato alterato un solo bit del messaggio (si
ipotizza una codifica in binario delle informazioni); doppio se sono stati alterati
due bit, etc.
Come si fa a riconoscere che un bit ricevuto differente da quello inviato, e
quindi ad individuare la presenza di un errore? A tal fine si utilizzano tecniche di
codifica dellinformazione basate sulluso di codici ridondanti. In linea di
principio, ad una parola dati di m bit si aggiungono r bit di controllo e si ottiene
una parola codice di n = m + r bit: quando si legge una parola, vengono
controllati gli r bit in eccesso al fine di rilevare lerrore (cio ad invalidare il dato)
o correggerlo (cio a sostituire il dato errato con quello esatto).
11.1.3. La trasmissione dellinformazione
Per trasferire un messaggio binario lungo una linea di trasmissione, i bit che
costituiscono gli elementi da trasmettere devono essere convertiti in segnali
elettrici: una soluzione pu essere quella di associare al valore logico 1 un dato
valore di tensione, ad esempio +V , e al valore logico 0 un valore di tensione ben
distinto, ad esempio V . Il ricevitore sar in grado di interpretare i valori di
tensione ricevuti, secondo la convenzione assunta.
Rappresentando il valore nel tempo del fenomeno fisico come una funzione
s(t), si pu studiare matematicamente il segnale risultante.
Il segnale fondamentale che prendiamo in considerazione una funzione
sinusoidale del tipo: s(t) = A sin(2 f t).
Esso, come noto, caratterizzato dai seguenti parametri: ampiezza A (il
massimo valore in modulo del segnale); periodo T (il tempo entro cui la funzione si
ripete); frequenza: linverso del periodo f = 1/T , misurata in cicli al secondo (Hz).
In realt una qualsiasi funzione s(t), definita in un intervallo T, pu essere espressa
come una somma di un numero infinito di funzioni sinusoidali (analisi di Fourier):
s(t) a0 an cosn2 f 0 t bn sinn2 f 0 t
n 1 n 1
dove f0 = 1/T la frequenza fondamentale ed an e bn sono le ampiezze
dellennesima armonica (o termine), che ha una frequenza n volte pi grande della
frequenza.
Un segnale variabile nel tempo di fatto equivalente ad una somma di
funzioni sinusoidali aventi ciascuna una propria ampiezza e frequenza. Si pu
quindi rappresentare un segnale s(t) di durata T in un modo diverso, e cio
attraverso il suo spettro di frequenze, ossia attraverso la sua scomposizione in
sinusoidi.
Qualunque segnale dunque caratterizzato da un intervallo di frequenze nel
quale sono comprese le frequenze delle sinusoidi che lo descrivono. Tale intervallo
va sotto il nome di banda di frequenza del segnale. Anche i mezzi fisici sono
caratterizzati da una banda di frequenze, detta banda passante del mezzo fisico.
Essa rappresenta lintervallo di frequenze che il mezzo fisico in grado di
trasmettere (senza alterarle oltre certi limiti). Le alterazioni principali sono la
attenuazione e lintroduzione di ritardo, che di solito variano al variare delle
Le reti di comunicazione 371

frequenze trasmesse. A volte la dimensione della banda passante dipende solo


dalle caratteristiche fisiche del mezzo trasmissivo, a volte deriva anche dalla
presenza di opportuni filtri che tagliano le frequenze oltre una certa soglia (detta
frequenza di taglio, fc ). Ad esempio, nelle linee telefoniche la banda passante
dellordine dei kHz.
E opportuno notare che i mezzi trasmissivi attenuano i segnali in proporzione
alla distanza percorsa e alla frequenza del segnale e che propagano i segnali a
velocit proporzionali alle loro frequenze. Da queste considerazioni discende che
la banda passante si riduce allaumentare della lunghezza del mezzo stesso. Perch
un segnale sia ricevuto come stato trasmesso, necessario che la banda passante
sia almeno uguale o pi ampia della banda di frequenza del segnale stesso,
altrimenti, il segnale viene privato di alcune delle sue armoniche (quelle di
frequenza pi elevata) e viene quindi distorto. Se un numero sufficiente di
armoniche arriva a destinazione, il segnale comunque utilizzabile. Nyquist ha
dimostrato (teorema del campionamento o teorema di Nyquist) che un segnale
analogico di banda B pu essere completamente ricostruito mediante una
campionatura effettuata 2 B volte al secondo.
11.1.4. I mezzi trasmissivi
Trasmettere un segnale s(t) elettrico esige un mezzo trasmissivo che
generalmente una linea di trasmissione. Nel caso storicamente pi semplice, la
linea costituita da una coppia di conduttori (fili), oppure si possono avere onde
elettromagnetiche che si propagano nello spazio o fasci di luce che vengono
convogliati e guidati in una fibra ottica. Avere conoscenza del tipo di mezzo
trasmissivo a cui si fa riferimento importante in quanto determina il numero
massimo di bit che possono essere trasmessi in un secondo, o bps. Di seguito sono
descritti i mezzi trasmessivi pi diffusi.
La linea bifilare formata da due fili (di rame), isolati luno dallaltro. Viene
generalmente usato per collegare dispositivi che non distano pi di 50 m, ad una
velocit di circa 19.2 bps. In uno dei due fili viaggia di solito una tensione (o
corrente), nellaltro una tensione di riferimento. Un cavo multiplo formato da n
fili su cui viaggia linformazione ed un filo per il riferimento. Pur essendo molto
semplice, questo tipo di linea affetta da fenomeni di interferenza dei segnali
elettrici dei fili adiacenti nel cavo (diafonia). Per rendere pi robusta la
trasmissione rispetto al rumore, si pu utilizzare una linea bifilare con fili
intrecciati (binatura), detta coppia simmetrica o doppino. In questo modo si
riducono i fenomeni di diafonia. Il doppino pu essere singolo (una sola coppia)
oppure in una treccia di una serie pi meno numerosa di coppie. Queste linee,
dette anche in inglese Unshielded Twisted Pair (UTP) non prevedono alcun tipo di
schermatura. La versione schermata (Shielded Twisted Pair, STP), riduce
ulteriormente linterferenza. I cavi UTP sono costituiti solitamente da quattro
coppie di fili, isolati singolarmente ed avvolti in spire a due a due senza
schermatura aggiuntiva. I cavi sono caratterizzati da categorie (level) e le
differenze consistono nella realizzazione degli avvolgimenti; i livelli sono definiti
in base a capacit di banda entro distanze definite (100 m), come nel seguito
riportato:
- UTP level 3: garantisce fino a 16 MHz di banda;
- UTP level 4: garantisce fino a 20 MHz;
372 Capitolo undicesimo

- UTP level 5: garantisce fino a 100 MHz.


- doppini performanti, level 5 e, 6 e 7.
I doppini UTP level 3 sono detti anche di qualit fonica, e sono utilizzati sia
per la telefonia che per la trasmissione dati fino a 10 Mbps. I doppini UTP level 5
sono utilizzati nelle reti locali a velocit superiore (fino a 1 Gbps). Il doppino per
le sue caratteristiche di maneggevolezza e di basso costo molto diffuso sia per la
telefonia (quasi tutte le connessioni del sistema telefonico nellultimo tratto sono
costituite da doppini), che per le reti locali (generalmente realizzato tramite UTP o
STP).
Il cavo coassiale costituito da un conduttore interno in rame, avvolto in un
isolante di materiale plastico (dielettrico) attorno al quale posto il conduttore esterno
(una calza metallica), il tutto ricoperto da un isolante. Per la sua struttura, il cavo
coassiale mostra una minore sensibilit alle interferenze nonch una minore
attenuazione del segnale in funzione della distanza, rispetto al doppino. Il cavo
coassiale ha una larghezza di banda fino a 500 MHz: per questo molto diffuso per le
connessioni a lunga distanza e per le trasmissioni che richiedono una banda larga.
Come il doppino telefonico, sulle distanze superiori al Km necessita di amplificatori o
ripetitori.
Il cavo in fibra ottica costituito da un sottile filo di sostanza vetrosa,
generalmente silicio, molto fragile, detto core (nucleo), attraverso il quale si propaga la
luce; il nucleo avvolto da una sostanza (mantello) con propriet ottiche differenti dal
nucleo stesso; a sua volta il mantello avvolto in una guaina che protegge il cavo da
umidit deformazioni. Le propriet ottiche del nucleo e del mantello sono tali che la
luce introdotta nel nucleo non ve ne esce pi, e viene riflessa in modo da viaggiare
lungo il nucleo fino a destinazione. Il segnale luminoso pu essere generato in due
modi differenti:
- tramite LED (Light Emitting Diode): pi economico, adatto per trasmissioni a
tratta corta su fibre multimodali ed a basso tasso trasmissivo;
- tramite diodi ad emissione laser: molto pi costoso, adatto per trasmissioni ad
alto tasso trasmissivo per lunghe distanze, pi sensibile al calore.
La banda trasmissiva della fibra si aggira intorno ai 30 THz (30000 GHz); la
tecnologia attuale permette tassi trasmissivi fino a 10 Gbps, ma in laboratorio si raggiungono
tassi maggiori a breve distanza. Tipicamente, i cavi a fibra ottica contengono centinaia di
fibre distinte. Le fibre sono molto pi sottili e leggere dei cavi in rame (e ci pu essere
fisicamente un problema quando si vuole stendere un cavo sulle lunghe distanza, ad
esempio uno transoceanico); di contro, la fibra garantisce una attenuazione
significativamente inferiore al rame; i continui miglioramenti tecnologici del mezzo
trasmissivo hanno ad oggi consentito di effettuare una trasmissione, senza ripetitori, fino a
25/30 km di distanza.

Figura 3 - Doppino Telefonico, Cavo coassiale, Fibra Ottica


Le reti di comunicazione 373

In figura 3 sono mostrati schematicamente i tre diversi mezzi trasmissivi


guidati.
La trasmissione di dati viene spesso realizzata utilizzando la trasmissione di
onde elettromagnetiche nellaria o nello spazio (wireless), caratterizzate dallo
spettro di trasmissione. Se le onde sono trasmesse in una banda compresa tra il
KHz ed il GHz, si parla di radiodiffusione. Si utilizza di solito in modalit
unidirezionale per le trasmissioni radio o televisive. Nella regione compresa tra 1 e
40 GHz (microonde), la propagazione delle onde elettromagnetiche abbastanza
direzionale (o direzionabile con antenne paraboliche), e viene utilizzata per
trasmissioni punto-punto in ponte radio, o trasmissioni satellitari punto-punto o
broadcast. La banda di frequenza delle microonde (1-40 GHz) ha la caratteristiche
di poter utilizzare antenne paraboliche di dimensioni maneggevoli (fino a qualche
metro di diametro).
Si pu quindi realizzare una comunicazione punto-punto tra sorgente e
destinazione con allineamento ottico delle antenne. Molto usate sono anche le
trasmissioni satellitari, in cui microonde vengono trasmesse da una stazione di
terra al satellite. Di solito nelle telecomunicazioni le trasmissioni satellitari si
avvalgono di satelliti GEO (Geostationary Earth Orbit), a 36000 Km di quota in
orbita equatoriale, che appaiono in posizione fissa nel cielo.

11.2. Le reti di calcolatori


La storia dellumanit ha registrato negli ultimi trecento anni lintroduzione di
nuove tecnologie che hanno modificato profondmente la vita delluomo. Daltra
parte, come dice il filosofo Hannah Arendt, lessenza di tutte le rivoluzioni legata
allapparire di una novit nellesperienza umana. Ci vero anche e soprattutto
per le innovazioni tecnologiche, quali la rivoluzione industriale, favorita dalla
nascita dei primi sistemi meccanici e dallinvenzione dei motori a vapore; senza
dubbio gli ultimi cinquantanni del secolo scorso sono stati invece caratterizzati
dalle tecnologie dellinformazione e delle comunicazione. Nel secolo appena
passato si sono via via diffusi a livello mondiale il sistema telefonico, la radio e la
televisione, i computer ed i satelliti per telecomunicazioni.
Queste tecnologie stanno rapidamente convergendo: la combinazione di
elaboratori e sistemi di telecomunicazione, in particolare, ha avuto una profonda
influenza sullorganizzazione dei sistemi di calcolo, passando, infatti, dal vecchio
modello mainframe terminali, in cui la potenza di calcolo concentrata in un
unico grande elaboratore a cui si accede per mezzo di un certo numero di
terminali, a quello attuale in cui vi un grande numero di elaboratori autonomi
connessi in rete.
Le reti di computer o computer network rappresentano quindi levoluzione
tecnologica, sia software sia hardware, dei primi sistemi informatici e nascono
dallesigenza, sempre pi impellente, di permettere agli utenti che operano su
diversi elaboratori di comunicare fra di loro.
Nellaccezione pi propria del termine, rete di computer sta ad indicare un
insieme di computer autonomi interconnessi. Il termine interconnesso, quando
applicato ad un insieme di elaboratori, sta ad indicare che questi offrono la
possibilit di scambiarsi informazioni in un formato comune. Lautonomia si
riferisce, invece, sia alla capacit intrinseca di elaborazione locale, cio alla
374 Capitolo undicesimo

possibilit di ogni singola macchina di lavorare con il proprio software senza far
riferimento alla connessione in rete, sia alla possibilit di ogni utente di
amministrare il proprio computer seguendo criteri personali.
Tramite una rete, gli utenti condividono: programmi, dati, risorse di calcolo,
dispositivi hardware indipendentemente dalla loro allocazione fisica. Lo scopo
primario di una rete quello di migliorare la comunicazione fra i vari utenti che vi
afferiscono. Questa affermazione, cos come enunciata, potrebbe sembrare del tutto
generica e superficiale. Le potenzialit di quanto detto si esplicano, invece, nelle
modalit in cui una rete consente agli utenti la reciproca comunicazione e
soprattutto, negli effetti pratici che lintroduzione di questi nuovi metodi di
comunicazione comportano su diversi aspetti dellorganizzazione del lavoro.
Citeremo, alcuni dei motivi, che possono motivare, in alternativa ad un sistema
centralizzato, l adozione di un sistema di rete.
- Riduzione dei costi. Sono diversi i settori in cui, ladozione di unadeguata
struttura di rete, permette una consistente riduzione dei costi sia come effetto
diretto, sia come conseguenza dellaumento di efficienza e della diminuzione
dei tempi necessari per lespletamento di alcune procedure. Si pensi, ad
esempio, al sistema di posta elettronica (e-mail): che permette, da un lato, la
drastica riduzione dei costi telefonici e parallelamente la riduzione dei tempi di
trasferimento dei documenti tra gruppi di utenti dislocati geograficamente.
Inoltre una rete di personal computer costa molto meno di un main-frame.
- Condivisione delle risorse. probabilmente la funzionalit pi utilizzata nelle
reti: la condivisione delle risorse rende i programmi, i dati e le
apparecchiature, disponibili a qualsiasi utente della rete, indipendentemente
dalla dislocazione sia di queste che dellutente. Si pu, ad esempio, investire in
una stampante di alta qualit condivisa tra pi utenti piuttosto che, a parit di
costo, acquistare un certo numero di stampanti pi piccole, guadagnando cos,
sia in prestazioni che in efficienza. La condivisione di un dispositivo di
trasmissione fax permette, come si pu facilmente immaginare,
lottimizzazione della sua utilizzazione e nel contempo la riduzioni di costi e
di tempi di attesa. Ancora, un utente potrebbe vedere il disco di un altro utente
come se fosse una risorsa locale utilizzando quindi i dati ed i programmi
disponibili su quel disco, esattamente come se fossero presenti sul proprio
computer.
- Aumento dellaffidabilit. La possibilit di replicare i dati, ed in generale le
risorse e programmi pi importanti, ai quali hanno necessit di accedere pi di
un utente su diverse macchine, rende una rete molto pi affidabile di un
sistema ad elaborazione concentrata. In questultimo caso, infatti, un blocco
del sistema centrale renderebbe inservibile lintera struttura mentre, nel caso di
una rete, esistono - grazie appunto alla possibilit di replicazione - tecniche
automatiche o semiautomatiche di recovering che permettono agli utenti di
continuare a lavorare tranquillamente mentre i tecnici ripristinano la
configurazione ordinaria. ). Tale caratteristica fondamentale sistemi che
devono funzionare a tutti i costi (traffico aereo, centrali nucleari, sistemi
militari, ecc.)
- Decentralizzazione del calcolo e distribuzione delle attivit al fine di
migliorare la produttivit ed efficienza del sistema complessivo.
- Cooperazione tra utenti/programmi nello svolgimento di operazioni.
Le reti di comunicazione 375

- Scalabilit. Si possono aumentare le prestazioni del sistema aumentando il


numero di elaboratori (entro certi limiti).
11.2.1. Tipologie di reti di calcolatori
La Prima di introdurre le principali caratteristiche hardware e software delle reti,
necessario premettere una serie di concetti che in buona parte provengono dalla
teoria pi generale delle reti di comunicazione. Iniziamo anzitutto a distinguere tra
le comunicazioni di tipo broadcast e quelle punto punto.
Le reti broadcast sono dotate di un unico canale di comunicazione (bus) che
condiviso da tutti gli elaboratori (vedi figura 4). In particolare, dei messaggi di
breve lunghezza (spesso chiamati pacchetti) vengono inviati da un elaboratore e
sono quindi ricevuti da tutti gli altri elaboratori. Per specificare chi leffettivo
destinatario del messaggio, il trasmettitore specifica nel messaggio un indirizzo
del destinatario, inteso, per ora, come un riferimento unico nel sistema del
computer destinatario. Quando un elaboratore riceve un pacchetto, esamina
lindirizzo di destinazione: se questo coincide col proprio indirizzo, allora il
pacchetto viene elaborato altrimenti viene ignorato. Le reti broadcast, in genere,
consentono anche di inviare un pacchetto a tutti gli altri elaboratori usando un
opportuno indirizzo (broadcasting): in tal caso tutti prendono in considerazione il
pacchetto.

Figura 4 - Rete broadcast (a bus)

Le reti punto a punto consistono invece di un insieme di connessioni fra


coppie di elaboratori (vedi figura 5). Per arrivare dalla sorgente alla destinazione,
un pacchetto pu dunque dover passare per uno o pi elaboratori intermedi, e
spesso esistono pi cammini alternativi per arrivare da un sorgente ad un
destinatario: si comprende, allora, intuitivamente il ruolo importante degli
algoritmi di instradamento o routing in questo contesto. In generale, anche se
non sempre vero, le reti localizzate geograficamente tendono ad essere di tipo
broadcast, mentre le reti molto estese tendono ad essere punto a punto.
Ulteriore differenza spesso fatta sulla base del modello di elaborazione
effettuata, ovvero il modello client-server e quello peer to peer.
Una rete client-server costituita da entit che richiedono servizi, o client, e
da entit che forniscono tali servizi, o server.
376 Capitolo undicesimo

Figura 5 - Rete punto a punto

Il server di solito un calcolatore pi potente che gestisce risorse condivise,


come ad esempio stampanti, basi di dati, file, programmi. Un client di solito un
elaboratore leggero, poco potente (al limite - ma ci accadeva soprattutto in
passato - un terminale con tastiera e schermo).
Nelle reti peer to peer la filosofia completamente differente: tutti gli
elementi della rete sono allo stesso livello ed i calcolatori della rete comunicano
direttamente gli uni con gli altri senza far riferimento ad un server. In altri termini
un computer pu fungere in unarchitettura P2P sia da client che da server a
seconda delle necessit.
Una ulteriore ed importante classificazione delle reti quella basata sulle loro
dimensioni. Come si pu osservare in tabella 1, la principale distinzione tra reti
locali, reti metropolitane e reti geografiche

Distanza Ambito Tipo di rete


10 m Stanza Rete locale
100 m Edificio Rete locale
1 Km Campus Rete locale
10 Km Citt Rete Metropolitana
100 Km Nazione Rete geografica
1000 km Continente Rete geografica
10.000 km Pianeta Internet (Interconnessione di reti)
Tabella 1 - Tipi di Rete

Le reti locali, o Local Area Network, LAN, sono reti in genere possedute da
una singola organizzazione (reti private) ed hanno unestensione che arriva fino a
qualche km, allinterno di un singolo edificio o di un campus (si ricordi che allo
stato non si pu di norma, posare cavi sul suolo pubblico).
Le LAN sono molto usate per connettere tra di loro Personal Computer e/o
workstation. Esse si distinguono dagli altri tipi di rete per tre caratteristiche: (i)
hanno una dimensione ridotta; (ii) usano una tecnologia trasmissiva di tipo
broadcast; (iii) hanno una topologia classicamente a stella, bus o ad anello
Le reti di comunicazione 377

(ring). Si ricorda che con il termine topologia si fa riferimento alle strutture


architettoniche che rappresentano la disposizione dei cavi della rete e il
conseguente interfacciamento delle postazioni.
Nella topologia a stella, il ruolo centrale della trasmissione svolto da un
dispositivo o insieme di dispositivi chiamati centri stella (vedi figura 6) o hub,
ripetitori che semplicemente inviano le informazioni che ricevono a tutte le porte
collegate. Lhub permette la comunicazione tra i vari computer fornendo un
sistema di connessione comune e localizzato (concentrato). Gli hub possono
essere disposti a cascata in modo da espandere la rete in modo progressivo. Nelle
reti con topologia a stella i pacchetti che vengono inviati da un elaboratore ad un
altro sono ripetuti su tutte le porte del centro stella: questo permette a tutti i PC di
vedere qualsiasi pacchetto inviato sulla rete.
La topologia a stella consente un controllo centralizzato (grazie agli hub) delle
comunicazioni con prestazioni elevate per le connessioni; come rovescio della
medaglia, si possono verificare dei punti critici nella linea, proprio in
corrispondenza degli hub.

Figura 6 - Topologia a stella

Nella topologia a bus (vedi figura 4), in ogni istante un elaboratore solo pu
trasmettere, mentre gli altri devono astenersi: dunque necessario un meccanismo
di arbitraggio, centralizzato o distribuito, per risolvere i conflitti quando due o pi
elaboratori vogliono trasmettere contemporaneamente. In un arbitraggio
centralizzato, una apposita apparecchiatura accetta richieste di trasmissione e
decide chi abilitare, mentre nell arbitraggio distribuito, ognuno decide per conto
proprio.
Lo standard IEEE 802.3 (chiamato impropriamente Ethernet) lo standard di
riferimento per la trasmissione su reti broadcast, basate su un bus, con arbitraggio
distribuito, operante a 10 oppure 100 Mbps (oggi anche a 1 Gbit/s e a 10 Gbit/s).
Pi nel dettaglio, per risolvere una contesa si utilizza uno schema di accesso a
canale condiviso detto CSMA/CD: Carrier Sense Multiple Access Collision
Detection. Il principio di funzionamento di tale tecnica estremamente semplice:
quando una stazione presente sul canale deve trasmettere lo fa senza attendere
alcuna autorizzazione. Se la trasmissione ha successo, cio i dati trasmessi non
collidono con quelli trasmessi da altre stazioni, bene; altrimenti la stazione in
grado di rilevare la collisione e provvede, in un secondo momento, a ritentare la
trasmissione dei dati, fino a quando questa non ha successo In altri termini, ogni
stazione della rete in ascolto sul canale, e, non appena il canale libero (lo si
378 Capitolo undicesimo

scopre individuando la presenza o meno di un segnale, onde il nome carrier


sense), essa, qualora abbia informazioni da inviare, pu iniziare a trasmettere. In
generale, pi stazioni sono in attesa di trasmettere (onde il nome multiple
access), e le diverse informazioni si possono propagare da diverse zone fino a
collidere. Non appena le trasmittenti rilevano queste collisioni, si arresta il
tentativo di trasmissione, si aspetta un tempo casuale e poi si riprova a trasmettere,
nel caso di mancata collisione, invece, la trasmittente pu completare linvio del
messaggio
La topologia a bus una topologia passiva nel senso che, le stazioni non
concorrono in alcun modo alla trasmissione dei messaggi lungo la linea: esse
rimangono solo in ascolto, nell attesa o di inviare un messaggio o di ricevere un
messaggio a loro destinato. Ci conduce a diverse implicazioni, di cui due
piuttosto importanti: se una stazione va in errore (o viene a mancare) il
funzionamento del resto della rete non verr alterato; se, per, il cavo venisse
interrotto in un punto qualsiasi, la trasmissione e quindi la comunicazione,
risulterebbe bloccata per lintera rete. A suo vantaggio va inoltre citato anche il
costo estremamente basso sia dei cavi che della connessione.
Nella topologia a ring, le macchine sono disposte lungo un anello (vedi figura
7) ed ogni bit-informazione circumnaviga lanello in un tempo tipicamente
inferiore a quello di trasmissione di un messaggio. Anche qui necessario un
meccanismo di arbitraggio spesso basato sul possesso di un gettone (token) che
abilita alla trasmissione. Pi nel dettaglio, il diritto di trasmettere si basa sul
continuo passaggio del token circolante fra le stazioni della rete: la stazione che ha
il token pu trasmettere (le altre si trovando in modalit di ascolto) fino al
completamento dellinvio del messaggio; il gettone viene quindi passato alla
stazione successiva che passa allo stato di trasmissione se ha qualcosa da
trasmettere, altrimenti passa, a sua volta, il token alla stazione che la segue
nellanello. Si noti che il token altro non che un insieme di bit con particolare
configurazione che circola continuamente sullanello.

Figura 7 - Topologia ad anello

Lo standard IEEE 802.5 (derivante dalla rete IBM Token Ring) lo standard
di riferimento per reti broadcast basate su ring, con arbitraggio distribuito.
A titolo di esempio, si mostrano di seguito le classiche componenti di una rete
locale, come anche mostrato dalla figura 8.
- Sistema di cablaggio: il sistema fisico di interconnessione costituito dai cavi (UTP
o STP, coassiali, fibre ottiche) o connessioni wireless (onde radio) e dai dispositivi
Le reti di comunicazione 379

(hub, switch, etc) che permette il collegamento fisico tra i vari computer che
compongono la rete. Il cablaggio segue norme ben precise cablaggio strutturato
(ad esempio, TIA/EIA 568B, ISO/IEC 11801 ed EN 50173), a cui si fa in genere
riferimento per quanto riguarda linstallazione dei cavi, la topologia della rete, i
mezzi trasmissivi, le tecniche di identificazione dei cavi, la documentazione e le
caratteristiche tecniche dei prodotti impiegati. Il sistema di cablaggio comprende di
solito un cosiddetto cablaggio di dorsale, che collega diversi edifici (dorsale di
campus) e piani di differenti edifici (dorsale di edificio), di solito in fibra ottica, e
cablaggio di piano che partendo da un armadio tecnologico contenente concentratori
raggiunge tutti i vari posti di lavoro, realizzando una topologia a stella. Il sistema di
cablaggio condiziona, in modo a volte determinante, la velocit e le prestazioni di
una rete.
- Server e Workstation: i servizi utente di una rete sono offerti da macchine che
ricoprono ruoli specifici e che sono denominati, come gi accennato, server. In
particolare, i servizi relativi a programmi, dati e file in genere, sono offerti dai file
server. Su queste macchine risiedono, di norma, le risorse che devono essere
condivise da tutti gli utenti. Altri servizi comunemente disponibili sono i servizi di
stampa (print server) e quelli di comunicazione (fax server, communication server,
etc.). Una singola macchina pu offrire pi di un servizio per cui, ad esempio, una
macchina pu essere contemporaneamente file-server e print-server. Lalta
specializzazione dei server, ossia uno per ogni servizio, giustificabile solo in quelle
installazioni in cui, il particolare servizio presenta un volume di operazioni talmente
elevato, nellunit di tempo, da portare rapidamente alla saturazione ununica
macchina nel caso in cui coesistessero anche altri servizi. Gli utenti accedono ai
servizi offerti dai server dalle proprie stazioni di lavoro (denominati anche:
workstation, stazioni client o semplicemente client). In linea di principio, non c
nessun motivo per cui le stazioni di lavoro siano concettualmente diverse dai server
di una rete: entrambi sono computer che possono essere in tutto e per tutto uguali,
salvo che per il loro utilizzo: la differenza tra server e stazioni di lavoro, in linea di
principio, nel software di base delle macchine (il sistema operativo). Nella realt si
preferisce - per motivi di efficienza, prestazioni e sicurezza - che i server siano
macchine mediamente pi potenti delle relative stazioni di lavoro il cui carico di
elaborazione sia inferiore, nelle normali applicazioni, a quello dei server.
- Schede di rete: per creare una rete, occorre istallare su ogni elaboratore una scheda di
rete che permetta al computer di inviare e ricevere messaggi, via cavo o via onde
radio.
- Dispositivi condivisi: stampanti, scanner, dispositivi di memorizzazione di massa e
altre periferiche a seconda delle esigenze degli utenti.
380 Capitolo undicesimo

Figura 8 - Componenti di una rete locale

Le reti geografiche o Wide Area Network, WAN, invece, si estendono a livello


di una nazione, di un continente o dellintero pianeta.
Per introdurre i principali aspetti tecnologici legati a tale tipologia di rete,
prendiamo consideriamo una rete di comunicazione planetaria di uso comune, la
rete telefonica. La rete disegnata in questo modo: esiste un distretto telefonico
che contiene una centrale di smistamento, che comunica con le centrali degli altri
distretti. Quando facciamo una telefonata, la chiamata viene fatta passare
attraverso una o pi centrali, fino a raggiungere il numero chiamato: le centrali
costruiscono una connessione diretta fra i due telefoni, che dura per tutto il tempo
della telefonata. In altre parole, viene creato un circuito virtuale che unisce i due
telefoni allatto della chiamata: per questo, tale tipologia di comunicazione viene
anche detta a commutazione di circuito, in quanto il canale viene costruito per
ogni nuova sessione di comunicazione, collegando singoli tratti di linee dedicate.
E chiaro che la soluzione adottata per le reti telefoniche non si adatta bene
alle comunicazioni tra elaboratori: si utilizza in questo caso, infatti, un diverso tipo
di commutazione detta a pacchetto.
Nella commutazione a pacchetto (packet switching), ogni messaggio diviso
in tanti elementi di dimensione fissa detti pacchetti e opportunamente numerati.
Ogni pacchetto contiene altres linformazione relativa allindirizzo del computer
destinatario e a quello del mittente e viene trasmesso separatamente, facendo
virtualmente una strada diversa dagli altri pacchetti del messaggio per arrivare al
destinatario. Si noti, allora, che i pacchetti non arrivano necessariamente nello
stesso ordine con cui sono stati inviati: per questo il destinatario deve aspettare la
ricezione di tutti i pacchetti per poterli poi ricomporre e ricostruire il messaggio
(vedi figura 9). Una rete di comunicazione che basata su questo principio viene
anche detta punto a punto, o store and forward.
Le reti di comunicazione 381

Figura 9 - Commutazione di pacchetto


Una WAN, dunque, costituita di due componenti distinte: un insieme di
elaboratori detti host oppure end system ed una communication subnet (o subnet).

Figura 10 - LAN collegate da una WAN

A sua volta, la subnet consiste di due componenti: linee di trasmissione (dette


anche circuiti, canali, trunk) ed elementi di commutazione (switching element),
detti anche sistemi intermedi, oppure nodi di commutazione o anche router.
Come mostrato in figura 10, una WAN usata per connettere pi LAN tra di loro.
In generale una WAN contiene numerose linee (spesso telefoniche) che
congiungono coppie di router. Ogni router allora deve:
- ricevere un pacchetto da una linea in ingresso;
- memorizzarlo in un buffer interno;
- instradare il pacchetto appena la necessaria linea in uscita libera: ogni
nodo, infatti, mantiene una tabella che indica a quali vicini ritrasmettere
un pacchetto non destinato a lui, in base allindirizzo di destinazione del
pacchetto.
Per concludere, citiamo le reti metropolitane (Metropolitan Area Network,
MAN), che hanno unestensione tipicamente urbana. Per le reti metropolitane
stato introdotto uno standard apposito, IEEE 802.6 o DQDB, che prevede
lesistenza di un mezzo trasmissivo di tipo broadcast (due bus 802.6) a cui tutti i
computer sono attaccati.
382 Capitolo undicesimo

11.2.2. Cenni allInternetworking


Con il termine internetworking ci si riferisce allinsieme di norme tecniche,
protocolli e dispositivi che consentono la connessione di due o pi reti
eterogenee.
Una internetwork quindi formata quando reti diverse (sia LAN che MAN o
WAN) vengono collegate fra loro. Alcuni problemi per sorgono inevitabilmente
quando si vogliono connettere fra di loro reti progettualmente diverse (spesso
incompatibili fra loro). In questo caso si deve ricorrere a speciali attrezzature, dette
gateway (o router multiprotocollo), che oltre ad instradare i pacchetti da una rete
allaltra, effettuano le operazioni necessarie per rendere possibili tali trasferimenti.
Oltre al router, per linterconnessione delle reti si utilizzano altri dispositivi
che citeremo brevemente:
- repeater: e un dispositivo che collega reti LAN identiche e fornisce la possibilit di
rigenerare i segnali in transito tra una rete e laltra, amplificandoli (in tal modo
possibile estendere larea della rete);
- bridge: un dispositivo che collega reti diverse aventi per uno stesso schema di
indirizzamento; di solito il bridge rimane in ascolto sulle due reti che connette e,
quando riconosce un pacchetto proveniente da una rete e destinato a una stazione
appartenente allaltra rete, lo preleva, lo memorizza e lo ritrasmette con il metodo di
accesso proprio della rete di destinazione (viene di solito usato per connettere reti LAN
con tecnologia diversa, e.g. reti token-ring con reti ethernet);
- gateway: un dipositivo che crea collegamenti tra reti con ambienti applicativi
differenti.
11.2.3. Aspetti software delle reti di calcolatori
Dopo aver mostrato quelle che sono le connessioni fisiche tra calcolatori,
dobbiamo cercare di capire come farli comunicare dal punto di vista del
software. Gli elaboratori, infatti, devono seguire alcune regole dette protocolli di
comunicazione.
Un protocollo stabilisce le regole di comunicazione che debbono essere seguite da due
interlocutori.
Consideriamo il classico esempio del colloquio tra due persone che si parlano al
telefono: le prime frasi scambiate (pronto? chi parla? Sono Carlo, con hi parlo?)
costituiscono un esempio di regola in cui gli interlocutori stabiliscono la loro identit prima
di iniziare un colloquio vero e proprio.
Per protocollo di comunicazione tra due elaboratori si intende, pi precisamente, un
insieme di regole che permette la corretta instaurazione, mantenimento e terminazione di
una comunicazione di qualsiasi tipo tra due o pi entit. Per questo motivo, il protocollo
deve poter definire la sintassi da seguire (il formato del messaggio), e lordine dello scambio
di messaggi.
Data la complessit del problema derivante dal problema della comunicazione tra gli
host di una rete, pi che un protocollo, in realt, si definiscono famiglie di protocolli, in cui
ogni protocollo gestisce univocamente una componente ben definita della comunicazione
condividendo con gli altri protocolli i dati di cui essi necessitano.
Larchitettura dei protocolli organizzata a livelli. Lo scopo di ogni livello come
consuetudine di ogni sistema fatto a strati di fornire servizi alle entit del livello
immediatamente superiore, mascherando il modo in cui questi sono implementati e
Le reti di comunicazione 383

sfruttando opportunamente i servizi che gli vengono a sua volta forniti dal livello
immediatamente inferiore, come mostrato in figura 11.

Figura 11 - Architettura a livelli

Per quanto attiene la comunicazioni tra computer, cerchiamo anzitutto di comprendere


quali sono gli strati fondamentali da considerare, in quanto una visione a livelli permette
di semplificare notevolmente il problema della comunicazione. A tal fine, pensiamo alla
seguente analogia con la comunicazione fra esseri umani (vedi figura 12), nella quale un
filosofo indiano vuole conversare con uno stregone africano, sapendo che il filosofo indiano
parla solo lhindi, mentre lo stregone africano solo lo swahili. C allora bisogno
innanzitutto di due traduttori, che parlino una lingua in comune tra di loro, ad esempio
linglese: un traduttore traduce da hindi in inglese ed un traduttore da swahili in inglese.
Dopo aver fatto la traduzione, si inviano quanto tradotto su un mezzo fisico, ad esempio via
fax. Dal punto di vista logico, il filosofo dialoga con lo stregone, il traduttore indiano con il
traduttore africano, e il fax indiano con il fax africano.

Figura 12 Problema della comunicazione


384 Capitolo undicesimo

Dallesempio fatto notiamo anzitutto che per comunicare necessaria


lesistenza di un canale fisico di comunicazione, ovvero di una infrastruttura che
permetta di scambiare segnali tra le due entit della comunicazione. A ci occorre
aggiungere la conoscenza da parte del trasmittente e del ricevente dei protocolli di
trasmissione, ovvero di regole che permettono di interpretare i segnali scambiati.
Infine, necessario concordare delle regole che permettono di dare una
interpretazione ai segnali scambiati (protocollo applicativo). Si noti che dal punto
di vista dellutente finale, le soluzioni adottate per i diversi livelli della
comunicazione devono essere completamente trasparenti. Le entit (processi) che
effettuano tale conversazione si chiamano peer entitiy (entit di pari livello). Il
dialogo fra due peer entity di livello n viene materialmente realizzato tramite i
servizi offerti dal livello precedente e virtualmente mediante il procollo applicativo
definito allo steso livello, mentre il dialogo tra peer entity dello stesso host avviene
sfruttando apposite interfacce di comunicazione(vedi figura 13).

Figura 13 - Comunicazione tra host

Nellesempio mostrato in figura i protocolli applicativi potrebbero essere


quelli di livello N e livello N + 1, mentre il protocollo di trasmissione coincide con
quello di livello N 1.
Dato che i protocolli devono essere usati da tutti gli elaboratori, essi sono
definiti da organismi internazionali di standardizzazione. Il pi famoso lISO
(International Standard Organization) che ha proposto lo standard OSI (Open
System Interconnection) per la schematizzazione a livelli di unarchitettura di rete
con lobiettivo di garantire linteroperabilit tra vari sistemi.
I livelli del protocollo ISO-OSI, mostrati in figura 14 , sono i seguenti:
(1) Livello Fisico (Physical Interface Layer): preposto alla gestione
degli aspetti fisici della comunicazione, dei meccanismi di
Le reti di comunicazione 385

collegamento ed offre ai livelli superiori funzionalit indipendenti dal


mezzo trasmissivo utilizzato.
(2) Livello dei collegamenti dei dati (Data Link Control): si occupa della
correttezza del trasferimento dei dati (suddivisione dei pacchetti in
frame, rilevazione e correzione di errori, controllo del flusso dei
pacchetti).
(3) Livello di rete (Network Layer): si occupa del controllo della
congestione della rete e gestisce e controlla il routing.
(4) Livello di trasporto (Transport Layer): ha lo scopo di segmentare una
unit di trasmissione in messaggi fisici di uguale grandezza
(pacchetti) e di garantire laffidabilit della comunicazione (controllo
flusso dei messaggi).
(5) Livello sessione (Session Layer): si occupa di aprire e chiudere il
dialogo tra gli elaboratori.
(6) Livello di presentazione (Presentation Layer): si occupa di convertire
codici e formati tra il mittente ed il destinatario del messaggio.
(7) Livello applicazione (Application Layer): responsabile di offrire
servizi telematici generalizzati tra cui, ad esempio, la posta
elettronica ed il trasferimento dei file.
A partire dal livello 4 le comunicazioni trai vari peer entity diventano di tipo
host to host (end to end), in altri termini a questo livello completamente
nascosta linfrastruttura di comunicazione fisica sottostante.

Figura 14 - Modello ISO/OSI

Qualche parola infine, sul sistema operativo o sui sistemi operativi presenti
sugli host di una rete, indispensabili per la comunicazione software tra sistemi.
386 Capitolo undicesimo

Iniziamo col dire che le definizioni fornite finora non implicano, in alcun modo, la
presenza del medesimo sistema operativo, su tutte le macchine della rete. Anzi, un
condizionamento del genere sarebbe estremamente riduttivo agli scopi di una rete.
Addirittura ogni macchina potrebbe, in linea teorica, avere un proprio sistema
operativo diverso da quello presente sulle altre macchine o sui server. Tra i due
eccessi appena esposti, esistono diverse soluzioni intermedie che dipendono dal
tipo di applicazione della rete: alcune situazioni - ad esempio programmi
preesistenti, formazione del personale, etc. - potrebbero vincolare i sistemi
operativi client (cio quelli installati sulle stazioni di lavoro), mentre in generale il
sistema operativo server (quello che gestisce e controlla lattivit di uno o pi
server) generalmente vincolato da considerazioni di efficienza, tipologia delle
prestazioni, sicurezza e costi.
Il sistema operativo server (spesso chiamato impropriamente sistema
operativo di rete) in generale un s.o. piuttosto complesso che richiede, il pi delle
volte, buone capacit tecniche da parte di chi preposto alla sua amministrazione.
Sovrintende tutte le attivit di rete, controlla che le operazioni richieste non
invalidino lintegrit dei dati, verifica laccesso da parte degli utenti a dati riservati
e altro ancora. Il s.o. client interagisce con il s.o. server rigirando le richieste
utente a questultimo ogni qualvolta coinvolgano un server della rete (una richiesta
di apertura di file o di inoltro di messaggi, etc...).
11.2.4. Il modello Internet
Differentemente dal modello teorico OSI, il modello Internet, alla base
dellattuale rete Internet, impostato su unarchitettura a 5 livelli:
(1) Livello fisico (Physical Interface Layer): funge da interfaccia fisica tra le
stazioni e il mezzo fisico di comunicazione per la trasmissione dei dati.
(2) Livello di accesso alla rete (Medium Access Control Layer): regola lo
scambio dati fra un sistema finale e la rete a cui collegato, specificando
come organizzare i dati in frame e come trasmetterli sulla rete.
(3) Livello internet (Internet Layer): si occupa dello scambio di dati tra
sistemi che non appartengono alla stessa rete. In particolare, a tale livello
si trova lInternet Protocol (IP) che definisce le procedure per
lattraversamento di reti multiple interconnesse. Pi nel dettaglio, esso
specifica il formato dei pacchetti inviati attraverso la rete e i meccanismi
utilizzati per farli transitare dal calcolatore sorgente attraverso uno o pi
router e verso il destinatario (instradamento o routing). Si nota che lIP
non gestisce laffidabilit della comunicazione: i pacchetti vengono
instradati sulla rete senza alcun controllo con il solo obiettivo di farli
giungere a destinazione nel tempo minore possibile. Laffidabilit
invece demandata ai protocolli di livello superiore
(4) Livello di trasporto (Transport Layer) (host to host): a tale livello i
messaggi provenienti dai livelli superiori sono segmentati (e riassemblati
quando giungono dai livelli inferiori) in pacchetti. Il protocollo base di
tale livello, il Transmission Control Protocol (TCP), garantisce inoltre
che i pacchetti siano trasmessi in modo affidabile, con la garanzia che tutti
giungano a destinazione nello stesso ordine di partenza (controllo del
flusso).
Le reti di comunicazione 387

(5) Livello di applicazione (Application Layer): (host to host) specifica come


unapplicazione pu utilizzare linsieme dei protocolli TCP/IP
comunicando cooperativamente con calcolatori differenti.
Il successo di questa architettura si deve al fatto che stata ed uneccellente
piattaforma per la realizzazione di applicazioni di rete affidabili ed efficienti ed ha
permesso da subito di condividere informazioni tra organizzazioni diverse. Il
TCP/IP ormai implementato in tutti i sistemi operativi di rete ed stato
supportato dalle grandi casi costruttrici di apparati attivi di rete.
11.2.5. La struttura di una rete TCP/IP
Come descritto, larchitettura di una rete TCP/IP si basa su uno schema di
riferimento costituito dai seguenti elementi fondamentali:
- linfrastruttura di comunicazione;
- il protocollo di comunicazione o di base;
- il protocollo applicativo, ossia linsieme di regole e il possesso di
competenze comuni per il trattamento di informazioni in diversi
contesti applicativi (il web, la posta elettronica, lo scambio di file,
etc);
- un insieme di computer o host.
Il protocollo di base , come gi descritto, il protocollo TCP/IP (Transmission
Control Protocol/ Internet Protocol). Tale protocollo consente linvio affidabile di
dati sulla rete. In particolare, ogni dato spedito sulla rete viene suddivisa in sotto
unit denominate pacchetti, che vengono poi ricostruite allatto della ricezione.
Quando si richiede, ad esempio, unimmagine ad un computer remoto, la
spedizione avverr nel modo seguente: prima limmagine suddivisa in pacchetti
(ad esempio 1000), tutti di uguale dimensione e poi ogni pacchetto inserito in una
busta su cui saranno indicati: l'indirizzo del mittente, quello del destinatario e il
numero d'ordine. Le 1000 buste viaggeranno in piena autonomia e, nel caso in cui
esistessero 1000 tragitti diversi percorribili tra mittente e destinatario, ogni busta
potrebbe viaggiare transitando su un diverso percorso. Lordine di arrivo di ogni
pacchetto pu essere indifferente e, qualunque esso sia, le varie parti saranno
ricomposte dal destinatario al fine di ottenere limmagine di partenza.
I pacchetti possono trasportare informazioni di qualsiasi tipo: parti di una
immagine, di un messaggio, di una pagina di testo. I protocolli applicativi rendono
possibile, a due sistemi capaci di comunicare con il TCP/IP, la comprensione delle
informazioni scambiate.
In una rete TCP/IP, come in qualsiasi altra architettura di rete, ogni computer
deve essere identificato in maniera univoca. La tecnica usata, in questo caso,
attribuisce ad ogni host un numero tipicamente rappresentato in una notazione
simile alla seguente:
192.20.48.125

Si tratta, per la precisione, di un numero a 32 bit rappresentato come quattro


numeri di 8 bit (un byte) separati da un punto. Tale numero detto indirizzo IP
dell'host in questione. Una parte dell'indirizzo IP, quella pi a sinistra, usata per
identificare una rete mentre la rimanente parte, per identificare i singoli host della
rete. Le dimensioni delle due parti, in termini di numero di bit, sono variabili come
illustrato schematicamente nella figura 15.
388 Capitolo undicesimo

Net Host
10. 31.112.32

Net Host
192.168.4. 114

Figura 15 - Schema della struttura di un indirizzi IP

Poich esistono reti di dimensioni notevolmente diverse, da quelle costituite


da pochi computer ad altre composte da migliaia di host, la parte dell'indirizzo IP
che identifica la rete varia in funzione della dimensione della stessa. stata quindi
necessaria la suddivisione convenzionale degli indirizzi IP in cinque classi, in
funzione della loro suddivisione tra indirizzo di rete e indirizzo di host.
Per poter indicare quale parte dellindirizzo si usa per identificare la rete,
necessario specificare la cosiddetta maschera di sottorete o subnet mask. Si tratta
di un numero, simile a un indirizzo IP, i cui elementi assumono solo i valori 0 o
255. I byte posti a zero identificano lhost e quelli posti a 255 la rete, il tutto
facendo riferimento all indirizzo IP cui si riferisce la maschera.
Ad esempio con la scrittura 192.168.1.24 / 255.255.255.0 nella quale il
primo lindirizzo IP e il secondo la relativa maschera di sottorete si intende
specificare che per lindirizzo in questione la terna 192.168.1 (corrispondente a
255.255.255) identifica lindirizzo di rete, mentre il numero 24 identifica un
particolare host allinterno della suddetta rete.
chiaro che una comunicazione basata unicamente sugli indirizzi IP sarebbe
improponibile nel mondo reale. Si ricorre, pertanto, a indirizzi simbolici cio a
nomi che possono essere immediatamente significativi per l'utente. Ogni host della
rete , secondo questa convenzione, identificabile da un indirizzo che ha un
formato di questo tipo:

host_name.subdomain.top_level_domain

nel quale l host_name il nome della singola macchina, mentre


top_level_domain, unito ad un subdomain, identificano quella che possiamo
definire la posizione logica dell'host all'interno della rete. Un nome cos costruito
tecnicamente definito: Fully Qualified Domain Name (FQDN) o anche
semplicemente "indirizzo simbolico".
Si pu facilmente intuire che, l'uso degli indirizzi simbolici, rende pi
agevole l' utilizzo della rete. In questo modo gli utenti si trovano a lavorare con
indirizzi significativi, piuttosto che con numeri, il pi delle volte indecifrabili.
Ad esempio l'indirizzo www.osys.com identifica l'host www del subdomain
osys appartenente al dominio com (organizzazioni commerciali). Analogamente,
lindirizzo garbo.uwasa.fi identifica l'host garbo della rete uwasa (University of
Waasa) a sua volta appartenente al top level domain fi (Finlandia). Ovviamente,
deve essere sempre prevista la traduzione da indirizzo simbolico a indirizzo IP, e
viceversa, ogni qualvolta sia necessario e, possibilmente, in modo trasparente per
Le reti di comunicazione 389

l'utente. Tale traduzione inizialmente era effettuata consultando un'unica tabella


mentre oggi, per le titaniche dimensioni raggiunte da Internet, loriginaria tabella
divenuta un database distribuito in tutta la rete. Pertanto, non necessario che ogni
macchina conosca tutte le corrispondenze IP-FQDN, necessario semplicemente
conoscere dove andare a reperire le corrispondenze di cui non si a conoscenza.
Questo sistema, che funziona a cascata, chiamato Domain Name System (DNS).
Gli host che effettuano le ricerche delle corrispondenze prendono il nome di
Domain Name Server (DNS). Siffatto sistema di ricerca, a dispetto della intrinseca
complessit, comunque molto veloce e la risoluzione di una corrispondenza
pressoch immediata.
Come gi indicato, una macchina connessa in rete, definita host, dotata di un
indirizzo IP e di un corrispondente indirizzo simbolico. Un host fa parte di una rete
(o di una sottorete) e questa, a sua volta parte di un dominio.
Un dominio identificato dal nome pi a destra di un indirizzo simbolico che,
in prima approssimazione, corrispondono ai numeri pi a sinistra di un indirizzo
IP. Generalmente c' una stretta corrispondenza tra un dominio e la corrispondente
parte dell'indirizzo IP.
I domini in Internet sono regolamentati da specifiche istituzioni. Negli
indirizzi citati in precedenza ad esempio, le estensioni: .com e .it
rappresentano il nome dei domini e forniscono indicazioni significative sull
indirizzo stesso. Le estensioni i pi comuni sono:
- .com: indica un organizzazione commerciale (microsoft.com, ad
esempio, il nome della rete dell'organizzazione Microsoft);
- .edu: indica una organizzazione educativa (generalmente riferito ad
universit o a centri di istruzione statunitensi. mit.edu denota il noto
Massachusset Institute of Technology, mentre ucla.edu l'indirizzo
dell'universit di Los Angeles in California);
- .gov: indica gli enti governativi americani (il pi celebre
whitehouse.gov, che l'indirizzo della Casa Bianca, ma notissimo
anche nasa.gov;
- .mil: indica organizzazioni militari americane;
- .net: Indica enti organizzativi o amministrativi di qualunque rete
(come internic.net);
- .org: indica organizzazioni di tipo privato, generalmente non a scopo
di lucro (Fidonet.org , infatti, il dominio della rete amatoriale
Fidonet).
In tale elenco di domini le estensioni .edu, .gov e .mil si applicano soltanto ad
organizzazioni americane, mentre gli altri domini possono identificare anche
organizzazioni di altri paesi. Le istituzioni di governo di Internet, hanno
predisposto domini identificativi del paese di residenza di una certa rete. Cos una
rete italiana , di norma, etichettata con il suffisso it, una francese con fr, una
tedesca con de e cos via.
Come gi descritto, un indirizzo simbolico viene decodificato a partire proprio
dal dominio e procedendo verso sinistra: ad esempio l'indirizzo na.infn.it identifica
la sottorete napoletana (na) della rete che fa capo all'Istituto nazionale di Fisica
Nucleare (infn) del dominio relativo all'Italia (it).
A ogni dominio associato un calcolatore responsabile del dominio: per
esempio, lindirizzo mac1. labadam. unina. it ) prevede un computer responsabile
390 Capitolo undicesimo

per il dominio it, un computer per il dominio unina.it, un terzo computer per il
dominio labadam.unina.it ed un ulteriore computer per mac1.labadam.unina.it. Il
calcolatore responsabile di un dominio mantiene un elenco dei calcolatori
responsabili dei suoi sottodomini (e ne conosce i relativi indirizzi IP): il calcolatore
responsabile del dominio it deve sapere chi sono i calcolatori responsabili di tutti i
suoi sottodomini (tra cui c unina.it, ma anche unisa.it, miur.it); il calcolatore
responsabile del dominio unina.it deve a sua volta sapere chi sono i calcolatori
responsabili di tutti i suoi sottodomini (tra cui c labadam.unina.it, ma anche
mobilab.unina.it) e cos via. Per tradurre, allora, lindirizzo DNS di un calcolatore
nel suo indirizzo IP si deve interrogare il responsabile di ciascuno dei domini cui
quel calcolatore appartiene.
Infine va ricordato che nella pratica, in TCP/IP lindirizzamento su due
livelli, lindirizzo IP e la porta TCP. Lindirizzo IP come visto un indirizzo
globale unico associato a ogni calcolatore collegato ad una sottorete e viene
utilizzato da IP per linstradamento e la consegna dei pacchetti; la porta TCP
invece un indirizzo unico allinterno dellhost e viene usato da TCP per consegnare
i dati, magari aggiungendovi altre informazioni di controllo, alla particolare
applicazione interessata.
11.2.6. Le applicazioni di una rete TCP/IP
In questo paragrafo andremo ad illustrare i servizi applicativi pi comuni offerti da
una tipica rete TCP/IP. Molti dei servizi utente, e soprattutto il modo con cui sono
presentati allutente, dipendono non solo dallinsieme di protocolli usati per
implementare la rete ma anche dal sistema operativo usato.
Le applicazioni che richiedono i servizi di rete, e che li rendono visibili ed
utilizzabili allutente, sono costituiti da processi che girano nel contesto del sistema
operativo della macchina sulla quale si utilizzano. In generale i sistemi operativi
server implementano questi servizi in maniera indipendente dal modello di
client: lutilizzo pi o meno efficiente di questi servizi dipende quasi in maniera
esclusiva dai sistemi operativi client. Nondimeno esiste un insieme minimo di
servizi che devono essere assicurati e che, salvo eccezioni, sono disponibili su
quasi tutti i sistemi operativi utilizzati sui client di rete: a questo insieme minimo
che faremo riferimento nellesposizione che segue.
- HTTP - il servizio HTTP, acronimo di HyperText Transfer Protocol, un
protocollo che regola lo scambio di ipertesti (pagine web) tra gli host
presenti in Internet. E il protocollo alla base del cosidetto World Wide
Web (WWW) che un sistema di rappresentazione di informazioni basate
sulle tecnologie ipertestuali. WWW ha portato il concetto di ipertesto,
generalizzandolo sotto vari aspetti, su Internet dando origine allidea del
villaggio globale dellinformazione su rete. WWW presenta le
informazioni sotto forma di pagine, dove una pagina pu contenere del
testo ordinario, immagini, filmati, suoni ed una serie di link ad altre
pagine. Il software che permette di usufruire del servizio WWW e di
visualizzare le pagine web viene, di norma, chiamato browser WWW o
semplicemente browser. In sintesi, attraverso lhttp, possibile esplorare
linsieme delle pagine web (residenti su apposite macchine, denominate
HTTP Server), da cui costituito il WWW.
Le reti di comunicazione 391

- FTP - il servizio FTP, acronimo di File Transfer Protocol, un protocollo


che si utilizza per trasferire file tra computer collegati ad internet. Con l
FTP ci si pu connettere a distanza ad un sistema remoto (FTP server),
visualizzare i suoi archivi di file e trasferire file dal computer personale a
quello remoto e viceversa. Per trasferire files con FTP c bisogno di
installare sul computer un programma ad hoc che viene quasi sempre
fornito dai sistemi operativi che supportano il protocollo TCP/IP.
Windows, ad esempio, include un client FTP nella sua installazione,
ciononostante, anche in rete sono disponibili molti client FTP, molti dei
quali openware o shareware.
- Telnet - Il servizio di terminale remoto virtuale forse il pi tecnico tra
i tools storici di Internet e pertanto successivamente superato dalle
evoluzioni delle tecnologie informatiche che hanno portato allo sviluppo
di tools di controllo remoto con uninterfaccia sempre pi amichevole
(servizi di desktop remoto). Telnet un protocollo di comunicazione che
consentiva all utente generico di un computer, nodo della rete, di
utilizzare la propria postazione di lavoro come terminale di un altro
qualsiasi nodo (con un servizio di telnet abilitato) e permetteva cos di
controllare un computer a distanza.In pratica, tramite Telnet si entra in
un computer remoto (mediante un proprio login e una propria password),
e nel caso si dispone di unarea personale (una parte del suo hard disk a
propria disposizione), si potevano svolgere a distanza tutte le normali
operazioni (eseguire programmi, leggere e spedire posta elettronica,
copiare, cancellare, rinominare file...)
- E-mail - : La posta elettronica o e-mail realizza la versione elettronica del
tradizionale sistema postale. Come sempre, per poter utilizzare un servizio
di Internet, occorre disporre di due cose: un calcolatore connesso alla rete
e che parli in TCP/IP e un prodotto software che fornisce linterfaccia
utente per utilizzare lo specifico servizio. Nella fattispecie della posta
elettronica il prodotto software di e-mail (client di posta elettronica o
mailer) deve consentire, dal punto di vista del mittente, di: (i) scrivere una
lettera in formato elettronico (dunque un banale word processor), (ii)
specificare un mittente ed un destinatario su una sorta di busta elettronica,
(iii) consegnare il messaggio alla rete per la trasmissione , e ,
naturalmente, dal punto di vista del destinatario di: (i) ricevere dalla rete il
messaggio, (ii) leggere la lettera. Il tutto, come nel tradizionale servizio
postale, deve avvenire in maniera asincrona tra i due attori della
comunicazione (ovvero, il mittente deve poter scrivere e spedire la lettera
senza preoccuparsi di cosa sta facendo il destinatario in quel momento e
viceversa). In atri termini, la posta elettronica (e-mail) un servizio di
messaggistica personale, di norma protetto, che permette di facilitare le
comunicazioni tra gli utenti. Per implementare un servizio simile
necessario che una macchina, detta mail server, agisca da gestore
dellufficio postale, cui pervengono tutti i messaggi e dal quale sono
inoltrati ai rispettivi destinatari. In questo tipo di servizio il sistema
operativo si limita a fornire il supporto per un mail server e, nelle stazioni,
per i mail client assicurando, quando possibile, la massima segretezza per
i messaggi. La comunicazione trai client e i server di posta elettronica
392 Capitolo undicesimo

avviene attraverso due appositi protocolli applicativi denominato SMTP


(Simple Mail Transfer Protocol) e POP (Post Office Protocol) che
governano, rispettivamente, linoltro e la ricezione dei messaggi di posta.
La carrellata si conclude ricordando che lintroduzione di Internet ha dato
grande impulso ai sistemi informativi aziendali, proponendo soluzioni a basso
costo ed efficaci simili al paradigma di internet.
Una rete intranet una rete privata interna ad una azienda che utilizza
linfrastruttura classica di una rete TCP/IP. Attraverso lintranet, lazienda
consente ai propri dipendenti di accedere con rapidit alle informazioni interne
aziendali e di condividere risorse utili per il proprio lavoro. A ci si aggiunge che
viste di quelle informazioni possono essere messe anche a disposizione dei clienti o
di altri soggetti interessati.
Sviluppando la tecnologia intranet, si pu creare una rete extranet che offre un
accesso esterno (ad esempio a fornitori o collaboratori aziendali) sicuro e
controllato. Le reti extranet si sono molto diffuse per particolari applicazioni del
buisiness to buisness (b2b), come gli acquisti e le vendite. Sia per le reti internet
che per quelle intranet, la sicurezza un requisito fondamentale.
Una delle tecniche oggigiorno pi usate per prevenire accessi non autorizzati
nelle reti quella che si basa su firewall. Un firewall un sistema hardware e
software che blocca gli utenti non autorizzati impedendogli laccesso alla intranet:
ci si ottiene costringendo tutti i pacchetti a passare attraverso una porta che regola
i flussi di ingresso tra le reti, identificando gli utenti, filtrando eventuali virus e
mettendo in essere altre sofisticate misure di controllo e sicurezza.
Capitolo dodicesimo

Il mondo di Internet

12.1. Introduzione
Il passaggio da uneconomia basata quasi esclusivamente sulla produzione e
lo scambio di beni materiali ad una sempre pi incentrata su servizi, informazioni
e idee, comporta la trasformazione della societ e delle sottostanti regole del
gioco. La conoscenza, da sempre chiave dellinnovazione e supporto allo sviluppo
economico, diventa oggi lelemento chiave nel processo di creazione del valore.
Negli ultimi venti anni, si sono verificate trasformazioni di portata epocale che
hanno determinato profondi mutamenti in tutti gli aspetti sociali, economici e
culturali del nostro modo di vivere. Nella nuova economia che sta prendendo
forma, i mercati stanno cedendo il passo alle reti, le risorse fisiche stanno
perdendo parte del loro valore e del loro significato e la propriet tende ad essere
sostituita da forme di fruizione basate sul concetto di accesso.
In uneconomia basata sullinformazione e sulla comunicazione, le capacit
innovative diventano pi importanti di quelle produttive. Lincertezza e la rapidit
del cambiamento diventano la norma e cresce lo spirito competitivo, poich le
idee sono molto pi semplici da copiare e da replicare rispetto ai beni materiali.
Di conseguenza, per svilupparsi le imprese hanno bisogno di rinnovarsi e di
adottare nuovi modelli organizzativi in cui linterazione risulter sempre pi
mediata tecnologicamente.
Internet diventa cos il centro di una rete di relazioni complesse in cui, il possesso
dellinformazione crea la differenza. La conoscenza, sempre stata lingrediente
imprescindibile dellinnovazione e dello sviluppo economico, tuttavia, essa ha
smesso oggi di essere un semplice supporto alla crescita, diventando invece
lelemento determinante del processo stesso di creazione della ricchezza.
Nella societ postmoderna linformazione diventata, quindi, il nuovo bene
economico attorno a cui si concentrano gli interessi produttivi primari. Pi del
60% della forza lavoro, non a caso, impiegata proprio in questo settore, che
divenuto rapidamente la principale fonte doccupazione causando la profonda
trasformazione del rapporto delluomo con i propri strumenti di lavoro.
Oggi il lavoro , in tutte le sue manifestazioni, mediato tecnologicamente da
programmi, sistemi, elaboratori, supporti e memorie, ma nella knowledge
society non mutano unicamente i mezzi di produzione, ma anche gli strumenti
della comunicazione.
394 Capitolo dodicesimo

Attualmente le telecomunicazioni, Internet in primis, svolgono un ruolo


fondamentale, rimpiccioliscono la dimensione del mondo e lo riducono a
villaggio globale. Gli strumenti di divulgazione del sapere: multimedialit, realt
virtuale, reti telematiche e satelliti, modificano quindi ontologicamente i processi
di comunicazione e di acquisizione delle conoscenze.
La nostra epoca vive un sovvertimento culturale assimilabile a quello del secolo
scorso, siamo nella stessa condizione vissuta dai nostri avi alle soglie della
Rivoluzione Industriale. Allora, si richiedeva al cittadino una nuova preparazione,
diversa da quella necessaria ad una societ basata esclusivamente sulla
produzione agricola ed anche oggi, si richiede un aggiornamento e una
preparazione rispondente ai bisogni del nuovo millennio.
Allepoca della manifattura, e successivamente durante il lungo apogeo della
fabbrica fordista, lattivit lavorativa era muta, chi lavorava taceva, la produzione
era una catena silenziosa in cui era ammesso solo un rapporto meccanico ed
esteriore. Nella metropoli postfordista invece, il processo lavorativo descrivibile
come complesso di atti linguistici e di interazioni simboliche. Poich il processo
produttivo ha per materia prima linformazione e le relazioni sociali, ne consegue
che chi lavora deve saper agire comunicativamente.
Lo sviluppo di Internet e le applicazioni delle tecnologie dellinformazione e della
comunicazione si presentano oggi come il fattore condizionante per la
competitivit e il progresso dellintero sistema, poich la cultura dellinnovazione
coincide con la cultura tecnologica e digitale. Internet, garantisce quindi la
simultanea disponibilit di conoscenze tecniche, sociali e umane grazie
allaccesso a banche dati da parte di persone, imprese e istituzioni.
In passato si riteneva che la semplice adozione delle nuove tecnologie potesse
risolvere tutti i problemi. La risposta per si rivelata parziale, a volte persino
controproducente, poich le nuove tecnologie possono addirittura aumentare la
congestione informativa a livello operativo, senza produrre sostanziali
miglioramenti nella fruizione dellinformazione necessaria per scegliere, decidere
e governare. Questi inconvenienti sono la diretta conseguenza della negligenza
mostrata verso limpatto ambientale della tecnologia nel contesto sociale di
applicazione e verso la trasformazione che essa comporta nella dimensione
cognitiva dellutente. Molte applicazioni tecnologiche non hanno soddisfatto gli
obiettivi prefissati proprio perch nella progettazione si considerato solamente il
livello uomo-macchina, tralasciando la valutazione del contesto organizzativo pi
ampio nelle quali le tecnologie si andavano ad impattare.
Le tecnologie di rete non sono quindi neutre. Internet cambia il modo di pensare e
di interagire degli individui, modifica gli ambienti aziendali, di apprendimento e
di divertimento sia nel contenuto sia nel tipo di operazioni mentali richieste.
Le tecnologie di rete introducono attraverso la velocit, laccessibilit e la
malleabilit dellinformazione nuove dinamiche nei flussi di informazione,
producono laccelerazione dei processi comunicativi e nuovi modus operandi in
cui esser connessi, essere on line diventa sempre pi una sistema che accomuna
ogni espressione del nostro vivere quotidiano. La rete valorizza e ottimizza al
massimo le risorse in campo, sia il medium, che la stessa informazione
trasportata.
Loggetto informatico che si sta creando grazie ai nuovi modelli di rete e di
distribuzione dellinformazione il computer globale, che ha generato a livello
Il mondo di Internet 395

sociale, militare e economico delle forti accelerazioni e questo perch la rete


sempre meno un media, e sempre pi un locus, un ambiente virtuale che ha un
suo linguaggio, un suo alfabeto e suoi codici di comportamento.
I cambiamenti epocali in corso hanno stimolato le disquisizioni di molti filosofi,
sia dello schieramento tecnofobo che tecnofilo, tra cui ad esempio il filosofo
francese Pierre Lvy che ha definito Internet un momento rivoluzionario per la
societ umana. Ci che per lui in atto sarebbe infatti la produzione di un
Intelligenza collettiva cio di un intelligenza omogeneamente distribuita,
continuamente rivalutata che, posta in sinergia in tempo reale condurr, nel
cyberspazio, ad un processo di reciproco riconoscimento degli individui e dei
gruppi, proprio tramite la rinnovata interazione comunicativa e la facilt di
fruizione dei flussi informativi.
12.1.1. Una ragnatela di connessioni
Lo scambio di informazioni, la cui importanza vitale stata sottolineata nel
capitolo precedente, si evoluto nel tempo dal trasferimento di beni materiali,
come le lettere tradizionali, alla trasmissione di segnali fisici, come i suoni sulla
linea telefonica o telegrafica e, infine, alla trasmissione di bit, attraverso computer
e servizi elettronici.
Oggi difficile che un elaboratore elettronico lavori in isolamento, poich
regolarmente si utilizzano i servizi messi a disposizione da altri elaboratori
elettronici sparsi nel mondo. Tutto ci reso possibile alla presenza di una fitta
rete di connessioni tra computers, nota con il nome di Internet.
Se si desidera, ad esempio, effettuare una ricerca su Dante Alighieri e non si
hanno a disposizione fonti tradizionali cartacee (come i libri ad esempio),
possibile, tramite specifiche applicazioni pensate per Internet, reperire facilmente
tutte le informazioni a cui si interessati, anche se dislocate su computer che sono
geograficamente distanti. Un ulteriore esempio costituito dai contesti aziendali,
in cui gli elaboratori sono localmente interconnessi, per velocizzare lo scambio
interno di documenti condivisi, attraverso reti locali di piccole dimensioni (LAN)
, o a livello mondiale attraverso Internet (WAN).
Internet, anche nota come la Rete delle reti deve essere vista, innanzitutto, come
uno strumento potentissimo che consente la comunicazione tra computer -
convenzionalmente denominati host - di tutto il mondo.
Per comprendere lentit di un fenomeno che vanta oggi una crescita
esponenziale, si possono osservare i dati riportati in molte pubblicazioni.
Tuttavia, importante sottolineare che la rilevazione della dimensione del
fenomeno e le previsioni del suo sviluppo futuro, si basano su metodi che non
forniscono dati certi ed assoluti, sia per lassenza di un sistema di registrazione
unico degli utenti ma, soprattutto, per il tumultuoso ed incontrollato sviluppo
della rete. Alcune pubblicazioni riportano che, agli inizi del 2000, gli utenti attivi
nel mondo risultavano essere circa 260 milioni. Gli utenti italiani erano circa 9,5
milioni, di cui l85% dotati di una connessione da casa, mentre il 37% dal posto
di lavoro. Nel sito dell Internet Software Consortium (http://www.isc.org) si
trovano informazioni precise sul numero di host presenti nella rete e sulla
modalit di correlazione tra tale numero a quello degli utenti di Internet. Recenti
rilevazioni statistiche, riportano che i sistemi host presenti in Internet sono passati
da 1,7 milioni del gennaio 1993 ai 170 milioni dello stesso mese del 2003. Una
396 Capitolo dodicesimo

crescita che ha visto raddoppiare, di anno in anno, il numero dei sistemi erogatori
di servizi in rete. Con un margine di approssimazione accettabile, il numero di
utenti pu essere calcolato moltiplicando il numero di host per un valore
compreso tra tre e sei in base alla diffusione di Internet nel paese considerato. In
passato, anche le previsioni pi ottimistiche si sono dimostrate eccessivamente
prudenti ed un dato di fatto che, la crescita degli utenti di Internet, registri un
aumento esponenziale.
Internet , quindi, la Rete delle reti per antonomasia, la pi estesa ed articolata
connessione di elaboratori elettronici. Connettendosi ad essa, possibile
usufruire dei servizi e delle informazioni messi a disposizione da Universit,
laboratori di ricerca, banche dati, societ private, strutture scientifiche, etc. Tutto
questo possibile su scala mondiale, superando le barriere spazio-temporali e i
confini fisici e culturali.
Internet pu essere vista come un insieme di collegamenti (e di apparecchiature
dedicate alla loro gestione) specificamente progettati per creare un efficiente
sistema di comunicazione tra elaboratori elettronici. Questa rete, concepita
originariamente con finalit militari, non possiede alcun centro nevralgico ed un
messaggio (in termini tecnici: un pacchetto), spedito da un computer ad un altro,
in caso di interruzione di un percorso, ha la possibilit di seguirne un altro
aggirando cos l'ostacolo.

Figura 1 - Architettura di riferimento di uninfrastruttura di rete

La comunicazione fisica tra i vari host della rete avviene mediante i mezzi pi
disparati: reti telefoniche, reti locali, cavi sottomarini, collegamenti via satellite,
trasmissioni via radio, etc.
Per spiegare linfrastruttura tecnologica che sorregge Internet, possiamo usare la
metafora delle autostrade: i cavi sono le autostrade e le informazioni che
viaggiano sono le auto. Come accade sulla rete viaria, anche in Internet si
possono verificare rallentamenti causati dal traffico se, in un dato istante, sono
molte le informazioni che transitano per un tratto della rete.
Come la rete stradale, quindi, anche linfrastruttura su cui si basa Internet una
maglia di connessioni pertanto, tra due nodi non esiste un unico cammino
percorribile. Come per i caselli autostradali, anche laccesso alla rete regolata da
Il mondo di Internet 397

sistemi di accesso simili e indispensabili a stabilire il sistema di pagamento per


luso della rete.
Linfrastruttura di base della rete Internet pertanto simile a quelle di cui
dotata attualmente la nostra societ: dalla rete idrica a quelle elettrica, per finire a
quella telefonica. Tutte le summenzionate infrastrutture sono caratterizzate da:
- sistemi che erogano un servizio sullinfrastruttura (come le centrali
elettriche: nucleari, a carbone, eoliche, idriche, etc., che producono
lenergia elettrica; i bacini idrici che alimentano gli acquedotti; le
centrali telefoniche pubbliche che provvedono alla distribuzione delle
telefonate);
- sistemi che utilizzano quanto prodotto dai primi (come le macchine
elettriche: ad es. lavatrici, televisori, rubinetti dellacqua; telefoni);
- linfrastruttura (costituita dai fili e dai tubi, che servono a collegare i
primi sistemi ai secondi, per il trasporto della corrente elettrica,
dellacqua o del segnale telefonico).
I primi sistemi, cio quelli che erogano il servizio, sono definiti server, mentre
quelli che sono fruitori del servizio, client. La figura 1 mostra larchitettura di
riferimento per tutte le infrastrutture di cui si parlato.
In generale, la stessa architettura deriva da un modello molto utilizzato in
Informatica, in cui si distinguono due entit: quella del produttore e quella del
consumatore di un servizio. Poich in Internet, le informazioni viaggiano in
formato digitale, il consumatore pu ricevere il servizio prodotto solo nel caso in
cui sussistano tre precise condizioni, cio:
- le due entit devono essere collegate da una infrastruttura per il trasporto
di quanto prodotto;
- affinch la comunicazione abbia luogo, indispensabile che le due entit
condividano lo stesso linguaggio;
- le due entit, oltre a condividere lo stesso linguaggio, devono
necessariamente comprendersi.
12.1.2. Internet ed il modello di comunicazione
Lutilizzo di Internet consiste, generalmente, nella fruizione delle funzionalit
messe a disposizione da opportuni server che lutente percepisce come servizi
erogati da questi ultimi. Un server, cos inteso, una macchina che mette a
disposizione servizi. In realt, il termine server , a volte, ambiguo poich
identifica sia la macchina (lhost), sia il software che consente lerogazione del
servizio stesso. L ambiguit summenzionata non considerata un problema,
poich una macchina pu essere contemporaneamente server di pi servizi.
Gli utenti accedono alle funzionalit offerte dai server, mediante specifici
programmi, denominati client, installati sul proprio elaboratore. I client
trasmettono le richieste ai server che a loro volta inviano le risposte seguendo
delle regole prestabilite.
Il modello di erogazione di servizi descritto, un modello di tipo client/server. Il
motivo del suo successo da ricercarsi soprattutto nell essere riuscito a mettere
contemporaneamente a disposizione di pi utenti, un sistema efficiente per
lerogazione di servizi in rete. La connessione di rete effettuata solo per un arco
di tempo molto breve: giusto lintervallo necessario per trasmettere la richiesta e
recuperare la risposta dal server.
398 Capitolo dodicesimo

Il vero motivo dellefficienza della rete da individuare proprio nell assenza di


una connessione continua: in altri termini le linee di trasmissione non sono
impegnate costantemente ma solo quando c effettiva necessit di trasmissione.
Pi in dettaglio, nel modello client/server, i processi di elaborazione sono
suddivisi tra il client e il server e la comunicazione si basa su una sequenza di
richieste e risposte tra i due soggetti:
- il client, che richiede servizi o informazioni a un altro computer (il
server);
- il server, che risponde alla richiesta (del client) inviandogli i risultati
della richiesta.
La figura 16 schematizza il meccanismo di comunicazione client/server:

Figura 16 - Modello Client/Server

Il client, sulla base di quanto specificato dallutente, prepara una richiesta in un


formato appropriato (che dipender, tra i tanti fattori, anche dal tipo di servizio)
che successivamente trasmetter al server.
Il server, a sua volta, analizzer la richiesta del client e la elaborer al fine di
soddisfarla. Qualora lelaborazione non presentasse problemi, sar confezionata la
risposta che verr inviata al client.
Il client, infine, ricever la riposta e la formatter affinch essa sia disponibile,
o anche leggibile se si tratta di un servizio come il web, allutente. Si pu
facilmente intuire che le richieste e le risposte devono essere confezionate in
modo tale da essere comprensibili ai vari server e client disponibili in commercio,
in maniera tale che per quanto possibile le funzionalit siano indipendenti dai
particolari software.
Ci presuppone la presenza di norme che disciplinino quegli aspetti della
comunicazione che, nel caso specifico, prendono il nome di protocolli. Per la
rete Internet essi sono quelli di una rete TCP/IP descritti nel precedente capitolo.
12.1.3. La storia di Internet
Lidea di una rete Internet fu proposta per la prima volta da J.C.R. Licklider del
Massachusetts Institute of Technology (MIT) nel 1962. Licklider immaginava un
insieme di computer interconnessi, attraverso cui, da ogni localit si potesse
facilmente e velocemente avere accesso a dati e programmi. In quegli stessi anni,
fu pubblicato il primo lavoro sul metodo, battezzato packet switching, utilizzato
Il mondo di Internet 399

per trasportare dati sulla rete, attraverso la separazione in pacchetti indipendenti


ricomposti una volta giunti a destinazione.
Intorno alla fine degli anni sessanta, lARPA (Advanced Research Projects
Agency) del Ministero della Difesa Statunitense avvi un programma di ricerca
alla cui direzione pose Licklider. Vista limportanza del progetto e la sua utilit a
fini bellici, ARPA pass presto nelle mani del Ministero della Difesa statunitense:
la sua missione divenne quella di applicare le conoscenze tecnologiche acquisite
alla difesa statunitense per rispondere efficacemente, in caso di attacco, ai
progressi tecnologici dei nemici.
Nel 1969 nacque Internet, allora chiamata ARPANET, che si basava sul
collegamento di quattro computer che, allepoca, utilizzavano un protocollo
innovativo chiamato Network Control Protocol (NCP). Il concetto base era la
segmentazione delloggetto della comunicazione in unit di informazione pi
piccole (pacchetti) al fine di poter essere efficientemente trasmesse anche nel caso
in cui le linee di comunicazione fossero state inefficienti.
Tra la fine degli anni sessanta e gli inizi degli anni settanta, anche altri centri di
elaborazione iniziarono ad utilizzare, per il collegamento dei propri sistemi,
l'innovativa tecnologia del packet switching di ARPANET. In quegli stessi anni,
un numero sempre crescente di computer, inizi rapidamente a collegarsi alla rete
ARPANET. Nel 1971, si contavano gi 23 host in rete, mentre nel 1980, con i
primi collegamenti internazionali, ce n erano gia pi di 200.
Nel 1972 si ebbe la prima vera dimostrazione pubblica di ARPANET
allInternational Computer Communication Conference (ICCC). Sempre in quegli
anni, furono sviluppati i primi software applicativi per la rete ARPANET, tra cui
lelectronic mail, o oggi pi nota semplicemente come email.
A causa dei limiti di cui soffrivano alcuni dei neonati programmi, Robert Kahn e
Vint Cerf incominciarono a sviluppare una nuova versione del protocollo NPC,
affinch fosse consentito ai packet switching di soddisfare le esigenze di un
ambiente ad architettura aperta, nel quale le informazioni potessero essere inviate
da un computer ad un altro fino al raggiungimento della destinazione finale.
Questo protocollo venne in seguito definito Transmission Control
Protocol/Internet Protocol (TCP/IP) e, per tale motivo, Vint Cerf e Bob Khan
furono universalmente riconosciuti come i padri fondatori di Internet proprio
perch spetta a loro il merito dell invenzione della definizione Internet
Protocol.
In quegli stessi anni, il Defense Advanced Research Projects Agency (DARPA)
degli Stati Uniti, avvi un programma di ricerca sulle tecnologie per collegare
reti di differente tipologia. Lobiettivo era lo sviluppo di un protocollo di
comunicazione in grado di far interagire in modo trasparente e immediato i
computer in rete. Tale programma venne definito Internetting Project e il sistema
di reti che nacque dalla ricerca Internet. Il sistema di protocolli sviluppato dalla
ricerca in corso diede vita al TCP/IP Protocol Suite, in omaggio ai due primi
protocolli sviluppati: Transmission Control Protocol (TCP) e Internet Protocol
(IP).
Nel 1979, finalmente la rete ARPANET fu trasferita, come rete operativa, dal
DARPA alla Defense Communications Agency. I vantaggi dell'interconnessione
tra reti divennero sempre pi popolari grazie alla geniale invenzione di efficaci
400 Capitolo dodicesimo

servizi di rete che resero possibile lo sviluppo di modalit comunicative sincrone


ed asincrone quali la Posta elettronica, i Newsgroup, l Irc, etc.
La conseguenza di questo successo fu la nascita, durante gli anni ottanta, di tre
reti principali:
- BITNET (Because It's Time Network);
- CSNET (Computer Science Network);
- NSFNET (National Science Foundation Network).
NSFNET divenne la rete portante di Internet (definita backbone o spina dorsale)
grazie al collegamento a 56 Kbps.
Nel 1983 avvenne la transizione, del protocollo ospite di ARPANET, da NCP a
TCP/IP. ARPANET da quel momento, incominci ad essere utilizzato, oltre che
dagli organismi per la difesa militare, da un numero sempre pi significativo di
dipartimenti di ricerca e da organizzazioni operative. Nel frattempo, nel 1984, al
fine di facilitare la ricerca dei sempre pi numerosi host connessi alla rete (il
loro numero continuava a crescere in modo esponenziale), fu introdotto il Domain
Name System (DNS).
Nella met degli anni ottanta, Internet era considerata la tecnologia in grado di
mettere in contatto una larga comunit di ricercatori e sviluppatori. Anche altri
tipi di comunit cominciarono ad adoperarlo come strumento quotidiano di
comunicazione telematica. La posta elettronica cominciava ad essere utilizzata in
vari paesi, anche se spesso i sistemi su cui ci si basava erano differenti. Solo alla
fine degli anni ottanta, Internet ebbe un momento di grande attenzione da parte
dei mass-media poich il primo mitico virus (verme o "worm") inventato da
Robert J. Morris caus il blocco di alcune migliaia di calcolatori presenti nel
network.
Alla fine del 1986, si potevano gi contare alcune migliaia di hosts connessi
(computer che fungono da nodi della rete). Alla fine degli anni ottanta: Australia,
Germania, Israele, Italia, Giappone, Messico, Olanda, Nuova Zelanda, Porto Rico
e Regno Unito, erano connessi al NSFNET.
Nel 1990 ARPANET venne sostituito da NSFNET, tutto il mondo era online e
world.std.com divenne il primo provider commerciale per laccesso telefonico ad
Internet.
Tra la fine degli anni ottanta e l'inizio degli anni novanta, Internet sub alcune
trasformazioni radicali. Nel 1989, il canale di comunicazione principale
(backbone) venne potenziato con il passaggio ad una linea ad alta velocit (1,544
Mbps) poich il numero di hosts connessi alla rete aveva superato le 100.000
unit. Inoltre, per superare il divieto imposto dal backbone NFSNET di un uso a
fini di lucro della rete, ARPANET venne eliminato e fu creato il Commercial
Internet Exchange (CIX) dando cos il via definitivo ad un uso commerciale della
rete stessa. La conseguenza di tale scelta, fu la crescita esponenziale degli host
collegati ad Internet che, in un arco di tempo brevissimo, arrivarono ad essere pi
di 700.000.
Nel frattempo, la veloce diffusione della rete impose lesigenza di standardizzare
sia i protocolli, sia le modalit di connessione al network, con la conseguente
istituzione dell Internet Society (1992). Nello stesso anno, in Svizzera, il CERN
di Ginevra, introdusse la prima realizzazione di uno dei programmi pi usati sulla
rete: un sistema multimediale ipertestuale con tecnologia client/server chiamato
World-Wide-Web. Poco dopo, nel 1993, negli Stati Uniti, il National Center
Il mondo di Internet 401

for Supercomputing Application (NCSA) presso la University of Illinois a Urbana-


Champaign, diffuse Mosaic, un programma client (browser) con interfaccia utente
per navigare nel World-Wide Web.
Lo sviluppo dei browser signific lo sviluppo di un accesso diffuso e democratico
alla rete per cui, non solo chi lavorava allinterno delle universit o dei
dipartimenti di ricerca, ebbe il diritto di accesso ad Internet, ma da qualsiasi
posto e chiunque, grazie alla semplicit della navigazione permessa dai browser
web, avrebbe potuto connettersi, avendo a disposizione un computer ed un
modem. Le semplici operazioni da effettuare con un browser Web resero, inoltre,
possibile laccesso ai documenti presenti sul Web anche allutenza priva di
conoscenze tecniche approfondite. Il World Wide Web divenne cos uno
strumento di informazione e di comunicazione di massa.
Nella prima met degli anni novanta, anche i media incominciarono ad affacciarsi
sulla rete; la Casa Bianca e le Nazioni Unite erano online. Nel dicembre del 1993
si contavano, nel mondo, 623 siti Web. Mentre nel 1994 usciva sul mercato
linnovativo browser con interfaccia grafica Netscape Navigator per la
navigazione in rete, ARPANET/Internet celebrava il suo venticinquesimo anno di
vita.
Nella seconda met degli anni 90, nacquero i primi fornitori di accesso ad Internet
(Provider) quali CompuServe, AOL e Prodigy. Dalla fine degli anni novanta ai
giorni nostri, Internet incominci ad avere una crescita esponenziale, sia nelle
dimensioni, che nella diversificazione dei servizi offerti, diventando un
fenomeno rivoluzionario di respiro mondiale con effetti molto profondi sul vivere
quotidiano.

12.2. Il World Wide Web


Come gi accennato, alle soglie degli anni '90, Internet si afferma come fenomeno
di dimensioni mondiali. Nel 1989 presso i laboratori del CERN di Ginevra, un
ricercatore di nome Tim Berners Lee svilupp il primo esempio di un
applicazione che avrebbe rivoluzionato il modo di concepire Internet. Tale
applicazione venne chiamata World Wide Web.
Il World Wide Web costituisce attualmente l'uso pi diffuso e popolare di
Internet, tuttavia non lunico. E spesso abbreviato in WWW o W3, e viene
comunemente designato come l'insieme di iperoggetti, cio ipertesti o ipermedia,
navigabili attraverso i collegamenti ipertestuali.
E importante a questo punto definire cosa si intenda per ipertesto e ipermedia.
Gli ipertesti possono essere definiti come documenti elettronici in cui le singole
sotto-unit non sono disposte secondo un ordine sequenziale (come le pagine, i
paragrafi, i capitoli, allinterno di un libro), bens secondo un ordinamento
reticolare o anche definito rizomatico. Da ogni sotto-unit di un ipertesto,
chiamato nodo, si pu accedere direttamente a qualsiasi altra sotto-unit ad essa
collegata. I collegamenti tra i nodi sono gestiti mediante link che rappresentano
legami significativi stabiliti dallautore.
Quando si legge un ipertesto, sullo schermo del computer appare un documento al
cui interno appaiono delle indicazioni, che possono essere testuali o frecce,
rimandi, parole in neretto, sottolineate, o altro, che stanno ad indicare che da quel
punto si pu saltare verso un altro nodo dellipertesto, cio verso unaltra unit
402 Capitolo dodicesimo

testuale. Scegliendo una di queste opzioni con il sistema di puntamento, ci si


trover automaticamente in un altro elemento testuale, che a sua volta pu
presentare unaltra serie di link verso altri nodi, tra i quali possibile scegliere di
nuovo e cos via.
Lipermedia, invece, estende semplicemente lidea di ipertesto, includendovi
anche informazioni sonore, visive, animazioni e altre forme di dati, quindi denota
un locus che collega informazioni verbali a informazioni non verbali. I
collegamenti ipertestuali collegano sia informazioni interne allo stesso file, che
contenute in file diversi, che a nodi esterni al sito considerato, cio ad altre
pagine web. Il testo cos generato sar un testo aperto, fluido e multilineare.
Il vantaggio degli iperoggetti quello di fornire all'utente una funzione in pi:
non solo quella statica di contenere in s informazioni finite (come ad esempio
un libro, un quadro, un programma televisivo), ma anche quella dinamica di
richiamare su richiesta dell'utente altre informazioni correlate.
Esiste una differenza tra Internet e il World Wide Web, nonostante oggi i 2
termini siano speso confusi. Fisicamente, Internet semplicemente una grande
rete di elaboratori interconnessi. Il World Wide Web, invece, un insieme di
oggetti virtuali che stato realizzato sfruttando la possibilit offerta da Internet di
collegare questi oggetti tra loro: mentre Internet , tutto sommato, qualcosa di
essenzialmente fisico, il World Wide Web invece estremamente virtuale, cio
un insieme di informazioni multimediali codificate. Internet l insieme di vie di
comunicazione che permette il passaggio di veicoli di qualsiasi tipo, mentre il
www utilizza una parte di questo insieme, e alcuni veicoli ben specifici, per
collegare tra loro alcuni punti della rete e trasportare un determinato tipo di
oggetti.
Grazie alla possibilit di richiamare in modo molto semplice qualsiasi risorsa in
qualunque parte del mondo, identificata univocamente attraverso l indirizzo
(URL), lautore di ipertesti pu facilmente creare collegamenti tra le proprie
pagine e altre pagine del web, permettendo quindi all'utente di spostarsi non per
vicinanza geografica, ma per correlazione tematica. Non ha pi importanza se una
pagina web sia a New York piuttosto che a Parigi o a Mosca, poich la rete rende
nulle le distanze geografiche; interessa piuttosto che gli argomenti siano correlati.
Ci permette di ritrovare una quantit enorme di informazioni, in tutto il mondo,
con un semplice click del mouse.
L'idea geniale del WWW risiede, in breve, nella organizzazione delle
informazioni sulla rete in formato ipertestuale e nella sua presentazione
multimediale.
Le pagine web sono individuate attraverso il loro specifico indirizzo web, mentre
ogni computer dal relativo indirizzo IP. Tempi di risposta della rete permettendo,
si potr avere accesso allinformazione globale in modo semplice ed istantaneo.
Nel mondo del Web ben definita la distinzione del modello client-server, che
definisce chi svolge il ruolo di fornitore dell informazioni e di chi ne fa richiesta
risultando cliente dei servizi offerti dai primi. La parte client dell'applicazione
Web costituisce l'interfaccia verso l'utente finale e viene anche detta browser. Il
suo scopo consiste nel presentare le pagine web, interpretando opportunamente la
descrizione del loro contenuto che stato scritto mediante uno specifico
linguaggio chiamato HTML (HyperText Markup Language), che utilizza i
cosiddetti tag per lorganizzazione delle informazioni in una pagina web. I link,
Il mondo di Internet 403

quindi, contengono l' indirizzo di una pagina Web o, pi in generale, di una


risorsa Web.
L indirizzo web, ancora una volta derivazione ed estensione degli indirizzi IP,
come gi visto, detto URL (Uniform Resource Locator). Un URL contiene una
porzione che specifica il linguaggio (protocollo) che si sta usando per reperire la
risorsa, l'indirizzo IP dell'host e, l'indicazione (il percorso nell'albero delle
directory) della collocazione della risorsa sull'host.
Un esempio di questo tipo di indirizzo il seguente:

http://www.dol.unina.it/index.html
in cui:

http:// identifica il protocollo

www.dol.unina.it il nome dell' host

index.html il file che contiene la pagina cercata.

Il protocollo indica come il documento viene servito dal computer che fornisce
l'informazione. Per quanto riguarda il nome dell host, ogni computer come gi
descritto collegato a Internet pu essere identificato con un nome (oltre ad un
numero) e talvolta anche pi di uno. Questo nome (come il numero) viene in parte
assegnato seguendo alcuni criteri e in parte deciso arbitrariamente dal possessore
del computer.
Le altre informazioni che si hanno nellURL, se presenti, servono a localizzare il
documento sul disco del computer che contiene altri documenti, indicando il
nome del file ed il percorso per arrivare allo stesso.
Quando, dunque, l'utente seleziona un determinato link, normalmente attraverso
lazione del mouse, viene attivata una connessione TCP/IP con il nodo Internet
che ospita la pagina richiesta e, si richiede che il lato server dell'applicazione web
localizzi e fornisca al browser richiedente la pagina in questione.
Naturalmente, la pagina appena ottenuta pu contenere link ad altri nodi
localizzati in qualunque parte del mondo. Questo processo di visitazione,
denominato navigazione pu essere ripetuto progressivamente fino a
coinvolgere centinaia o migliaia di pagine e relativi server.
Il protocollo che stabilisce le regole con le quali i browser ed i server web
dialogano tra loro definito HTTP (HyperText Transfer Protocol).
Naturalmente, la capacit di trattare informazioni e link multimediali
(l'ipermedialit) nasce proprio dal fatto che sia l'HTML che l'HTTP sono
rispettivamente un linguaggio ed un protocollo specificamente progettati per
consentire un esplicito ed efficiente trattamento di questa tipologia di
informazione.
Un ulteriore punto di forza del WWW consiste nellaver inglobato, in una forma
molto attraente ed accessibile all'utente medio, poco alfabetizzato
tecnologicamente, anche altri servizi fondamentali di Internet quali la posta
elettronica e l'FTP. Questi servizi ultimamente sono stati arricchiti della
dimensione multimediale. Infatti possibile, ad esempio, inviare un e-mail che
contiene messaggi vocali o un videoclip, e visionarli in un ambiente unico;
404 Capitolo dodicesimo

effettuare uno scambio di file mediante FTP, associando ai file degli iperlink e
ottenendo quindi il loro trasferimento con un semplice "click" sul nome del file.
12.2.1. Nuovi standard per il Web
L'evoluzione di Internet procede incessantemente. La crescente richiesta di nuove
potenzialit e applicazioni trasforma la rete in un continuo work in progress, un
laboratorio dove si sperimentano tecnologie e soluzioni innovative.
Se, da una parte, questo processo produce sviluppi disordinati spesso determinati
da singole aziende che cercano di trarre il massimo profitto dal boom di Internet,
dall'altro lato, le organizzazioni indipendenti, che gestiscono l'evoluzione della
rete, svolgono una continua attivit di ricerca per la definizione di nuovi standard.
L'organizzazione ufficiale deputata allo sviluppo degli standard per la rete il
World Wide Web Consortium o W3C (http://www.w3.org), che raccoglie
centinaia di aziende, organizzazioni e centri di ricerca interessati allo sviluppo
delle tecnologie di rete. In questi ultimi anni il W3C ha prodotto una serie di
specifiche divenute standard ufficiali. Tutti i materiali prodotti dal W3C,
pubblicati sul sito Web del consorzio sono di pubblico dominio.
La maggiore parte delle innovazioni, riguardano il funzionamento del World
Wide Web. I settori di maggior interesse per il W3C sono sostanzialmente:
- il potenziamento delle funzionalit di gestione editoriale e grafica dei
documenti su Web;
- la certificazione ed il controllo del contenuto dei siti;
- l'individuazione ed il reperimento di documenti e risorse su Internet.
In principio, il World Wide Web era concepito come un sistema per la
distribuzione di semplici documenti testuali in rete. La comunit di utenti a cui
era destinato era molto circoscritta e poco preoccupata degli aspetti stilistici nella
presentazione dell'informazione.
Tuttavia, con il passar del tempo il Web diventato un vero e proprio sistema di
editoria elettronica on-line. Ovviamente, l'espansione della rete discostandosi dal
progetto originale, ha stimolato una serie di revisioni e di innovazioni degli
standard tecnologici originari. Un grande interesse stato mostrato verso il
potenziamento della capacit di gestione e controllo dei documenti multimediali e
dei testi elettronici pubblicati su Web.
Il formato usato nella realizzazione di pagine Web il linguaggio HTML che ha
subito, nel corso degli anni, una notevole evoluzione. Un ruolo propulsivo in
questo processo stato svolto dalle grandi aziende produttrici di browser. Nel
corso degli anni, sia Microsoft che Netscape, hanno introdotto innovazioni ed
estensioni al linguaggio originario, al fine di conquistare fette di mercato sempre
pi grandi. La corsa all' innovazione, ha migliorato l'aspetto e la fruibilit delle
pagine pubblicate su Web tuttavia, ha avuto effetti deleteri dal punto di vista della
portabilit dei documenti. Per ovviare a questa situazione il W3 Consortium ha
accelerato il processo di aggiornamento dello standard ufficiale, che di volta in
volta ha accolto (o rigettato) parte delle modifiche introdotte. Parallelamente
all'aggiornamento delle attuali tecnologie, l'organizzazione ha iniziato a
sperimentare nuove soluzioni per la creazione e gestione dei documenti su Web
come ad esempio lXML.
Il mondo di Internet 405

12.2.2. I browser
Poich la dimensione e la struttura del Web richiamano alla mente l'immagine di
un oceano di informazione, la consultazione delle sue pagine comunemente
definita navigazione. La navigazione tradizionale richiede una barca per
navigare, nel caso della navigazione telematica la barca uno specifico
software, la cui funzione di richiamare dalla rete le pagine che l'utente desidera
consultare e mostrarne il loro contenuto sullo schermo.
Nel gergo telematico i programmi di questo tipo vengono chiamati browser,
dall'inglese to browse (scorrere), poich permettono, appunto, di scorrere i
documenti. Il browser visualizza le pagine Web in modalit grafica. Un browser,
un programma che permette di leggere, ma non di modificare i file e rende
possibile laccesso a qualsiasi oggetto si desideri recuperare inserendo un
indirizzo, come g accennato, definito URL, che racchiude in s tutte le
informazioni necessarie per l'operazione richiesta. La parte client
dell'applicazione Web, detta appunto browser, costituisce l'interfaccia verso
l'utente finale. Il suo scopo consiste nel presentare le pagine web, interpretando
lHTLP.
I due browser pi diffusi tra gli utenti della rete sono Netscape Navigator
dall'inventore dell'interfaccia Mosaic, Marc Andreessen, Microsoft Internet
Explorer oggi fornito come corredo standard a Windows, ed ultimamente, Mozilla
Firefox.
Tutte le applicazioni, accanto al modulo di navigazione su Web vero e proprio,
offrono dei programmi per l'accesso alla posta elettronica, ai newsgroup e persino
degli editor per realizzare le pagine da pubblicare sul Web.
I browser sono stati, fin dall'inizio, progettati al fine di esaltarne semplicit e
funzionalit duso, (facendo ricorso a concetti come quelli di bottone, men a
tendina, ecc.). Quando, dunque, l'utente seleziona un determinato link,
cliccandoci su con il mouse, viene attivata una connessione TCP/IP con il nodo
Internet che ospita la pagina richiesta, e si richiede che il lato server
dell'applicazione web localizzi e fornisca al browser richiedente la pagina in
questione.
12.2.3. La ricerca dellinformazione ed i motori di ricerca
Lintera storia delluomo caratterizzata dal desiderio di organizzare le
informazioni per renderle fruibili ed accessibili in modo semplice ed immediato.
Le biblioteche sono la testimonianza pi evidente del grande lavoro di raccolta e
classificazione delle informazioni necessarie ad alimentare la trasmissione del
sapere. Il web diventato, negli ultimi anni, lo strumento principale per
pubblicare e rendere disponibile una quantit enorme di informazione e i motori
di ricerca sono, oggi, lo strumento utilizzato per reperire velocemente e con
facilit il dato pertinente. Pu sembrare paradossale, ma disporre di tantissima
informazione, equivale a non possederne alcuna, se non si in possesso di
metodi o strumenti efficaci ed efficienti di ricerca. Il grosso problema di un
qualsiasi sistema che accoglie troppa informazione sempre stato quello del
reperimento dellinformazione utile. Su Internet, questo problema gi esploso:
probabilmente esistono in rete informazioni su qualsiasi argomento, ma non
sempre facile riuscire a sapere dove esse siano esattamente collocate.
406 Capitolo dodicesimo

Esistono alcuni siti che offrono la possibilit di ritrovare gli indirizzi web di
pagine utili alla nostra ricerca. Questi strumenti sono sostanzialmente di due tipi:
Indici di rete e Motori di ricerca. Essi si basano su due diversi metodi di
catalogazione dellinformazione. Sebbene concettualmente siano abbastanza
diversi, di fatto, i due sistemi tendono verso l'unificazione, per cui i motori di
ricerca offrono anche una divisione in categorie e gli indici di rete permettono
anche ricerche per parole chiave.

Indici di rete
Negli indici di rete sono memorizzati gli indirizzi di un immenso numero di
pagine, raggruppati per categoria. quindi necessario scegliere la categoria a cui
si interessati. Cliccando sullo specifico link-categoria, si ricever in risposta un
elenco di siti con i relativi titoli. I siti sono, solitamente, inseriti su segnalazione
degli autori o dei singoli utenti. In molti indici di rete l'inserimento gratuito,
mentre altri richiedono il pagamento di una quota. L indice di rete pi diffuso
sicuramente Yahoo! In questi ambienti, la catalogazione manuale, cio prevede
che lautore della pagina sottometta la propria opera mediante il form di
inserimento disponibile.

Motori di ricerca
In inglese Search Engine, sono programmi che percorrono il www leggendo e
catalogando le pagine che incontrano; l'utente per effettuare la sua ricerca deve
inserire una o pi parole chiave e in risposta ricever, dal programma, un elenco
con gli indirizzi delle pagine che contengono la/le parole inserite nella query,
solitamente ordinati in funzione del numero di occorrenze e quindi dell'interesse
probabile. Anche in questo caso, gli utenti possono segnalare gli indirizzi. Qui le
pagine, diversamente dagli indici di ricerca, non sono suddivise in categorie ma,
di ogni indirizzo web memorizzato un breve sommario (in genere il titolo e le
prime righe), la cui lettura guider lutente nella selezione delle pagine pi
rispondenti ai personali obiettivi di ricerca. Nei motori di ricerca, la catalogazione
degli indirizzi web effettuata automaticamente dai gestori dei motori, attraverso
gli spider (ragni), cos chiamati per il loro crawling (zampettare) in giro per la
Rete, al fine di trovare e catalogare le pagine Web, monitorandone poi le
eventuali variazioni. Gli spider, possono essere tenuti alla larga dal proprio sito
inserendo determinati codici all interno della pagina, al contrario, altri codici
possono rendere il nostro sito rintracciabile con pi facilit. I motori di ricerca
catalogano non solo le pagine Web, ma documenti di ogni tipo (come immagini,
newsgroups, etc.) Ogni motore di ricerca, riesce ad aggiornare la propria base di
dati tenendo conto di link non pi attivi, aggiungendo nuovi documenti o
aggiornando gli indirizzi gi esistenti. Esistono molti motori di ricerca, il
consiglio di provarne un certo numero e di trovare quello che si adatta meglio
alle specifiche esigenze di ricerca. Il motore attualmente pi popolare Google,
che usa un sofisticatissimo meccanismo di analisi delle pagine (detto PageRank).
In breve tempo divenuto uno dei pi raffinati strumenti di ricerca presenti sul
web.
Il mondo di Internet 407

Per concludere, tutti i motori di ricerca presentano unarchitettura che deve


provvedere:
- al reperimento delle pagine web;
- alla indicizzazione dei contenuti in esse presenti;
- alla creazione delle liste in risposta alle interrogazioni.
Devono pertanto essere in grado di:
- conoscere gli indirizzi degli host che ospitano le informazioni;
- fornire un elenco delle informazioni che possibile reperire;
- fornire una risposta veloce ed esauriente alle pi svariate richieste.
Il segreto per una ricerca efficace (trovare cio informazioni pertinenti e valide)
ed efficiente (la ricerca non deve durare molto e non si deve perdere il senso
dell'orientamento) consiste nel saper:
- scegliere il motore adeguato
- definire una stringa d'interrogazione mirata
- utilizzare, quando occorre, gli operatori booleani
Nella ricerca dell informazione, il problema pi complesso legato proprio alla
sua efficacia, ossia alla rilevanza, alla pertinenza e alla coerenza dei risultati
restituiti dalla ricerca operata. La bont di un motore di ricerca legata, pertanto,
alla rispondenza dei risultati ottenuti e alla capacit di semplificare la selezione di
un numero elevatissimo di pagine, i cui contenuti spesso non sono veramente
attinenti agli obiettivi personali della ricerca.
Nonostante l'uso dei motori sia molto intuitivo, per ottimizzare la ricerca
opportuno leggere le istruzioni per luso contenute in ognuno di essi. Quando
viene effettuata una ricerca per parole chiave importante capire come sia
possibile formulare la richiesta al fine di ottenere il risultato migliore. Molti siti
permettono luso degli operatori booleani. Si tratta di quattro operatori principali:
AND, OR, AND, NOT, NEAR, i quali sono stati standardizzati dai pi celebri
motori e consentono di restringere e affinare la nostra ricerca. Non sono case
sensitive, cio non tengono conto delle lettere maiuscole o minuscole e
ultimamente sono stati sostituiti da interfacce amichevoli per la ricerca avanzata
(v. Google) per facilitarne ancora di pi il loro uso. Segue un elenco degli
operatori pi comuni.

- AND. Se uniamo due o pi parole chiave con loperatore AND, in


alternativa al quale pu usarsi il segno +, significa che vogliamo solo i
documenti che contengono tutte le parole indicate (questo AND quello) e
non soltanto una di esse considerata singolarmente. Le parole vanno
inserite in ordine di importanza, le pi importanti devono essere al prino
posto. Se cerchiamo gli accordi delle canzoni di Battisti, meglio
inserire Battisti AND accordi piuttosto che accordi AND Battisti,
visto che prima di tutto ci interessano le pagine dedicate al cantante e, tra
queste, quelle che riportano gli accordi. In questo modo il motore
restituir in risposta tutti i documenti indicizzati che contengono le
parole inserite.

- OR. Questo operatore utilizzato quando la ricerca si concentra su


diversi termini e non necessario che li comprenda tutti, ma anche solo
uno di essi. Luso di OR, quindi, allarga il campo della ricerca; ostelli
408 Capitolo dodicesimo

OR campeggi, ad esempio, cerca i documenti che parlano sia di ostelli


che di campeggi.

- NOT. Luso di NOT importante quando vogliamo escludere delle


sottocategorie di documenti. Esclude i documenti contenenti il termine o
la frase specificata. Ad esempio, alberghi NOT pensioni trover i
documenti contenenti il termine alberghi ma non il termine pensioni.
Nelle interfacce di ricerca semplice loperatore NOT in genere
sostituito dal segno - (meno). Ha un funzionamento opposto
alloperatore AND.

- NEAR. Funziona in modo simile ad AND ma, oltre a ricercare i


documenti che contengono le parole chiave inserite, restringe il campo di
ricerca stabilendo che i termini debbano trovarsi ad una certa distanza
luno dallaltro. Tale distanza diversa a seconda del motore che si sta
usando. AltaVista, per esempio, imposta loperatore NEAR su 10 parole,
mentre Lycos su 25. Altri servizi (quali Excite), al contrario, non lo
riconoscono.

- Asterisco (*). Alcuni motori di ricerca accettano lasterisco come


sostituto di una o pi lettere. Lasterisco pu quindi essere usato per
cercare tutte le declinazioni di una parola, come il genere e il numero dei
sostantivi o il tempo e il modo dei verbi. Ad esempio, gatt* sta per
gatto, gatta, gatti, gatte, ma anche per gattopardo, gattabuia e per
tutte le altre parole che cominciano per gatt. Lasterisco pu essere
usato anche allinterno di una parola, ad esempio quando non si sicuri
della sua ortografia.

- Virgolette ( ). Le virgolette alte ___ indicano al motore di ricerca


che il loro contenuto deve essere trattato come una frase, cio come una
sequenza di parole che devono comparire nel testo come un blocco unico
(ad esempio bed & breakfast, ma anche Giuseppe Verdi). Se
inseriamo una frase senza racchiuderla tra virgolette il motore di ricerca
interpreta le parole come legate da OR e quindi, invece di restringere
lambito della ricerca, lo allarga, pertanto non trover solo i documenti
che contengono la frase bed & breakfast, ma tutti quelli che
contengono la parola bed e tutti quelli che contendono la parola
breakfast.

Motori di ricerca e indici di rete sono quindi tra le applicazioni pi complesse del
mondo dellinformatica se si pensa alle risorse hardware e software necessarie per
far funzionare correttamente uno strumento che deve indicizzare, archiviare e
mantenere aggiornate decine (a volte centinaia) di milioni di pagine Web.
12.2.4. I Portali
Molto utilizzati dagli utenti meno esperti, ma poco adatti ai professionisti della
ricerca in Internet, i portali si candidano a costituire il sito di riferimento dei
navigatori non solo per la ricerca di informazioni ma anche per ogni altra attivit
Il mondo di Internet 409

effettuabile in Rete (comunicazione, giochi, acquisti in linea, prenotazione di


servizi, etc). Includono quasi sempre una directory per argomento molto orientata
alle necessit della vita quotidiana, un motore di ricerca, sviluppato in proprio, e
un offerta dei pi svariati servizi: notiziari, quotazioni di borsa, indirizzi e-mail e
spazio Web gratuiti, oroscopi, stradari, chat e forum, invio di Sms, previsioni del
tempo e cos via.

12.3. Internet ed il mondo del business


La diffusione a macchia dolio di Internet negli ultimi anni ha, per cos dire,
contagiato anche il mondo del business. Con lo sviluppo delle reti di
trasmissione del web e con lemergere di concetti quali connettivit e
convergenza, le imprese hanno la possibilit di modificare le proprie strategie ed
attivit commerciali per sfruttare appieno le opportunit offerte dalle tecnologie
ICT ed in particolare, dalla rete Internet.
Le sfide imposte dalla globalizzazione richiedono alle aziende di operare in un
mercato dove velocit e efficienza sono condizioni irrinunciabili: si fa strada
quindi il concetto di connessione continua con clienti, fornitori, partner e si
impone il modello di unimpresa estesa. In un tale contesto, la rete Internet
diventa lunica e pi importante piattaforma su cui progettare limpresa, poich
rappresenta lelemento in grado di mettere in comunicazione facilmente tutti gli
attori in gioco.
Oggi si parla di e-business o Net Economy, proprio a testimonianza del fatto
che parte dei volumi di affari di un gran numero di aziende, si svolgono oramai su
Internet che diventa cos, sia una infrastruttura primaria di comunicazione, sia uno
strumento di business utile a migliorare lefficienza di alcuni processi aziendali
(commercializzazione e approvvigionamento) e, in prospettiva capace di
sviluppare nuove opportunit di business (incremento del numero di clienti).
Grazie alle ultime innovazione tecnologiche nel campo dellinformatica, l e-
business ha superato la fase di scetticismo iniziale, legata alla scarsit di banda
e alla scarsa sicurezza e affidabilit della rete, imponendosi come soluzione
globale e investendo anche in settori e in aziende tradizionali, legate alla Old
Economy.
Negli ultimi tempi stato intenzionalmente coniato il termine B2B (business to
business) per indicare e caratterizzare il modello su cui si basano le transazioni
economiche tra imprese svolte mediante lutilizzo della rete Internet.
Non sono pi dunque gli ambienti fisici ma quelli virtuali ad essere i nuovi
depositari delle relazioni tra clienti e fornitori, delle attivit di
commercializzazione e dell'approvvigionamento e dell'incrocio tra la domanda e
l'offerta. Il tutto nella prospettiva di accedere ad informazioni generaliste e/o di
settore, ricercare nuovi partners commerciali, condividere tutta una serie di servizi
comuni da quelli finanziari a quelli logisitici, per arrivare alla consulenza. Quindi
nellattuale mercato, caratterizzato da una continua innovazione e da una
concorrenza sempre maggiore (dovuto allallargamento geografico dei confini di
operativit delle aziende), l adozione di soluzioni e-business diviene un fattore
necessario per le aziende che intendono aprirsi al Web e ad Internet.
In un cos ampio e complesso scenario, le applicazioni di e-business pi diffuse in
ambito aziendale e allinterno delle Pubbliche Amministrazioni, che si sono fatte
410 Capitolo dodicesimo

strada nel caotico universo della rete, sono le-commerce, le-banking, le-trading
e le-procurement.
12.3.1. Le-commerce
Per commercio elettronico (e-commerce) si intende la vendita tramite sito Web
(dellazienda o di terzi) di prodotti e servizi sia allutenza finale (individui,
aziende) che a rivenditori e distributori. Perch sia possibile parlare di commercio
elettronico necessario che almeno lordine di acquisto debba essere compilato
on line, il pagamento pu essere invece effettuato tramite canali tradizionali
(bonifico,assegni, contante ecc.) o via Web mediante lutilizzo di carta di credito.
I progressi compiuti soprattutto nel campo della sicurezza su rete (crittografia,
firma digitale, etc) e, la contemporanea nascita di enti che certificano la
sicurezza di un portale di e-commerce, hanno abbattuto liniziale diffidenza nei
confronti di questa tecnologia (soprattutto per quel che riguardava la privacy e la
sicurezza in rete del cliente, che doveva digitare i propri dati online e effettuare
pagamenti a rischio con carta di credito) e hanno fatto s che essa diventasse una
realt per tutti: per le aziende che possono oggi ordinare merci in tempo utile
(on time), acquistare materiali da fornitori, o vendere beni/servizi, e, per i
privati che, comodamente da casa, possono acquistare libri, biglietti, musica, etc..
I vantaggi legati alladozione delle moderne soluzione di e-commerce sono
duplici. Da un lato esse offrono alle aziende una sempre pi variegata gamma di
prodotti e strategie di web marketing attraverso cui definire proficuamente la
propria presenza in rete: le aziende che attivano portali di e-commerce possono
vendere i loro prodotti in un negozio virtuale accessibile a tutti, facile da gestire,
sicuro e, portare il proprio marchio on-line. Dallaltro lato i clienti possono
acquistare merci (riempiendo il proprio carrello elettronico) in negozi sempre
aperti, con offerte e prezzi convenienti, indipendentemente dalla loro collocazione
geografica.
12.3.2. Le-banking
L'imponente sviluppo delle tecnologie dell'informazione e della comunicazione e
i cambiamenti economici e normativi hanno modificato in modo sostanziale il
settore bancario. La possibilit di offrire servizi attraverso la rete Internet ha
intensificato la competizione interna del settore bancario prescindendo, almeno in
parte, dalla necessit della presenza di filiali sul territorio. Tale situazione ha
comportato il rapido sviluppo, in termini qualitativi e quantitativi, dei servizi on
line offerti dalle banche, cio delle-banking.
Le-banking permette ai correntisti di una banca di operare per mezzo di
applicazioni gestite direttamente on line e relative all interrogazione di conti
correnti, alla visualizzazione dei movimenti sul conto corrente, alla possibilit di
eseguire bonifici e pagamenti, etc. Luso personale delle-banking consente
allutente di effettuare on line, oltre alle normali operazioni bancarie, anche il
pagamento di tasse e bollettini postali, di accedere e operare sui principali mercati
finanziari e di fare shopping on line.
Inizialmente le iniziative di e-banking sono sorte per soddisfare la domanda dei
privati, successivamente, le banche italiane hanno incominciato a proporre servizi
di e-banking anche alle imprese. Attualmente l'offerta di servizi bancari on line
Il mondo di Internet 411

per le imprese presenta gi delle interessanti proposte. Le imprese, ad esempio,


possono gi sfruttare i servizi di eBanking per gestire, almeno parzialmente,
pagamenti e riscossioni via Internet.
12.3.3. Le-trading
Internet divenuto un valido ausilio tecnico che accompagna lofferta di
erogazione di servizi d'investimento. Le-trading o on line trading rappresenta
quellinsieme di procedure telematiche che consente la negoziazione di titoli
attraverso la rete. L'impiego della rete ha rappresentato una straordinaria
opportunit di crescita per i mercati finanziari e costituisce l'area principale
dell'internet banking poich, l'immaterialit del denaro e del concetto stesso di
possesso, rendono il mondo della rete il locus ideale per questo tipo di
transazioni.
Il mercato telematico rappresenta un mercato altamente concorrenziale grazie
allofferta di informazioni virtualmente illimitate e accessibili a costo quasi nullo.
Ci ha portato ad una drastica riduzione delle commissioni di negoziazione e alla
possibilit di operare su molti mercati, monitorando in tempo reale le quotazioni,
di inserire il proprio ordine al livello desiderato (in acquisto o vendita) e di
visualizzare tempestivamente le operazioni effettuate.
Sorto a met degli anni '90 negli Stati Uniti , solo dal 1998 le-trading ha iniziato
a suscitare anche in Italia l'interesse di alcune banche pioniere.
Oggi lo sviluppo delle telecomunicazioni, in termini di sicurezza, capacit
trasmissiva ed economicit, ha favorito l'affermarsi di mercati finanziari
altamente informatizzati: la diffusione delle informazioni di mercato, l'incontro
tra domanda e offerta di titoli, il collegamento automatico con i sistemi di
regolamento delle transazioni sono affidati in misura crescente a procedure
telematiche.
Gli altri fattori che hanno contribuito maggiormente allo sviluppo del trading on
line sono stati la sicurezza, intesa come creazione di chiavi di crittografia pi
affidabili, l'evoluzione della tipologia dellutenza, la tecnologia che ha reso
disponibile labassamento dei costi di collegamento alla rete, la diffusione della
cultura informatica e finanziaria e infine, il miglior grado di trasparenza dovuto
dall'aumento dell'informazione.
12.3.4. Le-procurement
Il termine e-procurement indica quellinsieme di tecnologie, procedure,
operazioni, e modalit organizzative che consentono lacquisizione di beni e
servizi on line, grazie alle possibilit offerte dallo sviluppo della rete Internet e
del commercio elettronico. Le-procurement permette di fatto alle imprese di
gestire completamente il rapporto con i fornitori dalla conduzione della trattativa
all'approvvigionamento, dall'ordine al fornitore, fino alle consegne. Vengono
inoltre soddisfatte tutte le necessit relative alla gestione dei rapporti con i terzi.
Una migliore gestione delle scorte, la diminuzione del numero di errori che
avvengono nella fase di gestione degli ordini, il risparmio sul costo dei beni
acquisiti, la possibilit di pianificare in maniera ottimale la gestione della propria
supply chain (flussi di materiali, delle informazioni e dei mezzi di pagamento),
di effettuare il tracking degli ordini in tempo reale, la diminuzione dei tempi di
412 Capitolo dodicesimo

gestione, sono i principali vantaggi dell'e-procurement. Tra le modalit di


attuazione delle-procurement rientrano, infine, anche le cosiddette Aste on
line, che rappresentano delle procedure telematiche per acquisti di beni e servizi
secondo le norme che regolano le normali gare e licitazioni pubbliche o private.
12.3.5. Internet e la Pubblica Amministrazione: le-governement
Anche il mondo della Pubblica Amministrazione, negli ultimi anni, ha risentito
della diffusione di Internet ed ha avvertito come lutilizzo della rete potesse
portare ad un miglioramento qualitativo dei propri servizi, soprattutto per quanto
riguarda la comunicazione tra amministrazioni nello scambio di documenti o
informazioni, e, per quanto concerne la fruizione dei servizi da parte del
cittadino/impresa. A tale proposito stato introdotto il termine di e-government
per indicare linsieme di tutte quelle iniziative atte a favorire il cambiamento della
Pubblica Amministrazione, attraverso lutilizzo delle moderne tecnologie ICT e
lapertura verso la rete Internet.
Tra le azioni previste nel piano di e-government ricordiamo:
- azioni dirette ad informatizzare la erogazione dei servizi ai cittadini e
alle imprese che spesso implicano una integrazione tra i servizi di
diverse amministrazioni;
- azioni dirette a consentire laccesso telematico degli utilizzatori finali ai
servizi della pubblica amministrazione e alle sue informazioni;
- azioni di informatizzazione dirette a migliorare la efficienza operativa
interna delle singole amministrazioni.

In unottica di rete, in cui tutte le amministrazioni centrali e locali sono abilitate


per una cooperazione informatica paritetica, viene assegnato un ruolo particolare
alle amministrazioni locali, le quali dovranno assumere, in un modello distribuito,
sempre pi il ruolo operativo di front-office del servizio pubblico, mentre le
amministrazioni centrali sono destinate a svolgere un ruolo di back-office e
coordinamento. In questo disegno, il cittadino/impresa potr ottenere il servizio
pubblico, cui ha diritto, rivolgendosi ad una qualsiasi amministrazione di front-
office abilitata al servizio, indipendentemente da ogni vincolo di competenza
territoriale o di residenza.
Per lattuazione delle azioni e dei progetti previsti, si identificano tre strumenti
fondamentali:
- la rete nazionale, cio la rete che connette tra loro tutte le reti centrali,
regionali, locali, di categoria e di settore amministrativo, quelle gi
esistenti e quelle in via di attivazione;
- la carta didentit elettronica, come sistema unificato di accesso alle rete
e che dar al cittadino il diritto allaccesso a tutti i servizi della Pubblica
amministrazione erogati on-line;
- la firma digitale, che servir per dare validit giuridica a tutti quei
rapporti tra le pubbliche amministrazioni e i privati che la richiedono .
In tale contesto i portali web per lerogazione di servizi consentiranno, oltre
allaccesso alle informazioni, anche la formulazione interattiva di richieste di
servizio o la esecuzione di transazioni. Laccesso ai portali di servizi richieder
anche luso della firma digitale come meccanismo di convalida legale delle
Il mondo di Internet 413

dichiarazioni trasmesse e la carta di identit elettronica, come mezzo di


identificazione per laccesso ai servizi dei portali.
12.3.6. Internet ed il mondo della formazione: le-learning
Internet e il World Wide Web hanno spinto il mondo della formazione verso
radicali cambiamenti metodologici, tecnologici ed organizzativi. In particolare i
progressi compiuti nellarea delle nuove tecnologie della comunicazione; delle
reti telematiche, della multimedialit, della simulazione e della realt virtuale,
costituiscono un arricchimento dei mezzi messi a disposizione delle strategie
formative e possono offrire potenzialit rinnovate alle modalit di
apprendimento.
La conoscenza non pi un privilegio di una elit ristretta, poich ormai,
unenorme quantit di informazioni e risorse accessibile in maniera semplice e
rapida tramite il web. In particolare, gli strumenti forniti dalle nuove tecnologie
hanno permesso, da un lato, la creazione e divulgazione di materiale didattico
innovativo e fortemente interattivo, dallaltro hanno reso pi pervasivo lutilizzo
delle nuove metodologie per la formazione a distanza di terza generazione ,
meglio nota con il nome di e-learning o on line education.
Lelearning fortemente basato sulluso di tecnologie informatiche e telematiche
che rendono possibile la creazione di nuove metodologie di apprendimento nelle
quali l'interazione tra i partecipanti, attiva la condivisione delle esperienze per
lacquisizione di nuove conoscenze e la realizzazione degli obiettivi prefissati.
La on line education si rivela adatta, in particolare, a progetti di formazione in
cui, la condivisione del vissuto personale e la possibilit di sviluppare una
situazione di apprendimento non rigidamente eterodiretto, ma orientato e
collaborativo, diventano fattori determinanti di successo. Inoltre, diventa
necessaria quando i tempi a disposizione sono brevi e lutenza numerosa.
Oggetto dell e-learning , dunque, accrescere limpegno nella formazione ad
ogni livello, in particolare promuovendo una cultura digitale per tutti e
generalizzando modelli formativi fondati sulla gestione dei mutamenti.
Lattenzione si concentra sempre pi su colui che impara superando la
compartimentazione tra i diversi settori e livelli di istruzione. Si quindi giunti ad
un modello educativo centrato sulla figura del discente che pu ora interagire in
maniera autonoma e personale con i contenuti didattici reperibili sulla rete.
La particolare flessibilit del mezzo adoperato, che rende possibile, non solo
lannullamento delle distanze geografiche tra i partecipanti al corso, ma anche la
possibilit di comunicare con tempi e in momenti diversi, fa della comunicazione
in rete uno strumento particolarmente funzionale ai progetti di formazione e
aggiornamento professionale in azienda.
Le-learning si diffuso, dapprima, in ambito aziendale come strumento per
laggiornamento degli skills professionali: a tale scopo sono nate le prime
piattaforme di e-learning, attraverso le quali era possibile erogare corsi digitali per
il personale aziendale, che poteva seguire comodamente le lezioni dallufficio o
da casa, tramite il proprio PC. Tali piattaforme si sono poi evolute nel tempo per
soddisfare esigenze di realt differenti da quella aziendale a quella universitaria,
in cui necessit e caratteristiche dei processi formativi sono molto differenti da
quello che un semplice aggiornamento professionale.
414 Capitolo dodicesimo

Attualmente, sul mercato, esiste una vasta gamma di piattaforme, sia commerciali
che open-source, ognuna con proprie peculiarit: tutte le piattaforme pi
recenti, spinte anche da ragioni di mercato, tentano, in realt, a loro modo, di
venire incontro alle esigenze del mondo universitario, fornendo innovativi tools di
supporto alle attivit didattiche e avanzati strumenti collaborativi; chat, lavagne
virtuali, bacheche elettroniche, test di valutazione, forum, web-conference, sono
tutti oramai servizi consolidati delle moderne piattaforme di e-learning.
Oggi, circa il 70% della aziende europee e buona parte delle Universit ha attivato
al proprio interno esperienze di e-learning, che vanno da una semplice erogazione
di corsi web-based alle pi avanzate modalit di apprendimento a distanza. Il
diffondersi delle-learning la testimonianza di come, lesplosione della rete
Internet, abbia reso possibile la strutturazione di ambienti in cui possibile
apprendere senza vincoli di tempo, di spazio e soprattutto, senza vincoli di
appartenenza sociale.
Lofferta formativa in rete non , come si visto, monolitica. Lutilizzo della rete
nella formazione spazia dai percorsi di autoaggiornamento, basati sulluso dei
materiali didattici strutturati per essere fruiti in autoistruzione, alla gestione di
percorsi interattivi centrati sullapprendimento collaborativo, fino alluso di
strategie di apprendimento reciproco, tipico delle comunit di pratica. Ne
consegue che, le diverse modalit di utilizzo delle reti a supporto della
formazione, determinano altrettante tipologie di apprendimento. Ciononostante
le-learning, idealmente, dovrebbe presentare alcune specificit trasversali.
Tra le caratteristiche principali dell'e-learning ricordiamo innanzitutto la
dinamicit. e-learning sinonimo di aggiornamento continuo, di specializzazione
ed approfondimento. Non vi spazio nei corsi online per informazioni obsolete
n per conoscenze vaghe e superficiali, in questo caso l'efficacia ne risulterebbe
compromessa. Pertanto, offrire e-learning comporta la presenza di un esperto in
materia, di fonti sicure e rilevanti, di aggiornamento continuo delle informazioni
offerte e di un immediato intervento tecnico in caso di emergenza e
malfunzionamenti.
Nella formazione tradizionale il momento di studio personale e il momento di
fruizione della lezione in aula (spesso unicamente frontale), sono rigidamente
separati e il materiale di riferimento viene letto e studiato, in un secondo
momento, specialmente nella formazione universitaria. Un corso online
caratterizzato invece, oltre che dallerogazione di contenuti, anche dalla costante
presenza di figure di riferimento, cio il docente e il tutor on line, con cui il
discente pu costantemente interagire in modalit sincrona o asincrona allinterno
della classe virtuale.
Tutti i partecipanti sono coinvolti in un percorso formativo che non esisterebbe
senza una intensa collaborazione tra pari (collaborative learning); grazie alla
cooperazione possibile far emergere le conoscenze "tacite", cio il patrimonio
culturale silenzioso degli utenti che, attraverso il coinvolgimento in attivit e
discussioni di gruppo spontaneamente daranno vita al processo di costruzione
della conoscenza. Lobiettivo principale dell' e-learning , da questo punto di
vista, mettere insieme risorse, sia all'interno sia all'esterno di una stessa
organizzazione: la condivisione di esperienze e la collaborazione nel
raggiungimento di determinati obiettivi favoriscono l'interscambio di
Il mondo di Internet 415

informazioni rilevanti, e nellottica costruzionista, sono pi rilevanti dei contenuti


stessi del corso.
Altra specificit dell'e-learning la possibilit che offre alla personalizzazione del
servizio erogato centrato sulle esigenze del singolo. Non si tratta pi di portare gli
utenti verso la formazione, ma la formazione verso gli utenti. Allutente offerta
la possibilit di scegliere le attivit formative pi rispondenti alle proprie esigenze
personali, al proprio background, al proprio lavoro e alle prospettive di carriera.
L'e-learning, si differenzia metodologicamente dalla formazione tradizionale,
poich eroga un offerta formativa multimodale, permettendo al discente di
scegliere quella pi consona al proprio stile individuale di apprendimento.
L'atteggiamento di fondo di libert di scelta all'interno di un ambiente che offre
svariate modalit di apprendimento degli stessi contenuti. E evidente il
cambiamento della prospettiva dalla formazione tradizionale, in cui era
unicamente il docente, il magister, a programmare lunico percorso espletabile.
Nell'e-learning non vi sono percorsi obbligati, ma "consigli" e "suggerimenti" che
si limitano a dare un'idea di ci che possibile fare, senza limitare i movimenti
dell'utente. Tuttavia, la libert di scelta pu essere un'arma a doppio taglio: non
sempre avere molte possibilit porta a scegliere le migliori, o le pi adatte al
proprio stile di apprendimento e alle proprie reali esigenze formative.
Non si deve dimenticare che ogni discente ha propri ritmi, tempi ed uno stile
personale di apprendimento; per tale motivo esistono percorsi che prevedono
attivit formative sincrone o asincrone e, nei migliori dei casi, la formazione in
rete progettata proponendo un mix di entrambe. La sincronicit permette di
essere pi vicini allo stile dell'aula, in cui, docente e discenti, sono virtualmente
compresenti; l'asincronicit permette invece, a chi ha problemi di tempo, di
apprendere in totale autonomia, perdendo la possibilit di condivisione sincronica
della propria esperienza con gli altri discenti ma non escludendo la
comunicazione a livello asincrono. In breve, ad esigenze diverse l'e-learning,
offre soluzioni diverse.
La fruizione di un corso on line potrebbe mettere in difficolt l'utente
scarsamente alfabetizzato tecnologicamente, tuttavia a volte anche i discenti
pi esperti si sentono disorientati dinanzi alla variet dei percorsi offerti. Affinch
sia efficace necessario che la formazione sia progettata in modo funzionale e
trasparente.
Per concludere, le-learning, per essere un valido strumento di apprendimento,
dovrebbe:
- offrire un'ampia gamma di percorsi per laggiornamento professionale in
ambito aziendale, ma anche essere uno strumento efficace per la
formazione scolastica e universitaria;
- offrire opportunit di formazione che siano motivanti e coinvolgenti per
il discente e di stimolo all'interazione per la comunit di apprendimento;
- offrire, attraverso i docenti e i tutor on line, un supporto consistente e
informale, sia sotto forma di istruzioni e contenuti specifici, sia sotto
forma di sostegno emotivo e affettivo in itinere;
- stimolare gli utenti alla collaborazione per offrire aiuto reciproco nella
soluzione dei problemi proposti;
- tracciare i percorsi di apprendimento dei discenti e registrare i risultati
ottenuti nei momenti di valutazione formativa e sommativa;
416 Capitolo dodicesimo

- consentire la creazione di percorsi di apprendimento personalizzati


rispondenti alle esigenze e agli obiettivi specifici del singolo utente.
Capitolo tredicesimo

Basi di dati e Sistemi Informativi

13.1. Sistemi Informativi e Sistemi Informatici


Linformazione rappresenta oggi uno dei beni pi preziosi di una
organizzazione, in particolare per quel concerne il supporto alle varie attivit
aziendali, siano esse organizzative e di controllo, decisionali e di pianificazione
oppure operative. Linformazione un caso molto particolare di risorsa su cui
operano tutte le organizzazioni: tutti i processi aziendali, - intesi come insiemi di
attivit correlate per la realizzazione di un risultato definito e misurabile che
coinvolge pi risorse e attraversa pi strutture - per poter operare, hanno bisogno di
informazioni.
Linsieme delle informazioni gestite - generate, utilizzate, elaborate dallinsieme
dei processi aziendali costituisce il cosiddetto Sistema Informativo. Un sistema
informativo costituito da pi elementi - procedure, mezzi, persone, etc- , tra cui
avvengono interazioni determinanti ai fini del conseguimento degli obiettivi del
sistema, che possiamo indicare nella produzione e gestione delle informazioni. In
questa ottica, il Sistema Informativo costituisce una parte del sistema
organizzativo, visto come un insieme di risorse (persone, informazioni, denari,
materiali, etc..) e regole necessari per il raggiungimento degli obiettivi aziendali.
Quando possibile individuarlo in forma esplicita, un sistema informativo risulta
composto dalle seguenti categorie di elementi:
- un patrimonio di dati: come noto i dati rappresentano la materia prima
(grezza) con cui si producono le informazioni;
- un insieme di procedure per lacquisizione e il trattamento di dati e per la
produzione di informazioni;
- un insieme di persone che sovrintendono a tali procedure (nel senso che
le svolgono di persona, o le alimentano con i dati necessari, oppure
gestiscono le apparecchiature che svolgono le procedure in modo
automatico);
- un insieme di mezzi e strumenti necessari al trattamento, trasferimento,
archiviazione, eccetera, di dati e informazioni;
- un insieme di principi generali, di valori e di idee di fondo che
caratterizzano il sistema e ne determinano il comportamento.
In figura 1 sono rappresentate alcune delle componenti base di un moderno sistema
informativo.
418 Capitolo tredicesimo

Figura 1 - Componenti di un Sistema Informativo

Spesso, nella pratica, si tende a confondere il termine Sistema Informativo con


quello Sistema Informatico. Anche se i relativi concetti sono strettamente
correlati, essi presentano tuttavia delle differenze sostanziali. Un sistema
informativo esiste da molto prima dellinvenzione dei sistemi informatici, e tuttora,
molti aspetti di un sistema informativo non sono implementati dai sistemi
informatici. Un sistema informatico ha a che fare con gli aspetti tecnologici dei
sistemi di elaborazione dellinformazione, in particolare per quanto attiene
lhardware, il software e le reti di comunicazione. Facendo propria una
terminologia oggi molto usata, un sistema informatico , in altri termini, linsieme
delle tecnologie (note anche con lacronimo ICT, Information and Communication
Technology) a supporto della acquisizione, della elaborazione, della
memorizzazione, del recupero, della condivisione e della trasmissione
dellinformazione allinterno di una qualsiasi organizzazione. In figura 2 vengono
riportate quelle che sono le relazioni funzionali tra azienda, organizzazione,
sistema informativo e sistema informatico. In altre parole, un sistema informativo
rappresenta il modo con cui, attraverso le tecnologie, si raccolgono, elaborano,
memorizzano, usano e distribuiscono le informazioni, mentre il sistema
informatico rappresenta linsieme delle tecnologie (hardware, software, reti) di
supporto alla gestione delle informazioni.

Figura 2 - Sistema Informativo vs Sistema Informatico

Per meglio comprendere le caratteristiche di un sistema informativo e del relativo


sistema informatico a supporto, si consideri l'esempio di un Comune dotato di un
sistema per il rilevamento giornaliero del livello di smog dovuto al traffico
cittadino. Le fasi per la produzione e gestione dellinformazione risultano in tale
caso quelle elencate di seguito:
- un insieme di centraline di disposte in vari punti della citt rilevano ed
acquisiscono giornalmente i valori di smog consente (acquisizione ed
aggiornamento dellinformazione);
Basi di dati e Sistemi Informativi 419

- invio dei dati mediante unapposita rete di comunicazione ad un


elaboratore o server centrale che li immagazzina in un appositi archivi
digitale, noti anche col nome di basi di dati (archiviazione delle
informazioni);
- elaborazione ed analisi dei dati mediante appositi software da parte degli
impiegati, che dai vari uffici comunali accedono ad essi (elaborazione
dellinformazioni);
- presentazione dei risultati delle analisi giornaliere dei dati al sindaco, agli
assessori ed ai membri della giunta (comunicazione dellinformazione).
Nellesempio mostrato mentre il sistema informativo costituito dallinsieme
complessivo di persone (dipendenti comunali, sindaco, assessori, etc..), mezzi e
procedure necessari alla produzione e gestione dellinformazione relativa
allinquinamento cittadino, quello informatico riguarda, invece nello specifico, le
macchine hardware (server, centraline di rilevamento, etc), i programmi
software (programmi per la gestione di archivi, programmi per lelaborazioni dei
dati, etc) e lapparato di rete (rete comunale) necessari a supportare in maniera
efficace ed efficiente lintero processo di analisi del livello di smog. Tale analisi
impatta sulle attivit decisionali del comune: in particolare, a seconda del livello di
inquinamento riscontrato, il sindaco potrebbe prendere la decisione di vietare la
circolazione per determinati giorni della prossima settimana oppure di attendere i
risultati dellanalisi dei prossimi giorni prima di intraprendere alcuna decisione.
E' chiaro che lassenza di un sistema informatico di supporto non pregiudica
lesistenza del sistema informativo, ma ne comprometta lefficienza: tutte le
procedure di acquisizione ed elaborazione dei dati risulterebbero manuali e pi
lente, larchiviazione dei dati avverrebbe su supporto cartaceo, la comunicazione
dellinformazioni risulterebbe molto pi complicata.
Nel paragrafo successivo mostreremo brevemente una breve storia dei sistemi
informativi aziendali, per meglio comprendere la funzionalit che oggi sono messe
a disposizione da tale tipologia di sistemi.
13.1.1. Sistemi Informativi aziendali: levoluzione storica
I primi studi sullautomazione delle componenti di un sistema informativo
risalgono agli anni 70. A tale proposito, i primi sistemi (sistemi proprietari) furono
sviluppati per lo pi da software house per la gestione di singole esigenze
aziendali: contabilit, controllo di gestione, gestione del personale, gestione della
produzione, gestione dei magazzini, gestione della distribuzione, gestione acquisti,
gestione vendite, gestione progetti, gestione della manutenzione di impianti, etc
Il passo successivo si ha poi negli anni 80, quando si sviluppano i cosiddetti MRP
(Manufacturing Requirements Planning), ovvero sistemi che permettono la
copertura non di una sola, ma di pi aree funzionali, con integrazione stretta e con
funzionalit di pianificazione di materiali e risorse. In particolare i MRP si
preoccupano prevalentemente di supportare i processi primari di produzione come
lattivit in linea di produzione, la gestione degli approvvigionamenti dei materiali,
la gestione del magazzino, etc
Negli anni successivi fanno poi la comparsa i sistemi ERP (Enterprise Resource
Planning), che rappresentano oggi la soluzione standard per i moderni sistemi
informativi aziendali. Essi costituiscono unestensione dei sistemi MRP capaci di
affiancare allarea di gestione logistica (magazzini ed approvvigionamento)
420 Capitolo tredicesimo

funzionalit per la gestione dei processi di vendita e di processi non direttamente


legati alla produzione (contabilit, gestione personale, manutenzione impianti,
gestione progetti, etc).
A tuttoggi i sistemi ERP consentono la gestione integrata di una serie di processi
aziendali, coprendo tutte le aree che possono essere automatizzate e /o monitorate
allinterno di unazienda. Tra le tante cose, tali sistemi permettono di programmare
logiche di ordini automatici ai fornitori veramente sofisticate, tanto da tener conto
dei tempi di consegna e di messa in produzione del prodotto, ottimizzando la
rotazione dei materiali nei magazzini e minimizzando le giacenze in magazzino.
Le tendenze attuali delle varie organizzazioni per ci che concerne i sistemi
informativi sono quelle di integrare sistemi informativi eterogenei e relativi a
differenti realt in sistemi di tipo centralizzato e di rendere accessibili le
informazioni direttamente su web, utilizzando la rete Internet come principale
strumento di diffusione delle informazioni stesse.

13.2. Analisi e progettazione di un Sistemi Informativo


Cos come un qualsiasi altro sistema, visto come un insieme di componenti che
interagiscono fra loro al fine di raggiungere un determinato obiettivo, un sistema
informativo, prima di potere essere realizzato, necessita di una corretta fase di
analisi progettazione.
La progettazione e sviluppo di un sistema informativo possono essere analizzati
sotto due differenti punti di vista: quello dellutente finale e quello di chi realizza
le procedure automatizzate di supporto (sistema informatico). Da un lato, infatti,
gli utenti finali devono specificare le caratteristiche dei processi aziendali che
dovranno essere supportati dal sistema informativo; dallaltro lato, invece, analisti
e programmatori hanno il compito di verificare la fattibilit tecnica delle specifiche
richieste e concretizzarla in termini di applicativi efficienti. Nella pratica lanalisi e
progettazione di un sistema informativo una procedura articolata che si compone
di pi fasi, che costituiscono quello che comunemente viene definito ciclo di vita di
un sistema informativo. Di seguito vengono descritte le 6 fasi.
- Studio di fattibilit: serve a definire, dopo unanalisi preliminare degli
obiettivi realizzativi, in maniera pi precisa possibile i costi delle varie
alternative possibili e stabilire le priorit della realizzazione delle varie
componenti del sistema (scheduling delle attivit). Di norma, in tale fase,
viene effettuato un progetto di massima per valutare la convenienza della
realizzazione in termini di costi e benefici.
- Raccolta e analisi dei requisiti: consiste nell'individuazione e nello studio
delle propriet e delle funzionalit che il sistema informativo dovr
possedere. Questa fase richiede un'interazione con gli utenti finali del
sistema e produce una descrizione completa ma generalmente informale
dei dati coinvolti e delle procedure su di essi. Vengono inoltre stabiliti i
requisiti software e hardware del sistema informativo.
- Progettazione: si divide generalmente in progettazione dei dati,
progettazione delle applicazioni e progettazione dell'architettura tecnica
di sistema. Nella prima si individua la struttura e l'organizzazione che i
dati dovranno avere, nella seconda si definiscono le caratteristiche degli
applicativi atti ad automatizzare le procedure individuate. Queste due
Basi di dati e Sistemi Informativi 421

attivit sono complementari e possono procedere in parallelo o in cascata.


Le descrizioni dei dati e delle applicazioni prodotte in questa fase sono
formali e fanno riferimento a specifici modelli. La progettazione
dell'architettura tecnica di sistema, infine, rappresenter l'infrastruttura
individuandone le caratteristiche in termini di sistemi (server),
connettivit e sicurezza.
- Implementazione e test componenti: consiste nella realizzazione del
sistema informativo secondo la struttura e le caratteristiche definite nella
fase di progettazione. Viene costruita e popolata la base di dati e viene
prodotto il codice dei programmi. In tale fase i singoli componenti
software del sistema sono testati singolarmente
- Integrazione, validazione e collaudo: serve a verificare, a valle
dellintegrazione dei componenti del sistema, il corretto funzionamento e
la qualit del sistema informativo. La sperimentazione deve prevedere,
per quanto possibile, tutte le condizioni operative.
- Funzionamento e manutenzione: in questa fase il sistema informativo
diventa operativo ed esegue i compiti per i quali era stato originariamente
progettato. Se non si verificano malfunzionamenti o revisioni delle
funzionalit del sistema, questa attivit richiede solo operazioni di
gestione e manutenzione.
Va precisato che il processo di progettazione, come mostrato in figura 3, non quasi mai
strettamente sequenziale, in quanto spesso durante l'esecuzione di una attivit citata bisogna
rivedere decisioni prese nell'attivit precedente. Quello che si ottiene un ciclo di
operazioni. Inoltre alle attivit citate si aggiunge quella di prototipizzazione, che consiste
nell'uso di specifici strumenti software per la realizzazione rapida di una versione
semplificata del sistema informativo, con la quale sperimentare le sue funzionalit. La
verifica del prototipo pu portare a una modifica dei requisiti e una eventuale revisione del
progetto.

Figura 3 - Ciclo di vita di un Sistema Informativo


422 Capitolo tredicesimo

13.2.1. Le basi di dati


Le basi di dati o database rappresentano la tecnologia standard messa a
disposizione dei moderni sistemi informativi per ci che concerne
larchiviazione/memorizzazione, organizzazione e recupero delle informazioni
allinterno di una data organizzazione.
Le basi di dati costituiscono un aspetto fondamentale della vita di ogni giorno. Se
si vanno ad analizzare tutte le pi comuni operazioni che pu effettuare una
persona nel corso di una giornata, ci si rende conto di interagire con una o pi basi
di dati: laccesso alla rubrica di un telefonino, lacquisto di prodotti con carte di
credito, la prenotazione alberghiera presso un agenzia di viaggio, il pagamento di
una assicurazione, liscrizione ad un corso, limmatricolazione allUniversit, sono
tutto eventi che in vario modo richiedono luso di collezioni di dati che devono
essere memorizzate in modo persistente e organizzate a servizio di una
determinata organizzazione.
Dagli esempi sopra esposti possibile fornire una prima definizione intuitiva di
base di dati: una base di dati una collezione di dati tra di loro logicamente
correlati e dotati di una opportuna descrizione ed appartenenti una certa
organizzazione. In altri termini, le basi dati sono collezioni di dati utilizzate per
rappresentare le informazioni di interesse di una organizzazione.
Le basi di dati sono inoltre collezioni di dati solitamente: (i) di grandi dimensioni,
(ii) condivise da pi applicazioni/utenti diversi che devono poter accedere alle
stesse informazioni secondo adeguate modalit, (iii) persistenti, ovvero le
informazioni sono una risorsa con un tempo di vita molto pi lungo delle
procedure pensate per la loro gestione.
Si noti che nella definizione data, una base di dati deve poter mantenere non solo i
dati, ma anche una descrizione degli stessi. Per questo motivo spesso si parla di
collezione di dati autodescrittiva, cosa che possibile ottenere se un data base
mette a disposizione non solo un modo di organizzare gli archivi di dati ma anche
un catalogo, ovvero un dizionario di dati o, per dirla in modo informatico, un
insieme di dati che descrivono i dati (metadati).
13.2.2. I Data Base Management Systems
Affinch una base di dati costituisca effettivamente un valido supporto ai vari
processi aziendali, risultano necessari la definizione e sviluppo di procedure
automatizzate per laccesso e la gestione dei dati allinterno della basi di dati
stessa.
Fino allavvento dei linguaggi di programmazione di terza generazione (anni 60),
gli archivi di una qualsiasi procedura automatizzata erano realizzati mediante un
insieme di file sequenziali residenti su memoria di massa. Ogni procedura agiva su
un proprio archivio (base di dati), e, di conseguenza se altre applicazioni dovevano
accedere alla stesse informazioni era necessario creare ulteriori copie dei medesimi
archivi.
Questo approccio, che prevedeva unorganizzazione dei dati orientata ai file
generava i seguenti problemi:
1. ridondanza dei dati: gli stessi dati sono ripetuti pi volte in pi archivi;
Basi di dati e Sistemi Informativi 423

2. aggiornamento dei dati: ogni volta che un dato presente in un archivio


veniva aggiornato, era necessario apportare le stesse modifiche agli
archivi correlati;
3. dipendenza dei dati dai processi: ogni procedura automatizzata vede i
dati in una forma che pu essere diversa rispetto a quella di altre
applicazioni;
4. scarso supporto alla concorrenza: laccesso di pi applicazioni o utenti
agli stessi file era gestito mediante le primitive del file system del sistema
operativo.
Da quanto detto, si comprende la difficolt di realizzare una gestione efficiente di
grosse moli di informazioni condivise mediante un insieme di applicazioni o
procedure indipendenti che di volta in volta devono essere sviluppate per gestire
i propri dati sotto forma di insieme di file.
Al contrario, occorre pensare ad un unico strato software che gestisce in maniera
integrata tutti i dati, garantendo lesecuzione di una serie di operazioni in modo
efficiente ed efficace. Questo insieme di programmi il cosiddetto Data Base
Management System o DBMS (figura 4).

Figura 4 - Data Base Management System o DBMS

Un DBMS rappresenta quindi un insieme di programmi che permette di definire,


creare, mantenere e controllare una base di dati. Con lintroduzione dei DBMS
(anni 70) risulta pi semplice ed efficiente gestire collezioni di dati che siano
grosse, persistenti e condivise, garantendo nel contempo le seguenti funzionalit:
- definizione dei dati: ovvero specificare i tipi dei dati, le loro strutture, i loro
vincoli;
- manipolazione dei dati: ovvero recuperare i dati specifici, nonch il loro
aggiornamento;
- accesso controllato al data base: possibilit di condividere le informazioni
tra pi utenti, garantendo nel contempo protezione dei dati (da guasti,
malfunzionamenti e/o da accessi non autorizzati) e manutenzione evolutiva
del sistema.
Da un punto di vista architetturale un DBMS pu essere quindi visto come uno
strato software capace di gestire collezioni di dati residenti in memoria di massa
(file), ampliando quelle che sono le funzionalit base di gestione dei file di un
sistema operativo.
Linsieme costituito dal software DBMS e dalla base di dati sottostante prende il
nome di sistema di basi di dati.
Un DBMS, pertanto, facilita gli utenti per lutilizzo della propria banca dati: esso
funge da interfaccia trai programmi applicativi e la base di dati supportando le
operazioni di interrogazione e modifica su di essa, nonch la condivisione dei dati.
In un DBMS, i dati sono di solito descritti a tre livelli differenti di astrazione, come
si evince dalla figura 5. Pertanto, una base di dati consiste in un livello esterno, un
livello logico ed un livello fisico. Tutte le informazioni relative a tali schemi sono
424 Capitolo tredicesimo

memorizzate allinterno del catalogo di sistema. In particolare, procedendo dal


livello pi interno a quello pi esterno, si ha la seguente schematizzazione:
- schema fisico: lo schema che specifica i dettagli della memorizzazione
fisica dei dati e specifica come tali informazioni sono effettivamente
memorizzate su dispositivi fisici di memorizzazione di massa. In particolare,
a questo livello viene descritto come sono memorizzati i dati (array di
record) in uno o pi file, e, quali tipi di strutture sono necessarie per
velocizzare laccesso fisico agli array (indici di accesso).
- schema logico: lo schema che descrive come sono organizzati i dati dal
punto di vista logico-concettuale. In particolare lo schema logico pu essere
visto come un insieme di record con le loro descrizioni, come illustrato in
figura 6.
- schema esterno: scopo di uno schema esterno quello di personalizzare
laccesso ai dati relativamente ad un singolo utente o ad una classe di utenti.
In particolare si noti che mentre un database ha sempre un singolo schema
logico ed un singolo schema fisico, pu possedere differenti schemi esterni
che costituiscono, in effetti, una o pi viste dei dati.

Figura 5- Livelli di astrazione forniti da un DBMS su un database

Il concetto di vista particolarmente utile e con essa, per il momento, si intende


concettualmente lo schema visibile da una classe di utenti o da un utente, schema
che non corrisponde necessariamente a dati memorizzati nel DBMS.

Figura 6 - Schema logico


Basi di dati e Sistemi Informativi 425

Il vantaggio fondamentale di una organizzazione siffatta di un DBMS la


cosiddetta data - application independence. Se si indica con il termine programma
applicativo un programma che interagisce con un database attraverso particolari
richieste fatte al DBMS, possibile con i tre livelli ottenere che le applicazioni
siano isolate dal modo in cui i dati siano organizzati. In particolare, (i) attraverso il
meccanismo delle viste, le applicazioni sono rese indipendenti dallo schema logico
della base di dati: cambiando lo schema di un DB non necessario cambiare le
applicazioni a patto che a queste vengono fornite viste di dati che corrispondono
agli schemi logici a cui precedentemente le applicazioni si riferivano; (ii)
attraverso lo schema logico, si garantiti dalla differente implementazione fisica
dei dati: un applicativo o un utente pu tranquillamente operare sul database anche
se nel tempo viene cambiato il modo in cui i dati sottostanti sono organizzati.
Possiamo concludere che lo schema a livelli di un DBMS permette di realizzare
concetti di information hiding (occultamento dellinformazione) tramite il quale i
dati sono a vari livelli resi visibili ad una applicazione esterna.
13.2.3. Levoluzione dei DBMS
A livello dello schema logico risulta fondamentale individuare il modo in cui i dati
sono organizzati e la struttura usata per renderli comprensibili ad un elaboratore
(modello dei dati).
Il modello dei dati pi diffuso senza dubbio oggi il modello relazionale, basato
sul concetto di relazione - spesso rappresentata attraverso una tabella. Si esaminano
tuttavia quelli che sono stati storicamente i modelli dei dati pi utilizzati nel corso
degli anni.
- modello gerarchico (anni 60): nel modello gerarchico i dati sono
organizzati in gerarchie attraverso luso di strutture dati ad albero;
- modello reticolare (inizio anni 70): nel modello reticolare i dati sono
organizzati in un reticolo attraverso luso di strutture dati a grafo;
- modello relazionale (definito inizio anni 70; implementato fine anni 70:
i dati sono organizzati in relazioni, ovvero un insieme di record aventi la
stessa struttura logica; tali relazione, sotto certe condizioni, sono a tutti gli
effetti delle tabelle;
- modello object oriented: i dati sono organizzati sotto forma di oggetti
software e di legami tra di essi;
- modello object relational: il modello rimane relazionale (struttura
tabellare), ma la struttura della tabella generalizzata al fine di contenere
oggetti oltre che valori elementari.
Oggigiorno vi sono diverse centinaia di DBMS relazionali che girano sia su
mainframe che su ambienti di Personal Computer, a partire da applicazioni
semplici come Access di MS Office, Visual FoxPro, a sistemi di medie prestazione
come mySQL e SQLServer, a sistemi complessi per medie/grosse aziende come
DB2 di IBM ed Oracle della Oracle Corporation. La tendenza attuale di
implementare modelli object relational a servizio delle applicazioni pi recenti
basati su rete (internet).
426 Capitolo tredicesimo

13.2.4. Le funzionalit di un DBMS


Nel 1969 il Data Base Task Group (DBTG) ha definito i compiti principali di un
DBMS che consistono nel:
- definire i dati, attraverso un opportuno linguaggio di definizione dei dati
detto Data Definition Language (DDL);
- manipolare, gestire i dati, attraverso un opportuno linguaggio di gestione
detto Data Manipulation Language (DML).
Un DBMS esegue dei programmi particolari detti transazioni. Una transazione, dal
nostro punto di vista molto astratto, una qualsiasi esecuzione di un programma
utente in un ambiente DBMS e costituisce una unit atomica (non divisibile) di
modifiche fatte allo stato di una base di dati. Da quanto detto, una qualsiasi
transazione o termina in uno stato finale previsto dal programma in esecuzione
(attraverso quello che in gergo viene detto commit) o porta il sistema ad uno stato
precedente allesecuzione della transazione attraverso un abort. Sistemi di basi di
dati basati su transazioni sono anche detti On Line Transaction Processing, o
OLTP. Si noti che talora le transazioni possono anche contenere solo
interrogazioni: in tal caso, la atomicit sempre assicurata in quanto una
interrogazione non modifica lo stato di una base di dati.
Le operazioni di modifica classiche sono le operazioni di (i) insert, permette di
inserire un nuovo oggetto allinterno di un database; (ii) update, permette di
modificare un oggetto preesistente allinterno di un database; (iii) delete, permette
di cancellare un oggetto allinterno di un database.
Le operazioni devono poter essere fatte garantendo il principio che una qualsiasi
modifica della base di dati deve essere persistente. Qualunque cosa accada, sia a
livello di crash fisico che di sistema, deve poter essere garantito che la transazione
effettuata sia permanentemente memorizzata nel data base.
Per quanto attiene le operazioni di interrogazione, un DBMS deve poter gestire
operazioni di interrogazioni (query), attraverso le quali un utente cerca
informazioni interne alla base di dati e si aspetta di avere risultati che siano
coerenti e consistenti (ovvero efficaci) nel minor tempo possibile (in modo
efficiente). Un DBMS deve poter gestire allora lesecuzione efficiente di una query
attraverso una ricerca di informazioni su una collezione di dati per lo pi sempre
molto grande.
Concludiamo questa breve introduzione ai DBMS cercando di riassumere in
maniera sintetica, relativa ai vantaggi (ma anche agli svantaggi) dellapproccio
basato su DBMS.
- Controllo della ridondanza dei dati e consistenza: un approccio basato su
DBMS tende ad eliminare duplicazioni inutili di dati (ridondanza) su vari
file, cercando di impedire che la stessa informazione sia presente pi volte
nel repository dei dati. In questo modo si riduce il rischio di
inconsistenza: se una informazione presente una sola volta dentro un
database, una sua modifica rende immediatamente disponibili a tutti il
nuovo valore. Una duplicazione di dati genera, invece, in generale
inconsistenza, l dove una modifica dello stato del database deve poter
effettuare modifiche su tutte le occorrenze di quella informazione.
Basi di dati e Sistemi Informativi 427

- Condivisione: i dati di una stessa organizzazione sono logicamente


condivisi, anche se con viste diverse, da tutti gli utenti - e soprattutto da
tutte le applicazioni relative a quella organizzazione.
- Integrit dei dati: per integrit dei dati ci si riferisce alla consistenza e alla
validit dei valori contenuti in base di dati. Il concetto di integrit dei dati
fortemente legato (nel modello relazionale) al concetto di vincoli o
constraints.
- Gestione efficiente delle operazioni: il DBMS fornisce le funzionalit per
lesecuzione efficiente di richieste di interrogazione e aggiornamento
(transazioni) sulla base di dati. A tale proposito, il DBMS fornisce
funzionalit di controllo della concorrenza, per garantire che transazioni
concorrenti operino correttamente sui dati, senza interferenze reciproche.
- Affidabilit: il DBMS fornisce funzionalit di salvataggio e ripristino (in
gergo, backup e recovery) dei dati contenuti nella base di dati, per
garantire che non ci siano perdite di dati anche in caso di guasti e
malfunzionamenti hw/sw durante lesecuzione di transazioni.
- Sicurezza: Per sicurezza di un DB si intende la prevenzione dellaccesso
ai dati ad utenti non autorizzati. Un approccio DBMS permette di definire
politiche di accesso ai dati per utenti e per profili di utente.
- Costi: Il costo di un DBMS dipende dalla complessit del sistema da
gestire e dalle funzionalit che devono essere garantite. Tipicamente si va
da oltre centinaia di dollari a centinaia di migliaia o milioni di dollari per
il solo software. A tali costi diretti vanno poi aggiunti quelli indiretti
legati, da un lato, allacquisizione della configurazione hardware adeguata
a sfruttare a pieno tutto le funzionalit del software, e, dallaltro, alla
formazione del personale predisposto alluso degli strumenti suddetti.
13.2.5. Ricerche in un database: introduzione al linguaggio SQL
Il modello relazionale permette, come accennato, di rappresentare una base di
dati attraverso un insieme di tabelle, che ne definiscono la struttura, caratterizzate
da un insieme di nomi di attributi, ed un insieme di vincoli, che servono a garantire
la coerenza delle informazioni allinterno della base di dati stessa. La strutturazione
dei dati in tabelle permette di semplificare notevolmente, non solo lorganizzazione
delle informazioni, ma anche laccesso alle stesse.
A tale proposito tutti i DBMS relazionali mettono a disposizione un apposito
linguaggio, denominato SQL (Structured Query Language) per linterazione con
una base di dati.
Le operazioni supportate dal linguaggio SQL sono di vario tipo:
- operazioni per la creazione di oggetti (tabelle, indici, utenti, etc) e
definizione di vincoli (la parte dellSQL che si occupa di tali operazioni
prende il nome, come detto, di DDL);
- operazioni per linserimento, cancellazione e modifica dei dati (la parte
dellSQL che si occupa di tali operazioni prende il nome, come detto, di
DML);
- operazioni per la ricerca di informazioni, conosciute anche col nome di
query.
Per istanze di basi di dati di grosse dimensioni si avverte la necessit di introdurre
meccanismi per il recupero veloce dellinformazione di interesse. Spesso, infatti,
428 Capitolo tredicesimo

per le interrogazioni che si effettuano su una base di dati, non occorre conoscere
tutto il contenuto delle tabelle, ma solo poche tuple.
Per tale motivo stato introdotto il linguaggio SQL con lobiettivo di semplificare
e velocizzare laccesso alle informazioni di interesse. Uninterrogazione alla base
di dati o query, espressa nel linguaggio SQL, permette di estrarre dalla base di dati
solo linsieme di record di interesse per le applicazioni o gli utenti che
interagiscono con il database.
Il risultato di uninterrogazione SQL quindi una tabella che comprende tutti dati
che soddisfano i requisiti definiti nellinterrogazione. In altri termini, SQL un
linguaggio dichiarativo. Questo significa che un comando SQL specifica il risultato
che si intende ottenere e non la sequenza di istruzioni necessaria per raggiungerlo.
A puro titolo di esempio e per completezza, una query SQL ha la forma:

select [Lista Attributi]


from [Lista Tabelle]
where [Condizione Logica]

- dopo la clausola select vanno specificati i campi di interesse di cui si


vogliono visualizzare i valori;
- dopo la clausola from vanno specificate le tabelle dove si trovano i valori
di interesse;
- dopo la clausola where va specificata la condizione logica che tutte le
tuple appartenenti al risultato dovranno soddisfare.
Se ad esempio si considera la tabella:
GIOCATORE(CodTessera, Nome, Cognome, Squadra)

ovvero una tabella avente per nomi di attributi CodTessera Nome, Cognome,
Squadra, se vogliamo determinare il nome ed il cognome di tutti i giocatori che
giocano nel Napoli, la query SQL che permette di estrarre le informazioni di
interesse :

select Nome, Cognome


from GIOCATORE
where Squadra=Napoli

SQL permette di definire una serie di operazioni anche estremamente complesse,


che sono particolarmente adatte al modello relazionale dei dati e che per sinteticit
omettiamo, rimandando a testi specializzati per una loro trattazione.
Appendice A

Vademecum dei principali termini usati in


informatica

In questa sezione vengono elencati i principali termini utilizzati nel


mondo dellinformatica di consumo, al fine di fornire una guida veloce e sintetica
delle componenti fondamentali dei calcolatori elettronici, con particolare
riferimento alla fascia dei Personal Computer. In particolare vengono mostrate,
senza alcuna pretesa di completezza:
a) una classificazione dei moderni calcolatori
b) la struttura interna del personal computer
c) una panoramica delle periferiche di ingresso uscita di uso pi
comune

14.1. Fasce di Computer


Personal Computer (PC): sono i normali
computer da casa e da ufficio, si usano per lo pi
come elaboratori di testo (word processor), per
reperire o gestire informazioni (Internet, basi di
dati), come strumenti da ufficio (amministrazione,
programmi gestionali), per la comunicazione (e-
mail), per la grafica o i giochi. Costituiscono oggi
la tipologia di computer pi diffusi.

Workstation: sono computer pi potenti spesso


presenti in laboratori di ricerca; possono essere
usati per il calcolo e la programmazione oppure
per funzionalit di grafica avanzata.

Mainframe: sono computer usati in grandi


aziende, e, in generale, ovunque ci sia bisogno di
gestire in maniera centralizzata complessi sistemi
di computer distribuiti.
430 Appendice A

Supercomputer: sono computer con elevate


prestazioni in termini di potenza elaborativa; si
usano in ambienti con necessit di calcolo
avanzato.

Se poi si concentra lattenzione all'ambito dei soli computer per uso personale,
esiste una tradizionale ulteriore classificazione in base alla forma e alle
dimensioni della macchina:

Home Computer: sono i normali PC da casa e ufficio, con


cassa orizzontale o verticale.

Notebook: sono i cosiddetti computer portatili, utili per chi


deve spostarsi spesso per lavoro avendo sempre il proprio
computer a portata di mano. Sono dotati di una batteria che
consente un'autonomia di alcune ore per lavorare anche
durante gli spostamenti.
Palmtop o Pocket PC: sono dei computer di capacit ridotta
nati dall'evoluzione delle agende elettroniche tascabili. Oltre
alle normali funzioni delle agende (appuntamenti, rubrica
telefonica, calcolatrice), i palmari sono in grado di svolgere
alcune funzioni base dei personal computer, come la
navigazione in Internet, la posta elettronica, l'elaborazione di
testi, ecc.

14.2. Componenti Interni di un Computer


Aprendo la cassa di un computer possibile scorgere quelli che sono i
componenti interni (collegati da una marea di cavi e fili) di un calcolatore. Essi
sono opportunamente alimentati da un apposita scatola dell'alimentazione
provvista di trasformatore elettrico e relativa ventola di raffreddamento (poste di
solite nella parte posteriore del calcolatore). Di seguito riportata una breve
descrizione delle principali componenti.

Scheda Madre (Motherboard): La scheda madre


rappresenta, insieme al processore, il componente
principale di un calcolatore. Essa pu essere vista come
una sorta di connettore fra tutti i componenti interni
di un computer, inoltre, grazie a circuiti particolari
(chipset, bios), una scheda madre in grado anche di
eseguire il controllo delle varie parti.
In alcuni computer le schede madri svolgono anche le
funzioni audio, video e rete (in gergo, audio, video e
Vademecum termini 431

rete sono integrati nella scheda madre). In altri invece


tali funzionalit sono delegate ad apposite schede di
espansione. Sulla scheda madre si trovano inoltre le
prese per la connessione dell'hard disk e ai lettori dei
dischi mobili (floppy e CD).
Microprocessore: spesso identificato con la CPU, il
nucleo del computer; si tratta, come gi visto, del
componente che esegue le istruzioni dei vari programmi
e sovrintende al funzionamento dellintera macchina.
il microprocessore che esegue tutte le elaborazioni,
gestisce il trasferimento di dati attraverso la memoria e i
dischi e attiva/disattiva i componenti della macchina. Il
ritmo di lavoro del microprocessore scandito da un
apposito segnale elettrico (detto clock) generato
internamente al computer e costituito da rapidissimi
impulsi che si ripetono centinaia di milioni di volte per
secondo. La velocit del clock (e quindi del
microprocessore) si misura oramai in GigaHertz (GHz,
miliardi di impulsi per secondo).
Memoria RAM (Random Access Memory): la
memoria, come gi visto, dove vengono conservati i dati
e le istruzioni dei programmi in esecuzione; si tratta di
una memoria veloce (ovvero i tempi di accesso per
loperazioni di lettura/scrittura sono bassissimi), ma
volatile, ovvero, che si cancella completamente quando
si spegne il computer. La capacit della RAM si misura in
MegaByte (Mbyte) o GigaByte (Gbyte), ovvero milioni o
miliardi di byte. Se la RAM non sufficiente capiente per
contenere tutti i dati necessari, il computer esegue delle
onerose operazioni di trasferimento temporaneo (swap)
di parte dei dati dalla memoria centrale a quella di massa,
al fine di liberare dello spazio per lelaborazione dei
nuovi dati. chiaro per che questa operazione tende a
rallentare tutte le altre operazioni. Per evitare tale
fenomeno sufficiente aggiungere pi RAM. La capacit
della RAM, quindi, insieme alla velocit del
microprocessore, sono i due parametri che pi
pesantemente influiscono sulle prestazioni della
macchina.
Hard Disk: la memoria permanente del computer, in
cui si conservano tutti i dati e i programmi. Viene usato
dunque come memoria di immagazzinamento dati (in
gergo memoria di massa). La sua capacit si misura in
GigaByte (Gbyte), ovvero in miliardi di byte.
Attualmente gli hard disk vengono realizzati secondo due
diverse tecnologie: EIDE (Enhanced Integerated Drive
Electronics) e SCSI (Small Computer Systems Interface);
432 Appendice A

i primi sono pi economici, i secondi sono pi veloci. La


velocit del disco in genere non influisce molto sulle
prestazioni della macchina, a meno che questa non venga
impiegata per funzioni che richiedono frequenti
operazioni di lettura/scrittura di dati (questo accade ad
esempio per macchine che gestiscono alcuni servizi di
rete centralizzati, come la posta elettronica o per i
cosiddetti database server).
Drive: sono gli sportelli in cui si inseriscono il floppy
disk, o il CD, o qualsiasi altro tipo di disco. Contengono
una testina di lettura/scrittura tramite cui avviene il
trasferimento dei dati fra disco e macchina. Il drive per il
floppy ormai un componente standard che non presenta
varianti significative, invece i drive per CD esistono in
vari modelli che si differenziano soprattutto per la
velocit di lettura.
Schede di Espansione: si tratta di schede che
espandono le funzionalit della scheda madre per
pilotare dispositivi interni od esterni. La pi importante
la scheda video su cui si connette il monitor. Dalla
scheda video dipendono il numero di colori del monitor,
la risoluzione massima, la velocit grafica (di giochi,
filmati, ecc.) e tutto ci che riguarda in generale le
prestazioni grafiche. Molto diffusa anche la scheda
audio, attraverso cui il computer in grado di produrre
o registrare suoni. Per le connessioni dirette alla rete
(senza modem) occorre invece dotarsi di una scheda di
rete. Infine la scheda SCSI (letto scasi) consente di
pilotare dispositivi che richiedono una particolare
velocit nel trasferimento dei dati. Esistono poi
numerosi altri tipi di schede, create per funzioni
particolari, quali ad es. la scheda di acquisizione video
per collegarsi alla televisione, ad un videoregistratore o
ad una videocamera, e molte altre ancora di uso
specialistico.
BIOS (Basic Input/Output System): un componente
che fa parte integrante della scheda madre. Il suo scopo
quello di gestire la fase di accensione del computer. Il
BIOS conserva in una ROM la sequenza di istruzioni di
avvio che viene eseguita automaticamente ad ogni
accensione del computer. L'operazione di avvio detta
boot, e passa per 3 fasi successive: test di
funzionamento del sistema; attivazione dell'hardware
installato; verifica della presenza del sistema operativo e
suo caricamento. In una piccola memoria RAM
(alimentata da una batteria interna) sono conservate le
informazioni relative all'hardware installato.
Vademecum termini 433

ROM (Read Only Memory):


Contrariamente alla RAM, la memoria ROM non esiste
in forma di componente separato e individuale, esistono
invece numerose piccole ROM incorporate all'interno dei
vari circuiti integrati (sulla scheda madre, sulle schede
d'espansione, ecc.) come nel BIOS.

14.3. I dispositivi di input e output


Tutti i dispositivi che mettono in comunicazione il computer con il mondo
esterno sono detti genericamente periferiche oppure dispositivi periferici di
Input/Output (o di I/O, o di Ingresso/Uscita). Alcuni dispositivi sono solo di
ingresso perch inviano dati al computer ma non ne ricevono mai (ad esempio il
mouse e la tastiera), altri sono solo di uscita perch ricevono dati dal computer
senza inviarne mai (come il monitor, la stampante e le casse audio), altri sono
contemporaneamente di ingresso e di uscita (come i dischi). I dispositivi pi
comuni sono: tastiera, mouse, monitor, lettore CD-Rom, floppy, stampante, casse,
modem, masterizzatore. Alcuni dei dispositivi di I/O, possono essere collegati
direttamente al calcolatore attraverso apposite prese dette porte di ingresso/uscita
(I/O). Le porte di I/O sono una serie di prese, localizzate sul lato posteriore del
computer, che vengono utilizzate per collegare alla macchina tutti dispositivi
esterni (monitor, tastiera, mouse, ecc.).
Tipicamente sono poste direttamente sulla scheda madre le seguenti porte:

porte PS/2 per il collegamento del mouse e della tastiera;

porta seriale per il modem, o in generale per i vari dispositivi che


non richiedono flussi di dati molto veloci

porta parallela per la stampante, ma in generale adatta per


qualunque dispositivo che richieda un flusso di dati pi veloce
rispetto alla capacit della porta seriale;

porta USB (Universal Serial Bus), di recente introduzione, adatta


per connettere al computer qualunque tipo di dispositivo compatibile
(mouse, tastiera, pen-drive, etc).

Di contro, altri dispositivi per poter essere collegati alla macchina, richiedono la
presenza di una scheda despansione inserita allinterno del computer. Ad
esempio il monitor richiede solitamente la presenza di una scheda video, le casse
richiedono una scheda audio, ecc.
Le schede di espansione che vengono montate sulla scheda madre rendono quindi
disponibili molte altre porte, fra cui le principali sono:
- porta video (talvolta integrata direttamente sulla scheda madre,
soprattutto nei modelli di marca) per connettere il monitor al computer;
434 Appendice A

- porta di rete per collegare la macchina direttamente ad una rete di


computer, senza usare il modem. Ne esistono di vari tipi, ma ormai la
presa RJ45 ha di fatto rimpiazzato tutte le altre;
- porta SCSI per dispositivi che richiedono un flusso di dati molto veloce
(scanner, masterizzatore esterno, ecc.).
Di seguito si riporta una rapida carrellata dei principali dispositivi di input output
di un calcolatore.

Tastiera: collegata al calcolatore attraverso una porta


PS/2 appositamente dedicata o USB, permette
limmissione dei vari caratteri attraverso digitazione .
I simboli riconosciuti dal computer ma non presenti
sulla tastiera, possono essere comunque inseriti
tenendo premuto Alt e digitando il corrispondente
codice ASCII col tastierino numerico
Mouse: Il mouse fu introdotto assieme ai sistemi
operativi di tipo grafico (Macintosh, Windows, ecc.)
per semplificare l'invio dei comandi verso il
computer, comandi che in precedenza venivano
impartiti unicamente attraverso la tastiera. Lo
spostamento del mouse controlla il movimento di un
puntatore sullo schermo, mentre i tasti inviano il
comando. Il mouse, come la tastiera, si collega al PC
o attraverso una porta PS/2 appositamente dedicata o
mediante USB.
Monitor: il monitor la principale interfaccia di
comunicazione fra lutente e lattivit del computer. I
monitor pi diffusi sono quelli a tubo catodico, che
funzionano sullo stesso principio dei televisori.
Esistono poi i monitor piatti a cristalli liquidi (LCD),
a maggiore costo, che producono un'immagine molto
pi nitida e non emettono nessuna radiazione.
Alcuni modelli comprendono al loro interno anche le
casse audio ed il microfono. Esistono infine modelli
di monitor sensibili al tocco di una speciale penna
luminosa, in modo da poter essere usati anche come
una tavoletta grafica, altri sono invece sensibili al
semplice tocco delle dita (si trovano soprattutto in
luoghi pubblici, dove il mouse o la penna luminosa
avrebbero vita breve). Il monitor si collega al PC
attraverso la porta che si trova sulla scheda video.
Stampanti: attualmente si dividono in due principali
categorie:
- laser, usano una tecnologia simile a quella delle
fotocopiatrici, sono adatte per grossi volumi di
lavoro perch riescono a stampare molto
velocemente e silenziosamente, offrendo inoltre
Vademecum termini 435

la migliore qualit di stampa;


- a getto dinchiostro, producono stampe di
qualit leggermente inferiore rispetto alle
stampanti laser, sono generalmente pi lente, ma
anche pi economiche e di dimensioni pi
contenute. La stampa avviene spruzzando sulla
carta un sottilissimo getto dinchiostro liquido.
Esistono poi stampanti per usi professionali o
tipografici, come le stampanti a sublimazione e
thermal-wax per riproduzioni di altissima qualit. Una
particolare categoria di stampanti sono i plotter che
usano dei pennini ad inchiostro per disegnare su fogli
di grande formato. Servono per il disegno tecnico e
sono usati perci negli studi professionali e nei centri
di progettazione tecnica. Le stampanti si collegano al
PC attraverso la porta parallela o USB.
Casse: La scelta delle casse deve avvenire in funzione
della scheda audio: se la scheda audio comprende
solo le funzioni di base si useranno casse standard, se
invece capace di riproduzioni audio di alta qualit,
effetti audio particolari come il Dolby surround, ecc.,
si potranno usare casse di qualit superiore e impianti
audio sofisticati.
Masterizzatori: Sono i dispositivi usati per la
scrittura su CD. Funzionano anche come normali
lettori di CD. Come gli hard disk (e altri dispositivi).
Esistono masterizzatori EIDE (pi economici) e
masterizzatori SCSI (pi veloci).
Scanner: si tratta di dispositivi che consentono di
acquisire testo e immagini stampate su carta per
trasferirle allinterno del computer. I modelli pi
versatili consentono anche lacquisizione direttamente
da diapositiva o da negativo fotografico. Gli scanner
migliori usano la tecnologia SCSI per collegarsi al
computer.
Modem: si usa per la trasmissione e ricezione di dati
attraverso la linea telefonica ed in particolare per la
connessione ad Internet. I modem possono essere
esterni al computer (collegati con un cavo) oppure
interni (in forma di scheda di espansione), ma in
questo ultimo caso presentano spesso problemi di
incompatibilit col resto dell'hardware. La velocit
con cui i modem sono in grado di scambiare i dati si
misura in Kbit/secondo (Kbps) ovvero il numero di
bit che il modem riesce a trasferire in un secondo.
Esistono tre tipi principali di modem, a seconda del
tipo di linea telefonica disponibile:
436 Appendice A

- Standard, per la normale linea telefonica a


56Kbps. Quando il modem collegato la linea
occupata e non possibile usare il telefono (di
fatto, il collegamento alla rete tramite modem
costituisce a tutti gli effetti una normale
telefonata);
- ISDN, raggiungono i 128 Kbps, ma necessitano
della linea ISDN, la quale consente anche l'uso del
telefono mentre il modem collegato sacrificando
per met della velocit (64 Kbps); altrimenti si
pu scegliere di dedicare l'intera linea al modem;
- ADSL, raggiungono i 640 Kbps, ma necessitano
della linea ADSL (una tecnica di trasmissione su
linea telefonica particolare). L'ADSL costituisce
un collegamento permanente 24 ore su 24 con la
rete e non interferisce in nessun modo col
telefono.
Videocamere: utile per catturare immagini fisse o
in movimento ed collegata al calcolatore tramite la
scheda video. Si va da videocamere professionali per
riprese di alta qualit, a piccole videocamere dette
webcam usate per trasmettere riprese video attraverso
la rete.
Appendice B

Esercizi di programmazione

15.1. Premessa
Il capitolo elenca un insieme di esercizi da progettare utilizzando uno dei linguaggi
di programmazione presentati nel libro. Nel testo degli esercizi sono state indicate
solo le principali funzionalit di elaborazione, lasciando al programmatore la
libert di decidere sulle modalit di inserimento dei dati di prova e di presentazione
dei risultati prodotti. Tutti gli esercizi proposti iniziano con frasi del tipo
assegnati o data una struttura che sottintendono che per i dati indicati devono
essere previste funzionalit specifiche di assegnazione dei valori iniziali; daltro
canto, non si fa sempre riferimento al fatto che i dati prodotti devono essere
presentati in uscita in quanto si presuppone che per poter controllare la correttezza
dellalgoritmo tale operazione sia fondamentale.
Tutti gli esercizi devono quindi essere progettati prevedendo una struttura del
programma finale del tipo:
inserimento dati di prova
algoritmo
stampa dei risultati

Il lettore libero di prevedere che linserimento del valore dei dati avvenga da
tastiera o da un file in precedenza generato. Tale seconda ipotesi da preferire nei
casi in cui il programma in fase di testing o debugging e i dati da inserire sono
tanti (si pensi ad una matrice). Laver inserito i dati in un file ha significativi
vantaggi, che possiamo elencare nel seguito:
i dati non devono essere reinseriti ad ogni prova del programma ma solo
in fase di generazione del file che avviene al di fuori di esso;
i dati possono essere controllati prima del loro uso evitando una delle
pi frequenti cause di errore del programma: una loro errata
interpretazione nella fase di inserimento;
gli stessi dati possono essere usati per provare programmi diversi;
la generazione del file, infine pu essere fatta con un qualsiasi editor di
testo nel caso i dati vengano prelevati da un text file.
Nel progettare un qualsiasi esercizio, lo studente deve fare riferimento ai principi
della programmazione strutturata che hanno permeato i capitoli precedenti. In
438 Appendice B

particolare, lalgoritmo deve essere disegnato pensando a condizioni di tipo


generale nelle quali gli esempi di INPUT/OUTPUT presentati sono solo casi
particolari. Inoltre si devono cercare soluzioni parametriche che facilitino la
manutenzione dei programmi utilizzando quanto pi possibile, definizioni di
costanti che diano ad esse un nome e ponendo tali dichiarazioni tra le prime righe
del testo sorgente. I programmi vanno poi progettati privilegiando leggibilit e
correttezza: la leggibilit di fondamentale importanza per il riuso delle soluzioni
in lavori di gruppo.
A tal fine si ribadiscono i seguenti principi generali:
gli identificatori devono avere nomi che facciano capire luso che se ne vuol
fare;
la nidificazione delle strutture di controllo deve far ricorso alla indentazione
per rendere pi chiara la struttura dellintero programma;
i commenti devono essere non solo presenti ma soprattutto chiari; inoltre
devono essere articolati in motivazioni ed asserzioni;
la modularit deve ispirare lintero progetto per cui funzionalit importanti
devono essere organizzate in procedure o funzioni.
Anche se gli esercizi sono di piccole dimensioni, si deve approntare una
documentazione dellalgoritmo dalla quale si comprendano almeno quali sono le
variabili di input, quali sono invece quelle di output e quali sono quelle necessarie
al calcolo, ed infine come il procedimento si sviluppa descrivendolo ad un
adeguato livello di astrazione.
E altres importante notare che la classificazione degli esercizi stata fatta per
indicare quale la struttura dati su cui principalmente esercitarsi.

15.2. Esercizi sulle variabili non strutturate


1) Sia assegnato un numero intero in base dieci, effettuare la conversione in una
qualsiasi altra base.
INPUT
Numero = 14
Base = 2
OUTPUT
1110
2) Dati tre numeri, verificare quale di essi ha il valore pi grande.
INPUT
3 24 8
OUTPUT
24
3) Dato un numero intero verificare se primo
INPUT
24
OUTPUT
No
Esercizi 439

4) Dati tre numeri verificare se uno di essi il prodotto degli altri due.
INPUT
3 24 8
OUTPUT
si
5) Date tre lettere verificare se sono tutte diverse.
INPUT
abc
OUTPUT
No
6) Dati tre numeri verificare se possono essere le misure dei lati di un triangolo e,
in caso affermativo, dire anche di quale tipo (scaleno, isoscele, equilatero,
rettangolo)
INPUT
345
OUTPUT
scaleno
rettangolo

15.3. Esercizi sui vettori


7) Dato un vettore determinare se i valori dei suoi elementi sono tutti uguali
INPUT
[3 24 8]
OUTPUT
no
8) Dato un vettore determinare se i valori dei suoi elementi sono ordinati
INPUT
[24 8 4 1]
OUTPUT
si
9) Dato un vettore V ordinato ed un elemento a, effettuare linserimento di a nel
vettore rispettando lordinamento
INPUT
[3 24 88]
55
OUTPUT
[3 24 55 88]
10) Dati due vettori V1 e V2 ordinati nello stesso modo, generare per fusione dei
primi un terzo vettore V3 due che abbia lo stesso ordinamento

INPUT
V1 = [1 3 5 7]
V2 = [2 3 4 6]
440 Appendice B

OUTPUT
V3 = [1 2 3 3 4 5 6 7]
11) Dati i valori del riempimento N e degli elementi di un vettore V di numeri reali
determinare:
la somma degli elementi del vettore.
la media degli elementi del vettore.
il minimo degli elementi del vettore.
il massimo degli elementi del vettore.
12) Dato un vettore di numeri reali ordinato e due suoi elementi a e b, tali che a<=b,
memorizzare in un vettore di uscita tutti gli elementi del vettore di ingresso
compresi tra a e b.
INPUT
[1,3,6,8,70]
a=2
b=8
OUTPUT
[3,6]
13) Dato un vettore di numeri effettuare lo shift (spostamento) a destra con
linserimento di uno zero in testa degli elementi del vettore di ingresso (con
perdita dellelemento di coda)
INPUT
[1,2,3,4]
OUTPUT
[0,1,2,3]
14) Dato un vettore di numeri effettuare lo shift (spostamento) a sinistra con
linserimento di uno zero in coda degli elementi del vettore di ingresso (con
perdita dellelemento di testa)
INPUT
[1,2,3,4]
OUTPUT
[2,3,4,0]
15) Dato un vettore di numeri effettuare lo shift (spostamento) circolare a destra
degli elementi del vettore di ingresso (in questo caso lelemento di coda va in
testa).
INPUT
[1,2,3,4]
OUTPUT
[4,1,2,3]
16) Dato un vettore di numeri interi memorizzare in primo vettore di uscita solo i
numeri pari e in un secondo vettore di uscita solo i numeri dispari.
INPUT
v_in=[1 2 33 11 8]
Esercizi 441

OUTPUT
pari=[2 8]
dispari=[1 33 11]
17) Siano assegnati i due vettori (V1 e V2) di numeri interi. Verificare se allinterno
di uno dei due vettori (VY) esiste una successione di valori in posizioni
consecutive tali che ogni suo elemento sia compreso tra due elementi successivi
di una successione di elementi dellaltro vettore (VX):
VX[i]<VY[j]<VX[i+1] e VX[i+1]<VY[j+1]<VX[i+2]
Si noti che, perch la relazione sussista, la successione di elementi VY deve
avere almeno due elementi e la successione di elementi VX deve contenere il
doppio degli elementi di VY. In caso la verifica sia positiva, generare e
stampare il vettore che si ottiene fondendo le due successioni nel rispetto della
relazione trovata:
., VX[i], VY[j], VX[i+1], VY[j+1], VX[i+2], .
18) Siano assegnati due vettori di numeri interi con ugual riempimento. Verificare
che per ogni coppia V1i e V2j (con V1i appartenente al primo vettore e V2j al
secondo) esista una delle due condizioni:
una sequenza delle ultime cifre (almeno due) di V1i coincida con una
sequenza di cifre iniziali di V2j come si pu riscontrare nelle seguenti coppie
(2321, 21456), (6357,6357), (12908,2908);
una sequenza delle ultime cifre (almeno due) di V2i coincida con una
sequenza di cifre iniziali di V1j.
Per ciascuna delle coppie che soddisfa una delle due condizioni riportare la
sequenza di cifre in comune, il tipo di condizione e la posizione i e j allinterno
dei vettori V1 e V2.
19) Siano assegnati tre vettori (V1, V2 e V3) di numeri interi. Verificare la presenza
nel vettore V3 di tutti e soli gli elementi diversi sia del primo che del secondo
con la condizione che le posizioni dispari di V3 siano occupate dagli elementi
diversi di V1 o V2 e quelle pari dagli elementi diversi del restante vettore. Nel
caso sussistano tutte le condizioni richieste stampare il messaggio 1 pari e 2
dispari per indicare la presenza degli elementi diversi del primo vettore nelle
posizioni pari del terzo e la presenza degli elementi diversi del secondo vettore
nelle posizioni dispari; il messaggio 1 dispari e 2 pari in caso contrario, o
infine non sussiste la condizione nel caso non si verifichi quanto richiesto.
INPUT
V1: 5 4 8 5 9 3 4 9
V2: 0 8 3 4 0 7 7 9 8 0 3 7 8 4 4
V3: 0 3 3 9 7 8 4 4 9 5 8
OUTPUT
1 pari e 2 dispari
20) Dato un vettore di interi estrarre e stampare, ad ogni passo di un ciclo, lelenco
dei valori diversi contenuti in esso. Al primo passo il vettore assegnato in
ingresso; ad ogni passo successivo il vettore da considerare quello ottenuto nel
passo precedente mediante leliminazione dei valori diversi. Lalgoritmo
termina quando il vettore da elaborare vuoto.
442 Appendice B

INPUT
1 12 3 12 3 655 6 4 655 6 12

OUTPUT
passo Vettore da elaborare Vettore estratto
1 1,12,3,12,3,655,6,4,655,6,12 1,12,3,4,655,6
2 12,3,655,6,12 12,3,655,6
3 12

15.4. Esercizi sulle matrici


21) Data una matrice quadrata determinarne il valore pi grande e la sua posizione
di riga e di colonna.
INPUT
1 6 1 7
6 4 5 2
2 7 10 1
OUTPUT
3 3 10
22) Data una matrice A di numeri interi, memorizzare in un vettore di uscita il
massimo di ogni riga
INPUT
1 6 1 7
6 4 5 2
2 7 10 1
OUTPUT
7 6 10
23) Data una matrice A di numeri interi:
1. segnalare errore nel caso di matrice non quadrata
2. memorizzare in un vettore di uscita gli elementi positivi (maggiori di
0) della diagonale, solo nel caso in cui la matrice sia quadrata
3. calcolare la media del vettore determinato al punto precedente.
INPUT
1 2 1 8
4 1 2 6
9 8 0 1
15 2 4 5
Esercizi 443

OUTPUT
v _ out 1 5
media 3
24) Data una matrice A di numeri interi positivi, memorizzare in un vettore di uscita
la media di ogni colonna
INPUT
1 6 15 1
3 4 5 2
5 2 1 3
OUTPUT
3 4 7 2
25) Data una matrice A di numeri interi positivi e due indici r1 e r2, memorizzare in
una matrice di uscita la matrice di ingresso con le righe di indici r1 e r2
scambiate.

INPUT
1 6 15 1
3 4 5 2
5 2 1 3

r1 1
r2 2

OUTPUT
3 4 5 2
1 6 15 1
5 2 1 3
26) Gestire una matrice quadrata di ordine N per:
determinare e memorizzare i massimi di ciascuna riga;
determinare e memorizzare i minimi di ciascuna colonna;
calcolare la differenza tra i massimi e minimi relativi alle stesse posizioni;
stampare una tabella riportante massimi, minimi e loro differenze.
27) Data una matrice quadrata di ordine N, determinare se al suo interno ci sono
colonne i cui elementi coincidono in valore e posizione con quelli della
diagonale principale.
28) Estrarre da una matrice di NxM elementi di tipo intero le posizioni di riga e di
colonna dei valori negativi.
444 Appendice B

29) Contare tra gli elementi della diagonale principale di una matrice rettangolare
tutti i valori uguali ad un valore preassegnato.
30) Data una matrice di numeri reali:
calcolare la trasposta della matrice.
compattare la matrice nel caso vi siano righe uguali (ovvero se la matrice ha
due righe uguali ne viene eliminata una).
INPUT
123
456
456
OUTPUT
123
456
31) Data una matrice di numeri memorizzare:
in un primo vettore di uscita, una dietro laltra, le righe pari.
in un secondo vettore di uscita, una dietro laltra, le righe dispari.
INPUT
123
456
789
OUTPUT
v1=[4 5 6]
v2=[1 2 3 7 8 9]
32) Sia assegnato un vettore V di RIEMP numeri interi. Generare una matrice con
tre colonne e tante righe quante sono le terne di elementi in posizioni
consecutive di V che godono della propriet che l'elemento centrale risulta
essere contemporaneamente maggiore degli elementi nelle posizioni precedente
e seguente (V[i-1]<V[i]<V[i+1]), e infine verificare se nelle sue colonne esiste
una delle seguenti relazioni:
a) gli elementi sono tutti uguali;
b) gli elementi rispecchiano l'ordinamento crescente;
c) gli elementi rispecchiano l'ordinamento decrescente.
Nel caso in cui una delle relazioni esista, stampare un messaggio riportante il
tipo di relazione individuata e la posizione di colonna dove essa stata
individuata.

INPUT
10 20 15 30 15 21 30 40 15 17 18 19 50 15 16

OUTPUT
20 15 30
30 15 21
40 15 17
50 15 16
La colonna 1 gode della propriet b)
Esercizi 445

La colonna 2 gode della proprirt a)


La colonna 3 gode della propriet c)
33) Sia assegnata una matrice quadrata di N elementi di tipo intero. Supposto:
che gli elementi della prima riga seguiti nellordine da quelli dellultima
colonna, da quelli dellultima riga (a partire dallultima colonna fino alla
prima) e infine da quelli della prima colonna (anche qui a partire dallultima
riga per finire con la prima) formino un anello di elementi pi esterno della
matrice;
che allinterno di tale anello ne esistano altri che si riducono di una
dimensione fino a degenerare nellelemento centrale (quando esiste per N
dispari);
e che ciascuno degli N/2 anelli sia individuato a partire dalle posizioni degli
elementi della diagonale principale comprese proprie nellintervallo 1..(N/2)
(con la posizione 1 indicante lanello pi esterno);
effettuare la rotazione antioraria degli elementi dellanello i-esimo e quella
oraria dellanello j-esimo con i e j assegnati da tastiera.

INPUT
6
10 11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27
28 29 30 31 32 33
34 35 36 37 38 39
40 41 42 43 44 45
1 3

OUTPUT
11 12 13 14 15 21
10 17 18 19 20 27
16 23 30 24 26 33
22 29 31 25 32 39
28 35 36 37 38 45
34 40 41 42 43 44

34) Si diano per una matrice di ordine n le seguenti definizioni:


1. lelemento di posto (1,1) sia detto vertice superiore sinistro VSS;
2. lelemento di posto (1,n) sia detto vertice superiore destro VSD;
3. lelemento di posto (n,1) sia detto vertice inferiore sinistro VIS;
4. lelemento di posto (n,n) sia detto vertice inferiore sinistro VID;
5. il minore di ordine m, con m<n e con VSS uguale, sia detto minore superiore
sinistro MSS;
6. il minore di ordine m, con m<n e con VSD uguale, sia detto minore
superiore destro MSD;
7. il minore di ordine m, con m<n e con VIS uguale, sia detto minore inferiore
446 Appendice B

sinistro MIS;
8. il minore di ordine m, con m<n e con VID uguale, sia detto minore inferiore
destro MID.
Allora, assegnate due matrici di ordini rispettivamente N1 e N2, e fissato
lordine M, con M<N1 e M<N2, individuare lesistenza dei minori su indicati
che abbiano valori uguali. Eventualmente si generalizzi estraendo tali minori per
un qualsiasi valore di M compreso nellintervallo ]1,N[ con n valore minimo tra
N1 e N2.

INPUT
N1 e MAT1 N2 e MAT2
8 6
54326426 543264
13299768 132946
88745531 887321
43587534 989546
56789554 111167
54656832 712089
16784561
08967418
M=3

OUTPUT
MSS di MAT1 uguale a MSS di MAT2
MIS di MAT1 uguale a MID di MAT2
35) Sia assegnata una matrice di interi con valori 0 o 1. La matrice riporta
limmagine del campo di gioco di una battaglia navale in cui le configurazioni
dei due seguenti minori di ordine tre:
111 111
111 101
111 111
indicano rispettivamente le navi da colpire e le trappole mortali del nemico da
evitare. Dopo aver fissato la matrice riportante il piano di gioco, indicare per
ogni mossa consistente nella indicazione di una posizione di riga e di colonna
se:
stata affondata una nave mediante lindividuazione del suo centro;
stata semplicemente colpita una nave;
si caduti in una trappola cadendo in uno qualsiasi dei suoi punti.
Terminare con la condizione di vittoria quando tutte le navi sono state affondate
o con quella di sconfitta quando si cade in una trappola.
36) Sia data una matrice di caratteri di R righe e C colonne.
Verificare se su righe consecutive vi sono sequenze di vocali uguali a partire
dalla stessa colonna e indicare quante volte la sequenza si presentata in quella
posizione, la riga in cui si presentata la prima volta e la colonna da cui
iniziata la sequenza.
Esercizi 447

input
1 2 3 a e i 2
2 a 3 a e i 3
a o u x y t 3
a o u f h 6 8
a o u h 7 8 9
output
la sequenza aei si presentata 2 volte a partire d riga 1, col. 4
la sequenza aou si presentata 3 volte a partire dalla riga 3, colonna 1
37) Sia assegnata una matrice quadrata contenente NxM numeri interi. Individuare
allinterno della matrice assegnata la presenza di elementi che:
a) per x posizioni successive di una stessa riga devono soddisfare la relazione
dordine
Mat[i,j] < Mat[i, j+1]
b) e che confermino la stessa propriet a) per un totale di y righe successive
alla riga i a partire sempre dalla stessa posizione di colonna, ma x+1 volte
per la riga i+1, x+2 volte per la riga i+2, e infine x+y-1 volte per lultima
riga.
Qualora risulti x>1 e y>1, bisogner stampare dapprima gli elementi costituenti
il trapezio rettangolo cos individuato e successivamente verificare se la stessa
propriet a) vale per ciascuna delle colonne del trapezio.

INPUT
8
99 10 20 30 40 11 23 44
66 11 22 33 44 55 33 22
12 20 30 40 50 66 70 22
23 12 11 34 22 11 44 11
66 88 22 98 33 21 44 22
23 54 76 98 32 11 88 99
12 13 42 63 76 83 88 31
11 76 44 35 87 65 78 10

OUTPUT
10 20 30 40
11 22 33 44 55
20 30 40 50 66 70

viene anche soddisfatta la condizione sulle colonne

15.5. Esercizi sui record


38) Data una matrice sparsa generare un elenco che riporti le posizioni di riga e di
colonna ed il valore degli elementi non nulli.
(si definisce matrice sparsa una matrice in cui gli elementi non nulli sono pochi)
448 Appendice B

INPUT
0 6 0 1
0 4 0 0
0 0 0 3

OUTPUT
Riga Colonna Valore
1 2 6
1 4 1
2 2 4
3 4 3
39) Data una rubrica telefonica effettuare:
linserimento di un nuovo anagrafico;
la modifica di uno preesistente
la eliminazione di uno preesistente
la ricerca di un numero telefonico
la visualizzazione della rubrica
40) Sia assegnata una matrice di NxM numeri interi con M>>N. Dopo aver
individuato nella matrice le diagonali dei minori di ordine N x N, con N
elementi tutti di valore uguale, stampi lelenco delle posizioni di colonna e dei
valori del primo elemento di siffatte diagonali riportando, nel caso alcune di
esse si riproponessero con gli stessi valori in posizioni consecutive, il numero
delle rispettive ripetizioni.
INPUT
3
20
23465812333443322234
12345681433344331223
91234878163334433222
OUTPUT
Colonna Valore Ripetizioni
1 2 1
2 3 1
3 4 1
6 8 1
7 1 1
9 3 3
12 4 2
14 3 2
17 2 2
41) Siano assegnati i valori di due numeri interi N1 e N2 con Cn1 cifre il primo
numero e Cn2 il secondo. Operando il prodotto di N1 per N2, generare una
matrice di Cn2+1 righe contenenti nelle prime Cn2 righe i risultati,
Esercizi 449

opportunamente incolonnati, dei prodotti delle Cn2 cifre per le Cn1 cifre, e nella
ultima riga le cifre del risultato del prodotto N1xN2. Comunque si produca la
matrice, se ne effettui la stampa in modo che risulti chiaro il procedimento
necessario per calcolare N1 per N2. Si raccomanda, per una corretta
impostazione del progetto, di introdurre almeno le due procedure seguenti:
1) procedura conversione_base per la determinazione delle cifre componenti
un valore intero;
2) procedura tabellina per il calcolo del prodotto di una cifra per unaltra
con determinazione del risultato come coppia di cifre (lunit e la decina).
INPUT
1369
256
OUTPUT
1369x
256=
----------
8214
6845
2738
----------
350464

42) Scrivere un programma per la gestione delle merci contenute in un magazzino.


Per ogni merce si vogliono gestire le informazioni relative a l'identificativo, il
nome, la descrizione e la quantit residua nel magazzino. In particolare si
realizzino delle funzioni per: a) l'inserimento da tastiera di una nuova merce, b)
la stampa a video del contenuto del magazzino, c) la gestione degli ordini che
consistono prima nella ricerca della merce nel magazzino e poi nel decremento
della quantit residua.
43) Scrivere un programma per la gestione di cartelle cliniche. Per ogni cartella
clinica si vogliono gestire le informazioni relative al codice, il nome e il
cognome del paziente, e, la descrizione dell suo stato clinico. In particolare si
realizzano delle funzioni per: a) l'inserimento da tastiera di una nuova cartella,
b) la stampa a video di una cartella di un dato paziente, c) la gestione dei
ricoveri che consistono nell'aggiornamento della descrizione di una cartella
clinica di un dato paziente. (Utilizzare un unica funzione che ricerca un paziente
in base al suo codice)

15.6. Esercizi sulle stringhe


44) Data una stringa:
memorizzare in una stringa di uscita la stringa dingresso invertita
determinare, fissato lalfabeto delle lettere (a,b,c,d,e,f,v,w,z), quali e quante
sono le lettere effettivamente presenti nella strina (si consiglia di creare per il
450 Appendice B

confronto un vettore alfabeto)


INPUT
hello

OUTPUT
olleh
a 0, b 0,,e 1, , h 1,, l 2, , o 1,, z 0
45) Date due stringhe:
segnalare se le due stringhe sono uguali o meno
e nel caso non siano uguali determinare il numero di caratteri e i caratteri per
cui differiscono
INPUT
ciao
cimaro
OUTPUT
NON SONO UGUALI
diff=2
mr
46) Sia assegnato un testo. Individuare la seguente relazione tra due parole
consecutive del testo: tra le due parole deve esistere una sequenza di lettere che
sia la terminazione della prima parola e linizio della seconda. Stampare quindi
lelenco delle parole che godono della propriet indicata verificando anche
leventuale presenza della relazione sia con la parola che precede che con quella
che segue.

INPUT
un altro trovatello camminava
in casa sapendo dove andare
reperendo i quaderni

OUTPUT
altro trovatello
casa sapendo
sapendo dove
andare reperendo
47) Sia assegnato un testo organizzato in righi separati. Individuare e tabellare le
sottosequenze composte da almeno due caratteri disposti in ordine strettamente
crescente. In particolare si stampino le sottosequenze accompagnate dalla loro
occorrenza nel testo.

INPUT
ZZZABCDXCCCCCCGPOGDB
XXXXXXABCDXAKPRSTSSSSAAAAA
ZSTKJIXYZCGPO
IXYZABPRSTSSSSAAAABCDX
Esercizi 451

OUTPUT
ABCDX 3
CGPO 2
AKPRSTS 1
IXYZ 2
48) Sia data una sequenza di stringhe. Definita come parola una sequenza di
caratteri separati da un o pi spazi bianchi, per ogni stringa individuare le
parole che si ripetono pi volte allinterno di essa. Nellipotesi che il numero di
parole individuate sia minore di 100, stampare lelenco delle parole individuate
e la parola pi frequente.
INPUT
andrea giacomo giovanni andrea
marina bambi carletta bambi bambi maria
giacomina
OUTPUT
andrea
bambi
La parola bambi la piu frequente essendo comparsa 3 volte.
49) Sia assegnata una sequenza di cifre decimali. verificare la presenza di
sottosequenze di lunghezza data L che a partire dalla posizione L+1 abbiano le
cifre disposte in modo da risultare lanagramma delle prime L cifre. Si
escludano dalla verifica le sottosequenze che risultano essere identiche alla
sottosequenza costituita dalle prime L cifre. Per ogni sottosequenza individuata
se ne riporti la stampa con la posizione della prima cifra ed eventualmente un
computo delle occorrenze di quelle tra loro uguali.
INPUT
12345895432123451239876001254321345
L=5
OUTPUT
Sottosequenza Posizione
54321 8
23451 13
34512 14
45123 15
12543 26
54321 28
21345 31
(opzionale)
Sottosequenza Occorrenza
54321 2
23451 1
34512 1
45123 1
12543 1
21345 1
452 Appendice B

50) Siano assegnati tre vettori V1, V2 e V3 contenenti parole. Individuare le parole
di V1 che hanno:
1. tutte le vocali uguali a quelle di una parola di V2,
2. e le consonanti uguali a quelle di una parola di V3.
Nel caso esistano le condizioni precedenti, stampare la terna di parole
riportando per ciascuna di esse la posizione assunta nel vettore di appartenenza.
INPUT
V1 V2 V3
porta casa talete
solitario arto parata
latte esiste fase
parere pena peso
aglio pallino esempio
paese matematica lago
pizza pasta
saluto
OUTPUT
porta 1 arto 2 parata 2
latte 3 pena 4 talete 1
aglio 5 pallino 5 lago 6
51) Sia assegnato un testo nel quale sia stata cifrata una sequenza di numeri interi.
Estrarre i numeri al massimo di cinque cifre nascosti nel testo tenendo conto che
ogni frase del testo ne contiene uno e che le cifre di ciascuno di essi sono date
dal conteggio delle vocali presenti allinterno della frase (conteggio supposto
minore di 10 per ogni vocale) e considerate secondo lordine stabilito dalla
successione delle posizioni da esse occupate. In particolare, se la prima vocale
che compare nella frase la i, il numero di tutte le i fornisce la prima cifra del
numero, se la seconda vocale diversa la u, il numero complessivo di u
determiner la seconda cifra del numero e cos via.

Esempio:
Questa prova sembra ueaoaea 1231
essere davvero eeeaeo 411
semplice eie 21
52) Sia assegnata una matrice di parole. Eliminare le righe e le colonne che
contengono almeno una coppia di parole per le quali si dimostri che:
1. sono diverse;
2. luna lanagramma dellaltra;
3. la pi corta lanagramma di una parte della pi lunga e non una sua
sottosctringa.

Si tenga presente che una stessa parola pu essere nelle relazioni specificate con
altre parole sia della stessa riga che della stessa colonna. Infine prima di
procedere alla eliminazione delle righe e delle colonne, stampare per ciascuna
riga e colonna lelenco delle parole in relazione tra loro.
Esercizi 453

INPUT
6
5
casa partire piega vassoio male
esame mela mese cane lame
ancora pippo pluto faro platea
porta parto sedia troppa pino
pera processore foglio fiore pera
gesso perfetto quaderno etto menta

OUTPUT
Per le righe
esame mela mese lame
porta parto troppa
Per le colonne
Male lame
Matrice ridotta
casa partire piega vassoio
ancora pippo pluto faro
pera processore foglio fiore
gesso raso quaderno lana

15.7. Esercizi sui file


53) Dati due file di gradi dimensioni contenenti ognuno elementi tra loro ordinati,
generare un terzo file per fusione dei primi due senza introdurre buffer in
memoria centrale
54) Dati due file di gradi dimensioni contenenti ognuno elementi tra loro diversi,
verificare quali sono gli elementi in comuni tra essi.
55) Sia assegnato un file contenente un vettore sparso di numeri reali,
memorizzare in un vettore solo gli elementi non nulli.
56) Sia assegnato un file di numeri reali:
leggere e memorizzare in un vettore gli elementi del file dingresso.
effettuare lordinamento del vettore
generare un file duscita contenente il vettore ordinato.
57) Sia assegnato un file testo contenente un racconto organizzato in righi lunghi al
massimo 80 caratteri ciascuno. Esaminare il testo contenuto nel file per
memorizzare lelenco delle parole che si ripetono in righi consecutivi fornendo
per ciascuna di esse lindicazione del rigo in cui compare per la prima volta e il
numero di righi successivi in cui si ripete (solo il numero di righi consecutivi e
non quante volte eventualmente si ripete nello stesso rigo). Nel caso siano
presenti parole uguali con le caratteristiche citate, se ne riporti solo quella con
454 Appendice B

numero maggiore di ripetizioni o una qualsiasi tra quelle con lo stesso valore di
ripetizione. Stampare, infine, lelenco ordinato per valori decrescenti del
numero di ripetizioni.
INPUT
nel mezzo del cammin di nostra vita
sono caduto nel fosso del mare e del cielo
il quale cielo era di colore azzurro
pi azzurro del cielo di casa nostra
e azzurro del mare della vita
passata a cercare di superare lesame
che difficile non sembra.
OUTPUT
parola rigo ripetizioni
cielo 2 3
azzurro 3 3
nel 1 2
del 1 2
di 3 2
58) Siano assegnati i valori degli elementi di tre vettori distinti in tre text file diversi
residenti su memoria di massa. Nellipotesi di non poter istanziare un quarto
vettore, operare lordinamento di tutti gli elementi dei tre vettori in senso
crescente e senza ripetizioni di valori uguali.
Per effettuare lordinamento si estenda lalgoritmo della selezione (select sort)
cercando ad ogni passo il valore minimo appartenente allinsieme formato da
tutti e tre i vettori e lo si accodi ad un file text; successivamente si stampi il
contenuto del file cos generato.
INPUT
File 1:
10 22 11 44 10 33 55
File2:
55 22 19 99 77 66 11 45
File3:
90 12 34 11 23 45 11 23 56 77 85
OUTPUT
10 11 12 19 22 23 33 34 44 45 55 56 66 77 85 90 99
Indice dei termini

A
algoritmi di base in C 228
algoritmo 107
ALU 61
ALU (Aritmetic Logic Unit) 57
ambiente MATLAB 329
ambienti di programmazione integrati 323
ARPANET 409
array 176
array bidimensionale 179
array monodimensionale 176
ASCII 42
assemblatore 84
automa a stati finiti 109

B
Backus Normal Form 122
basi di dati 432
browser 415
bus 63

C
cache 72
calcolabilit 111
campionamento 39
caricatore 317
carte sintattiche 122
Central Processing Unit (CPU) 56
ciclo del processore 62
client/server 407
456 Appendice C

clock 65
codifica 13
Command Window 329
commutazione a pacchetto 390
complemento a due 26
complemento a uno 28
complessit computazionale 113
Control Unit (CU) 61
convergenza digitale 37
costrutti condizionali 136
costrutti di controllo 135
costrutti di sequenza 135
costrutti iterativi 137
CPU 61

D
dato 163
DBMS 433
debugging 322
DEV-C++ 324
dichiarazion 133
DOC 44
documentazione dei programmi 131
Domain Name System (DNS) 399
DOS 367

E
eccesso 2l -1 28
E-mail 401
equivalenza funzionale 137
Ethernet 387

F
file184
firmware 68
frasi di commento 134
FTP 401
funzione 145

H
hardware 56
HTML 412
HTTP 400
Indice termini 457

I
immagini bitmap 48
immagini vettoriali 49
Informatica 12
information hiding 162
informazione 163
ingegneria del software 124
Internet 403
internetworking 392
interprete 319
interruzioni 71
ISO-OSI 394
istruzioni 115
istruzioni elementari di calcolo ed assegnazione 135

J
Job Control Language 365

K
kernel 369

L
linguaggio assemblativo 84
linguaggio C 195
linguaggio di programmazione 120
linguaggio HTML 44
linker 315
Linux 367
Local Area Network 386

M
Mac OS 368
Macchina di Turing 111
memoria 56
memoria centrale 60
memorie 58
memorie di massa 60
metadato 53
metalinguaggi 122
Metropolitan Area Network 391
mezzi trasmissivi 381
M-file editor 334
458 Appendice C

microprocessori 77
middleware 70
motori di ricerca 415
Mp3 52
MPEG 51

O
OS/2 367
overhead 364

P
parametri attuali 148
parametri formali 148
procedura 145
processo 370
processo di compilazione 311
processo di traduzione 310
progettazione dei programmi 127
programma 120
programmazione nel linguaggio assemblativo 89
programmazione strutturata 123
protocolli di comunicazione 392
puntatore 182

Q
quantizzazione 39

R
RAM 59
rappresentazione binaria 15
rappresentazione in virgola mobile 33
rete client-server 385
rete intranet 402
rete TCP/IP 397
reti broadcast 385
reti di calcolatori 383
reti peer to peer 386
reti punto a punto 385
ricorsione 159
ROM 59
Indice termini 459

S
schedulatore 371
segno e modulo 26
sistema di numerazione 20
Sistema Informatico 428
Sistema Informativo 427
Sistema Operativo 359
software 69
sostituzione per riferimento 149
sostituzione per valore 149
sottoprogrammi 145
SQL (Structured Query Language) 437
strutture di controllo. 115
swapping 365; 369; 373

T
TCP/IP 397
Telnet 401
tesi di Church-Turing 112
testing 320
throughput 363
tipo booleano 167
tipo carattere 169
tipo coda 193
tipo intero 170
tipo per enumerazione 173
tipo pila 192
tipo reale 171
tipo stringa di caratteri 179
tipo strutturato 174
tipo strutturato record 181
tipo subrange 173
tipo tabella 193
topologia a bus 387
topologia a ring 388
topologia a stella 387
tourn around time 363
trattabilit 113

U
UNIX 367
URL 413
460 Appendice C

V
visibilit 153
Von Neumann 56

W
Wide Area Network 390
Windows 367
World Wide Web 411

X
XML 54
Gli autori

Antonio Picariello si laurea nel 1991


in Ingegneria Elettronica presso
l'Unviersit di Napoli Federico II.
Nel 1993 ottiene una borsa di studio
presso il CNR - Istituto Ricerca Sui
Sistemi Informatici Paralleli, Napoli.
E dottore di Ricerca in Ingegneria
Informatica nel 1998, Ricercatore
Universitario dal 1999 al 2004 e
Angelo Chianese si laurea nel 1980 in Professore Associato dal 2005 ad
Ingegneria Elettronica presso oggi, presso il Dipartimento di
lUniversit degli Studi di Napoli Informatica e Sistemistica
Federico II. Dal novembre del 2005 in dell'Universit di Napoli Federico II.
servizio presso la stessa Universit in I suoi interessi di ricerca attuali
qualit di professore straordinario. riguardano i seguenti settori:
Dal 1984 afferisce al Dipartimento di computer vision, processing di
Informatica e Sistemistica dell'Universit immagine biomediche, pattern
degli Studi di NapoliFederico II dove recognition, basi di dati multimediali
svolge attivit didattiche e di ricerca. ed integrazione di informazioni
Dal 2000 membro del Consiglio di multimediali, gestione ed estrazione
Amministrazione dell'Universit. Dal delle conoscenza, gestione delle
2003 responsabile del progetto IDEA transazioni in ambienti mobili e
per lo sviluppo delle tematiche dell' e- sviluppo di applicazioni per la video
learning. E stato consulente del Ministro sorveglianza. E' stato coinvolto in
MUR per le-learning. vari progetti di ricerca internazionali
I suoi attuali interessi di ricerca (in particolare con lUniversit del
riguardano i settori della computer Maryland), nazionali e locali ed
vision, del pattern recognition, delle basi autore di numerose pubblicazioni su
di dati multimediali, della riviste e congressi internazionali,
rappresentazione e gestione della testimonianti le attivit di ricerca
conoscenza, dellinformation retrieval in svolte. Nel 2006 ha vinto, assieme ai
462 Autori

ambienti di e-learning. colleghi dellUniversit del


Ha partecipato alla organizzazione di Maryland, il premio Computer
diversi convegni nazionali ed World Horizon Award per le
internazionali. Ha partecipato o stato migliori ricerche nel campo
responsabile di diversi progetti di dellInformatica. Ha inoltre
ricerca. autore di numerose partecipato allorganizzazione ed
pubblicazioni su riviste e congressi stato nel comitato di programma di
internazionali, testimonianti le attivit di diversi convegni nazionali ed
ricerca svolte. autore di diversi libri. internazionali.
attualmente docente dei corsi di E attualmente docente per i corsi di
Fondamenti di Informatica e Basi di Programmazione I e Basi di Dati per
Dati per il corso di laurea di Ingegneria il corso di laurea di Ingegneria
Informatica presso lUniversit degli Informatica presso lUniversit degli
Studi di Napoli Federico II. Studi di Napoli Federico II.
Email: angchian@unina.it Email: picus@unina.it
Vincenzo Moscato ha ricevuto nel 2002 la laurea con lode in
Ingegneria Informatica presso l'Universit degli Studi di Napoli
Federico II. Nel 2005 ha acquisito il titolo di Dottore di
Ricerca in Ingegneria Informatica ed Automatica presso la
medesima Universit, dove attualmente lavora in qualit di
assegnista di ricerca in collaborazione col gruppo di ricerca sui
Sistemi Informativi Multimediali del Dipartimento di
Informatica e Sistemistica.I suoi interessi di ricerca attuali
riguardano le seguenti tematiche: basi di dati multimediali ed
integrazione di informazioni multimediali, gestione delle transazioni in ambienti
mobili, sviluppo di applicazioni per la video sorveglianza, integrazione di reti di
sensori ed information retrieval in ambienti di e-learning. E' stato coinvolto in
vari progetti di ricerca internazionali, nazionali e locali ed autore di varie
pubblicazioni su riviste e congressi internazionali, testimonianti le attivit di
ricerca svolte.
E stato docente nellanno accademico 2005/2006 del corso di Sistemi Operativi
per il corso di Laurea in Ingegneria delle Telecomunicazioni presso lUniversit
degli Studi di Napoli Federico II e dal 2002 effettua assistenza didattica per i
corsi di Fondamenti di Informatica e Basi di Dati nella medesima Universit.
Email: vmoscato@unina.it

Sito web di riferimento:


www.campus.unina.it
e e
i d i d

u o r

u o r
i t o r

i t o r
g

g
l i e l i e

A. Chianese, V. Moscato, A. Picariello ALLA SCOPERTA DEI FONDAMENTI DELLINFORMATICA


ANGELO CHIANESE
VINCENZO MOSCATO
ANTONIO PICARIELLO

Alla scoperta dei fondamenti


dellinformatica
Un viaggio nel mondo dei BIT

e e
i d i d
u o r

u o r
i t o r

i t o r
g

g
l i e l i e

Potrebbero piacerti anche