Problema - Server users.dimi.uniud.it

annuncio pubblicitario
Informatica Generale
a.a. 2006/2007
Demis Ballis <[email protected]>
Dipartimento di Matematica e Informatica
Università degli Studi di Udine
Obiettivi
• conoscere il calcolatore (parte HWe SW)
• apprendere le basi della programmazione
(imparare a formalizzare e risolvere
problemi con l’ausilio del calcolatore)
Programma del corso
• PARTE 1 (Algoritmi)
Il trattamento automatico dell’informazione.
Il modello di Von Neumann.
Formalizzare l’informazione: problemi e algoritmi.
Rappresentazione degli algoritmi mediante diagrammi di flusso,
pseudocodice e codice Java.
Elementi base sui linguaggi di programmazione.
La codifica dell’informazione: rappresentazione dei dati testuali e
codifica dei dati numerici.
Programma del corso
• PARTE 2 (Architetture)
Elementi di architettura degli elaboratori.
Il modello di funzionamento della CPU.
Memoria: organizzazione e funzionamento.
Dispositivi di I/O.
Elementi di sistemi operativi. Struttura e funzionalità di un
sistema operativo. Gestione dei processi, della memoria e dei
dispositivi di I/O. Il file system. Applicazioni utente.
Reti di calcolatori e internet: LAN e WAN. World Wide Web,
browser e protocollo http (cenni). Il linguaggio HTML per la
creazione di ipertesti.
Programma del corso
• PARTE 3 (Programmazione ad oggetti)
Elementi base della programmazione ad oggetti.
Classi, istanze e messaggi.
Principali caratteristiche del paradigma di programmazione ad oggetti:
ereditarietà, incapsulamento e polimorfismo.
Un linguaggio orientato agli oggetti: Java (cenni).
(Sarà il linguaggio che useremo nel corso di laboratorio)
Altre informazioni
• Testo consigliato: D. Sciuto, G. Buonanno,
W. Fornaciari e L. Mari. Introduzione ai sistemi
informatici. McGraw-Hill, seconda edizione,
2002.
• Trasparenze e dispense del docente
• Reperibili sul sito Web
http://www.dimi.uniud.it/~demis
Altre informazioni
• Orario di ricevimento:
Lunedì (dopo lezione).
• Modalità d’esame: esame scritto +
eventuale orale.
Un po’ di storia...
Sumeri e
Babilonesi
Abitanti delle prime civiltà di Sumeri
tengono già traccia di operazioni
commerciali utilizzando apposite
tavolette. L'estratto conto è molto
antico!
Leonardo da
Vinci
(1452-1519)
Disegni e progetti di calcolo ritrovati
solamente nel 1967 e che dimostrano come
egli, già attorno al 1500 (150 anni prima di
Blaise Pascal!) avesse immaginato un sistema
meccanico di calcolatrice basata su ruote
dentate (lo scritto fa parte di quello che oggi
viene chiamato "Codice di Madrid)
perfettamente funzionante.
Blaise Pascal
(1623-1662)
Filosofo, matematico e fisico francese. Blaise
Pascal a venti anni realizza una celebre macchina
per eseguire addizioni e sottrazioni
automaticamente, la 'Pascalina'.
Le addizioni venivano eseguite mediante la
somma delle rotazioni degli ingranaggi e le
sottrazioni come complemento al 10 (principio
che fu utilizzato anche da molte calcolatrici
meccaniche fino a pochi anni fa). Le
moltiplicazioni erano delle addizioni ripetute.
Lo scopo per cui progettò questa calcolatrice fu
quello di aiutare il padre nel calcolo della
riscossione delle tasse. Pensò che la macchina
potesse essere utile anche ad altri, la fece
brevettare e ne costruì anche un certo numero di
esemplari (circa 50).
Gottfried W.
Leibniz
(1646-1716)
Oltre a una macchina calcolatrice automatica in
grado di eseguire le quattro operazioni e
l'estrazione di radici quadrate, lasciò alcune idee
fondamentali per lo sviluppo della logica
matematica e per il futuro funzionamento dei
calcolatori digitali. Nel 1670, ignaro delle
invenzioni di B.Pascal e di W.Schickard, il grande
matematico e filosofo tedesco si immerse nella
progettazione di una macchina che non fosse una
semplice calcolatrice, ma che potesse eseguire
qualsiasi processo di ragionamento. Più tardi,
apprese dalla lettura dell'opera "Pensieri"
dell'esistenza della pascaline, Leibniz concentrò il
suo sforzo nella realizzazione di un congegno che
potesse eseguire velocemente moltiplicazioni e
divisioni, cosa che la macchina di Pascal non era
in grado di eseguire.
Nel 1674 Leibniz presentò a Londra il suo
progetto, denominato Stepped Reckoner
(calcolatrice a scatti). Il prototipo, però,
aveva molte difficoltà a funzionare.
Charles
Babbage
(1791-1871)
Matematico inglese. A lui si deve la descrizione
del primo calcolatore digitale automatico di uso
generale, la cosiddetta 'macchina analitica',
modello per tutti i successivi calcolatori digitali
universali. Per questa macchina, precorrendo i
tempi, aveva immaginato la possibilità di
introdurre da un lato le regole (gli algoritmi) e
dall'altro i valori (le variabili e le costanti). Il
modo più semplice di fare questo consisteva nell'
utilizzo di schede perforate o nastri perforati. La
macchina doveva essere in grado di eseguire
operazioni ricorrenti nel calcolo delle tavole e,
per questo, dovevano esserci varie schede, una
per ogni operazione da compiere, che venivano
unite in un nastro nella opportuna sequenza.
Altre schede perforate contenevano i dati.
La macchina analitica era costituita da due
parti: lo store (memoria) che immagazzinava i
dati e i programmi e che nella quale erano
conservati anche tutti i risultati intermedi dei
calcoli. Il mill (unità di calcolo) che conteneva il
programma vero e proprio. Babbage non vedrà
mai funzionare la sua Macchina Analitica.
Ada Lovelace
(1815-1852)
Il primo software mai scritto da un essere umano
fu ideato da una mano femminile e fu una mente
di donna a prefigurare alcune delle basi
concettuali della programmazione: Ada Lovelace.
Ada si appassiona all’opera di Babbage, di cui
intuisce “l’universalità delle idee” e tra i due inizia
un fitto scambio di lettere, piene di numeri, fatti
e fantasie. Ada Byron descrive la Macchina di
Babbage come uno strumento programmabile, in
grado di agire in base a delle istruzioni generali.
Con incredibile lungimiranza, ne prevede le
applicazioni nel calcolo matematico, prefigura
l’intelligenza artificiale e persino la computer
music, affermando che la macchina sarà cruciale
per il futuro della scienza.
A titolo di esempio, spiega il modo in cui la
macchina potrebbe effettuare un determinato
calcolo, scrivendo quel che viene unanimemente
riconosciuto come il primo software della storia.
George Boole
(1815-1864)
Logico e matematico inglese. George Boole creò
lo strumento concettuale che sta alla base del
funzionamento del calcolatore e che, in suo
onore, va sotto il nome di 'algebra booleana'. Si
tratta di un calcolo logico a due valori di verità
con alcune leggi particolari, che consente di
operare su proposizioni allo stesso modo che su
entità matematiche. La sua logica, oggi, sta alla
base della struttura dei componenti elettronici
denominati "porte logiche" ed è la base del
funzionamento dei calcolatori elettronici.
John Von
Neumann
(1903-1957)
Nell'agosto 1944, von Neumann si buttò a
capofitto nel progetto del calcolatore ENIAC.
ENIAC permetteva la memorizzazione interna
dei programmi. La programmazione, che fino ad
allora richiedeva una
manipolazione diretta ed
esterna dei collegamenti, era così ridotta ad
un'operazione dello stesso tipo dell'inserimento
dei dati, e l'ENIAC diveniva la prima realizzazione
di un computer programmabile nel senso
moderno del termine. All'Istituto di Princeton si
dedicò alla progettazione di un nuovo calcolatore,
producendo una serie di lavori che portarono alla
definizione di quella che oggi è nota come
architettura von Neumann: in particolare, la
distinzione tra memoria primaria (ROM) e
secondaria (RAM), e lo stile di programmazione
mediante diagrammi di flusso.
Alan M.
Turing
(1912-1954)
La macchina di Turing non è altro che (la
semplificazione) dell'odierno computer. Turing
descrisse una macchina che sarebbe stata capace
di leggere una serie su una banda composta dalle
cifre uno e zero. Questi uni e questi zeri
descrivevano i passaggi che erano necessari per
risolvere un particolare problema o per svolgere
un certo compito. La macchina di Turing avrebbe
letto ogni passaggio e l'avrebbe svolto in
sequenza dando la risposta giusta. Questo
concetto era rivoluzionario per quel tempo in
quanto molti computer negli anni '50 erano
progettati per un scopo preciso o per uno spettro
limitato di scopi. Ciò che Turing intravvedeva era
una macchina che riusciva a fare tutto, una cosa
che oggigiorno diamo per scontata.
Turing mise le sue capacità matematiche al
servizio del Department of Communications
inglese per decifrare i codici usati nelle
comunicazioni tedesche (codice Enigma).
Turing pensava che il si potesse riprodurre
l’intelligenza umana nel calcolatore (TEST di
TURING).
L’informazione
• Diverse proposte in letteratura
• Bateson, “Ricevere informazioni vuol dire
necessariamente ricevere notizie di
differenza” (Es.: Luce accesa/spenta, 1/0,...)
• Shannon, visione probabilistica. Un evento
porta molta informazione se e’ poco
probabile. (”Al polo nord fa freddo”).
Problemi e soluzioni
• Ogni problema necessita di informazione per
essere risolto.
• L’informazione deve essere elaborata al fine
di ottenere una soluzione (Elaborazione
dell’informazione).
• Ogni problema è dunque caratterizzato da:
• insieme di dati di partenza
• un risultato cercato
Problemi e soluzioni
• Una soluzione può essere intesa come una
procedura che genera un risultato a partire
dai dati iniziali.
• Creazione di una soluzione ed esecuzione di
una soluzione sono generalmente competenze
distinte che possono riguardare soggetti
distinti
Problemi e soluzioni
•
Supponiamo di avere due soggetti: il primo capace di formulare una
soluzione (uomo), il secondo in grado di eseguire una soluzione
(calcolatore)
•
analisi del problema e identificazione di una soluzione da parte
del primo soggetto;
•
traduzione della soluzione da parte del primo soggetto in termini
comprensibili al secondo (linguaggi di programmazione ad alto
livello);
•
interpretazione e attuazione della soluzione da parte del secondo
soggetto.
Problemi e
sottoproblemi
• La descrizione di un problema può essere
piuttosto complessa. Es.: Calcolo dell’area del
cerchio A=!R2
• Soluzione scomporre il problema in
sottoproblemi più semplici (approccio Topdown), Es. calcolo del qudrato del raggio al
fine di calcolare l’area del cerchio.
Problemi e
sottoproblemi
•
Un problema si dice elementare se la sua soluzione corrisponde ad
un’azione elementare che può essere compiuta direttamente
dall’esecutore.
•
Una soluzione e’ effettiva per un esecutore se
•
l’esecutore e’ in grado di interpretare la soluzione ed associarvi
le operazioni che devono essere compiute;
•
l’esecutore e’ in grado di compiere tali azioni in un tempo finito.
Problemi e
sottoproblemi
• l’approccio top-down alla soluzione di un
problema e’ il seguente
• se la soluzione del problema è effettiva,
allora l’esecutore la attua;
• altrimenti il problema viene scomposto in
sottoproblemi e per ognuno di questi si
riapplica la metodologia di scomposizione
top-down.
Problemi e
sottoproblemi
•
•
•
•
•
•
In generale, un insieme di problemi è una procedura effettiva se
tutti i problemi dell’insieme sono elementari
è fissato l’ordine di soluzione dei problemi
si specifica esplicitamente come un problema utilizza i risultati dei
suoi sottoproblemi.
Esempio: calcolo dell’area di una figura complessa.
L’esecutore
•
•
L’esecutore è caratterizzato da
•
il linguaggio che è in grado di interpretare, il quale deve essere
formalmente specificato (caratterizzazione sintattica)
•
•
l’insieme delle azioniche è in grado di compiere
l’insieme di regole che associano ad ogni costrutto sintattico le
opportune azioni da compiere (caratterizzazione semantica)
Le soluzioni effettive caratterizzate formalmente si chiamano
ALGORITMI!
Algoritmi
• Un algoritmo è dunque una sequenza finita di
passi, scritta in un opportuno linguaggio
interpretabile dall’esecutore, che permette di
calcolare un risultato a partire da un insieme
di dati in ingresso.
• Un algoritmo permette di risolvere una
classe di problemi omogenei.
Proprietà degli
algoritmi
Un algoritmo deve essere
• Finito
• Non ambiguo
• Effettivo
Realizzazione di un
programma
Esigenze utente
Analisi
soluzione informale
Formalizzazione
algoritmo
programmazione
programma
traduzione
Debugging
esecuzione
Esempio di algoritmo
Calcolo del massimo fra 2 numeri
1. Leggi un numero dall’esterno e mettilo nella variabile X.
2. Leggi un numero dall’esterno e mettilo nella variabile Y.
3. Calcola la differenza d fra x e y (d ! X-Y)
1. Se (d > 0) allora stampa “il massimo è X”,
altrimenti stampa “il massimo è Y”.
Altri esempi:
• Determinare il maggiore fra tre numeri
• Determinare il massimo fra n numeri naturali.
Diagrammi di flusso
• Un metodo per rappresentare graficamente
gli algoritmi.
Input/
Output
predicato
sotto
programma
Start
Elaborazione
Stop
Esempio
Start
Leggi X
Leggi Y
d ! X-Y
d>0?
SI
NO
Stampa X
Stampa Y
Stop
La programmazione
strutturata
Un algoritmo è strutturato
in blocchi di istruzioni.
• Vantaggio:
codice.
maggior leggibilità e pulizia del
• Blocchi: sequenziali, condizionali, iterativi.
• Le istruzioni di input/output e di
assegnamento possono essere considerate
come dei blocchi sequenziali atomici.
Blocco sequenziale
• E’ costituito da una sequenza di
(sotto-)blocchi che saranno eseguiti
sequenzialmente.
{
Blocco 11
Blocco
Blocco Sequenziale
Blocco 12
Blocco
}
Blocco 1
Blocco 2
.
.
.
Blocco N
Blocco 1N
Blocco
Blocco i, i=1,..N, può essere un blocco sequenziale,
condizionale, iterativo
Blocco condizionale
• Il blocco condizionale permette di scegliere
tra due azioni in base a una condizione
logica.
Blocco Condizionale
Condizione
SI
Blocco 11
Blocco
NO
Blocco 12
Blocco
Se <Condizione> allora
Blocco 1
altrimenti
Blocco 2
Blocco i, i=1,..2, può essere un blocco sequenziale, condizionale, iterativo
Blocco condizionale
(semplificato)
• Tale blocco permette di decidere di eseguire
un’azione in base a una condizione logica.
Blocco Condizionale
Semplificato
Condizione
Se <condizione> allora
Blocco 1
SI
Blocco 11
Blocco
Blocco 1 può essere un blocco sequenziale, condizionale, iterativo
Blocco iterativo
(controllo in testa)
• Il blocco iterativo con controllo in testa
permette di ripetere un blocco di istruzioni
finché la condizione logica rimane vera
Blocco Iterativo
(controllo in testa)
Mentre <condizione> fai
Blocco 1
Condizione
SI
NO
Blocco 11
Blocco
Blocco 1 può essere un blocco sequenziale, condizionale, iterativo
Blocco iterativo
(controllo in coda)
• Permette di eseguire almeno una volta il
blocco contenuto nel ciclo. Si ripete il blocco
finché la condizione logica viene verificata.
Blocco Iterativo
(controllo in coda)
Ripeti
Blocco 1
finché <condizione>
Blocco 11
Blocco
NO
Condizione
SI
Blocco 1 può essere un blocco sequenziale, condizionale, iterativo
Diagramma di Flusso
Start
Leggi
X,Y
D!X-Y
D>0?
SI
NO
Scrivi
Max è
X
Scrivi
Max è
Y
Stop
Max fra 3 numeri
Input: tre numeri distinti
Output: il massimo fra i tre numeri
1. Leggi X,Y,Z
2. Se (X>Y) allora
2.1. Se (X>Z) allora
2.1.1. Stampa
altrimenti
2.1.2. Stampa
altrimenti
2.2. Se (Y>Z) allora
2.2.1. Stampa
altrimenti
2.2.2. Stampa
“il max e’ X”
“il max e’ Z”
“il max e’ Y”
“il max e’ Z”
Diagramma di Flusso
Start
Leggi
X,Y,Z
SI
NO
X>Y?
SI
Scrivi
max e' X
X>Z?
NO
SI
Scrivi
max e' Z
Scrivi
max e' Y
Stop
NO
Y>Z?
Scrivi
max e' Z
Codifica
dell’informazione
• Gli algoritmi sono costituiti da istruzioni
(blocchi sequenziali, condizionali, iterativi)
che operano su dati.
• Per trasformare un programma in una
descrizione eseguibile da un calcolatore è
necessario rappresentare istruzioni e dati in
un formato memorizzabile e facilmente
manipolabile.
Codifica
dell’informazione
•
Rappresenteremo l’informazione numerica e non numerica mediante
sequenze di simboli scelti da un insieme chiamato alfabeto.
•
Ad ogni alfabeto è associato un insieme di regole di composizione
che consentono di costruire le successioni di simboli. Successioni che
sono costruite mediante le regole di composizione si dicono “ben
formate”.
Esempio
Rappresentazione usuale dei numeri frazionari in base 10
Alfabeto={”0”,”1”,”2”,”3”,”4”,”5”,”6”,”7”,”8”,”9”, “,”}
103,56 successione ben formata
12,45,67 successione non ben formata
Codifica
dell’informazione
• Oltre a dare delle regole di composizione per
rappresentare l’informazione (parte
sintattica), è necessario assegnare
all’informazione un significato mediante dei
codici (parte semantica).
Esempio
2
1
0
-1
-2
103,56 significa 1*10 +0*10 +3*10 +5*10 +6*10
Codifica
dell’informazione
• Dato un alfabeto di n simboli, si possono
generare nk successioni di k simboli.
• Generalmente non tutte le successioni
codificano dell’informazione (solo le
successioni ben formate)
Esempio
4
Con un alfabeto di 10 simboli si possono ottenere 10 =10.000 sequenze di
lunghezza 4.
Codifica binaria
•
•
•
•
Un alfabeto piuttosto semplice e allo stesso tempo molto comodo è
l’alfabeto binario, il quale è composto da soli due simboli.
A2={0,1}
I calcolatori utilizzano per la memorizzazione dell’informazione dei
dispositivi bistabili (bit - Binary digIT), in grado di assumere due
sole configurazioni.
Nell’ipotesi che ogni successione di bit sia ben formata, utilizzando
k
l’alfabeto A2 e k bit si possono ottenere 2 successioni diverse.
Codifica binaria
• 8 bit = 1 Byte
• 2 Byte = 1 KByte
• 2 KByte = 2 Byte = 1 MByte
• 2 MByte = 2 KByte = 2 Byte = 1 GByte
10
10
10
20
20
30
Dati non numerici
• Dati non numerici esempi: caratteri
alfanumerici (’a’,’b’,’=’,...), sequenze di
caratteri (”pippo”, “mamma”, ...).
• Problema: come codificare mediante un
codice binario dei dati non numerici?
Dati non numerici
•
Dato un insieme di dati non numerici S costituito da #S elementi,
qual è il numero minimo di bit per codificare tutti gli elementi
mediante una codifica binaria che sia univoca?
•
k
Sappiamo che con k bit possiamo codificare n=2 elementi. Se n=#S
allora k è uguale al tetto di log #S, dove il tetto di un numero p è
2
il minimo intero superiore a p.
•
Esempio: S= {Lun,Mar,Mer,Gio,Ven,Sab,Dom}, #S=7. Quindi log #S
2
tetto(log2 #S)=tetto(log2 7)= 3
Algoritmo per la codifica dei
dati non numerici
Problema: dato un insieme S di dati non numerici, determinare una
codifica binaria univoca per gli elementi di S.
Soluzione: Dato un insieme S da codificare, un
singolo bit permette di distinguere i dati in due sottoinsiemi. Iterando
tale procedimento sui sottoinsiemi identificati, siamo in grado di
generare delle successioni di bit che identificano in maniera non
ambigua i singoli elementi di S.
Esempio
S
Lun
Mar
Mer
Gio
Lun
Mar
Mer
Gio
Ven
Sab
Dom
Ven
Sab
Dom
Lun
Mar
Mer
Gio
Ven
Sab
Dom
Non usata!
000
001
010
011
100
101
110
111
0
1
Lun
Mar
00
Mer
Gio
01
Ven
Sab
10
Dom
11
Dati non numerici
• Volendo realizzare una codifica binaria per
documenti scritti in linguaggio naturale
bisogna prima stabilire il numero di simboli
necessari. (Es. 26 lettere minuscole, 26
lettere maiuscole, segni di interpunzione, 10
cifre decimali,caratteri speciali...)
• Sono circa 120 simboli, per la cui codifica
sono necessari almeno 7 bit.
Dati non numerici
• Codifica ASCII (128 caratteri, 7 bit)
• Codifica ASCII estesa (256 caratteri, 8 bit)
• codifica UNICODE (65535 caratteri, 16 bit)
• i primi 128 caratteri della codifica
UNICODE corrispondono al codice ASCII
• Anche UNICODE non è sufficiente :-(
Istruzioni
•
I programmi sono codificati mediante un linguaggio di basso livello
chiamato linguaggio macchina.
•
Anche le istruzioni del linguaggio macchina sono codificate mediante
un codice binario.
•
•
assegnare un codice univoco ad ogni singola istruzione (opcode)
•
il numero di operandi dipende dal tipo di istruzione. (ES:
l’istruzione ADD (somma) ha due operandi, l’istruzione HALT ha 0
operandi).
oltre all’opcode è necessario codificare gli eventuali riferimenti
agli operandi necessari all’esecuzione dell’istruzione.
Codifica dei dati
numerici
•
Codifica dei numeri senza segno
•
•
rappresentzione dei numeri senza segno in base B, B>1.
conversioni di base:
•
•
•
•
Da base 10 a base B, B>1
Da base B, B>1 a base 10
Da base B, B>1 a base B’, B’>1
Conversioni rapide:
•
•
da base 8 a base 2 e viceversa
da base 16 a base 2 e viceversa
Notazione
Una base B di dimensione n e’ un insieme di n cifre {0,1,... n-1}
Esempi:
{0,1} base 2
{0,1,2} base 3
{0,1,2,3,4,5,6,7} base 8
{0,1,2,3,4,5,6,7,8,9} base 10
{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F} base 16
(cn-1 cn-2 ... cn-1 c1 c0)B !rappresenta un numero senza segno
! di n cifre in base B.
Conversioni di base
Problema: convertire un numero senza segno da base B a
base 10.
Soluzione:
dato il numero senza segno in base B (cn-1 cn-2 ... cn-1 c1 c0)B il
corrispondente valore in base 10 si calcola con la seguente formula:
cn-1*2n-1 + cn-2*2n-2 + ... + c1*21 + c0*20
Esempio: (101011)2 corrisponde a (43)10, infatti
1*25+0*24+1*23+0*22+1*21+1*20 = 32+0+8+0+2+1 = 43
Conversioni di base
Problema: convertire un numero senza segno da base 10 a base B.
Soluzione:
dato un numero senza segno X in base 10, si deve calcolare il
corrispondente valore in base B (cn-1 cn-2 ... cn-1 c1 c0)B.
Dividendo X per la base B, si ottiene come resto la cifra c0 e un certo
quoziente Y1.
Dividendo Y1 per la base B, si ottiene come resto la cifra c1 e un certo
quoziente Y2.
Iterando il procedimento fino a raggiungere il quoziente 0,
si ottiene il numero in base B cercato.
Conversioni di base
Esempio: (12)10 corrisponde a (112)3, infatti
14:3=4
2
c0
4:3=1 1:3=0
1
1
c1
c2
Esempio: (12)10 corrisponde a (1100)2, infatti
12:2=6
0
c0
6:2=3 3:2=1 1:2=0
0
1
1
c1
c2
c3
Conversioni di base
Problema: convertire un numero senza segno da base B1 a base B2.
Soluzione: convertire prima il numero da base B1 a base 10 e in
seguito convertire il valore risultante da base 10 a base B2.
Esempio: (101011)2 corrisponde a (1121)3, infatti
(101011)2 = (43)10 = (1121)3
Conversioni rapide
In alcuni casi passare da una base B1 a una base B2 può essere
molto semplice. È questo il caso delle conversioni da base 8 a base
2, da base 2 a base 8, da base 16 a base 2 e da base 2 a base 16
Problema: convertire un numero senza segno da base 8 a base 2.
Soluzione: convertire indipendentemente ogni singola cifra del
numero in base 8 in tre bit.
Problema: convertire un numero senza segno da base 16 a base 2.
Soluzione: convertire indipendentemente ogni singola cifra del
numero in base 16 in 4 bit.
Conversioni rapide
Esempio: (766401)8 corrisponde a
(111 110 110 100 000 001)2
7 6 6 4
0
1
Esempio: (A01F)16 corrisponde a
(1010 0000 0001 1111)2
A
0
1
F
Conversioni rapide
Problema: convertire un numero senza segno da base 2 a base 8.
Soluzione: raggruppare, da destra verso sinistra, i bit del numero in
base 2 in gruppi di 3 bit e convertire indipendentemente ogni
singolo gruppo di bit in una cifra ottale.
Problema: convertire un numero senza segno da base 2 a base 16.
Soluzione: raggruppare, da destra verso sinistra, i bit del numero in
base 2 in gruppi di 4 bit e convertire indipendentemente ogni
singolo gruppo di bit in una cifra esadecimale.
Conversioni rapide
Esempio: (10101011)2 corrisponde a
(2
010
5
101
3)8
011
Esempio: (1110101011)2 corrisponde a
( 3
0011
A
1010
B )16
1011
Codifica dei dati
numerici
• Codifica dei numeri interi (bisogna codificare
numero e segno)
0, ±1, ±2,±3,±4,...
• Due metodi:
• codifica con modulo e segno
• codifica in complemento a due
Modulo e segno
• Codifica del
segno seguita dalla codifica del
valore assoluto
• Si utilizza il primo bit (bit più significativo)
per codificare il segno: 0 codifica “+”, 1
codifica “-”
• I restanti bit si utilizzano per codificare il
valore assoluto (i.e. numero senza segno)
Modulo e segno
-10 (su 5 bit)
-10 (su 7 bit)
1
1
0
1
0
1
0
0
1
0
1
• Considerando n bit, questa codifica permette
di rappresentare i numeri interi
da -(2
n-1
-1) a (2
n-1
-1)
0
Modulo e segno
• Problema: doppia rappresentazione dello 0
(+0 e -0!)
• spreco di spazio (si sprecano due
successioni di bit per codificare lo stesso
valore)
• gestione delle operazioni di controllo e
aritmetiche più complessa
+0
0
0
0
0
-0
1
0
0
0
Somme e sottrazioni
in base 2
+
0
1
0
0
1
1
1
0 (riporto 1)
-
0
1
0
0
1 (prestito 1)
1
1
0
Esempi
10111011 +
11010011
110001110
10111011 +
1
10111100
10111011 10000101
10000000 1
00110110
01111111
Complemento a 1
Dato un numero binario (X)2 , il
complemento a 1 di (X)2 è un numero
binario (Y)2 che si ottiene invertendo i bit
di (X)2.
Esempio:
il complemento a 1 di (00111011)2 è
(11000100)2
Complemento a 2
• Unica rappresentazione dello 0!
• Data una successione di n bit, per codificare
un numero intero X, si utilizza il valore
binario corrispondente a (2n+X).
•
Es: codifica su 4 bit => 24=16
+6 = 16+6 = +22 => 10110
-6 = 16-6 = +10 => 1010
0
1
1
0
1
0
1
0
Complemento a 2
•
Fatti:
•
il bit più significativo di un numero positivo in complemento a due
è sempre 0
•
il bit più significativo di un numero negativo in complemento a
due è sempre 1
•
Considerando n bit, questa codifica permette di rappresentare i
numeri interi da
•
-2n-1 a (2n-1-1)
Problema: dato un numero intero codificato in complemento a due,
determinare il corrispondente valore in base 10
Complemento a 2
Problema: Convertire un numero codificato in
complemento a 2 (X)2 nel corrispondente
valore decimale.
Soluzione:
Se (X)2 >= 0
stesso procedimento della codifica modulo e segno
Se (X)2 < 0
1. Calcolare il complemento a 1 di (X)2 e
chiamarlo (Y)2
2. Sommare 1 a (Y)2, convertire in decimale
il risultato, e chiamarlo (Z)10
3. Il valore corrispondente è -(Z)10
Esempi
Caso numero negativo
Il valore decimale di (1011)2 è (-5)10 infatti...
complemento a 1
0100 +
1
0101
e convertendo (0101)2 si ottiene 5.
Caso numero positivo
Il valore decimale di (0011)2 è (+3)10 infatti...
convertendo (011)2 si ottiene 3.
Compressione dei
dati
• Finora non abbiamo valutato il costo e
l’efficienza delle codifiche scelte.
• La compressione dei dati permette di ridurre
il numero di bit necessari alla codifica di un
insieme di elementi di informazione.
• costo di memorizzazione minore
• trasmissione dati più veloce
Esempio
•
supponiamo di avere l’alfabeto A={A,C,G,T} e una successione S di
1.000.000 di caratteri scelti in A.
•
Possibile codifica binaria dell’alfabeto: A=00, C=01, G=10, T=11 => la
codifica di S prevede l’uso di 2.000.000 di bit.
•
Altra possibilità: assegnare codici binari (non ambigui!!) di lunghezza
variabile agli elementi dell’alfabeto, in base alla loro frequenza
relativa rispetto a S (più la frequenza è alta, più il codice sarà
corto). Se A si presenta in S il 50% dei casi, C il 25%, G e T il
12.5%, allora, per esempio,
A=0, C=10, G=110, T=111
in questo caso, la codifica di S risulta più corta, infatti
(1*0.5+2*0.25+3*0.125+3*0.125) bit/carattere * 1.000.000 carattei = 1.750.000 bit
•
Compressione dei
dati
due tipi di algoritmi di compressione
•
lossless (senza perdita di informazione)
•
•
•
tutta l’informazione è importante e non si può perdere!
Es: slide precedente, documenti word, programmi eseguibili,...
lossy (con perdita di informazione)
•
si è disposti a perdere informazione pur di ottenere un
maggior tasso di compressione
•
Es.: formati per immagini (JPEG, GIF,...), formati audio (MP3),
formati video (famiglia MPEG)
Il calcolatore
• È un sistema complesso costituito da un
numero elevato di componenti.
• è strutturato in forma gerarchica
• ogni livello di descrizione è caratterizzato
da una struttura rappresentante
l’organizzazione dei componenti del livello
• ogni componente è caratterizzato dalla
funzione che deve svolgere.
Funzioni
• Le funzioni svolte da un calcolatore sono
classificabili in 4 tipologie:
• elaborazione dati
• memorizzazione dati
• trasferimento dati
• controllo
Proprietà
• Alcune proprietà
• flessibilità nel calcolo (general-purpose)
• modularità della struttura
• componentistica scalabile e standard
• semplicità di installazione
• larga disponibilità di SW a basso costo
Architettura di
riferimeto
• Architettura di Von Neumann
• sottosistema di interfaccia
• sottosistema di elaborazione
• sottosistema di memorizzazione
• canale (bus) di connessione
Sottosistema di
interfaccia
• Permette di far interagire il calcolatore con
il mondo esterno.
• dispositivi di ingresso/uscita (unità
periferiche) gestiti mediante interfacce che
controllano il trasferimento dei dati
• Schermo, tastiera, mouse, memoria di
massa,...
Sottosistema di
elaborazione
• il cuore (cervello!) del calcolatore è la CPU
(Central Processing Unit).
• Gestisce le funzioni di
• controllo e coordinamento
• elaborazione dei dati
• Fisicamente è rappresentato dal
microprocessore
Sottosistema di
memorizzazione
• Per la memorizzazione dei dati è presente
un’unità chiamata memoria.
• Può essere vista come
una serie di celle
adiacenti, ognuna delle quali è identificata
mediante un indirizzo (memory address).
Canale di
connessione
•
La connessione dei sottosistemi avviene mediante una linea
per il trasferimento dati chiamata bus.
•
Problema: il collegamento contemporaneo di tutti le unità
può essere difficilmente gestibile.
•
Soluzione: tecnologia master-slave
•
la gestione dell’intero sistema di comunicazione affidata
a un master (la CPU) il quale gestisce l’accesso al bus
•
le unità periferiche rivestono il ruolo di slave, non
possono accedere al bus autonomamente
•
si evitano possibili collisioni fra dati
Pregi e difetti del
collegamento a BUS
semplicità
estendibilità
standardizzabilità
lentezza
limitata capacità
sovraccarico della CPU
Il BUS
•
È suddiviso funzionalmente in 3 componenti:
•
bus dati => trasferimento dati
•
•
CPU <=> memoria
CPU <=> interfacce di ingresso/uscita
•
bus indirizzi => trasferimento degli indirizzi di memoria in
cui la CPU va a leggere e scrivere
•
bus di controllo =>trasferimento di informazione di
controllo per coordinare l’intero sistema
•
•
gestione della politica master-slave
direzione dello scambio (lettura/scrittura)
Esecuzione di un
programma
•
un calcolatore basato sull’architettura di Von Neumann
esegue un programma sulla base dei seguenti principi:
•
dati e programmi sono memorizzati in una memoria
unica
•
i dati sono indirizzati in base alla loro posizione,
indipendentemente dalla loro natura
•
le istruzioni vengono eseguite in modo sequenziale
Il linguaggio
macchina
•
il linguaggio per cui la CPU si comporta da esecutore è il linguaggio
macchina (o linguaggio assembly).
•
È un linguaggio a basso livello
•
•
•
numero di operazioni ridotto
numero di operandi ridotto
non esiste il concetto di tipo di dato
•
L’utilizzo di tale linguaggio implica un’ottima conoscenza della
struttura fisica del calcolatore
•
ogni CPU è caratterizzata dal suo linguaggio macchina (set di
istruzioni)
il ciclo fetchdecode-execute
• Nell’esecuzione di un programma, la CPU
opera ciclicamente nel seguente modo:
• acquisizione dalla memoria di un’istruzione
del programma (fase di fetch)
• identificazione dell’istruzione fra quelle
che compongono l’insieme delle istruzioni
(fase di decode)
• esecuzione dell’istruzione (fase di execute)
Struttura di una
CPU
•
Una CPU è costituita da 3 sottosistemi principali
•
l’unità aritmetico-logica (ALU), la cui funzione è di
effettuare operazioni aritmetiche (somme, sottrazioni,...)
e logiche (AND, OR,...).
•
i registri: celle di memoria interne alla CPU, utilizzate
per memorizzare gli operandi delle operazioni
aritmetiche e informazioni di controllo
•
l’unità di controllo (CU), che ha funzione di
coordinamento
Alcuni registri
•
Tra i vari tipi di CPU, il numero e il tipo di registri è variabile. Sono
però sempre presenti i seguenti:
•
PC (Program Counter) contiene l’indirizzo di memoria della
prossima istruzione da eseguire
•
IR (Instruction Register) contiene una copia dell’istruzione da
eseguire
•
MAR (Memory Address Register) contiene l’indirizzo di memoria
dove scrivere o leggere un dato
•
MDR (Memory Data Register) contiene una copia del dato da
trascrivere o estratto dalla memoria.
•
PSW (Process Status Word) contiene informazioni inerenti allo
status del sistema a seguito dell’esecuzione di un istruzione
FETCH
Ciclo F-D-E
nel dettaglio
•
La CU fornisce alla memoria l’indirizzo della cella
contenente l’istruzione da eseguire, la richiesta viene
eseguita mediante la scrittura di tale indirizzo nel
registro MAR e l’attivazione di un messaggio di
controllo “LEGGI” sul BUS.
•
La memoria seleziona la cella contenente l’istruzione e
la invia al registro MDR. La CU copia dal MDR al IR
l’istruzione corrente.
Ciclo F-D-E
nel dettaglio
DECODE
•
La CU incrementa il PC in modo che punti alla
prossima istruzione da eseguire.
•
La CU esamina l’istruzione in IR e determina
l’operazione da svolgere
Ciclo F-D-E
nel dettaglio
EXECUTE
•
Le unità interessate all’esecuzione dell’istruzione
vengono opportunamente comandate. Si provvede a
prelevare eventuali operandi dalla memoria (fetch degli
operandi) e a trasferire il risultato in un registro o in
memoria
Coordinamento delle
attività
•
il ciclo F-D-E richiede che le varie unità operino in modo coordinato
anche dal punto di vista della temporizzazione degli eventi.
•
Si introduce un orologio (CLOCK) che fornisce una cadenza temporale
per la sincronia delle singole attività
•
La frequenza del clock (numero di attività elementari nell’unità di
tempo) è un parametro per valutare la velocità di una CPU. Le CPU
attuali hanno una frequenza di CLOCK dell’ordine del GHz (1000000
di operazioni al secondo).
Prestazioni di un
sistema
• Parametri valutabili
• tempo di risposta o di latenza (cioè il
tempo che trascorre dall’inizio alla fine di
un compito)
• throughput (ammontare del lavoro svolto in
un dato tempo)
Prestazioni di un
sistema
•
Si può misurare il tempo complessivo necessario al completamento di
un compito (elapsed time), che comprende l’accesso al disco, alla
memoria, attività di I/O, tempo di CPU,...
•
•
è influenzato dagli altri processi attivi, in particolare dal
sovraccarico apportato dal sistema operativo
Tempo effettivo di elaborazione (tempo di CPU), non comprende il
tempo di attesa dovuto alle operazioni di I/O e all’esecuzione di
altri processi.
Tempo di CPU
tCPU= nCK * TCK
tCPU: tempo di CPU
nCK: numero di cicli di CLOCK necessari al completamento del processo
TCK: periodo di CLOCK
oppure
tCPU= nCK / fCK
tCPU: tempo di CPU
nCK: numero di cicli di CLOCK necessari al completamento del processo
fCK: frequenza di CLOCK
Tempo di CPU
Consideriamo nI numero di istruzioni che vengono eseguite
CPI = nCK / nI
CPI: numero medio di cicli di CLOCK per istruzione
Quindi,
tCPU= CPI * nI * TCK
Oppure,
tCPU= (CPI * nI) / fCK
Tempo di CPU
tCPU= (CPI * nI) / fCK
Il tempo di CPU è influenzato da
1. frequenza di CLOCK
2. numero medio di cicli di CLOCK per istruzione
3. numero di istruzioni
CISC vs RISC
• Due filosofie di progettazione dei processori
• CISC (complex instruction set computer)
• RISC (reduced instruction set computer)
Tipo di CPU
CISC
RISC
CPI
alto
basso
nI
basso
alto
fCK
media
alta
C-RISC soluzione intermedia!
Altri indicatori
•
Il tempo di CPU è generalmente il parametro più
importante nella valutazione delle prestazioni di un
sistema informatico
•
Ci sono comunque altri indicatori
•
•
MIPS (Mega Instructions per Second)
MFLOPS (Mega Floating Point Operations per Second)
La memoria
• Due tipologie:
•
Memoria centrale
•
•
contiene i programmi in esecuzione e i relativi dati, la velocità di
accesso incide fortemente sulle prestazioni del sistema.
Memoria di massa
•
destinata a contenere grandi quantità di dati che non vengono
utilizzati frequentemente, ma che devono essere mantenuti in
modo persistente.
Altra tassonomia
• Un’ulteriore classificazione può essere la
seguente
• memoria interna alla CPU (i registri)
• memoria esterna alla CPU ma interna al
calcolatore (memoria centrale)
• memoria esterna al calcolatore (memoria di
massa)
Criteri di valutazione
• Velocità di accesso
• Capacità
• Volatilità
• Costo per bit
Tipi di memoria
• La realizzazione delle unità di memoria si
basano su diverse tecnologie:
• memorie elettroniche
• memorie magnetiche
• memorie ottiche
Memorie
elettroniche
• sono caratterizzate
• da un’alta velocità (d’accesso ai dati)
• da una discreta capacità
• dalla necessità di essere continuamente
alimentate (memorie volatili)
• da un alto costo per bit
Memorie magnetiche
• Sono caratterizzate
• da un basso costo per bit
• da una bassa velocità di accesso
• da grandi capacità
• dalla capacità di mantenere le informazioni
in assenza di alimentazione (memorie non
volatili)
Memorie ottiche
•
hanno proprietà analoghe a quelle delle memorie magnetiche
•
•
sono in genere caratterizzate da supporti non riscrivibili
•
negli ultimi anni sono nati dispositivi magneto-ottici, che
consentono di modificare le informazioni memorizzate.
adatte a memorizzare grandi quantità di dati, ma non alla
memorizzazione di dati da elaborare.
Memorie centrali e
di massa
•
Memorie centrali => basate su tecnologie elettroniche. Sono veloci,
volatili, noon molto grandi e costose
•
Memorie di massa => basate su tecnologie magnetiche ed ottiche.
Sono lente, molto capaci, poco costose e non volatili.
•
Allo stato attuale
•
le memorie centrali sono 5 ordini di grandezza più veloci delle
memorie di massa
•
le memorie centrali sono due ordini di grandezza più costose
delle memorie di massa
La memoria centrale
•
Può essere vista come una successione di elementi binari (bit) che
sono in grado di assumere solo due stati (convenzionalmente, 0 o 1).
•
I bit sono raggruppati in unità minime di 8, 16, 32 o 64 bit, dette
celle.
•
Ogni sequenza di bit avente la lunghezza di una cella è detta
parola.
•
Ogni cella possiede un indirizzo che rappresenta la sua posizione
rispetto alla prima cella, la quale convenzionalmente ha indirizzo 0.
•
la dimensione massima della memoria indirizzabile dipende dipende
dal numero di bit a disposizione per codificare gli indirizzi di cella.
Ossia, k bit per cella => 2k indirizzi possibili.
La memoria centrale
•
Dal punto di vista dell’esecuzione delle istruzioni, la memoria
centrale è un oggetto monolitico al quale si accede mediante i
registri MAR e MDR e a un insieme di segnali di controllo (leggi/
scrivi).
•
La lettura di una parola, residente in una cella, avviene rendendo
disponibile sul bus dati (e dunque nel MDR) la parola presente nella
cella selezionata attraverso il suo indirizzo. Il contenuto della cella
non viene modificato.
•
La scrittura di una parola (residente nel MDR) in una cella avviene
copiando il contenuto del MDR nella cella indirizzata (l’indirizzo si
trova nel MAR).
Prestazioni della
memoria
•
Le prestazioni di una memoria si possono valutare secondo i seguenti
parametri:
•
tempo di accesso: intervallo di tempo necessario per completare
un’operazione di scrittura/lettura
•
ciclo di memoria: è valutato sommando il tempo d’accesso
all’intervallo di tempo necessario per effettuare una nuova
operazione di scrittura/lettura. Legato a fattori tecnologici.
misurato in numero di accessi su unità di tempo
•
velocità di trasferimento: quantità di dati trasferiti nell’unità di
tempo (misurata in bit/s o byte/s).
Metodi di accesso
•
Dato l’indirizzo della cella da leggere o scrivere, si possono
individuare le seguenti tipologie di accesso:
•
Accesso sequenziale: le celle sono poste in successione. La lettura
di un dato comporta la lettura di tutti i dati precedenti.
(Esempio: nastri magnetici). Il tempo di accesso è molto variabile,
dipende dalla posizione del dato nel supporto.
•
Accesso casuale: l’accesso a una cella non richiede la lettura
delle precedenti. Il tempo d’accesso è indipendente dalla
posizione del dato e può essere considerato costante. La memoria
centrale è caratterizzata da un accesso casuale, è anche detta
memoria RAM (Random Access Memory).
Metodi di accesso
•
Accesso misto: L’indirizzo di una cella non consente di identificare
con precisione la posizione fisica del dato sul supporto. Vengono
effettuati una serie di accessi per giungere in prossimità del dato e
successivamente una ricerca sequenziale per identificare con
precisone la posizione del dato. Esempio: unità a dischi. Tempo di
accesso variabile.
•
Accesso associativo: Il contenuto di una cella non è selezionato in
base all’indirizzo, ma in base a parte del contenuto della cella
stessa. E’ una sorta di accesso di tipo casuale, infatti il tempo di
accesso è costante. Esempio: memoria cache. Sono memorie molto
veloci e particolarmente costose.
Memoria ROM
•
Generalmente le memorie di tipo elettronico sono volatili. Esistono
comunque delle memorie basate su tecnologie elettroniche di tipo
non volatile:
•
•
memorie ROM (Read-Only Memory): possono essere lette ma non
modificate. Sono usate per memorizzare permanentemente le
informazioni di inizializzazione del calcolatore.
Negli ultimi anni si sono diffuse le memorie FLASH, le quali sono
memorie di tipo elettronico, non volatili e riscrivibili. Generalmente
sono di piccole dimensioni e piuttosto costose.
Organizzazione della
memoria
•
La memoria è divisa su almeno due livelli.
•
•
•
Memoria di livello superiore: piccola, veloce e costosa
Memoria di livello inferiore: grande, lenta e a buon mercato
La memoria di livello superiore contiene un sottoinsieme dei dati
e dei programmi residenti nella memoria di livello inferiore.
•
Quando si cerca una parola, si cerca prima nella memoria di livello
superiore e poi nella memoria di livello inferiore. Nel caso si trovi
nel primo livello, l’accesso al dato sarà rapido, in caso contrario
lento.
•
Un organizzazione di questo genere è efficiente solo se esiste un
buon criterio per scegliere quali dati devono essere trasferiti dalla
memoria lenta a quella veloce.
Organizzazione della
memoria
•
È necessario prevedere con una certa precisione il comportamento
dei programmi.
•
Statisticamente, un programma indirizza il 90% delle richieste di
lettura/scrittura a un’area di memoria contigua inferiore al 10%
dell’area complessiva.
•
Località spaziale: quando un programma fa riferimento a un dato,
è molto probabile che faccia riferimento a un dato fisicamente
vicino nell’immediato futuro.
•
Località temporale: quando un programma fa riferimento a un
dato, è molto probabile che si riutilizzi nell’immediato futuro.
Principio di località
•
Principio di Località: le informazioni usate di recente e quelle in
posizioni contigue saranno utilizzate con molta probabilità
nell’immediato futuro.
•
Se si favorisce l’accesso a tali informazioni (precaricandole nella
memoria di livello superiore), si migliorano le prestazioni del sistema.
•
Se la memoria di livello superiore è già piena (di solito è di piccole
dimensioni), le informazioni che soddisfano il principio di località
vanno a sostituire un blocco di memoria di livello superiore, i cui dati
non sono stati recentemente utilizzati (Least Recently Used Policy,
LRU).
Organizzazione
reale
• Generalmente ci sono più di due livelli.
Registri
Memoria Cache
Memoria RAM
Dischi magnetici
Nastri
Dispositivi di
memoria di massa
•
Nastri magnetici
•
•
sono dispositivi ad accesso sequenziale
•
informazioni scritte e lette a blocchi chiamati record fisici,
separati tra loro da spazi chiamati gap.
•
Dispositivi economici, lenti, ma di grandi capacità. Utili per i
backup.
le operazioni di lettura/scrittura sono effettuate mediante una
testina che può rilevare e modificare lo stato di magnetizzazione
del nastro
Dispositivi di
memoria di massa
•
Dischi magnetici
•
•
sono dispositivi ad accesso misto
•
per poter utilizzare un disco, si deve dapprima organizzarlo in
settori e tracce mediante l’operazione di formattazione.
•
per leggere e scrivere dei dati è necessario fornire alla testina
numero di traccia e numero di settore.
•
tipiche unità a dischi: floppy disk, hard disk.
l’informazione memorizzata in anelli concentrici detti tracce. In
ogni traccia è memorizzata la stessa quantità di informazione (=>
densità variabile di memorizzazione). Ogni traccia è suddivisa in
settori. Settori e tracce sono separati da gap.
•
Dispositivi di
memoria di massa
Dischi ottici
•
•
•
sono generalmente dispositivi non riscrivibili (CD-ROM)
•
oggigiorno esistono anche dischi ottici che permettono di essere
riscritti più volte: CD-RW (Rewritable)
•
DVD: dischi ottici di ultima generazione, memorizzano fino a 17
GByte di informazione. I normali CD-ROM arrivano a 800 MByte.
permettono di memorizzare grandi quantità di dati.
i dati sono memorizzati rendendo opache o lucide le zone del
disco (0 o 1). La lettura avviene mediante un raggio laser che
esplora la superficie e identifica il valore dei bit in base alla
riflessione o meno del raggio. L’informazione è organizzata in un
unico percorso a spirale. => accesso sequenziale, che comunque
risulta essere piuttosto veloce.
Interfacce di I/O
•
il calcolatore comunica con l’ambiente esterno (le periferiche)
mediante delle interfacce di ingresso/uscita, che hanno il compito di
tradure i segnali che giungono dal calcolatore in informazioni
comprensibili alle periferiche e vice versa.
•
La trasmissione dei dati può essere
•
•
•
seriale (l’informazione è trasmessa un bit per volta)
parallela (più bit trasmessi in parallelo)
Alcuni standard
•
•
RS-232C, USB, FireWire (tx seriale)
Centronics (tx parallela)
Interfacce di I/O
•
Ogni interfaccia di I/O è dotata almeno dei seguenti registri
•
Registro dati, utilizzato per scambiare i dati tra periferica e
calcolatore. Connesso con il bus dati.
•
Registro di stato (o di controllo), nel quale transitano informazioni
di controllo necessarie alla sincronizzazione tra CPU e periferica.
Connesso con il bus di controllo.
Sincronizzazione
•
Periferiche e CPU hanno generalemnte diverse velocità e necessitano
di sincronizzazione.
•
Ci sono tre diversi metodi di sincronizzazione:
•
•
•
a controllo di programma
a interruzione
con accesso diretto alla memoria
Sync. a controllo di
programma
•
•
La sincronizzazione è completamente gestita dalla CPU.
•
Esempio: stampa di una linea di caratteri mediante una stampante,
ogni singolo carattere viene trasferito alla stampante mediante il
registro dati, solo quando un carattere è stato stampato viene
trasferito nel registro dati il seguente.
•
•
Vantaggio: è una gestione della sincronizzazione semplice.
La CPU esegue un ciclo (detto ciclo di polling) che ispeziona/scrive
periodicamente il registro dati.
Svantaggio: rischio di sovraccarico della CPU
Sync. a interruzione
•
Elimina il problema di sovraccarico della CPU tipico della
sincronizzazione a controllo di programma.
•
Ogni interfaccia è dotata della possibilità di notificare il suo status
alla CPU mediante un segnale chiamato interruzione (o interrupt).
•
Quando la CPU riceve un interrupt, interrompe la sua attività ed
esegue un programma di risposta all’interruzione per gestire la
comunicazione con l’interfaccia (e quindi con la periferica).
•
La CPU è occupata solo per il trasferimento dei dati. (si evitano i
tempi di attesa del ciclo di polling)
Sync. con accesso
diretto alla memoria
•
Se si hanno grossi e frequenti trasferimenti di dati, la gestione della
sincronizzazione mediante interrupt rischia di essere inefficiente.
•
Esistono delle componenti HW chiamate DMA (Direct Memory Access)
che sostituiscono la CPU nella gestione del trasferimento dati.
•
La CPU controlla i DMA, comunica loro solo l’indirizzo di memoria da
cui leggere o sul quale scrivere e la quantità di dati da trasferire,
dopodiché il DMA gestisce l’intero processo di trasferimento.
•
Nelle architetture più sofisticate i DMA sono processori dedidati
all’input/output.
Infrastrutture
Software
• I componenti fisici di un sistema informatico
sono resi accessibili agli utenti attraverso un
complesso di strumenti software finalizzati
all’utilizzo dell’architettura.
• Si tratta di Software (programmi) di base
generalmente fornito insieme al Hardware.
• L’insieme di tali programmi di base è indicato
con il termine sistema operativo (S.O.).
Le funzioni del S.O.
•
Il S.O. è un interfaccia tra l’utente e l’hardware che facilita
l’utilizzo delle risorse di un sistema. In particolare deve svolgere le
seguenti funzioni:
•
•
•
•
•
•
esecuzione di applicazioni
accesso ai dispositivi di I/O
archiviazione di dati e programmi
controllo d’accesso
contabilizzazione
gestione dei malfunzionamenti
Elementi di un S.O.
•
Generalmente l’insieme dei programmi costituenti il S.O. permette di
gestire:
•
il processore (quali programmi eseguire e quali compiti assegnare
alla CPU, traduzione dei programmi ad alto livello al linguaggio
assembly mediante il supporto di compilatori e interpreti)
•
la memoria (allocazione della memoria per i diversi programmi in
esecuzione, definizione di zone riservate di memoria per
l’archiviazione dei dati dei programmi)
•
le periferiche (accesso ai dispositivi di I/O, si mascherano i
dettagli di basso livello, gestione dei conflitti)
Elementi di un S.O.
•
il file system (archiviazione e reperimento dei dati in memoria di
massa)
•
gli utenti e i relativi interpreti comandi (accesso semplice alle
funzionalità disponibili)
I gestori di memoria, processore, file system, periferiche e utenti
interagiscono fra loro per coordinare l’accesso alle risorse da parte di
utenti e SW applicativo.
Programmi
applicativi
•
Sono programmi utilizzati dall’utente per svolgere attività di alto
livello (elaborazione di testi e grafica, giochi, fogli di calcolo,...)
•
non fanno parte dei programmi del S.O. In particolare,
•
possono far riferimento ad un set ristretto di istruzioni del
processore (modalità utente vs modalità supervisore)
•
non possono decidere autonomamente quando e come avere
accesso alle risorse. È il S.O. stesso a fornire loro l’accesso alle
risorse.
Tassonomia degli
utenti
• Gli utenti di un S.O. possono
• programmatori di sistema
• amministratori di sistema
• utenti applicativi
essere
Un po’ di storia dei
S.O.
•
sistemi senza S.O: i programmi applicativi dovevano anche contenere
delle istruzioni per la gestione a basso livello dei dispositivi fisici.
•
I programmi erano caricati in memoria tramite un dispositivo di I/O
in grado di leggere schede perforate contenenti la codifica in
linguaggio macchina di dati e programmi.
•
Pessima gestione delle risorse: si doveva prenotare la macchina al
fine di stabilire un ordine di esecuzione dei programmi (Job).
•
•
La macchina consentiva l’esecuzione di un solo programma alla volta.
Perdita di tempo per la preparazione dell’ambiente di supporto
all’esecuzione.
•
Un po’ di storia dei
S.O.
Sistemi batch (o a lotti): sono dotati di una componente software
(un S.O. molto rozzo) chiamata monitor in grado di automatizzare
l’esecuzione dei programmi. Il monitor è dotato di un linguaggio di
controllo chiamato Job Control Language.
•
•
Si esegue un lotto di programmi (jobs) alla volta.
•
•
Efficiente utilizzo delle risorse
Non c’è nessuna interazione con l’utente. (ottimi per attività con
bassa interazione: esempio stampa estratti conto).
Tempi di attesa notevoli per ottenere i risultati dell’elaborazione (si
deve attendere la terminazione dell’esecuzione di un intero lotto di
job).
Un po’ di storia dei
S.O.
•
Nei primi sistemi informatici mancava
•
•
•
interattività
•
gestione dell’input/output i programmatori dovevano scriversi le
loro funzioni a basso livello per l’input e l’output)
•
sfruttamento parallelo delle risorse
protezione della memoria (evitare interferenze fra programmi in memoria)
temporizzazione dell’esecuzione (al fine di evitare il monopolio
dell’intero sistema da parte di un solo programma)
Un po’ di storia dei
S.O.
•
•
sistemi uniprogrammati
•
in memoria può risiedere al più un programma (processo) oltre al
S.O.
•
•
es. MS-DOS
ridotto uso della CPU
sistemi multiprogrammati (time-sharing)
•
•
•
più progammi contemporaneamente in memoria oltre al S.O.
es. Windows, MacOS, Unix,...
Uso più efficiente della CPU
Un po’ di storia dei
S.O.
•
Nei primi sistemi informatici mancava
•
•
•
interattività
•
gestione dell’input/output i programmatori dovevano scriversi le
loro funzioni a basso livello per l’input e l’output)
•
sfruttamento parallelo delle risorse
protezione della memoria (evitare interferenze fra programmi in memoria)
temporizzazione dell’esecuzione (al fine di evitare il monopolio
dell’intero sistema da parte di un solo programma)
Processi
•
Nei sistemi attuali, più copie dello stesso programma si possono
eseguire concorrentemente.
•
Processo = copia di un programma in esecuzione + dati necessari
all’esecuzione.
•
A un programma può corrispondere più di un processo (processi figli
e processi padre, es. videoscrittura + stampa).
•
Un S.O. è un’infrastruttura SW di supporto all’esecuzione
concorrente di più processi.
Modelli organizzativi
di S.O.
• Ogni S.O. può essere caratterizzato
funzionalmente da
• un nucleo (kernel)
• un insieme di processi di servizio.
• Modello monolitico vs modello a strati
Modello monolitico
•
Il S.O è costituito da un unico processo kernel che provvede alla
gestione di tutti i servizi di tutte le risorse del sistema (processore,
memoria, periferiche, file system, ...)
•
gli utenti e i processi applicativi interagiscono con il kernel
attraverso l’esecuzione di servizi (chiamate di sistema).
•
si hanno due modalità di funzionamento
•
modalità utente: i processi eseguiti in questa modalità non
possono accedere a tutte le risorse liberamente. Es. vietato
interagire direttamente con i dispositivi di I/O.
•
modalità supervisore (kernel mode): usata dal kernel per
implementare le funzionalità necessarie. Nessun limite nelle
operazioni effettuabili.
Modello a strati
•
consiste in un nucleo piuttosto semplice che gestisce solamente il
processore e l’esecuzione dei processi. Interagisce direttamente con
l’hardware.
•
Una serie di processi di servizio standard organizzati su diversi
livelli (macchine virtuali).
•
•
ogni processo di un livello implementa delle funzionalità facendo
uso dei servizi messi a disposizione dal livello inferiore
È un’organizzazione che favorisce la portabilità del S.O. su diverse
architetture HW.
Modello a strati
Applicazione (Editor)
Interprete dei Comandi
Applicazione
(Foglio Elettronico)
File System
Periferiche
Memoria
Nucleo
HW
Applicazione (EMail)
Applicazione (Browser)
Applicazione (Data Base)
Applicazione
(Word Processor)
Traduzione dei
programmi
•
La CPU si comporta da esecutore per programmi scritti in linguaggio
macchina (assembly)
•
•
E’ un linguaggio a basso livello difficile da usare.
Soluzione: usare un linguaggio L di alto livello più potente ed
espressivo. Utilizzare degli opportuni software per tradurre i
programmi scritti in L in programmi assembly.
•
•
Interpreti
Compilatori
Gestione dei
processi
•
Nelle architetturre HW moderne si tende ad elaborare
l’informazione in maniera parallela.
•
3 livelli di parallelismo
•
•
•
parallelismo a livello di dati
parallelismo a livello di istruzioni
parallelismo a livello di programmi
•
i primi due livelli di parallelismo sono gestibili solo mediante
architetture HW parallele (molte CPU), il modello di Von Neumann
può implementare solo il parallelismo a livello di programmi.
•
il gestore dei processi ha il compito di implementare in maniera
efficiente il parallelismo a livello di programmi.
•
•
•
Gestione dei
processi
Il componente in grado di eseguire i processi è la CPU (processore)
Se abbiamo un unico processore il parallelismo è simulato.
Un processo può trovarsi in un uno dei seguenti stati:
•
in esecuzione: ovvero il processo ha a disposizione il processore
per l’esecuzione del proprio codice
•
pronto: ovvero il processo è in grado e in attesa di essere
eseguito, non appena il processore diviene disponibile (i processi
in questo stato vengono generalmente posti in coda, FIFO policy)
•
in attesa: ovvero il processo non è in grado di essere eseguito
perché in attesa di qualche evento esterno (es. input da tastiera)
Evoluzione di un
processo
1. il processo viene creato e messo nella coda dei processi pronti
2. il primo processo nella coda dei processi pronti viene posto in stato di
esecuzione; se la coda era inizialmente vuota, il processo in esecuzione
coincide con quello creato al punto precedente
3. il processo in esecuzione ha la piena disponibilità del processore fino al
verificarsi di uno dei seguenti eventi:
a. scade il quanto di tempo a disposizione del processo; il processo
viene rimesso nella coda dei processi pronti
b. il processo effettua un’operazione I/O; il processo è messo in stato
d’attesa
c. il processo termina
4. in base a quale evento si è verificato in 3, il processo evolve nel
seguente modo:
a. il processo attenderà il suo turno nella coda per essere nuovamente
eseguito
b. il processo viene rimesso nella coda dei processi pronti, una volta che
l’operazione di I/O è terminata
c. il processo è rimosso dall’elenco dei processi esistenti
•
Problemi del
parallelismo
Morte per fame (Starvation): un processo in stato di pronto non
viene mai eseguito.
•
•
non accade nel caso di politica FIFO, può accadere nel caso di
utilizzo di code con priorità.
Blocco critico (Deadlock): un insieme di processi rimane
permanentemente bloccato. Es. due processi A e B. A richiede i dati
di B per essere eseguito, B richiede i dati di A per essere eseguito.
Oppure, mai invitare 5 filosofi a cena!!!
•
•
Tecniche di verifica statica per evitare deadlock
Tecniche di eliminazione dei deadlock a runtime
Gestione della
memoria
•
Nei S.O. multiprogrammati possiamo avere molti processi in memoria
centrale
•
Problema: la memoria centrale è tipicamente di piccole dimensioni
(Max 1Gb).
•
Si rende necessaria l’implementazione di un gestore della memoria
che scarichi in memoria di massa i processi poco utilizzati e che
inoltre permetta di
•
ridurre la necessità di spazio mantenendo in memoria solo parte
delle istruzioni e dei dati del processo.
•
ridurre la necessità di spazio condividendo il codice fra diversi
processi che corrispondono allo stesso programma.
(segmentazione della memoria: segmento codice, segmento dati)
Gestione della
memoria
•
il gestore della memoria permette di trasferire il contenuto di
un’area di memoria centrale in un’area di memoria di massa chiamata
memoria di swap.
•
si trasferiscono nell’area di swap i processi in attesa e alcuni dei
processi in stato di pronto al fine di liberare memoria centrale.
•
Per lo scarico nell’area di swap si segue il principio di località.
Gestione della
Memoria
• La politica migliore per la gestione della
memoria prevede di scaricare la pagina
che sarà utilizzata il più tardi
possibile. Soluzione impossibile!
• Approssimazioni dell’algoritmo ottimo:
e.g. scaricare la pagina usata meno di
recente (Least Recently Used - LRU).
Gestione della
Memoria
• Altro problema: protezione della
memoria.
• Ad ogni processo è assegnata un’area di
memoria distinta. Se un processo
“invade” aree di memoria diverse, viene
segnalata l’eccezione.
Gestione delle
periferiche
•
Il gestore delle periferiche mette a disposizione delle funzionalità di
lettura/scrittura da/verso dispositivi periferici di alto livello,
indipendenti dalla struttura HW delle periferiche.
•
Tali comandi di alto livello sono realizzati facendo uso di meccanismi
HW e SW di basso livello quali
•
•
driver (programmi SW destinati alla gestione delle periferiche)
controller (interfacce di I/O HW per il trasferimento di dati
gestiti generalmente via interrupt)
Gestione delle
periferiche
•
I driver permettono
•
•
di astrarre le operazioni di lettura/scrittura
•
di virtualizzare la presenza di più periferiche (spooling)
permettono di implementare operazioni di scrittura/lettura a
basso livello affidabili (se un’operazione non va a buon fine viene
ripetuta, nel caso in cui no sia possibile eseguirla viene segnalato
il malfunzionamento)
•
esempio: la coda di stampa
Il File System
•
È la componente del S.O. che si occupa della gestione della memoria
di massa e dell’organizzazione logica dei dati
•
Le operazioni supportate da un file system sono:
•
•
•
•
recupero dei dati precedentemente memorizzati
eliminazione di dati
modifica dei dati
copia dei dati fra diversi dispositivi di memoria di massa
Il File System
•
I dati sono memorizzati in contenitori logici detti file. Ogni file è
identificato da un nome (il nome può essere affiancato da
un’estensione che individua il tipo di file)
•
Per una miglior organizzazione dei dati, i file possono essere
memorizzati in contenitori detti directory o cartelle.
•
il file system è generalmente organizzato secondo una struttura ad
albero.
•
Possiamo individuare un file fornendo il percorso assoluto o relativo
all’interno dell’albero del file system.
•
L’accesso all’informazione può avvenire attraverso opportuni comandi
testuali o grafici
Organizzazione
fisica dei dati
• I file sono memorizzati sul supporto
fisico
(dispositivi di memoria di massa) in blocchi di
piccole dimensioni.
• I blocchi potrebbero essere non contigui!
• Due tecniche di memorizzazione
• File Allocation Table (FAT)
• I-nodes
FAT
•
L’associazione tra nome del file e blocchi fisici che contengono il file
viene gestita mediante una lista concatenata: a partire dal primo
blocco, in coda ad ogni blocco di dati viene riportato il successivo.
•
Tale struttura viene memorizzata in un’area del disco chiamata FAT
(File allocation Table)
•
Per ogni file, nella FAT è mantenuto un descrittore di file contenente
i seguenti dati
•
•
indirizzo del primo blocco del file
data e ora di modifica, dimensioni,...
•
L’organizzazione mediante FAT funziona bene per file di piccole
dimensioni
•
Usata in Windows 95/98
I-NODES
•
L’organizzazione in blocchi è basata su delle strutture dati chiamate
i-node, le quali possono mantenere sia informazioni inerenti al
descrittore del file sia inerenti ai blocchi di dati.
•
Un i-node può contenere informazioni inerenti ai blocchi di dati
quando il file è piccolo, altrimenti può indicare insiemi di altri inode.
•
Ai file di grandi dimensioni è associato un albero di i-nodes, le cui
foglie contengono i riferimenti ai blocchi di dati.
•
•
La struttura ad albero rende più efficiente l’accesso ai dati.
È una metodologia di memorizzazione tipicamente usata nei sistemi
UNIX.
La frammentazione
•
Frammentazione esterna: in caso di allocazione contigua dei file è
necessario avere un numero di blocchi liberi contigui pari al numero di
blocchi del file da memorizzare. FAT e I-Nodes risolvono questo
problema in quanto non prevedono allocazione contigua dei dati.
•
Frammentazione interna: un file deve comunque occupare uno spazio
pari ad un multiplo intero della dimensione dei blocchi. Problema non
risolvibile né con FAT né con I-Nodes.
Controllo degli
accessi
•
I S.O. multiutente possiedono meccanismi di identificazione degli
accessi al sistema.
•
La modalità più usata prevede di associare ad ogni utente un
account (i.e. nome) e una password.
•
in questo modo è possibile
•
•
•
personalizzare l’ambiente operativo di ogni utente
facilitare la distribuzione dei costi di gestione
fornire una diversa visibilità del sistema a differenti tipi di
utente
Controllo degli
accessi
•
Oltre a fornire un controllo sugli utenti è anche possibile stabilire un
sistema di protezione dei file.
•
Esempio: nei sistemi Unix, si possono distinguere 3 tipi di utenti: il
proprietario di un file, il gruppo di utenti a cui appartiene il
propietario del file e il resto del mondo.
•
•
Per ogni tipologia di utente possiamo abilitare le operazioni di
lettura (R) del file, scrittura del file (W), esecuzione del file (X).
Nei S.O. multiutente è anche possibile proteggere l’accesso alle varie
risorse di sistema mediante le Access Control List (ACL), ovvero liste
che specificano quali utenti possono utilizzare determinate risorse
(Es. ad alcuni utenti può essere proibito l’uso di una stampante di
rete)
Le applicazioni
•
Le applicazioni (programmi applicativi) nascondono i dettagli di basso
livello all’utente.
•
Un programma applicativo è composto da tre componenti
fondamentali:
•
•
sottosistema di interfaccia con l’utente (interfaccia utente): si
incarica di cotrollare gli input dell’utente e presentare gli output
dei risultati computati. Le interfacce possono essere grafiche o
testuali.
•
sottosistema di logica applicativa: implementa gli algoritmi per la
manipolazione di dati che caratterizzano l’applicazione
•
sottosistema di gestione dei dati: si occupa dell’organizzazione
dei dati, in particolare reperimento e memorizzazione.
Sono 3 sistemi indipendenti (gestione più semplice e rapida dello
sviluppo del SW)
Sviluppo delle
applicazioni
•
Le applicazioni possono essere sistemi complessi. Dunque si devono
progettare con cura
•
•
la programmazione di un’applicazione è solo una fase nella catena
di sviluppo del SW.
Lo sviluppo di un SW può essere suddiviso nelle seguenti attività:
•
•
•
•
•
analisi e specifica dei requisiti
progettazione
sviluppo e test
rilascio
manutenzione
Ciclo di vita del SW
•
L’insieme delle attività necessarie allo sviluppo di un’applicazione
formano il ciclo di vita del software.
•
Il ciclo di vita del software può essere strutturato secondo diversi
modelli:
•
•
modello a cascata: attività svolte in sequenza
•
modello evolutivo: si opera in modo incrementale, iniziando a
sviluppare le componenti più critiche del sistema e arrichendo via
via il sistema di nuove funzionalità.
modello a prototipi: si comincia lo sviluppo direttamente
implementando dei prototipi
Tipi di applicazioni
•
•
Word processors: videoscrittura, elaborazione del testo
•
•
Browser (per navigare in internet)
•
•
per presentazioni
•
per la posta elettronica e altri tipi di servizi di rete
spreadsheets (o fogli elettronici): per costruire tabelle, grafici e
fare dei calcoli.
Basi di dati (per memorizzare e reperire efficientemente
l’informazione)
per l’elaborazione grafica e video (fotoritocco, disegno, montaggio
digitale...)
Word Processors
• si possono distinguere in due categorie
• WYSIWYG (What You See Is What You
Get): es. Word
• non WYSIWYG: prevedono un linguaggio
per la formattazione del testo, es. LaTeX.
Esempio LaTeX
$$E_1=\{e\mid e\in\cI^- \mbox{ and }
\ll e\rr\not\in\bigcup_{\cI'\in \cA_1}\cI'\}$$
Reti di calcolatori
Reti di calcolatori
•
Rete di calcolatori: insieme di calcolatori interconnessi mediante una
rete di comunicazione.
•
Si possono distinguere
•
reti di calcolatori vere e proprie
•
•
ogni calcolatore mantiene una propria indipendenza, gli utenti
interagiscono in modo esplicito con la rete
sistemi distribuiti
•
•
gli utenti non hanno visibilità sull’architettura del sistema
si presentano come sistemi omogenei progettati per eseguire
un’applicazione particolare (Es: BANCOMAT)
Finalità di una rete
• condivisione di risorse (memoria di massa,
stampanti, CDROM, ...)
• comunicazione tra utenti (posta elettronica,
file transfer,...)
• miglioramento dell’affidabilità
• risparmio attraverso la condivisione di risorse
Classificazione
•
tecnologia di comunicazione
•
•
•
reti punto a punto
reti multipunto (o broadcast)
dimensione
•
Local Area Network (LAN): limitata estensione, calcolatori
all’interno di un edificio
•
•
Metropolitan Area Network (MAN): area urbana
•
reti di reti (internet working): collegamenti di più reti differenti
mediante elementi di interfaccia
Wide Area Network (WAN): ampie dimensioni, collegamenti anche
intercontinentali
Reti punto a punto
•
Ogni coppia di calcolatori è connessa mediante una linea di
comunicazione dedicata
•
È una soluzione poco praticata perché
•
se i calcolatori da connettere sono fisicamente molto distanti, il
costo della linea dedicata potrebbe essere molto elevato
•
se dei calcolatori devono essere collegati in modo non
continuativo, l’uso di linee dedicate non ha molto senso ed è
costoso
•
Nel caso si debbano connettere i calcolatori con modalità “tutti
con tutti”, il numero di connessioni dedicate da creare è molto
elevato.
Reti Broadcast
•
Le reti broadcast sono caratterizzate da canali di comunicazione
condivisi
•
Ogni calcolatore sulla rete è caratterizzato da un identificatore
univoco (indirizzo di rete)
•
Ogni messaggio spedito da un calcolatore include l’indirizzo del
destinatario.
•
Ogni messaggio spedito raggiunge tutti i calcolatori connessi, solo il
calcolatore il cui indirizzo di rete corrisponde a quello contenuto nel
messaggio riceve il messaggio.
WAN
•
•
Nel caso più generale una rete geografica (WAN) può essere
rappresentata su 3 livelli:
•
rete di trasmissione: si occupa della trasmissione
dell’informazione fra i diversi nodi (IMP - Interface Message
Processors), instradamento, verifica della correttezza dei
messaggi
•
rete di calcolatori (hosts): i calcolatori sono collegati agli IMP. Lo
scopo è quello di eseguire le applicazioni.
•
rete degli utenti: comunicazione fra utenti, esecuzione di
applicazioni distribuite in maniera trasparente
Le reti organizzate secondo questi livelli sono chiamate reti
commutate
WAN
•
Le reti geografiche si classificano a seconda della strategia
utilizzata per instradare i messaggi
•
commutazione di circuito
•
Viene inizialmente stabilita una connessione temporanea tra
mittente e destinatario. Una volta che la connessione è
stabilita, inizia il trasferimento dei dati.
•
Vantaggiosa nel caso in cui la comunicazione sia molto
frequente e non si abbiano periodi di inattività della linea. (es.
sistema telefonico).
WAN
•
commutazione di pacchetto
•
il messaggio è frammentato in pacchetti di piccole dimensioni.
Ogni pacchetto contiene l’indirizzo del destinatario e un numero
progressivo che indica la posizione del pacchetto nel messaggio.
•
Vantaggi: uso dei canali più efficiente, possibilità di invio anche in
caso di traffico elevato, gestione di diversi livelli di priorità
•
due metodi di instradamento
•
a datagrammi (spedizione dei pacchetti in maniera
indipendente, anche su linee diverse)
•
a circuito virtuale (si stabilisce un cammino univoco tra
mittente e destinatario per tutti i pacchetti).
LAN
•
Obiettivo: connettere dispositivi fisicamente vicini => tecnologie
diverse da quelle impiegate nelle WAN (tipicamente usano un
approccio broadcast).
•
Le LAN sono generalmente
•
•
•
•
veloci (canali di comunicazione con ampia capacità di banda)
facilmente espandibili, modulari
economiche
affidabili
LAN
•
Le LAN possono essere caratterizzate dalla loro topologia di rete,
ossia dalla struttura delle loro connessioni
•
•
topologia a bus (semplice, flessibile, economica, es: ethernet)
•
il guasto di un host non implica la disabilitazione dell’intera
rete
•
svantaggio: unico mezzo di comunicazione, pessime prestazioni
in caso di molto traffico
topologia a stella (connessione punto a punto)
•
•
controllo centralizzato delle risorse, ottime prestazioni
rischio di sovraccarico del server, dipendenza dall’affidabilità
del server
LAN
•
Topologia ad anello: prevede una connessione circolare degli host
•
•
•
•
possono avere dimensioni molto elevate
limitata flessibilità, è difficile espanderla
l’affidabilità della rete dipende dall’affidabilità di tutti gli host
(soluzione: reti a doppio anello)
Topologia Wireless: approccio broadcast
•
trasmissione basata su onde radio
Internetwork
•
Una LAN non può crescere oltre una certa misura, se non al prezzo
di un rilevante decadimento delle prestazioni.
•
Soluzione: connettere più LAN insieme (LAN estesa) mediante
•
•
•
repeater (se le LAN sono identiche)
•
router (per reti con schemi di indirizzamento distinti, ma stesso
protocollo di rete)
•
gateway (per reti completamente incompatibili)
switch (permette un maggior numero di tx in contemporanea)
bridge (per filtrare i pacchetti e in caso di reti distinte ma con
stesso schema di indirizzamento)
Architettura del SW
di rete
• I calcolatori collegati in rete devono
cooperare per stabilire una comunicazione e
per poter trasmettere dei dati.
• Le regole che formalizzano
questa
cooperazione sono chiamate protocolli di
comunicazione.
• Condividendo lo stesso protocollo due
calcolatori possono comunicare.
Protocolli di
comunicazione
•
mediante i protocolli di comunicazione si specificano tra l’altro
•
•
formati dei dati, struttura dei messaggi (pacchetti), velocità di
trasmissione, come e quando comunicare...
La comunicazione può essere piuttosto complessa, pertanto si
specificano insiemi di protocolli, ognuno dei quali formalizza aspetti
distinti della trasmissione. Ciò rende il progetto del SW di rete più
semplice e flessibile
Architettura di rete
•
Un’architettura di rete dovrebbe essere organizzata
gerarchicamente seguendo i principi qui elencati
•
ogni protocollo formalizza un diverso livello di astrazione della
comunicazione
•
le funzioni associate ad ogni livello sono ben definite e omogenee
tra loro
•
scopo di ogni livello è di fornire servizi al livello superiore,
mascherando il modo in cui sono implementati. Ogni livello è
caratterizzato da una interfaccia con il livello superiore.
•
Le interfacce sono progettate in modo da minimizzare gli scambi
tra un livello e l’altro
Architettura a livelli
•
Consideriamo due processi (sorgente e destinazione), residenti su
host distinti, che vogliono comunicare
•
ognuno dei due host è dotato di un insieme di protocolli organizzati
su livelli. In entrambi gli host, i livelli devono essere organizzati in
maniera compatibile.
•
La trasmissione avviene simulando la comunicazione tra livelli
corrispondenti, seguendo le regole stabilite dal corrispondenti
protocolli di livello.
•
Ogni protocollo è caratterizzato da sintassi, semantica e
temporizzazione
•
Standard ISO/OSI
Standard TCP/IP
•
È l’architettura a livelli che permette l’interoperabilità tra reti
fisiche diverse. È semplice ed efficiente
•
•
È lo standard de facto di Internet
È un’archittettura basata su 5 livelli
•
•
livello applicazione
•
•
livello internet (implementato dal protocollo IP-Internet Protocol)
livello di trasporto (implementato dal protocollo TCP-Transmission
Control Protocol)
livello di accesso alla rete
livello fisico
Standard TCP/IP
•
il livello fisico definisce l’interfaccia fisica tra stazione e mezzo di
trasmissione
•
il livello di accesso alla rete si occupa dello scambio di dati tra un
sistema finale e la rete. I dati sono organizzati in frame.
•
il livello internet si occupa di interfacciare sistemi su reti distinte
(formato dei pacchetti e meccanismi per farli transitare attraverso
uno o più router).
•
il livello di trasporto si occupa di garantire l’affidabilità della
trasmissione dei dati
•
il livello applicazione specifica come le applicazioni possono
utilizzare i servizi forniti dall’insieme di protocolli TCP/IP.
Funzionamento di
TCP/IP
•
•
Ogni host individuato da un indirizzo univoco all’interno della rete.
•
Per poter comunicare con un processo in un host è necessario
specificare l’indirizzo del host e la porta del processo.
Ogni applicazione di un host è individuata da un indirizzo univoco
all’interno del host (porta).
Funzionamento di
TCP/IP
•
Quando un processo in un host A vuole trasmettere un messaggio a
un processo in un host B deve:
•
consegnare il messaggio al livello TCP indicando l’host
destinatario (B) e la porta del processo destinatario
•
TCP aggiunge info di controllo al messaggio (lo può anche
spezzettare) e lo invia al livello IP. Il livello IP aggiunge
informazioni di controllo al messaggio e lo invia al livello di
accesso alla rete
•
il livello di accesso alla rete aggiunge un’ulteriore intestazione al
messaggio e finalmente lo invia al livello fisico che lo spedirà.
Indirizzi Internet
•
Il protocollo IP fornisce uno schema di indirizzamento universale.
•
indirizzi a 32 bit, di solito rappresentati come successione di 4
numeri decimali separati da punti:
X.Y.Z.W, con X,Y,Z,W
compresi tra 0 e 255.
•
•
Es.: 66.102.11.104
•
La versione attuale del protocollo IP non è più sufficiente: si è
ormai vicini alla saturazione. Nuovo protocollo: IPv6, indirizzi a
128 bit, presenza di un supporto per audio e video,...
Esiste un’organizzazione che assegna univocamente gli indirizzi
IP chiamata IANA (Internet Assigned Number Authority)
Indirizzi Internet
Simbolici
•
Gli indirizzi numerici IP sono machine-oriented e difficilmente
memorizzabili dall’uomo.
•
soluzione: associare ad ogni indirizzo numerico un indirizzo simbolico
mediante un sistema denominato DNS (Domain name system). Es.
www.google.com
•
I DNS eseguono la conversione degli indirizzi in maniera totalmente
trasparente all’utente. Gli indirizzi simbolici sono suddivisi in domini
e sottodomini.
•
Es. Considerate www.google.com
•
•
•
.com indica il dominio di primo livello
google.com il dominio di secondo livello
www.google.com individua il calcolatore nel sottodominio
Affidabilità di
TCP/IP
• Protocolli orientati alla connessione
(connection-oriented)
• TCP
• Protocolli non orientati alla connessione
(connectionless)
• IP, UDP (User Datagram Protocol)
Il World Wide Web
•
L’architettura client-server è alla base di quasi tutti gli applicativi di
Internet.
•
Il WWW (World Wide Web) è una tipica applicazione distribuita
client-server composta da:
•
•
Client, ovvero i browser (navigatori) Internet: e.g. Safari,
Netscape, Internet Explorer,...
•
i Web server (Apache, Internet Information Server, ...)
Client e server comunicano mediante il protocollo HTTP (HyperText
Transfer Protocol)
HTTP
•
il protocollo HTTP è utilizzato per condividere informazione sulla
rete (pagine Web, documenti multimediali, etc.)
•
•
Esempio d’uso:
•
Il server riceve la richiesta da parte del browser, reperisce
l’informazione nel suo disco locale e la spedisce al cliente insieme ad
alcune informazioni di controllo (e.g. codice d’errore, tipo di
documento, lunghezza del documento, tipo di web server,...)
•
è un protocollo stateless: non mantiene la storia delle richieste
ricevute.
Il cliente (browser) richiede un’informazione indicando un indirizzo
(Es.: http://polygen.org/web/Ghezzi.645.0.html) e genera un
messaggio di tipo GET contenente indirizzo ed altre informazioni
ausiliarie da inviare al server (e.g. versione del protocollo, tipo di
browser, etc.).
Altri servizi di rete
•
altri servizi Internet sono implementati mediante applicazioni client
server
•
TELNET, permette di impiegare il proprio calcolatore come
terminale di un calcolatore (protocollo SSH: versione di telnet sicura)
•
posta elettronica (SMTP - Simple Mail Transfer Protocol, POP3,
IMAP)
•
trasferimento file (FTP - File Transfer Protocol, SFTP - Secure
File transfer Protocol,...)
•
Utilità di rete
•
•
•
ping
traceroute
...
•
Struttura del
sistema email
è gestito mediante un protocollo client-server.
•
Il programma client (e.g. Eudora, Outlook) si connette al mail
server del mittente ed invia il messaggio mediante protocollo
SMTP.
•
Sempre mediante SMTP il mail server del mittente invia il
messaggio al mail server del destinatario.
•
L’utente destinatario scarica il messaggio dal server utilizzando
uno dei seguenti protocolli
•
•
Post Office Protocol 3 (POP3)
Internet Message Access System (IMAP)
Uniform Resource
Locator
• Uniform Resource Locator (URL) permette di
identificare in modo univoco la risorsa e il
metodo di accesso alla risorsa sulla rete.
• In generale,
protocollo://host:portaTCP/risorsa
Applicazioni su più
livelli
•
Un URL può individuare non solo dati ma anche programmi da dover
eseguire in maniera remota.
•
In questo caso il browser richiede l’esecuzione del programma al
server web che a sua volta delega il compito al programma vero e
proprio (back-end). Si tratta di un’architettura su 3 livelli (client,
server, back-end). Il sottosistema LA è gestito dal back-end.
•
È un sistema a deleghe successive: il server svolge anche un ruolo di
client verso il back-end.
•
La richiesta del client può contenere anche una lista di parametri
sui quali eseguire il programma. Essi vengono specificati mediante la
standard Common Gateway Interface (CGI).
Applicazioni su più
livelli
• Nelle applicazioni distribuite molto complesse
possiamo avere una struttura su 4 livelli. la
quale prevede un’applicazione (DBMS - Data
Base Management System) per
l’implementazione del sottosistema di
gestione dei dati connessa al Back-end.
•
Browser <-> Web Server <-> Back-end <-> DBMS
Sicurezza
•
Tecniche per filtrare il traffico di rete che operano a livello IP (sui
router)
•
•
Tecniche di sicurezza a livello TCP
•
•
•
packet filtering
permettono di definire limitazioni nell’accesso ai servizi internet
Virtual Private Network (VPN)
Esistono calcolatori destinati a proteggere reti private da eventuali
intrusioni (FireWall)
•
Spamming, virus, Deny of service attacks, mail bombing,...
Sicurezza
•
Ipotizziamo che un’entità A si metta in comunicazione con un’entità
B. I requisiti di sicurezza che si devono garantire sono
•
Privatezza dei dati trasmessi (evitare che un entità C intercetti il
flusso di dati)
•
Integrità dei dati e servizi richiesti (C potrebbe frapporsi tra A
e B e manipolare l’informazione in transito)
•
•
Identità dei partner (C potrebbe camuffarsi da A o B)
non ripudiabilità degli impegni (A potrebbe negare di aver inviato
dati a B o B potrebbe negare di avere ricevuto dati da A).
Sicurezza
• Per garantire i requisiti di sicurezza si
utilizzano tecniche di crittografia:
• A critta con una chiave il messaggio e lo
invia a B, B riceve il messaggio e lo
decritta con una chiave.
• Crittografia a chiave simmetrica
• Crittografia a chiave asimmetrica
C. a Chiave
simmetrica
• Le entità A e B devono condividere la stessa
chiave per codificare e decodificare il
messaggio e lo stesso programma di
crittografia.
• Svantaggio: come trasferire la chiave in
modo sicuro da A a B?
• La tecnica a chiave simmetrica non fornisce
le capacità per garantire l’integrità dei dati
e nemmeno l’identità del mittente.
C. a chiave
asimmetrica
• Non è necessario fornire un canale sicuro per
il trasferimento delle chiavi. Transitano infatti
sulla rete solo chiavi pubbliche.
• È necessario verificare a chi corrisponde una
determinata chiave pubblica.
• Esistono Autorità di Certificazione che
garantiscono l’identità del proprietario di
una data chiave pubblica.
• Problema: chi controlla i controllori?
C. a chiave
asimmetrica
•
Ogni entità dispone di una coppia di chiavi (SW: GnuPG, PGP):
•
•
la chiave pubblica
la chiave privata
•
A critta il messaggio M con la sua chiave privata (firma digitale)
ottenendo il messaggio firmato M1
•
A critta M1 con la chiave pubblica di B e ottiene il messaggio
crittato M2 da spedire a B.
•
B usa la sua chiave privata per decodificare il messaggio e poi la
chiave pubblica di A per verificarne l’autenticità (i.e. la firma).
Motori di ricerca
•
Sono delle risorse per il recupero dell’informazione
tipicamente accessibili dalla rete
•
Tipicamente i risultati ottenuti sono classificati
secondo la loro rilevanza mediante qualche metrica.
•
Permettono di ricercare informazione in differenti
ambienti (Web, newsgroups, basi di dati...)
Motori di ricerca
• Come funzionano?
•
Browsers automatizzati esplorano il web (Web
Crawlers, Web Spider, Web Robots) alla ricerca di
nuove pagine Web
•
Le nuove pagine Web vengono catalogate ed il loro
contenuto è indicizzato rispetto a delle parole
chiave (titolo, headings, metatags...)
•
L’utente interroga il motore di ricerca fornendo
tipicamente delle parole chiave (query) ed altri
criteri di ricerca (alcuni motori supportano
operatori booleani AND,OR,NOT, etc.)
Un esempio: Google
ambienti di ricerca
criteri di ricerca avanzati
query
Google: criteri di ricerca
Query complesse
Ricerca frase: “frase da cercare”
Ricerca di una delle seguenti query: query1 OR query2 OR... OR queryn
Ricerca negativa: -query
Ricerca formato: filetype:tipo_file_da_cercare
Ricerca in un sito o dominio: site:sito_o_dominio_in_cui_cercare
Ricerca pagine simili: related: pagina
Ricerca pagine che contengono link a una data pagina: related: pagina
Ricerca nell’url: allinurl:argomento
Ricerca nel titolo: allintitle:argomento
I criteri di ricerca possono esere composti per creare
query più complesse.
S.O. di rete
• Oltre ai tipici moduli per la gestione di
processore, memoria, periferiche, file system,
interprete comandi si aggiunge un modulo
per la
•
gestione delle risorse di rete
Modelli organizzativi
• I modelli organizzativi monolitico e a strati
non sono più applicabili.
• Modelli Client-server
• Modelli ibridi
M. Client-server
•
Il nucleo del S.O. è di dimensioni minime, la gestione delle
funzionalità affidate a processi serventi (printer server, memory
server, file server,...)
•
i processi clienti possono usufruire di un servizio, inviando una
richiesta ai processi serventi (scambio messaggi).
•
Il nucleo deve fornire le funzionalità necessarie per stabilire la
comunicazione tra processi clienti e processi serventi
•
I processi condividono informazione solo attraverso il nucleo
mediante lo scambio di messaggi
•
Sono S.O. di rete altamente portabili
Vantaggi
• indipendenza fisica tra processi server e
client.
• possibilità di specializzare l’interfaccia
grafica dei client, lasciando invariati i
processi serventi.
• riduzione della manutenzione (le parti che
potrebbero essere comuni a molti processi
sono contenute in un unico processo server)
Modelli ibridi
•
I S.O. Client-server permettono la comunicazione fra processi solo
attraverso lo scambio messaggi.
•
Nei S.O. ibridi, i processi (chiamati thread) sono suddivisi in gruppi
•
•
all’interno di uno stesso gruppo i thread possono scambiarsi
informazione mediante l’uso di aree di memoria comuni.
•
gruppi di thread distinti comunicano mediante scambio messaggi
Permettono un uso più efficiente della CPU
Traduzione dei
programmi in rete
•
In una rete ci possono essere calcolatori con diverse archittetture e
diversi linguaggi macchina.
•
Problema: come eseguire un programma su diversi calcolatori della
rete?
•
•
Soluzione:
•
•
•
Tradurre il programma ad alto livello in un programma bytecode
Dotare ogni calcolatore di un interprete per un linguaggio intermedio
(bytecode)
interpretare il programma bytecode sui differenti calcolatori
Esempio: il linguaggio Java
Gestione dei
processi
•
Una rete di calcolatori può essere vista come una generalizzazione
di un sistema multiprocessore. Si ha almeno un processore per ogni
nodo.
•
Il gestore dei processi deve dunque
•
•
gestire l’evoluzione di un singolo processo su ogni nodo
definire come distribuire i vari processi da eseguire sui nodi a
disposizione.
•
Ogni nodo ha installato un kernel per gestire l’esecuzione dei
processi che gli vengono assegnati
•
Esiste un processo a livello globale (dispatcher) che distribuisce i
processi da eseguire fra i vari nodi secondo un certo criterio. (Es.:
bilanciare il carico)
Gestione della
memoria
• La memoria è distribuita in maniera più o
meno uniforme fra i vari nodi.
• Per ragioni di efficienza si segue il principio
di località: si tende a mantenere sullo stesso
nodo il processo e la memoria che gli è stata
assegnata.
Gestione delle
periferiche
• Si assegna ad ogni periferica un nome
univoco.
• Si accede alle periferiche da ogni nodo
mediante il loro nome.
• Ogni periferica è gestita da un processo
responsabile.
File system
distribuiti
•
•
•
Un S.O. che consente una gestione distribuita del file system deve:
•
integrare in modo organico i singoli file system dei calcolatori
della rete
•
•
risolvere i problemi dell’univocità dei nomi
consentire un accesso efficiente anche ai file presenti su
calcolatori remoti
Generalmente si usa un modello client-server.
Esempio il Network File System (NFS) di Unix
Applicazioni come
sistemi distribuiti
•
Un’applicazione è definita mediante 3 sottosistemi: interfaccia
utente (IU), sottosistema di logica applicata (LA), sottosistema di
gestione dei dati (GD)
•
In un’applicazione di rete i 3 sottosistemi possono risiedere su
calcolatori distinti.
•
Gestione tipica: client-server
•
sul nodo client (che potrebbe essere anche un palmare o un
telefono cellulare) potrebbe essere implementata solo l’interfaccia
utente
•
Applicazione server e applicazione client si scambiano i dati
mediante un protocollo di comunicazione.
Applicazioni
peer to peer
•
Utilizzate tipicamente per lo scambio di file o per la comunicazione
sincrona
•
•
Non esiste una gerarchia tra i calcolatori che partecipano alla rete
Le applicazioni peer to peer integrano una componente SERVer con
una componente cliENT, si parla di sistemi SERVENT.
•
•
sistema di condivisione file in Windows
Gnutella, Kazaa (file sharing P2P), ....
Max fra n n numeri
Input: un naturale n e n naturali distinti
Output: il massimo fra gli n naturali
1.
2.
3.
4.
Leggi n
i!0
max ! 0
mentre (i<n) fai {
4.1 leggi x
4.2 se (x>max) allora
max ! x
4.3 i ! i+1
}
5. stampa max
Somma di n numeri
Input: un naturale n e n naturali
Output: la somma degli n naturali
1. leggi n
2. sum ! 0
3. mentre (n>0)fai {
3.1 leggi x
3.2 sum ! sum + x
3.3 n ! n-1
}
4. stampa sum
Esercizio
Calcolare la media aritmetica di n naturali
Media =
(X1+X2+X3+... +Xn)
n
Sottoprogrammi
• Per calcolare la media aritmetica fra n
naturali sarebbe comodo riutilizzare il codice
per la somma di di naturali.
• I sottoprogrammi permettono di scrivere
codice
• modulare
• leggibile
• riutilizzabile
Sottoprogrammi
(definizione)
• In un sottoprogramma è necessario definire
quali sono i parametri di input e i parametri
di output (definizione dell’interfaccia)
• Tali parametri sono chiamati parametri
formali.
Sottoprogramma <nome sottoprg> (in: x1, x2,... xn;
out: y1,y2,... ym)
Blocco
Esempio
sottoprogramma somma (in:n; out: sum)
{
1. sum ! 0
2. mentre (n>0)fai {
2.1 leggi x
2.2 sum ! sum + x
2.3 n ! n-1
}
}
Sottoprogrammi
(chiamata)
•
Un sottoprogramma per essere eseguito deve essere “chiamato” da
un’altro programma che lo utilizza esplicitando la lista di parametri
di input e output (parametri attuali).
•
i nomi dei parametri formali e attuali possono essere distinti. Al
momento della chiamata vengono messi in corrispondenza in base
all’ordine in cui sono stati dichiarati.
nomesottoprg(in:a1,...,an; out:b1,...,bm)
nomesottoprg(in: a1, an;
out: b1,..,bm)
Media aritmetica
Start
1.
2.
3.
4.
leggi n1
somma(in:n1,out: sum1)
media ! sum1/n1
stampa media
Leggi n1
somma(in:n1;out: sum1)
media ! sum1/n1
Stampa
media
Stop
Media aritmetica
Start
Leggi n1
1.
2.
3.
4.
5.
6.
7.
8.
leggi n1
somma(in:n1;out: sum1)
media ! sum1/n1
stampa media
n2 ! 5
somma(in:n2;out: sum2)
media ! sum2/n2
stampa media
somma(in:n1;out: sum1)
media ! sum1/n1
Stampa
media
n2!5
somma(in:n2;out: sum2)
media ! sum2/n2
Stampa
media
Stop
Media aritmetica
Leggi n1
somma(in:n1;out: sum1)
media ! sum1/n1
sottoprogramma somma (in:n; out: sum)
{
1. sum ! 0
2. mentre (n>0)fai {
2.1 leggi x
2.2 sum ! sum + x
2.3 n ! n-1
}
}
Stampa
media
n2!5
somma(in:n2;out: sum2)
media ! sum2/n2
Stampa
media
sottoprogramma somma (in:n; out: sum)
{
1. sum ! 0
2. mentre (n>0)fai {
2.1 leggi x
2.2 sum ! sum + x
2.3 n ! n-1
}
}
La ricorsione
• La ricorsione è una tecnica di programmazione attraverso la quale un
sottoprogramma chiama se stesso.
• Un esempio è il calcolo del fattoriale di un numero naturale. Il
fattoriale di 0 è 1. Il fattoriale di n, numero naturale maggiore di 0, è
dato dal prodotto di tutti i numeri interi compresi tra 1 ed n.
• Es:
0!=1, 1!=1, 5!=5*4*3*2*1=120
Fattoriale
(versione iterativa)
Input: numero naturale n
Output: fattoriale di n (n!)
sottoprogramma fattoriale(in:n; out: fatt)
{
fatt ! 1
mentre (n>0) fai
{
fatt ! fatt*n
n ! n-1
}
}
Fattoriale
(versione ricorsiva)
fattoriale(n)=
{
1
se n=0
n*fattoriale(n-1) se n>0
Fattoriale
(versione ricorsiva)
sottoprogramma fattoriale(in:n; out: fatt)
1. se (n=0)allora
1.1 fatt ! 1
altrimenti
{
1.2 fattoriale(in:(n-1); out: fatt1)
1.3 fatt ! n*fatt1
}
Fibonacci
Immaginiamo di chiudere una coppia di conigli in un recinto.
Sappiamo che ogni coppia di conigli:
a) inizia a generare dal secondo mese d’età
b) genera una coppia di conigli al mese
c) non muore mai.
Quanti conigli ci saranno nel recinto dopo un anno
?
Fibonacci
soluzione ricorsiva
fib(0) = 1
fib(1) = 1
fib(n) = fib(n-1)+fib(n-2) se n>1
dove fib(k)=”numero di coppie di conigli al mese k”
L’algoritmo
sottoprogramma Fibonacci(in: n; out: num_conigli)
{
1. se ((n=0) o (n=1)) allora
1.1 num_conigli ! 1
altrimenti
{
1.2 Fibonacci(in:n-1;out:num_conigli1)
1.3 Fibonacci(in:n-2;out:num_conigli2)
1.4 num_conigli ! num_conigli1+num_conigli2
}
}
Fibonacci
Soluzione iterativa
sottoprogramma Fibonacci_it(in:n;out:num_conigli)
{
1. num_conigli_prec ! 1
2. num_conigli ! 1
3. mentre (n>1) fai {
3.1 aux ! num_conigli
3.2 num_conigli ! num_conigli + num_conigli_prec
3.3 num_conigli_prec ! aux
3.4 n ! n-1
}
}
... e dopo un anno ci saranno 233 coppie di conigli
La torre di Hanoi
ll fine del gioco è trasferire i dischi dal piolo A al piolo C.
Regole:
•! muovere un disco alla volta
!• mai mettere un disco più largo su uno più stretto.
Soluzione ricorsiva:
•! trasferisci N-1 dischi da A a B.
!• muovi il disco più largo da A a C.
!• trasferisci N-1 dischi da B a C
La torre di Hanoi
sottoprogramma Hanoi(in:n,A,B,C)
{
1. se (n=1) allora
1.1 MuoviDisco(in: A,C)
altrimenti
{
1.2 Hanoi(in: (n-1), A,C,B)
1.3 MuoviDisco(in:A,C)
1.4 Hanoi(in: (n-1),B,A§,C)
}
}
sottoprogramma MuoviDisco(in:A,B){
1. stampa “Muovi il disco da A a B”
}
Vettori (array)
•
I vettori sono una struttura dati che permette di memorizzare
sequenze di dati omogenei (sequenze di interi, di valori booleani,...)
•
I vettori sono caratterizzati da
•
•
dimensione
tipo
•
•
Es. v[10]
•
notazione: v[i]=”i-esimo elemento del vettore v”
v=
3 5 7 9 0 0 2 1 3 4
0
1
2
3
4
5
6
7
8
9
I singoli elementi di un vettore possono essere riferiti mediante un
indice.
Esercizi
• Memorizzare n valori interi in un vettore di
dimensione n
• Stampare i valori contenuti in un vettore di
dimensione n
• Cercare un elemento X all’interno di un
vettore di n elementi (ricerca lineare, binaria)
Vettori (array)
•
Un vettore è una struttura dati che permette di memorizzare
sequenze di dati omogeneii (sequenze di interi, di valori booleani,...)
•
I vettori sono caratterizzati da
•
•
dimensione
tipo
3 5 7 9 0 0 2 1 3 4
•
•
Es. v[10]
•
notazione: v[i]=”i-esimo elemento del vettore v”
v=
0
1
2
3
4
5
6
7
8
9
I singoli elementi di un vettore possono essere riferiti mediante un
indice.
Operazioni sui
vettori
• Possiamo scrivere e leggere una singola cella
di un vettore.
Esempi di istruzioni di input/output su vettori
- leggi v[i]
- scrivi v[i]
Esempi di istruzioni di assegnamento su vettori
- v[i] ! exp
- X ! v[i]
- w[j] ! v[i]
Alcuni esercizi sui
vettori
Problema: Dato un vettore di interi w di dimensione m,
calcolare l’elemento minimo di w.
sottoprogramma minvet(in:w,m;out: min)
{
1. min!w[0]
2. i!1
3. mentre (i<m) fai{
3.1. se w[i]<min allora
3.1.1. min ! w[i]
3.2 i!i+1
}
}
Problema: dati due vettori di interi v1 e v2 di
dimensioni n1 e n2, verificare se v1 e v2 sono
uguali.
sottoprogramma vett=(in:v1,n1,v2,n2: out: uguali)
{
1. I!0
2. se (n1<>n2) allora
2.1 uguali!falso
altrimenti
{
2.2 uguali!vero
2.3 i!0
2.4 mentre (i<n1) e (uguali=vero) fai{
2.4.1 se v1[i]<>v2[i] allora
2.4.1.1 uguali!falso
2.4.2 i!i+1
}
}
}
Problema: Dato un vettore di caratteri v di
dimensione n, verificare se la parola o frase
contenuta è palindroma.
Esempi di palindrome:
“Onorarono”
“Avida di vita, desiai ogni amore vero, ma ingoiai sedativi da
diva”
"O mordo tua nuora o aro un autodromo"
“Was it a cat I saw?” (L. Carroll - Alice; citato da Titti
quando dice "Mi è semblato di vedele un gatto")
Soluzione
sottoprogramma palindroma?(in:v,n:out:pal)
{
1. I!0
2. J!n-1
3. pal!vero
4. mentre (I<n/2) e (pal=vero) fai{
4.1. se (v[I]<>v[J]) allora
4.1.2. pal!falso
4.2. I!I+1
4.3. J!J-1
}
}
Algoritmi di ricerca
• Problema: dato un vettore v di dimensione n
e un elemento X, determinare se X è
contenuto in v.
• Soluzioni possibili:
• ricerca lineare
• ricerca binaria
Ricerca lineare
• Soluzione: scorrere tutto il vettore v da
posizione 0 a posizione (n-1) e controllare
ogni singolo elemento. Fermarsi nel caso in
cui v[i]=X, per qualche i=1,...,n.
L’algoritmo
sottoprogramma ricerca-lineare (in:v,n,x;out: trovato)
{
trovato ! falso
i !0
mentre ((i<n) and (not trovato)) fai
{
se (v[i]=X) allora trovato ! vero
i ! i+1
}
}
• Nel caso pessimo (elemento non trovato):
dovrò scorrere tutta la lista di elementi
Indovina chi?
Gioco: Un giocatore A sceglie una persona in
un insieme di 80 persone. Un giocatore B deve
indovinare di chi si tratta ponendo ad A al
massimo 7 domande.
Ricerca binaria
•
Nel caso in cui il vettore fosse ordinato possiamo utilizzare un
metodo piu’ efficiente per ricercare un elemento in un vettore.
•
Metodo
•
•
Determino il valore v[m] che sta nella posizione centrale del
vettore
•
•
Se v[m]=x, allora ho trovato l’elemento cercato, altrimenti...
Se x<v[m], cerco l’elemento nella prima metà del vettore,
altrimenti lo cerco nella seconda metà.
Il metodo mi permette sempre di scartare metà degli elementi senza
doverli leggere.
Esempio
Cerco il valore 7 (di volta in volta calcolo l’estremo inferiore di (n-1)/2)
3
4
5
7
9 10 12 13 14 24
7<9
3
4
5
7
7>4
5
7
7>5
7
L’algoritmo
sottoprogramma RicercaBinaria(in:v,n,x;out:trovato)
{
trovato ! falso
max ! n-1
min ! 0
mentre (min <= max) and (not trovato) fai
{
m ! (max+min)/2
se (x = v[m]) allora
trovato ! vero
altrimenti
se (x < v[m]) allora
max ! m-1
altrimenti
min ! m+1
}
}
Ordinamento
• Problema dato un vettore v di lunghezza n
contenente una sequenza disordinata di
interi, ordinare la sequenza in senso
crescente (o decrescente).
• Esempio
input
3 5 7 9 0 0 2 1 3 4
output 0 0 1 2 3 3 4 5 7 9
Bubble sort
•
È l’algoritmo di ordinamento più vecchio e anche
il più lento!
•
Metodo: si scandisce il vettore confrontando
elementi adiacenti, nel caso sia necessario si
scambiano gli elementi. L’algoritmo ripete tale
operazione finché non ci sono più posizioni da
scambiare (vettore ordinato).
•
Durante l’esecuzione dell’algoritmo gli elementi
più grandi (piu’ piccoli, nel caso di ordinamento
decrescente) tendono a spostarsi (come bolle!)
verso la fine del vettore.
Esempio
Ordiniamo con bubble sort il vettore
3 2 0 1
2 0 1 3
0 1 2 3
2 3 0 1
0 2 1 3
0 1 2 3
2 0 3 1
0 1 2 3
2 0 1 3
3 2 0 1
0 1 2 3
L’algoritmo
sottoprogramma bubblesort(in:v,n;out:v)
{
i !0
mentre (i < n-1) fai
{
j !0
mentre (j < n-i-1) fai
{
se (v[j+1] > v[j]) allora
scambia(in:v[j],v[j+1];out:v[j],v[j+1]);
j ! j+1
}
i ! i+1
}
}
Merge sort
•
È un algoritmo di ordinamento ricorsivo basato sull’approccio “divide
and conquer”
•
•
•
•
“dividi” il problema in sottoproblemi
“conquista” i sottoproblemi, risolvendoli ricorsivamente
combina le soluzioni dei sottoproblemi per ottenere la soluzione
del problema originale
Algoritmo di merge sort
•
DIVIDE: dividi il vettore di n elementi in due sottovettori di n/2
elementi
•
•
CONQUER: ordina i due sottovettori
COMBINE: fondi assieme i due sottovettori ordinati in un unico
vettore ordinato
Esempio
3 2 0 1
3 2
3
2
0 1
0
1
Merge
2 3
0 1
Merge
0 1 2 3
Merge
• Problema: fondere assieme due sottovettori
(v[p...q], v[q+1..r]) ordinati ottenendo un unico
vettore ordinato v.
p
q
r
3
7
8
1
5
1
3
5
7
8
Merge - l’algoritmo
sottoprogramma merge(in:v,p,q,r: out v)
{
i !p
j ! q+1
k !0
mentre (i<=q) and (j<=r) fai
se v[i]<=v[j] allora {
aux[k] ! v[i]
k ! k+1
i ! i+1
}
altrimenti {
aux[k] ! v[j]
k ! k+1
j ! j+1
}
mentre (i<=q) fai {
aux[k] ! v[i]
k ! k+1
i ! i+1
}
mentre (j<=r) fai {
aux[k] ! v[j]
k ! k+1
j ! j+1
}
copia(in aux; out v)
}
Merge sort
l’algoritmo
sottoprogramma mergesort(in: v,p,r;out: v)
se (p<r) allora
{
q ! (p+r/2)
mergesort(in: v,p,q; out: v)
mergesort(in: v,q+1,r; out v)
merge(in:v,p,q,r)
}
ipertesti
• Obiettivo: strutturare l’informazione per
renderla accessibile a esseri umani.
• rappresentazione sequenziale (es. stampa)
• rappresentazione non sequenziale
(struttura fisica del documento differisce
dalla struttura logica) (es: enciclopedia)
Ipertesto
• si definisce ipertesto un documento la cui
struttura di consultazione è non lineare
• ogni parte del documento (chiamata nodo)
può contenere dei punti di aggancio (anchor
point) che collegano altre parti del
documento (chiamati nodi target) mediante
collegamenti ipertestuali (hyperlink)
Es. struttura
sequenziale
• Cap. 2:
Paolo Conte nasce il 6 gennaio 1937 e già da adolescente
coltiva la passione per il jazz classico americano [...]
• Cap. 5:
• Cap. 13:
Paolo Conte ha scritto Razmataz [...]
Razmataz è un album del 2000 che contiene [...]
Es. ipertesto
Paolo Conte nasce il 6
gennaio 1937 e già da
adolescente coltiva la
passione per il jazz
classico americano [...]
Paolo Conte ha scritto
Razmataz [...]
Razmataz è un album del
2000 che contiene [...]
Linguaggio per
ipertesti
•
Un linguaggio per descrivere gli ipertesti è
l’HyperText Markup Language (HTML)
•
•
Non è il solo (VRML,XML,...)
l’HTML è un linguaggio di formattazione e permette di
•
formattare del testo secondo certi criteri mediante
dei marcatori (tag)
•
fare riferimento ad altri testi o contenuti
multimediali mediante collegamenti (hyperlink o link)
HTML e sua evoluzione
• HTML iniziale
• basato su un sistema di marcatori (tag)
• permetteva di gestire la struttura di un documento
• la presentazione del documento era rozzamente gestita
• HTML 3.2 (e successivamente HTML 4.01)
• Aggiunti Tag per la presentazioneTags (e.g., font size o color)
• Problemi di compatibilità fra browsers
• Cascading Style Sheets (CSS)
• Obiettivo: Separare la presentazione dalla stuttura del doc.
• XHTML
• HTML di nuova generazione
• Include nuovi tags
• Impone regole più strette nella stesura dei documenti
ipertestuali
Tag
• Sono dei marcatori che servono a
• indicare l’aspetto grafico del testo (tipo di
font e stile del carattere, allineamento dei
paragrafi,...)
• indicare dove reperire altra informazione
multimediale e/o testuale
• far interagire l’utente con la pagina stessa
(es. moduli on-line)
Tag - sintassi e
semantica
• un tag t si usa in questo modo
<t> testo a cui si riferisce il tag t </t>
L’effetto di un tag t è di applicare il comando
associato al tag t al “testo a cui si riferisce il tag t”
I tag senza "contenuto" (e.g. <t></t>) si indicano in HTML
con il solo tag iniziale <t>; in XHTML con il tag <t />
Tag di base
• HTML
• HEAD
• TITLE
• BODY
Tag HTML
• Permette di delimitare l’inizio e la fine di un
documento HTML.
• Un documento HTML è racchiuso tra i tag
<HTML> e </HTML>
Tag HEAD
• Permette di definire l’intestazione del
documento (titolo, informazioni per il browser
...)
• Deve essere posto immediatamente dopo il
tag <html>
<html>
<head>
...
</head>
...
</html>
Tag TITLE
• Permette di definire il titolo della pagina
web, deve essere inclusonell’intestazione
<head> <title> ... </title> ... </head>
<title>
Demis Ballis’ Home Page
</title>
Tag BODY
• Contiene il corpo del documento html (testo,
immagini, suoni,...)
• È posto dopo il tag </head>
<head>
...
</head>
<body>
Questa è una pagina HTML
</body>
Struttura di un
documento HTML
Intestazione
Corpo
<html>
<head>
<title> Pagina di prova </title>
</head>
<body>
Questo è il contenuto della
pagina!
</body>
</html>
HTML o XHTML?
XHTML 1.0 Strict
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<HMTL>
...
</HTML>
XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML>
...
</HTML>
HTML 4.01
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN">
<HTML>
...
</HTML>
Esempio
Attributi dei tag
• Ad alcuni tag sono associati degli attributi
che specificano delle proprietà inerenti ai
tag.
• Se si vuole impostare l’attributo A1 del tag t
al valore 15 e l’attributo A2 al valore “pippo”
si dovrà scrivere
<t
a1=”15” a2=”pippo”> ... </t>
Attributi di BODY
• BGCOLOR fissa il colore di sfondo
(sconsigliato in XHTML)
<body BGCOLOR=”red”>... </body>
oppure
<body BGCOLOR=”#FF0000”>... </body>
Attributi di BODY
• BACKGROUND fissa un’immagine di sfondo
(sconsigliato in XHTML)
<body> BACKGROUND=”sfondo.gif”>... </body>
Attributi di BODY
• TEXT imposta un colore per il testo
(sconsigliato in XHTML)
<body TEXT=”#0000FF”>... </body>
Attributi di BODY
• VLINK,
ALINK,LINK impostano
rispettivamente i colori dei collegamenti
visitati, cliccati ma non ancora visitati e non
ancora cliccati. (sconsigliato in XHTML)
<body LINK=”#FFFFFF”>... </body>
Formattazione del
testo
• Alcuni tag per formattare il testo
• <H1>, <H2>,... <H6>
• <FONT>
• <U>, <I>, <B>, <STRIKE>
I Tag <H1>... <H6>
• Definisce lo stile dei titoli inclusi nel
documento HTML.
<H1> Sezione 1 </H1>
blahblah
blahblah
<H2> Sottosezione 1.1 </H2>
blahblah
blahblah
Tag <FONT>
•
Serve per definire gli attributi del testo al quale è riferito
(carattere, dimensione, ...)
•
Alcuni Attributi di FONT
•
•
•
SIZE
(dimensione del caratte, da 1 a 7)
FACE
(tipo di carattere)
COLOR
(colore del carattere)
<FONT COLOR=”RED” SIZE=”2” FACE=”Arial”>
questo è un testo di colore rosso,
dimensione 2 e font Arial!
</FONT>
I Tag
<U>,<B>,<I>,<STRIKE>
•
•
•
•
<U> testo sottolineato </U>
<B> testo in grassetto </B> (sconsigliato in XHTML)
<I> testo in corsivo </I> (sconsigliato in XHTML)
<STRIKE> testo barrato </STRIKE>
I Tag
<BLOCKQUOTE>,<CITE>
•
•
BLOCKQUOTE permette di definire delle
citazioni
CITE permette di definire la fonte della
citazione
<BLOCKQUOTE>
PENSATORE:! L'ippopotamo è un animale
completamente inutile nel creato.
LA FEMMINA DELL' IPPOPOTAMO: Lo dice lei!!
</BLOCKQUOTE>
<CITE> Da Tragedie in due battute, A. Campanile </CITE>
I Tag <EM>,<STRONG>
•
•
EM mette in evidenza il testo
STRONG marca il testo
<EM> evidenzia il testo </EM>
<STRONG> marca il testo </STRONG>
ANDARE A CAPO
• tutto il testo scritto in un documento HTML
è rappresentato in sequenza.
<BODY>
IL SIGNOR TALE: "Ciao, carissimo. Dove vai?".
IL SIGNOR TALALTRO: "All'Arcivescovado. E tu?".
IL SIGNOR TALE: "Dall'Arcivescovengo".
</BODY>
IL SIGNOR TALE: "Ciao, carissimo. Dove vai?". IL SIGNOR
TALALTRO: "All'Arcivescovado. E tu?". IL SIGNOR TALE:
"Dall'Arcivescovengo".
IL TAG <BR>
• si usa per andare a capo.
• <br /> in XHTML
<BODY>
IL SIGNOR TALE: "Ciao, carissimo. Dove vai?". <BR>
IL SIGNOR TALALTRO: "All'Arcivescovado. E tu?". <BR>
IL SIGNOR TALE: "Dall'Arcivescovengo". <BR>
</BODY>
IL SIGNOR TALE: "Ciao, carissimo. Dove vai?".
IL SIGNOR TALALTRO: "All'Arcivescovado. E tu?".
IL SIGNOR TALE: "Dall'Arcivescovengo".
Paragrafi e
giustificazione
• il tag P definisce un nuovo paragrafo
• il tag DIV allinea il testo
• il tag CENTER centra il testo
IL TAG <P>
• il tag P definisce un nuovo paragrafo.
• È dotato dell’attributo ALIGN per allineare il
testo a destra o a sinistra.
ALIGN=”LEFT”
ALIGN=”RIGHT”
ALIGN=”CENTER”
Some say the world will end in fire;
Some say in ice.
From what I've tasted of desire
I hold with those who favor fire.
Some say the world will end in fire;
Some say in ice.
From what I've tasted of desire
I hold with those who favor fire.
Some say the world will end in fire;
Some say in ice.
From what I've tasted of desire
I hold with those who favor fire.
IL TAG <DIV>
• il tag DIV allinea il testo.
• È dotato dell’attributo ALIGN per allineare il
testo a destra o a sinistra.
ALIGN=”LEFT”
ALIGN=”RIGHT”
ALIGN=”JUSTIFY”
ALIGN=”CENTER”
<DIV ALIGN=”RIGHT”> blablablabla </DIV>
IL TAG <P>
• il tag CENTER permette di allineare al centro
un oggetto.
<CENTER> oggetto da centrare </CENTER>
ELENCHI
•
•
•
•
il tag LI definisce un elemento in un elenco
il tag OL definisce un elenco numerato
il tag UL definisce un elenco non numerato
Es. Elenco non numerato
•
•
•
elemento a
elemento b
Es. Elenco numerato
1. elemento a
2. elemento b
IL TAG <OL>
• il tag OL definisce un elenco numerato
<OL>
<LI> elemento a </LI>
<LI> elemento b </LI>
<LI> elemento c </LI>
</OL>
1. elemento a
2. elemento b
3. elemento c
Attributi di <OL>
•
Il tag OL ha un attributo TYPE che permette di
definire il tipo di enumerazione
•
TYPE=”a” le etichette sono lettere minuscole
(a,b,c,...)
•
TYPE=”A” le etichette sono lettere maiuscole
(A,B,C,...)
•
TYPE=”i” le etichette sono numeri romani
minuscoli (i,ii,iii,...)
•
TYPE=”I” le etichette sono numeri romani
maiuscoli (I,II,III,...)
IL TAG <UL>
• il tag UL definisce un elenco non numerato
<UL>
<LI> elemento a </LI>
<LI> elemento b </LI>
<LI> elemento c </LI>
</UL>
• elemento a
• elemento b
• elemento c
Attributi di <UL>
•
Il tag UL ha un attributo TYPE che permette di
definire il tipo di etichette
•
•
•
TYPE=”disc” le etichette sono pallini pieni
TYPE=”circle” le etichette sono cerchi
TYPE=”square” le etichette sono quadrati pieni
Le immagini
• Per inserire un’immagine si utilizza il tag
IMG
• <img lista attributi /> in XHTML
• Gli attributi più importanti di IMG sono
• SRC: indica il niome dell’immagine da caricare
• ALT: indica la didascalia
• WIDTH, HEIGHT: specificano le dimensioni (in pixel o in
percentuale)
•
ALIGN: indica l’allineamento => TOP,BOTTOM, MIDDLE,LEFT,
RIGHT
Le immagini
• Per inserire un’immagine si utilizza il tag
IMG
• <img lista attributi /> in XHTML
• Gli attributi più importanti di IMG sono
• SRC: indica il niome dell’immagine da caricare
• ALT: indica la didascalia
• WIDTH, HEIGHT: specificano le dimensioni (in pixel o in
percentuale)
•
ALIGN: indica l’allineamento => TOP,BOTTOM, MIDDLE,LEFT,
RIGHT
Collegamenti
• Possono essere interni o esterni al
documento HTML
• Vengono definiti mediante il tag A.
• Gli attributi più importanti sono:
• HREF: indica un riferimento
• TITLE: indica il titolo del collegamento
• NAME: marca un riferimento interno
Esempi di
collegamenti
Per visitare il sito dell’università di Udine clicca
<A HREF=”http://web.uniud.it”> qui </a>
<A NAME=”rif”>
questo e’ un riferimento interno di nome rif
</a>
Nel documento, per accedere alla parte marcata dal collegamento
interno rif clicca
<A HREF=”#rif”>
qui
</a>
Tabelle
• Le tabelle si definiscono mediante il tag
TABLE
• Le singole righe si definiscono mediante il
tag TR
• le celle di ogni riga si definiscono mediante il
tag TD
Esempio Tabella
<TABLE>
<TR>
<TD>
<TD>
</TR>
<TR>
<TD>
<TD>
</TR>
</TABLE>
pippo </TD>
25/30 </TD>
pluto </TD>
30/30 </TD>
pippo
25/30
pluto
30/30
L’attributo BORDER
•
è un attributo del tag TABLE. Permette di creare una cornice
attorno alla tabella. Assume valori interi positivi => più grande è il
valore assunto, più spessa è la cornice.
<TABLE BORDER=2>
<TR>
<TD> pippo </TD>
<TD> 25/30 </TD>
</TR>
<TR>
<TD> pluto </TD>
<TD> 30/30 </TD>
</TR>
</TABLE>
Linguaggio Java: sintassi
Gli elementi costitutivi di un programma Java sono
chiamati token
I token sono suddivisi in 5 categorie:
•
•
•
•
•
parole chiave
letterali
identificatori
operatori
separatori
N.B. oltre ai token un programma Java può includere
spazi e commenti che il compilatore ignora.
Parole chiave
Le parole chiave hanno un uso e un significato speciale in Java.
abstract boolean
break
byte
case
default
do
double
else
if
implements
import
private
protected
this
throw
catch
char
class
const
goto
extends final
finally
float
for
package
instanceof
int
interface
long
native
new
public
return
short
static
strictfp
super
switch
throws
transient
try
void
volatile
while
continue
synchronized
Letterali
I letterali si dividono in
•
•
•
•
•
•
numeri interi (es: 679)
numeri decimali o in virgola mobile (es: 123.789)
valori booleani (true e false)
caratteri UNICODE (es: ‘a’)
stringhe (es: “pippo”)
il riferimento nullo null
Identificatori
Gli identificatori rappresentano nomi che possono
essere assegnati a variabili, metodi, classi, ecc.
Un identificatore è composto esclusivamente da
lettere, numeri e caratteri _ e $ e deve cominciare
con una lettera, con _ , oppure con $.
,
Un identificatore non può essere una parola chiave,
un letterale booleano, un letterale nullo.
Identificatori validi: PIPPO, H2So4, $bank, nome_var
Identificatori illegali: 2PIPPO, nome-var,int, true
N.B. Java distingue fra lettere maiuscole e minuscole
pertanto i due identificatori Pippo e PIPPO sono da
considerarsi distinti.
Operatori
Gli operatori indicano un tipo di calcolo da eseguire su
uno o piú dati, detti operandi, che possono essere
letterali, variabili o risultati di valutazioni di espressioni
=
>
< ! ? : ~
== <= >= != && || ++
-- +
- * / & |
^ += -= *= /= &= |= ^=
Separatori
I separatori sono i “segni di punteggiatura” del linguaggio
( )
{ }
[ ]
;
,
.
Commenti
/* questo e un commento */
tutti i caratteri da /* a */ sono ignorati
/** questo è un commento */
come /* */ ed inoltre permette di
creare automaticamente la
documentazione Javadoc
// questo è un commento
tutti i caratteri da // fino a fine linea
sono ignorati
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
public VotiEsame(int n) { voti = new int[n]; // inizializza un vettore di lunghezza n }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
5 commenti
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
17 parole chiave
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
9 letterali
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
36 identificatori
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
15 operatori
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Esempio
/** Esempio
di classe
*/
public class VotiEsame
{
private int voti[]; // variabile di tipo vettore di interi
52 separatori
public VotiEsame(int n) { voti = new int[n]; /* inizializza un vettore di lunghezza n*/ }
// genera un vettore contenente interi pseudo-casuali compresi tra 15 e 31
public void generavoti()
{
int i=0;
Random r=new Random();
for (i=0;i<voti.length;i++)
voti[i]=15+r.nextInt(16);
System.out.println("Vettore generato!");
}
// stampa vettore
public void stampavoti()
{
int i=0;
for (i=0;i<voti.length;i++)
System.out.println("Elemento in posizione "+i+": "+voti[i]);
}
Tipi di dato in Java
• Java è un linguaggio fortemente tipato in
quanto ogni variabile ed ogni espressione
hanno associato un tipo.
• I tipi limitano l’insieme di valori che una
variabile o un’espressione possono
assumere.
• Tipo di dato = (Supporto, Operazioni)
• Tipi di dato primitivi e Tipi di dato astratti
Tipi di dato primitivi
•
•
il tipo booleano boolean (valori: true e false)
•
i tipi per i numeri decimali float (32 bit), double
(64 bit)
•
il tipo carattere char
i tipi per i numeri interi byte (8 bit), short (16
bit), int (32 bit), long (64 bit).
Tipi di dato astratti
• In Java sono anche chiamati tipi riferimento
• I tipi riferimento sono classi, vettori,
interfacce.
Variabili
• Una variabile è una locazione della memoria
referenziabile mediante un identificatore.
• Una variabile di un tipo primitivo può
contenere solo valori del supporto di tale
tipo.
• Una variabile di tipo T, dove T è un tipo
riferimento, può contenere un riferimento a
qualunque istanza di T oppure il valore null.
Dichiarazione di variabili
• L’associazione di una variabile a un tipo ha
luogo al momento della dichiarazione di tale
variabile.
<tipo> <identificatore>;
oppure
<tipo> <identificatore1>,..., <identificatoreN>;
Esempi dichiarazioni
int X, pippo;
double radice;
float r,c;
String Codice_fiscale;
Persona p1,p2,p3;
Tipi primitivi
Tipi riferimento
Assegnamento (=)
L’operatore di assegnamento (=) permette di memorizzare in
una variabile un valore ottenuto dalla valutazione di una
espressione.
<identificatore> = <espressione>;
• Una variabile per essere assegnata deve
prima essere stata dichiarata;
• È lecito combinare dichiarazioni con
assegnamenti. La sintassi è la seguente:
•
<tipo> <identificatore> = <espressione>;
• In generale, <identificatore> e
<espressione>
devono avere lo stesso tipo.
Esempi di assegnamento
String parola=”pippo”;
dich. e
int x,y;
double d;
dichiarazioni
Persona p;
p
d
x
y
x
y
z
ass. combinati
= new Persona(“mario”,”Rossi”,34,’M’);
= 3.1459;
= 1;
=(x*5)+4;
= parola;
= 3.29;
errori di assegnamento
= 6;
Conversioni di tipo
• A volte è necessario assegnare espressioni di
tipo T1 a variabili di tipo T2, con T1 e T2 tipi
di dato distinti. È sempre possibile?
• L’operazione di conversione di tipo è
chiamata casting e può essere implicita o
esplicita.
Casting implicito
• Il casting implicito è lecito quando non
comporta nessuna perdita di precisione.
int i=5;
double j=3,1456;
j = i; /* casting implicito lecito */
i = j; /* casting implicito illegale
perdita di precisione */
Casting esplicito
• nel casting esplicito il tipo in cui si vuole
convertire una variabile deve essere fornito
esplicitamente.
• Può comportare perdita di precisione.
int i = 65;
char c;
double j = 3,1456;
i = (int) j; /* casting esplicito legale
con perdita di precisione */
c = (char) i; /* assegna a c il codice UNICODE i */
j = (double) i; /* casting esplicito legale
senza perdita di precisione */
Blocchi
Il codice Java è diviso in blocchi delimitati da parentesi
graffe aperte e chiuse.
I blocchi possono essere annidati gli uni dentro gli altri.
Public Class Esempio
{
// def. attributi
private int x;
private String s;
// def. metodi
public Esempio(int y, String s)
{
}
// corpo del costruttore
public void metodo()
{
// corpo del metodo
}
}
Ambito delle variabili
È possibile dichiarare ed usare variabili in ogni blocco del
programma. L’ambito (o scope) in cui tali variabili possono
essere utilizzate è limitato al blocco in cui sono state dichiarate
e ai sottoblocchi eventualmente annidati.
Le variabili dichiarate nel corpo di una classe definiscono gli
attributi della classe.
Le variabili dichiarate nel corpo di un metodo sono dette
variabili locali, in quanto il loro ambito è ristretto al corpo del
metodo.
Le variabili locali vengono create al momento dell’esecuzione di
un metodo e distrutte quando esso termina.
Esempio
Public Class Esempio
{
private int x=5;
// def. metodi
public Esempio(int y, String s)
{
char c=’B’;
System.out.println(“valore di x: ”+x);
System.out.println(“valore di c: ”+c);
}
public void metodo()
{
String s=”pippo”;
System.out.println(“valore di s: “+s);
System.out.println(“valore di c: ”+c);
}
}
Esempio
Public Class Esempio
{
private int x=5;
// def. metodi
public Esempio(int y, String s)
{
char c=’B’;
System.out.println(“valore di x: ”+x);
System.out.println(“valore di c: ”+c);
}
public void metodo()
{
Errore: la variabile c non è
visibile in questo blocco!
String s=”pippo”;
System.out.println(“valore di s: “+pippo)
System.out.println(“valore di c: ”+c);
}
}
Ambito (cont.)
Che succede se dichiaro variabili con lo stesso nome?
Non è possibile dichiarare variabili con lo stesso nome
all’interno dello stesso blocco.
public metodo()
{
int i;
char i; /* errore i è già definita! */
...
}
È possibile dichiarare variabili con lo stesso nome all’interno di
blocchi distinti anche se sono annidati. Ciò non crea alcun
conflitto, in quanto la dichiarazione più interna nasconde le
eventuali dichiarazioni più esterne.
Esempio
Che valore stampa l’esecuzione del metodo metodA()? E
metodoB()?
Public Class Esempio
{
private int x=5;
public void metodoA()
{
char x=’A’;
System.out.println(“valore di x: ”+x);
}
}
public void metodoB()
{
System.out.println(“valore di x: ”+x);
}
Esempio
Che valore stampa l’esecuzione del metodo metodA()? E
metodoB()?
Public Class Esempio
{
private int x=5;
Stampa il carattere ‘A’
public void metodoA()
{
char x=’A’;
System.out.println(“valore di x: ”+x);
}
}
public void metodoB()
{
System.out.println(“valore di x: ”+x);
}
Stampa l’intero 5
Espressioni
Un’espressione permette di calcolare un risultato applicando
opportuni operatori a un certo numero di operandi, che
possono essere variabili, letterali, valori di ritorno di metodi o
altre espressioni.
2*X+Y //esempio di espressione
N.B. il tipo degli operandi deve essere compatibile con il tipo
degli operatori. (Es. non posso moltiplicare un carattere e un
numero!)
Tipicamente il risultato di una espressione è memorizzato in una
variabile mediante l’operatore di assegnamento.
Z = 2*X+Y;
Operatori aritmetici
+
addizione
-
sottrazione
*
moltiplicazione
/
divisione
%
resto della divisione intera
Questi operatori si applicano sia a numeri interi che a numeri
frazionari. L’operatore / produce come risultato un intero se
applicato a operandi interi, mentre ritorna un valore frazionario
se applicato a operandi frazionari.
Il risultato che si ottiene applicando tali operatori è di tipo
numerico (intero o frazionario).
X % Y, produce il resto della divisione intera fra gli interi X e Y.
Es. 12 % 7 ritorna come valore 5.
Esempi di espressioni
aritmetiche
int X=4,Y=12;
double Z = 3.14;
double W;
W=((2*X-Z*Z)/2)+1;
Y = (Y/X)%2;
Esempi di espressioni
aritmetiche
int X=4,Y=12;
double Z = 3.14;
double W;
W=((2*X-Z*Z)/2)+1;
Y = (Y/X)%2;
Y ha valore 1
W ha valore -0.0702
Operatori relazionali
<
<=
>
>=
==
!=
minore
minore o uguale
maggiore
maggiore o uguale
uguale
diverso
Questi operatori confrontano due espressioni e ritornano un
valore booleano (true oppure false). Permettono di costruire
espressioni booleane.
N.B. non si confonda l’operatore di uguaglianza == con
l’operatore di assegnamento =.
Esempi di espressioni
booleane
int X=3,Y=5;
double Z = 3.14;
boolean W;
W = ((X+1) == (Y*2)%6);
Y = Z < X;
Esempi di espressioni
booleane
int X=3,Y=5;
double Z = 3.14;
boolean W;
W prende il valore true
W = ((X+1) == (Y*2)%6);
Y = Z < X;
Y prende il valore false
Operatori logici
&&
and logico o congiunzione
||
or logico o disgiunzione
!
not o negazione
Questi operatori permettono di combinare assieme più
espressioni booleane. Ritornano sempre un risultato di tipo
booleano.
Operatori logici
e1
e2
e1&& e2
e1|| e2
!e1
true
true
true
true
false
true
false
false
true
--
false
true
false
true
true
false
false
false
false
--
Esempi di espressioni
booleane
int X=3,Y=5;
double Z = 3.14;
boolean W1,W2;
W1 = (((X+1) == ((Y*2)%6))&& (3<4)) || !(9>=Z);
W2 = (((X+1) != ((Y*2)%6))&& (3<4)) || !(9>=Z);
Esempi di espressioni
booleane
int X=3,Y=5;
double Z = 3.14;
boolean W1,W2;
W1 prende il valore true
W1 = (((X+1) == ((Y*2)%6))&& (3<4)) || !(9>=Z);
W2 = (((X+1) != ((Y*2)%6))&& (3<4)) || !(9>=Z);
W2 prende il valore false
Operatori ++ e -Questi operatori sono utilizzati, in notazione sia prefissa che
postifissa, per incrementare o decrementare di 1 il valore di una
variabile.
Gli usi prefisso e postfisso di tali operatori non sono equivalenti.
Esempio:
{
int K,X=3,Y,W,Z=4;
Z++;
Y = X++;
W = ++X;
K = W--;
}
//
//
//
//
postincremento
postincremento
preincremento
postdecremento
Operatori ++ e -Questi operatori sono utilizzati, in notazione sia prefissa che
postifissa, per incrementare o decrementare di 1 il valore di una
variabile.
Gli usi prefisso e postfisso di tali operatori non sono equivalenti.
Esempio:
Z prende il valore 5
{
int K,X=3,Y,W,Z=4;
Z++;
Y = X++;
W = ++X;
K = W--;
}
//
//
//
//
K prende 5 e W diventa 4
Y prende 3 e X diventa 4
postincremento
postincremento
preincremento
postdecremento
W prende 5 e X diventa 5
Strutture di controllo
Sono istruzioni che permettono di modificare il
flusso di esecuzione di un metodo
• istruzioni condizionali
• istruzioni iterative (cicli)
Istruzioni condizionale
La più comune istruzione condizionale è il blocco if-else, la cui
sintassi è la seguente:
if (<condizione>)
<blocco di istruzioni 1>
else
<blocco di istruzioni 2>
La condizione deve essere un’espressione booleana. Se la
condizione è valutata true allora si esegue il blocco di istruzioni
1, altrimenti si esegue il blocco di istruzioni 2
Le parentesi graffe delimitanti i blocchi possono essere omesse
quando i blocchi di istruzioni sono costituiti da un’unica
istruzione.
Istruzioni condizionali esempio
if (X>0)
System.out.println(“X è positivo”);
else
{
System.out.print(“X è negativo ”);
System.out.println(“oppure nullo”);
}
Istruzioni condizionali
A volte il ramo else di una istruzione condizionale può essere
assente. In tal caso l’istruzione assume la seguente forma:
if (<condizione>)
<blocco di istruzioni>
Esegui il blocco di istruzioni se la condizione è valutata true.
if (X%2==0)
System.out.println(“X è pari”);
Istruzioni condizionali
È possibile unire più istruzioni if-else per esprimere più
possibilità condizionali. La sintassi è la seguente
if (<condizione 1>)
<blocco di istruzioni 1>
else
if (<condizione 2>)
<blocco di istruzioni 2>
...
else
<blocco di istruzioni n>
Se la condizione 1 è valutata true, esegui il blocco di istruzioni 1,
altrimenti se la condizione 2 è valutata true, esegui il blocco di
istruzioni 2, ... altrimenti se nessuna condizione è verificata,
esegui il blocco di istruzioni n.
Istruzioni condizionali esempio
if (X>0 && X<=10)
System.out.println(X);
else
if (X==11)
System.out.println(“Jack”);
else
if (X==12)
System.out.println(“Regina”);
else
System.out.println(“Re”);
Istruzioni condizionali:
switch
È possibile esprimere più possibilità condizionali, in maniera
molto intuitiva, utilizzando l’istruzione switch.
switch (<espressione>){
case <letterale 1>: <blocco istruzioni 1>
case <letterale 2>: <blocco istruzioni 2>
...
default: <blocco istruzioni n>
}
L’espressione deve produrre un risultato byte, short, int o char.
Viene valutata l’espressione. Il risultato viene confrontato con
ciascun case nell’ordine in cui questi compaiono. Se il risultato
dell’i-esimo case coincide con il risultato dell’espressione allora
tutti i blocchi di istruzioni da i a n vengono eseguiti. Se il risultato
non coincide con nessun case allora si esegue il blocco di
istruzioni n relativo al default.
Istruzioni condizionali:
switch (esempio)
{int X=2;
switch(X){
case 1: System.out.println(“Uno”);
case 2: System.out.println(“Due”);
default: System.out.println(“Default”);
}
}
Questo codice stampa le
stringhe Due e Default
Istruzioni condizionali:
break
Nell’istruzione switch, se si vuole eseguire solo il blocco di
istruzioni corrispondente al letterale uguale al risultato
dell’espressione, si deve terminare il blocco di istruzioni con la
parola chiave break.
{int X=2;
}
switch(X){
case 1: System.out.println(“Uno”);break;
case 2: System.out.println(“Due”);break;
default: System.out.println(“Default”);
}
Questo codice stampa la
stringa Due
Istruzioni iterative: while
L’istruzione while è una istruzione iterativa che permette di
ripetere più volte l’esecuzione di una porzione di codice. La
sintassi è la seguente:
while(<condizione>) do
<blocco di istruzioni da ripetere>
la condizione deve essere un’espressione booleana. Finché il
risultato dell’espressione è true, si ripete il blocco di istruzioni
successivo.
While (esempio)
{int i=0;
while(i<10){
System.out.println(i);
i++;
}
}
Questo codice stampa gli
interi da 0 a 9 e alla fine del
ciclo i vale 10
Istruzioni iterative: dowhile
L’istruzione do-while è una istruzione iterativa che permette di
ripetere più volte l’esecuzione di una porzione di codice. A
differenza dell’istruzione while, le istruzioni da ripetere sono
poste prima della condizione da valutare. Pertanto il blocco di
istruzioni si ripete sempre almeno una volta!
Sintassi:
do
<blocco di istruzioni da ripetere>
while(<condizione>);
la condizione deve essere un’espressione booleana. Finché il
risultato dell’espressione è true, si ripete il blocco di istruzioni.
Do-while (esempio)
{int i=0;
do
{
i++;
System.out.println(i);
}
while(i<10);
}
Questo codice stampa gli
interi da 1 a 10 e alla fine del
ciclo i vale 10
Istruzioni iterative: for
L’istruzione for è una istruzione iterativa che permette di
ripetere più volte l’esecuzione di una porzione di codice.
Sintassi:
for(<inizializzazione>;<condizione>;<espressione>)
<blocco di istruzioni da ripetere>
L’espressione inizializzazione è tipicamente un’istruzione di
assegnamento, che atribuisce ad una variabile di controllo un
valore iniziale. La condizione è un’espressione booleana che
tipicamente confronta il valore della variabile di controllo con un
valore limite. L’espressione specifica il modo in cui la variabile di
controllo deve essere modificata al termine di ogni iterazioni del
ciclo.
For (esempio)
{int i;
for(i=0;i<11;i++)
System.out.println(i);
}
Questo codice stampa gli
interi da 0 a 10 e alla fine del
ciclo i vale 11
I vettori (o array)
Il vettore (o array) è un oggetto che fornisce lo spazio di
memoria per un elenco di elementi tutti dello stesso tipo
componente T.
Un vettore deve essere innanzitutto dichiarato mediante la
seguente sintassi:
<tipo>[] <nome_vettore>;
int [] x,y; //dichiara x e y array di interi
String [] frase; // dichiara un array di
// stringhe di nome frase
Creazione di un vettore
Il tipo vettore è un tipo riferimento. Un riferimento ad un array
si crea mediante l’operatore new. Quando si crea un vettore è
necessario specificare la dimensione (ovvero il numero di celle
allocate).
new <tipo> [<dimensione>];
x = new int [10];//alloca un vettore di 10
//celle e memorizza il
//riferimento nella
//variabile vettore X
frase = new String[3]; //la variabile frase
//può contenere 3
stringhe
Creazione di un vettore
Un altro modo per creare un riferimento a un array consiste nel
dare esplicitamente l’elenco dei valori da memorizzare in fase di
dichiarazione.
int[] x={14,12,1,24,7,1,2,9,9,11};
String[] frase={“questa”,”e’una”,”frase”};
Accesso e scrittura di
un vettore
Le componenti di un array sono indicizzate mediante un numero
intero progressivo. Se l’array contiene n celle, la prima
componente ha indice 0 e l’ultima ha indice n-1.
La componente i-esima di un array può essere reperita o scritta
usando la seguente sintassi:
stampa ‘c’
<variabile di tipo array>[i]
char[] lettere={’a’,’b’,’c’};
char j;
mette ‘a’ in j
System.out.println(lettere[2]);
j=lettere[0];
scrive ‘k’ nella seconda
lettere[1]= ‘k’;
componente di lettere[]
Matrici
Una matrice è un vettore multidimensionale, in cui gli elementi
memorizzati sono riferiti attraverso delle n-uple di indici.
Ci limiteremo ad usare matrici di dimensione 2.
Nel caso di dimensione 2, una matrice può essere interpretata
come una griglia di valori (vettore di vettori). Ogni elemento di
una matrice di dimensione 2 è indicizzato mediante una coppia di
indici (numero di riga, numero di colonna).
0
1
2
0
1
2
5
1
10
1
3
9
0
7
8
elemento 7 identificato
dalla coppia di indici (1,2)
Matrici
Una matrice deve essere innanzitutto dichiarata mediante la seguente sintassi:
<tipo>[][] <nome_matrice>;
int [][] x;
//dichiara x matrice
//bidimensionale di interi
String [][] parole; // dichiara una matrice
// di stringhe di nome
// parole
Creazione di una matrice
Il tipo matrice è un tipo riferimento. Un riferimento ad una
matrice si crea mediante l’operatore new. Quando si crea una
matrice è necessario specificarne le dimensioni (i.e. numero di
righe e numero di colonne)..
new <tipo> [<dimensione1>][<dimensione2];
x = new int [10][3];//alloca una matrice di
//10 righe e 3 colonne e
//memorizza il riferimento
//in x.
parole = new String[2][2]; //parole può
//contenere una da
//tabella di stringhe
//di 2 righe e 2
//colonne.
Creazione di una matrice
Un altro modo per creare un riferimento a una matrice consiste
nel dare esplicitamente l’elenco dei valori da memorizzare
(linearizzato per righe) in fase di dichiarazione.
int[][] x={{14,12},{1,24},{7,1},{2,9}};
String[][] frase={{“ab”,”cd”},{”ef”,”gh”}};
Accesso e scrittura di
una matrice
Le componenti di una matrice sono indicizzate mediante coppie
di numeri interi. Se la matrice ha n righe e m colonne, essa
conterrà n*m celle. L’indice sulle righe può variare da 0 a n-1,
mentre quello sulle colonne da 0 a m-1.
La componente di riga i e colonna j di una matrice può essere
reperita o scritta usando la seguente sintassi:
stampa ‘c’
<variabile di tipo matrice>[i][j]
char[][] l={{’a’,’b’},{’c’,’d’}};
char j;
mette ‘a’ in j
System.out.println(l[1][0]);
j=lettere[0][0];
lettere[1][1]= ‘k’; scrive ‘k’ nella seconda componente della
seconda riga e seconda colonna
Le classi
Un programma Java è un insieme di definizioni di classi. La
sintassi per definire una classe è
class <nome classe>
{
<corpo della classe>
}
il corpo di una classe è costituito da dichiarazione di variabili
(attributi della classe) e da definizioni di metodi
(comportamento della classe)
Metodi
Un metodo ha la seguente sintassi:
<tipo> <nome_metodo> (<lista_parametri>)
{
<corpo del metodo>
}
dove tipo è il tipo del valore di ritorno del metodo,
nome_metodo è un identificatore, lista_parametri è
una sequenza (eventualmente vuota) di coppie tipo
parametro che rappresenta i parametri di input del metodo,
infine corpo del metodo è la definizione del metodo vera
e propria.
Se il tipo di ritorno è diverso da void (parola chiave che denota
l’assenza di un valore di ritorno), il corpo del metodo deve
terminare con la parola chiave return seguita dal valore che
deve essere restituito.
Esempi di metodi
void stampamatrice()
{
int i,j;
for(i=0;i<numero_righe;i++){
for(j=0;j<numero_colonne;j++)
System.out.print(matrix[j][i]+" ");
System.out.println("");
}
}
int somma_numeri(int m, int n)
{
int z;
z=m+n;
return z;
}
Esempi
class Matrice
{
char [][] matrix;
int numero_righe;
int numero_colonne;
Matrice(int n, int m)
{
}
}
matrix=new int [n][m];
numero_righe=n;
numero_colonne=m;
void stampaMatrice()
{
int i,j;
for(i=0;i<numero_righe;i++){
for(j=0;j<numero_colonne;j++)
System.out.print(matrix[j][i]+" ");
System.out.println("");
}
}
Esempi di metodi
tipo
nome
parametri
void stampamatrice()
{
int i,j;
for(i=0;i<numero_righe;i++){
for(j=0;j<numero_colonne;j++)
System.out.print(matrix[j][i]+" ");
System.out.println("");
}
}
corpo
int somma_numeri(int m, int n)
{
int z;
z=m+n;
return z;
}
Metodo costruttore
Un metodo costruttore è un metodo speciale che ha lo stesso
nome della classe e che permette di creare oggetti (istanze) della
classe. Nella definizione di tale metodo non compare il tipo di
ritorno. Tipicamente un metodo costruttore definisce una lista di
parametri attraverso i quali si assegnano dei valori agli attributi
della classe.
<nome_costruttore> (<lista_parametri>)
{
<corpo del metodo>
}
Un oggetto O di una classe C si crea invocando il metodo
costruttore della classe e istanziando gli opportuni parametri. La
sintassi è la seguente:
new <nome_costruttore>(<valori_parametri>);
Overloading
In una classe è possibile definire metodi con nome uguale ma
parametri distinti (e pertanto comportamento distinto). In
questo caso si parla di overloading.
class Esempio_overloading
{
void stampaDati(int n)
{
System.out.println("stampa numero "+n);
}
void stampaDati(String s)
{
System.out.println("stampa stringa "+s);
}
}
Esempi
class Matrice
{
char [][] matrix;
int numero_righe;
int numero_colonne;
Matrice(int n, int m)
{
}
}
matrix=new int [n][m];
numero_righe=n;
numero_colonne=m;
attributi
costruttore
void stampaMatrice()
{
int i,j;
for(i=0;i<numero_righe;i++){
for(j=0;j<numero_colonne;j++)
System.out.print(matrix[j][i]+" ");
System.out.println("");
}
}
metodo
Esempi
class Esempio_Uso_Classe_Matrx
{
void creaScacchiera()
{
int i,j;
char colore=’b’;
Matrix scacchiera= new Matrix(3,3);
for(i=0;i<numero_righe;i++)
for(j=0;j<numero_colonne;j++){
scacchiera[i][j]=colore;
if (colore==’b’) colore=’n’ else colore=’b’;
}
}
Ereditarietà
È possibile derivare una classe B (chiamata sottoclasse) a partire da
una classe A (chiamata superclasse). La sottoclasse B eredita tutti i
metodi e gli attribuiti della superclasse. Inoltre in B possiamo
definire nuovi metodi e nuovi attributi non presenti in A. Tale
meccanismo è chiamato ereditarietà.
SINTASSI:
class <nome_sottoclasse> extends <nome_superclasse>
{
<corpo del sottoclasse>
}
Alcune proprietà
È possibile definire il metodo costruttore della classe derivata a
partire dal costruttore della superclasse utilizzando il costrutto
super(<lista valori>);
dove lista valori contiene i valori da passare come parametri
al costruttore della superclasse.
È possibile definire nella sottoclasse metodi che hanno lo stesso
nome di alcuni metodi della superclasse, ma parametri e
comportamento distinti (overriding).
Esempio
class Persona
{
String nome;
String cognome;
int eta;
Persona(String n, String c, int e){
nome=n;
cognome=c;
eta=e;
}
void stampaDati()
{
System.out.println("Salve, sono una persona e mi chiamo "+nome);
System.out.println("Ho "+eta+" anni");
}
public void modificaNome(String n)
{
nome=n;
}
public String ottieniNome()
{
return “Mr.”+nome;
}
}
Esempio
public class Studente extends Persona
{
// sottoclasse derivata dalla classe Persona
int matricola;
// costruttore della sottoclasse Studente
// si richiama il costruttore della sopraclasse
// Persona mediante l'istruzione super
public Studente(String n, String c, int e, int m)
{
super(n,c,e);
matricola=m;
}
public void stampaDati()
{
System.out.println("Salve, sono uno stuente e mi chiamo "+
nome+" "+cognome);
System.out.println("Ho "+eta+" anni"+ " e il mio numero di
matricola e' "+matricola);
}
}
public void modificaMatricola(int matr)
{
matricola=matr;
}
Interfacce
Un’interfaccia permette di definire una serie di prototipi di metodi
che saranno successivamente implementati da una o più classi.
Un’interfaccia si definisce nel seguente modo:
interface <nome_interfaccia>
{
<corpo dell’interfaccia>
}
dove nel corpo dell’interfaccia si definisce una lista di segnature di
metodi (i.e. intestazioni di metodi).
Esempio
interface Figura
{
double Area();
double Perimetro();
}
Interfacce
Una classe può implementare una o più interfacce usando la
seguente sintassi:
class <nome_classe> implements <nome_interfaccia1>, <nome_interfaccia2>
{
<corpo della classe>
}
Class Rettangolo implements Figura
{
double base; double altezza;
double xcoord; double ycoord;
Rettangolo(x,y,a,b){
base=b;altezza=a;xcoord=x;ycoord=y;
}
double Area(){
return base*altezza;
}
double Perimetro(){
return 2*base+2*altezza;
}
}
La classe Random
la classe Random è una classe predefinita che permette di
generare numeri pseudocasuali. È contenuta nel package java.util
e pertanto per poterla utilizzare è necessario importare tale
package con l’istruzione
import java.util.Random;
che deve essere posta all’inizio della definizione della classe che
userà la classe Random.
Per maggiori informazioni...
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Random.html
La classe Random
Alcuni metodi della classe Random:
• Random() costruisce un oggetto della classe Random
• nextInt() genera un numero intero pseudo casuale
• nextInt(int n) genera un numero casuale compreso
•
tra 0 e n-1
nextDouble()genera un numero di tipo double
compreso tra 0.0 e 1.0.
Uso della classe
Random
Tipicamente per poter utilizzare i metodi della classe si seguono
i seguenti passi:
1) si dichiara una variabile R della classe Random
2) si istanzia un oggetto della classe Random e si memorizza
nella variabile R
3) Si invoca il metodo desiderato attraverso R
4) si memorizza il numero casuale generato in una variabile del
tipo opportuno.
Esempio
{
Random R;
int X;
//Dichiarazione della variabile
//di tipo Random
R = new Random(); //Generazione di un
//oggetto di tipo Random
//e suo assegnamento alla
//variabile R
X = R.nextInt(15); //invocazione del metodo
//nextInt, che genera un
//numero pseudocasuale
//compreso fra 0 e 14 e
//assegnazione del numero
//generato alla variabile
// di tipo intero X
}
La classe String
• La classe String permette di rappresentare
sequenze di caratteri (i.e. stringhe).
• Tale classe è dotata di numerosi metodi per
la manipolazione delle stringhe.
• Maggiori informazioni al link
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html
Alcuni metodi della
classe String
• Costruttori
String() - costruisce una stringa vuota
Es. String s=new String();
String(String s1) - costruisce una
stringa e assegna ad essa il contenuto
della stringa s1.
Es. String s=new String(”pippo”);
Stesso effetto con: String s=”pippo”;
length() - calcola la lunghezza di una stringa
es. String s=new String(”pippo”);
int l=s.length(); // l=5
charAt(int i) - seleziona l’i-esimo carattere della stringa.
es. String s=new String(”pippo”);
char c=s.charAt(4); // c=’o’
equals(Object s) - confronta la stringa con l’oggetto s1. Se
sono uguali torna true altrimenti false
es. String s1=new String(”pippo”);
String s2=new String(”pappa”);
boolean uguali=s1.equals(s2); // uguali=false
toUpperCase() - Converte i caratteri di una stringa in
caratteri maiuscoli.
es. String s=new String(”PipPo”);
String s1= new String(s.toUpperCase());
// s1=”PIPPO”
toLowerCase() - Converte i caratteri di una stringa in
caratteri minuscoli.
es. String s=new String(”PipPo”);
String s1= new String(s.toLowerCase());
// s1=”pippo”
substring(int i, int j) - seleziona la sottostringa dalla posizione
i (inclusa) alla posizione j (esclusa).
es. String s=new String(”Cappotto”);
String s2= new String(s.substring(4,s.length()));
// s2=”otto”
concat(String s) - Concatena la stringa con la stringa s.
es. String s1=new String(”No”);
String s2= new String(”Where”);
s1=s1.concat(s2); //s1=”NoWhere”
Nota: per concatenare due stringhe potete sempre usare
l’operatore +. Es. “No”+”Where” -> “NoWhere”
Applet
• Sono programmi scritti in Java che possono
• essere scaricati dalla rete
• essere eseguiti direttamente nei browser
Applet in Java
•
Ogni applet e’ implementato come sottoclasse della classe
predefinita java.applet.Applet
•
Ogni applet deve implementare (ridefinire) alcuni metodi
ereditati dalla classe java.applet.Applet
•
•
•
•
•
init()
start()
paint(Graphics g)
stop()
destroy()
il metodo paint
• Permette di disegnare degli oggetti grafici
nella finestra del browser.
• Prende in input come parametro un oggetto
della classe Graphics.
• Graphics è una classe predefinita che
permette di disegnare delle figure
geometriche.
Un semplice esempio
import java.applet.Applet;
import java.awt.Graphics;
public class HelloWorld extends Applet {
public void paint(Graphics g) {
g.drawString("Hello world!", 50, 25);
}
}
Applet nelle pagine Web
Per inserire un applet in una pagina Web è necessario usare il tag
HTML Applet nel seguente modo:
<APPLET
code=”<nomeApplet.class>”
codebase=”<percorso/URL dell’applet>”
width=”<larghezza dell’area grafica dell’applet>”
height=”<altezzadell’area grafica dell’applet>”
>
Esempio:
<APPLET
code=”HelloWorld.class”
codebase=”.”
width=”500”
height=”500”
>
La classe Graphics
alcuni metodi
Graphics() - è il costruttore dellaclasse e permette di
istanziare un nuovo oggetto della classe
drawLine(int x1, int y1, int x2, int y2) - disegna un segmento
di retta i cui estremi sono i punti (x1,y1) e (x2,y2)
drawOval(int x, int y, int width, int height) - disegna un ovale
con angolo superiore sinistro di coordinate (x,y), largo width
e alto height.
drawRect(int x, int y, int width, int height) - disegna un
rettangolo il cui vertice in alto a sinistra ha coordinate (x,y),
largo width e alto height.
La classe Graphics
alcuni metodi
drawArc(int x, int y, int width, int height, int startangle, int
arcangle) - disegna un arco che origina in (x,y), largo width,
alto height, il cui angolo iniziale e! startangle el!angolo
dell!arco e! arcangle.
drawString(String s,int x, int y) - stampa s alle coordinate
(x,y).
setColor(Color c) - setta il colore al colore Color.c
Alcuni valori possibili per c: black, blue, cyan, darkGray,
orange, pink, red, yellow, magenta, white.
fillRect(int x, int y, int width, int height) - disegna un
rettangolo e lo riempie con colore selezionato
La classe Graphics
alcuni metodi
fillOval(int x, int y, int width, int height) - disegna un ovale e
lo riempie con il colore selezionato.
fillArc(int x, int y, int width, int height, int startangle, int
arcangle) - disegna un arco e lo riempie fino alla corda con il
colore selezionato.
drawPolygon(int[] x, int[] y, int n) - disegna un poligono di n
vertici. Le coordinate dei vertici sono date mediante gli array
di interi x[] e y[].
fillPolygon(int[] x, int[] y, int n) - disegna un poligono di n
vertici e lo riempie con il colore selezionato.
Scarica