Fondamenti di Informatica 1 Settimana 1 Obiettivi del Corso Fondamenti di Informatica 1 ✔ Il Corso ha l’obiettivo di Presentazione del Corso – presentare le basi teoriche dell’informatica – proporre un approccio ingegneristico e progettuale alla programmazione – fornire una visione professionale alla risoluzione dei problemi – utilizzare concretamente le caratteristiche di programmazione del linguaggio Java 1 2 Legenda dei simboli grafici Errori frequenti Accenni ad argomenti che verranno approfonditi in seguito Cos’è un computer? Consigli per la produttività Suggerimenti per la qualità Regole di sintassi Java Argomenti avanzati Note di cronaca 4 3 Cos’è un computer? Cos’è un computer? ✔ Oggi molte persone usano computer per lavoro o ✔ Ogni programma svolge una diversa funzione, per svago ✔ Sul lavoro, i computer sono ottimi per svolgere operazioni ripetitive o noiose, come effettuare calcoli o impaginare testi ✔ Nel gioco, i computer sono ottimi per coinvolgere al massimo l’utente-giocatore, perché possono riprodurre con estremo realismo suoni e sequenze di immagini ✔ In realtà, tutto questo non è merito propriamente del computer, ma dei programmi che su di esso vengono eseguiti 5 Marcello Dalpasso anche complessa – impaginare testi o giocare a scacchi ✔ Un computer è quindi una macchina che – memorizza dati (numeri, parole, immagini, suoni...) – interagisce con dispositivi (schermo, tastiera, mouse...) – esegue programmi ✔ I programmi sono sequenze di istruzioni che il computer esegue e di decisioni che il computer prende per svolgere una certa attività 6 1 Fondamenti di Informatica 1 Settimana 1 Cos’è un computer? Cos’è un computer? ✔ Nonostante i programmi siano molto sofisticati e ✔ L’elevatissimo numero di tali istruzioni presenti svolgano funzioni molto complesse, le istruzioni di cui sono composti sono molto elementari, ad esempio in un programma e la loro esecuzione ad altissima velocità garantisce l’illusione di una interazione fluida che viene percepita dall’utente ✔ Il computer, in conclusione, è una macchina estremamente versatile e flessibile, caratteristiche che gli sono conferite dai molteplici programmi che vi possono essere eseguiti, ciascuno dei quali consente di svolgere una determinata attività – – – – estrarre un numero da una posizione della memoria sommare due numeri inviare la lettera A alla stampante accendere un punto rosso in una data posizione dello schermo – se un dato è negativo, proseguire il programma da una certa istruzione anziché dalla successiva (decisione) 7 8 Cos’è la programmazione? ✔ Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari per svolgere un particolare compito Cos’è la programmazione? ✔ L’attività di progettare e realizzare un programma è detta programmazione ✔ In questo corso imparerete a programmare un computer! 9 10 Cos’è la programmazione? ✔ Usare un computer non richiede alcuna attività di programmazione, così come per guidare un automobile non è necessario essere un meccanico ✔ Invece, un informatico professionista solitamente svolge una intensa attività di programmazione, anche se la programmazione non è l’unica competenza che deve avere ✔ La programmazione è una parte importante dell’informatica, ed è un’attività che in genere affascina gli studenti e li motiva allo studio 11 Marcello Dalpasso Algoritmi 12 2 Fondamenti di Informatica 1 Settimana 1 Cos’è un algoritmo? Cos’è un algoritmo? ✔ Quale tipo di problemi è possibile risolvere con un ✔ Il primo problema non può essere risolto dal computer? – Dato un insieme di fotografie di paesaggi, qual è il paesaggio più rilassante? – Avendo depositato venti milioni in un conto bancario che produce il 5% di interessi all’anno, capitalizzati annualmente, quanti anni occorrono affinché il saldo del conto arrivi al doppio della cifra iniziale? computer perché non esiste una definizione di paesaggio rilassante che possa essere usata per confrontare in modo univoco due paesaggi diversi ✔ Un computer può risolvere soltanto problemi che potrebbero essere risolti anche manualmente – è solo molto più veloce, non si annoia, non fa errori ✔ Il secondo problema è certamente risolvibile ✔ Il primo problema non può essere risolto dal manualmente, facendo un po’ di calcoli... computer. Perché? 13 Cos’è un algoritmo? 14 Un esempio di algoritmo ✔ Problema: Avendo depositato venti milioni in un conto ✔ Si dice algoritmo la descrizione di un metodo di soluzione di un problema che – sia eseguibile – sia priva di ambiguità – arrivi ad una conclusione in un tempo finito ✔ Un computer può risolvere soltanto quei problemi per i quali sia noto un algoritmo ✔ 1 2 3 4 5 bancario che produce il 5% di interessi all’anno, capitalizzati annualmente, quanti anni occorrono affinché il saldo del conto arrivi al doppio della cifra iniziale? Algoritmo: L’anno attuale è 0; il saldo attuale è 20M Ripetere i successivi passi 3 e 4 finché il saldo è minore di 40M, poi passare al punto 5 Aggiungere 1 al valore dell’anno attuale Il nuovo saldo attuale è il valore del saldo attuale moltiplicato per 1.05 (cioè aggiungiamo il 5%) Il risultato è il valore dell’anno attuale 15 16 Un esempio di algoritmo A cosa servono gli algoritmi? ✔ Il metodo di soluzione proposto – è non ambiguo, perché fornisce precise istruzioni su cosa bisogna fare ad ogni passaggio e su quale deve essere il passaggio successivo – è eseguibile, perché ciascun passaggio può essere eseguito concretamente (se, ad esempio, il metodo di soluzione dicesse che il tasso di interesse da usare al punto 4 è variabile in dipendenza da fattori economici futuri, il metodo non sarebbe eseguibile…) – arriva a conclusione in un tempo finito, perché ad ogni passo il saldo aumenta di almeno un milione, quindi al massimo in 20 passi arriva al termine ✔ L’identificazione di un algoritmo è un requisito 17 Marcello Dalpasso indispensabile per risolvere un problema con il computer ✔ La scrittura di un programma per risolvere un problema con il computer consiste, in genere, nella traduzione di un algoritmo in un qualche linguaggio di programmazione ✔ Prima di scrivere un programma, è necessario individuare un algoritmo! 18 3 Fondamenti di Informatica 1 Settimana 1 Intervallo L’anatomia di un computer 19 20 L’anatomia di un computer L’unità centrale di elaborazione ✔ Per capire i meccanismi di base della ✔ L’unità centrale di elaborazione (CPU, Central programmazione è necessario conoscere gli elementi hardware che costituiscono un computer ✔ Prendiamo in esame il Personal Computer (PC), ma anche i computer più potenti hanno un’architettura molto simile Processing Unit) è il cuore del computer – individua ed esegue le istruzioni del programma – effettua elaborazioni aritmetiche e logiche con la sua unità logico-aritmetica (ALU, Arithmetic-Logic Unit) – reperisce i dati dalla memoria esterna e da altri dispositivi periferici e ve li rispedisce dopo averli elaborati – è costituita da uno o più chip (microprocessori) 21 22 Il chip della CPU La memoria del computer ✔ Un chip, o circuito integrato, ✔ La memoria serve ad immagazzinare dati e è un componente elettronico con connettori metallici esterni (pin) e collegamenti interni (wire), costituito principalmente di silicio e alloggiato in un contenitore plastico o ceramico (package) ✔ I collegamenti interni di un chip sono molto complicati; ad esempio, il chip Pentium™ di Intel è costituito da circa tre milioni di transistori tra loro interconnessi 23 Marcello Dalpasso programmi all’interno del computer ✔ È suddivisa in celle o locazioni di memoria, ognuna delle quali ha un indirizzo ✔ Ogni cella contiene un numero predefinito di bit, solitamente uguale a otto – un bit è un dato elementare che può assumere due valori, convenzionalmente chiamati zero e uno – un insieme di otto bit si chiama byte ed è l’unità di misura della memoria (es. 128 MByte) ✔ Ci sono due tipi di memoria – primaria e secondaria 24 4 Fondamenti di Informatica 1 Settimana 1 La memoria primaria La memoria ROM ✔ La memoria primaria è veloce ma costosa ✔ La memoria di sola lettura, ROM – conserva i dati ed i programmi in essa memorizzati anche quando il computer viene spento • è una memoria non volatile – contiene i programmi necessari all’avvio del computer, programmi che devono essere sempre disponibili • nei PC, tali programmi prendono il nome di BIOS (Basic Input/Output System) ✔ È costituita da chip di memoria realizzati con la stessa tecnologia (al silicio) utilizzata per la CPU – memoria di sola lettura (ROM, Read-Only Memory) – memoria ad accesso casuale (RAM, Random Access Memory) • dovrebbe chiamarsi memoria di lettura e scrittura, perché in realtà anche la ROM è ad accesso casuale, mentre ciò che le distingue è la possibilità di scrivervi • accesso casuale significa che il tempo per accedere ad un dato non dipende dalla sua posizione nella memoria 25 26 La memoria RAM La memoria secondaria ✔ La memoria ad accesso casuale, RAM – è una memoria che consente la lettura e la scrittura dei dati e dei programmi in essa contenuti – contiene dati in fase di modifica e programmi che non devono essere sempre disponibili ✔ La memoria secondaria (o di massa) è di solito un disco rigido (o disco fisso, hard disk) ed è un supporto non volatile e meno costoso della memoria primaria (circa cento volte) – programmi e dati risiedono sul disco rigido e vengono caricati nella RAM quando necessario, per poi tornarvi aggiornati se e quando necessario – perde i dati quando si spegne il computer • è un supporto volatile ✔ Un disco rigido è formato da piatti rotanti rivestiti di materiale magnetico, con testine di lettura/scrittura ✔ Processo simile a quello dei nastri audio o video 27 28 La memoria secondaria La memoria secondaria ✔ Sono molto diffusi anche altri tipi di memoria ✔ Sono molto diffusi anche altri tipi di memoria secondaria a tecnologia ottica secondaria a tecnologia magnetica – CD-ROM (Compact Disc Read-Only Memory), viene letto da un dispositivo laser, esattamente come un CD audio; ha una elevata capacità ed è molto economico e affidabile; è un supporto di sola lettura, utilizzato per distribuire programmi e informazioni – CD-R (Compact Disc Recordable), utilizza una tecnologia simile al CD-ROM ma può essere scritto dall’utente (una sola volta; più volte se CD-RW) – DVD, rappresenta la nuova frontiera per questa tecnologia, con elevatissima capacità – floppy disk (dischetto flessibile), di capacità limitata ma con il vantaggio di poter essere agevolmente rimosso dal sistema e trasferito ad un altro sistema (dispositivo di memoria esterno) – tape (nastri per dati), di capacità elevatissima, molto economici, ma molto lenti, perché l’accesso ai dati è sequenziale anziché casuale (bisogna avvolgere o svolgere un nastro invece che spostare la testina di lettura sulla superficie di un disco) 29 Marcello Dalpasso 30 5 Fondamenti di Informatica 1 Settimana 1 Dispositivi periferici di interazione La scheda madre di un PC ✔ L’interazione fra l’utente umano ed il computer ✔ La CPU, la memoria primaria (RAM e ROM) e i avviene mediante i cosiddetti dispositivi periferici di Input/Output (dispositivi di I/O) ✔ Tipici dispositivi di input sono la tastiera, il mouse (dispositivo di puntamento), il microfono (per impartire comandi vocali), il joystick (per i giochi), lo scanner (per la scansione digitale di documenti e immagini) ✔ Tipici dispositivi di output sono lo schermo (monitor), le stampanti, gli altoparlanti circuiti elettronici che controllano il disco rigido e altri dispositivi periferici sono interconnessi mediante un insieme di linee elettriche che formano un bus ✔ I dati transitano lungo il bus, dalla memoria e dai dispositivi periferici verso la CPU, e viceversa ✔ All’interno del PC si trova la scheda madre (mother-board), che contiene la CPU, la memoria primaria, il bus e gli alloggiamenti (slot) di espansione per il controllo delle periferiche 31 Intervallo 32 Il modello di von Neumann 33 34 Il modello di John von Neumann Il modello di John von Neumann ✔ Nel 1946, John von Neumann elaborò un modello ✔ L’architettura di von Neumann è composta da teorico dell’architettura di un elaboratore che è tuttora valido e molto utilizzato ✔ La grande maggioranza degli elaboratori odierni ha una architettura che può essere (più o meno facilmente) ricondotta al modello di von Neumann – le eccezioni più importanti sono alcune macchine ad elaborazione parallela quattro blocchi comunicanti tra loro per mezzo di un bus, un canale di scambio di informazioni CPU Memoria principale Memoria secondaria Dispositivi di Input e di Output ✔ Il modello è importante in quanto schematizza in modo omogeneo situazioni diverse Bus – lo presentiamo in una versione un po’ modificata 35 Marcello Dalpasso 36 6 Fondamenti di Informatica 1 Settimana 1 L’unità centrale di elaborazione Ciclo di funzionamento della CPU ✔ Dal punto di vista logico, la CPU è costituita da ✔ Ogni ciclo di funzionamento è composto da tre fasi – accesso: lettura dell’istruzione da eseguire e sua memorizzazione nel registro istruzione – decodifica: decodifica dell’istruzione – esecuzione: esecuzione dell’istruzione tre parti principali – l’unità logico-aritmetica (ALU) – l’unità di controllo, che ne governa il funzionamento – un insieme di registri, che sono spazi ad accesso molto veloce per la memorizzazione temporanea dei dati ✔ Il funzionamento della CPU è ciclico ed il periodo di tale ciclo viene scandito dall’orologio di sistema (clock), la cui frequenza costituisce una delle caratteristiche tecniche più importanti della CPU (es. 800 MHz, 800 milioni di cicli al secondo) Si parla di ciclo fetch-decode-execute ✔ La posizione dell’istruzione a cui si accede durante la fase di fetch è contenuta nel contatore di programma (program counter) – viene incrementato di un’unità ad ogni ciclo, in modo da eseguire istruzioni in sequenza 37 38 Il bus nel modello di von Neumann ✔ Il bus è in realtà costituito da tre bus distinti – bus dei dati – bus degli indirizzi – bus dei segnali di controllo Programmazione in codice macchina ✔ Sul bus dei dati viaggiano dati da e verso la CPU ✔ Sugli altri viaggiano segnali che provengono soltanto dalla CPU CPU Memoria principale Memoria secondaria Dispositivi di Input e di Output Bus 40 39 Le istruzioni macchina Le istruzioni macchina ✔ Le istruzioni elementari eseguite da un computer (dalla sua CPU) si chiamano istruzioni macchina ✔ L’insieme di istruzioni macchina (instruction set) è specifico di una particolare CPU: quello di un Pentium™ è diverso da quello di uno SPARC™ ✔ Una particolare CPU è la cosiddetta macchina virtuale Java (JVM, Java Virtual Machine) – la JVM non è una vera CPU… ma per il momento possiamo considerarla tale… 41 Marcello Dalpasso ✔ Esempio di alcune istruzioni macchina: – carica in un registro il valore contenuto nella posizione di memoria 40 – carica in un altro registro il valore 100 – se il primo valore è maggiore del secondo, prosegui con l’istruzione contenuta nella posizione di memoria 240, altrimenti con l’istruzione che segue quella attuale ✔ La codifica delle istruzioni macchina avviene sotto forma di configurazioni di bit conservate in memoria, che possono essere viste come numeri ✔ Le precedenti istruzioni per la JVM diventano 21 40 16 100 163 240 42 7 Fondamenti di Informatica 1 Settimana 1 Le istruzioni macchina Le istruzioni macchina ✔ In tutte le CPU, le istruzioni macchina si possono ✔ Per eseguire un programma in un computer è suddividere nelle seguenti categorie – trasferimento dati, tra i registri e la memoria principale • LOAD (verso un registro), STORE (verso la memoria) – operazioni, eseguite dalla ALU • aritmetiche: ADD, SUB, MUL, DIV • logiche: AND, OR, NOT – istruzioni di salto, per alterare il flusso di esecuzione sequenziale (viene modificato il Program Counter) • incondizionato (JUMP), salta in ogni caso • condizionato: salta solo se un certo valore è zero (JZ) o se è maggiore di zero (JGZ) necessario scrivere all’interno della memoria primaria le configurazioni di bit corrispondenti alle istruzioni macchina del programma ✔ Per fare ciò è necessario conoscere tutti i codici numerici delle istruzioni macchina ✔ Questa operazione lunga e noiosa (che veniva eseguita agli albori dell’informatica) è stata presto automatizzata da un programma in esecuzione sul computer stesso, detto assemblatore (assembler) 43 44 L’assemblatore L’assemblatore ✔ Utilizzando l’assemblatore, il programmatore ✔ Un’altra caratteristica molto utile dell’assemblatore scrive il programma mediante dei nomi abbreviati (codici mnemonici ) per le istruzioni macchina, iload 40 molto più facili da ricordare – esempio precedente per la JVM bipush 100 if_icmpgt 240 ✔ L’uso di nomi abbreviati è assai più agevole, ed il programma assemblatore si occupa poi di tradurre il programma in configurazioni di bit ✔ Tali linguaggi con codici mnemonici si dicono linguaggi assembly (uno diverso per ogni CPU) è quella di poter assegnare dei nomi agli indirizzi di memoria e ai valori numerici e di usarli nelle istruzioni iload rate bipush maxRate if_icmpgt tooMuch ✔ In questo modo il programma è molto più leggibile, perché viene evidenziato il significato degli indirizzi di memoria e dei valori numerici 45 46 I linguaggi assembly ✔ Vantaggio: rappresentarono un grosso passo avanti rispetto alla programmazione in linguaggio macchina ✔ Problema: occorrono molte istruzioni per eseguire anche le operazioni più semplici ✔ Problema: la sequenza di istruzioni di uno stesso programma cambia al cambiare della CPU è molto costoso scrivere programmi che possano funzionare su diverse CPU, perché praticamente bisogna riscriverli completamente 47 Marcello Dalpasso Linguaggi di programmazione ad alto livello 48 8 Fondamenti di Informatica 1 Settimana 1 Linguaggi ad alto livello Linguaggi ad alto livello ✔ Negli anni ‘50 furono inventati i primi linguaggi di ✔ Un programma, detto compilatore, legge il programmazione ad alto livello – FORTRAN: primo “vero” linguaggio programma in linguaggio ad alto livello e genera il corrispondente programma nel linguaggio macchina di una specifica CPU ✔ I linguaggi ad alto livello sono • BASIC, COBOL – Anni ‘60 e ‘70: programmazione strutturata • Pascal (Niklaus Wirth, 1968) • C ( Brian Kernigham e Dennis Ritchie, 1970-75) – Anni ‘80 e ‘90, programmazione orientata agli oggetti indipendenti dalla CPU ma il prodotto della compilazione (codice eseguibile), non è indipendente dalla CPU • C++ ( Bjarne Stroustrup, 1979) • Java (James Gosling e Patrick Naughton, 1991) ✔ Il programmatore esprime la sequenza di operazioni da compiere, senza scendere al livello di dettaglio delle istruzioni macchina if (rate > 100) System.out.print("Troppo"); – occorre compilare il programma con un diverso compilatore per ogni CPU sulla quale si vuole eseguire il programma stesso 49 50 Linguaggi ad alto livello Linguaggi ad alto livello ✔ Esistono molti linguaggi di programmazione ad ✔ I linguaggi di programmazione, creati dall’uomo, alto livello, così come esistono molte lingue ✔ L’esempio seguente è in linguaggio Java hanno una sintassi molto più rigida di quella dei linguaggi naturali, per agevolare il compilatore ✔ Il compilatore segnala gli errori di sintassi if (rate > 100) System.out.print("Troppo"); e questo è l’equivalente in linguaggio Pascal if (rate > 100)) System.out.print("Troppo"); e non tenta di capire, come farebbe un utente umano, perché sarebbe molto difficile verificare le intuizioni del compilatore if rate > 100 then write (’Troppo’); ✔ La sintassi di un linguaggio viene scelta dai progettisti del linguaggio stesso, come compromesso fra leggibilità, facilità di compilazione e coerenza con altri linguaggi meglio la segnalazione di errori! 51 52 Il linguaggio di programmazione Java 53 Marcello Dalpasso 54 9 Fondamenti di Informatica 1 Settimana 1 Il linguaggio Java™ Il linguaggio Java ✔ Nato nel 1991 in Sun Microsystems, da un gruppo ✔ Il linguaggio Java è stato adottato da moltissimi di progettisti guidato da Gosling e Naughton ✔ Progettato per essere semplice e indipendente dalla CPU (o, come anche si dice, dall’hardware, dalla piattaforma o dall’architettura) ✔ Il primo prodotto del progetto Java fu un browser, HotJava, presentato nel 1994, che poteva scaricare programmi (detti applet) da un server ed eseguirli sul computer dell’utente, indipendentemente dalla sua piattaforma programmatori perché – è più semplice del suo più diretto concorrente, il C++ – consente di scrivere e compilare una volta ed eseguire dovunque (cioè su tutte le piattaforme) – ha una ricchissima libreria che mette a disposizione dei programmatori un insieme vastissimo di funzionalità standard, indipendenti anche dal sistema operativo 55 56 Il linguaggio Java per gli studenti ✔ Dato che Java non è stato progettato per la didattica – non è molto semplice scrivere programmi Java molto semplici! ✔ Anche per scrivere programmi molto semplici è necessario conoscere parecchi dettagli “tecnici”, e questo potrebbe essere un problema nelle prime lezioni ✔ Adotteremo lo stile didattico di usare alcuni costrutti sintattici senza spiegarli o approfondirli, rimandando tali fasi al seguito 57 Il nostro primo programma Java 58 Il nostro primo programma Java public class Hello { public static void main(String[] args) { System.out.println("Hello, World!"); } } ✔ Tradizionalmente, il primo programma che si scrive quando si impara un linguaggio di programmazione ha il compito di visualizzare sullo schermo un semplice saluto ✔ Occorre fare molta attenzione Hello, World! – il testo va inserito esattamente come è presentato ✔ Scriviamo il programma nel file • per il momento… Hello.java usando un editor di testi – maiuscole e minuscole sono considerate distinte – il file deve chiamarsi Hello.java 59 Marcello Dalpasso Compilare un semplice programma 60 10 Fondamenti di Informatica 1 Settimana 1 Il nostro primo programma Java Una nota stilistica ✔ A questo punto compiliamo il programma ✔ Diversamente da altri linguaggi (es. FORTRAN) il linguaggio Java consente una disposizione del testo a formato libero: gli spazi e le interruzioni di riga (“andare a capo”) non sono importanti, tranne che per separare parole javac Hello.java ed il compilatore genera il file Hello.class ✔ Ora eseguiamo il programma ✔ Sarebbe quindi possibile scrivere java Hello public class Hello{public static void main (String[ ] args) System.out. println("Hello, World!") ;}} ottenendo la visualizzazione del messaggio di saluto sullo schermo ✔ Bisogna però fare attenzione alla leggibilità! Hello, World! 61 Analisi del primo programma Analisi del primo programma ✔ La parola chiave public indica che la classe Hello ✔ La prima riga public class Hello definisce una nuova classe ✔ Le classi sono fabbriche di oggetti e rappresentano un concetto fondamentale in Java, che è un linguaggio di programmazione orientato agli oggetti (OOP, Object-Oriented Programming) ✔ Per il momento, consideriamo gli oggetti come elementi da manipolare in un programma Java 62 può essere utilizzata da tutti (in seguito vedremo private…) public class Hello ✔ Una parola chiave è una parola riservata del linguaggio che va scritta esattamente così com’è e che non può essere usata per altri scopi ✔ La parola chiave class indica che inizia la definizione di una classe ✔ Ciascun file sorgente (parte di un programma Java) può contenere una sola classe pubblica, il cui nome deve coincidere con il nome del file 63 64 Analisi del primo programma Analisi del primo programma ✔ Per ora non usiamo le classi come fabbriche di ✔ La costruzione oggetti, ma come contenitori di metodi ✔ Un metodo serve a definire una sequenza di istruzioni o enunciati che descrive come svolgere un determinato compito (in altri linguaggi i metodi si chiamano funzioni o procedure) ✔ Un metodo deve essere inserito in una classe, quindi le classi rappresentano il meccanismo principale per l’organizzazione dei programmi 65 Marcello Dalpasso public static void main(String[] args) { ... } definisce il metodo main (principale) ✔ Un’applicazione Java deve avere un metodo main ✔ Anche qui, public significa utilizzabile da tutti ✔ Invece, static significa che il metodo main non esamina e non modifica gli oggetti della classe Hello a cui appartiene 66 11 Fondamenti di Informatica 1 Settimana 1 Programma semplice Analisi del primo programma ✔ Gli enunciati del corpo di un metodo (gli enunciati ✔ Sintassi: contenuti tra le parentesi graffe) vengono eseguiti uno alla volta nella sequenza in cui sono scritti public class NomeClasse { public static void main(String[] args) { enunciati } } ✔ Ogni enunciato termina con il carattere ; ✔ Il metodo main del nostro esempio ha un solo enunciato, che visualizza una riga di testo ✔ Scopo: eseguire un programma semplice, descritto System.out.println("Hello, World!"); da enunciati e contenuto nel file NomeClasse.java ✔ Nota: la parte in blu viene per ora considerata una infrastruttura necessaria, approfondita in seguito ✔ Ma dove la visualizza? Un programma può inserire 67 68 Analisi del primo programma testo in una finestra, scriverlo in un file o anche inviarlo ad un altro computer attraverso Internet... Analisi del primo programma System.out.println("Hello, World!"); System.out.println("Hello, World!"); ✔ Nel nostro caso la destinazione è l’output ✔ Quando si usa un oggetto, bisogna specificare standard, una proprietà di ciascun programma che dipende dal sistema operativo del computer ✔ In Java, l’output standard è rappresentato da un oggetto di nome out cosa si vuol fare con l’oggetto stesso – come ogni metodo, anche gli oggetti devono essere inseriti in classi: out è inserito nella classe System della libreria standard, che contiene oggetti e metodi da utilizzare per accedere alle risorse di sistema – per usare l’oggetto out della classe System si scrive System.out – in questo caso vogliamo usare un metodo dell’oggetto out, il metodo println, che stampa una riga di testo – per usare il metodo println dell’oggetto System.out si scrive System.out.println(parametri) – la coppia di parentesi tonde racchiude le informazioni necessarie per l’esecuzione del metodo (parametri) ✔ A volte il carattere punto significa “usa un oggetto di una classe”, altre volte “usa un metodo di un oggetto”: dipende dal contesto... 69 Invocazione di metodo Analisi del primo programma ✔ Una sequenza di caratteri racchiusa tra virgolette si chiama stringa (string) "Hello, World!" ✔ C’è un motivo per dover racchiudere le stringhe tra ✔ Sintassi: oggetto.nomeMetodo(parametri) virgolette ✔ Scopo: invocare il metodo nomeMetodo dell’oggetto, fornendo parametri se sono richiesti ✔ Nota: se non sono richiesti parametri, le parentesi tonde devono essere indicate ugualmente ✔ Nota: se ci sono due o più parametri, essi vanno separati l’uno dall’altro con una virgola, all’interno delle parentesi tonde 71 Marcello Dalpasso 70 – come farebbe altrimenti il compilatore a capire che volete, ad esempio, stampare la parola class e non che volete iniziare la definizione di una nuova classe? ✔ Il metodo println può anche stampare numeri System.out.println(7); System.out.println(3 + 4); ✔ C’è anche il metodo print, che funziona come println ma non va a capo al termine della stampa 72 12 Fondamenti di Informatica 1 Settimana 1 Intervallo Errori di programmazione 73 74 Errori di programmazione Errori di sintassi ✔ L’attività di programmazione, come ogni altra ✔ In questo caso il compilatore riesce agevolmente ad System.aut.println("Hello, World!"); attività di progettazione, è soggetta ad errori di vario tipo individuare e segnalare l’errore di sintassi, perché identifica il nome di un oggetto (simbolo) che non è stato definito (aut) e sul quale non è in grado di “decidere” – errori di sintassi o di compilazione System.aut.println("Hello, World!"); System.out.println("Hello, World!); – errori logici o di esecuzione posizione (numero di riga) posizione (nella riga) System.out.println("Hell, World!"); C:\>javac Hello.java Hello.java:3: cannot resolve symbol symbol : variable aut location: class java.lang.System System.aut.println("Hello, World!"); ^ 1 error diagnosi 75 Errori di sintassi virgolette mancanti System.out.println("Hello, World!); ✔ Questo è invece un caso molto più complesso: viene giustamente segnalato il primo errore, una stringa non terminata, e viene evidenziato il punto dove inizia la stringa C:\>javac Hello.java Hello.java:3: unclosed string literal System.out.println("Hello, World!); ^ Hello.java:3: ')' expected System.out.println("Hello, World!); ^ 2 errors 77 Marcello Dalpasso 76 Errori di sintassi ✔ Viene però segnalato anche un secondo errore – il compilatore si aspetta di trovare una parentesi tonda chiusa, in corrispondenza di quella aperta – la parentesi in realtà c’è, ma il compilatore l’ha inserita all’interno della stringa, cioè ha prolungato la stringa fino al termine della riga C:\>javac Hello.java Hello.java:3: unclosed string literal System.out.println("Hello, World!); ^ Hello.java:3: ')' expected System.out.println("Hello, World!); ^ 2 errors 78 13 Fondamenti di Informatica 1 Errori logici Settimana 1 manca un carattere System.out.println("Hell, World!"); ✔ Questo errore, invece, non viene segnalato dal compilatore, che non può sapere che cosa il programmatore abbia intenzione di far scrivere al programma sull’output standard – la compilazione va a buon fine – si ha un errore durante l’esecuzione del programma, perché viene prodotto un output diverso dal previsto Errori logici ✔ Sono molto più insidiosi degli errori di sintassi – il programma viene compilato correttamente, ma non fa quello che dovrebbe fare ✔ L’eliminazione degli errori logici richiede molta pazienza, eseguendo il programma ed osservando con attenzione i risultati prodotti – è necessario collaudare i programmi, come qualsiasi altro prodotto dell’ingegneria ✔ Si usano programmi specifici (debugger) per C:\>java Hello Hell, World! trovare gli errori logici (bug) in un programma 79 80 Le fasi della programmazione ✔ L’attività di programmazione si esegue in tre fasi – scrittura del programma (codice sorgente) – compilazione del codice sorgente Le fasi della programmazione • creazione del codice eseguibile (codice macchina) – esecuzione del programma ✔ Per scrivere il codice sorgente si usa un editor di testo, salvando (memorizzando) il codice in un file Hello.java 81 82 La compilazione del sorgente L’esecuzione del programma ✔ Compilando il codice sorgente di un programma ✔ Per eseguire un programma si usa l’interprete javac Hello.java genera Hello.class ✔ Quindi il bytecode non è codice direttamente – carica il bytecode del programma (della classe Hello) – avvia il programma eseguendo il metodo main di tale classe – carica successivamente i file di bytecode di altre classi che sono necessarie durante l’esecuzione (ad esempio, la classe System) ✔ java Hello scrive Hello, World! sullo standard output (gli enunciati in linguaggio Java) si ottiene un particolare formato di codice eseguibile, detto bytecode, che è codice macchina per la Java Virtual Machine (JVM) Java, un programma eseguibile sul computer dell’utente che eseguibile, dato che la JVM non esiste… ✔ Il file con il codice bytecode contiene una traduzione delle istruzioni del programma 83 Marcello Dalpasso 84 14 Fondamenti di Informatica 1 Settimana 1 La libreria di classi standard Il processo di programmazione in Java ✔ Per scrivere sullo standard output è necessario interagire con il sistema operativo, un’operazione di basso livello che richiede conoscenze specifiche ✔ Queste operazioni, per chi utilizza il linguaggio Java, sono state già realizzate dagli autori del linguaggio (Sun Microsystems), che hanno scritto delle classi apposite (ad esempio, System) ✔ Il bytecode di queste classi si trova all’interno di librerie standard, che sono raccolte di classi ✔ Non è necessario avere a disposizione il codice sorgente di queste classi, né capirlo! Comodo... codice sorgente compilatore file di bytecode librerie interprete JDK - Java Development Kit programma in esecuzione E se qualcosa non funziona? 85 86 Modifica-Compila-Collauda Compilatore e/o interprete inizio ✔ Per passare dalla scrittura del file sorgente in linguaggio Si crea o modifica programma edit Hello.java compila programma javac Hello.java eventualmente usa debugger jdb Hello collauda programma java Hello Java all’esecuzione del programma su una particolare CPU, si usa il compilatore e l’interprete ✔ Con la maggior parte degli altri linguaggi di programmazione ad alto livello, invece, si usa soltanto il compilatore oppure soltanto l’interprete errori di sintassi? No Si errori di logica? No fine 87 librerie codice sorgente compilatore codice sorgente librerie file di bytecode 88 Compilatore e/o interprete Il processo di programmazione codice sorgente – con linguaggi compilati come Pascal, C e C++, si usa il compilatore per creare un file eseguibile, contenente codice macchina, a partire da file sorgenti (con l’eventuale ausilio di un caricatore, loader, che interagisce con una libreria) – con linguaggi interpretati come BASIC e PERL, l’interprete traduce “al volo” il file sorgente in codice eseguibile e lo esegue, senza creare un file eseguibile librerie ✔ Il fatto che un linguaggio sia compilato o interpretato influisce fortemente su quanto è compilatore (caricatore) interprete – facile eseguire lo stesso programma su computer aventi diverse CPU (portabilità) – veloce l’esecuzione di un programma (efficienza) ✔ Entrambi questi aspetti sono molto importanti file eseguibile interprete programma in esecuzione programma in esecuzione programma in esecuzione linguaggio Java linguaggi interpretati linguaggi compilati 89 Marcello Dalpasso nella fase di scelta di un linguaggio di programmazione da utilizzare in un progetto ✔ Il linguaggio Java, da questo punto di vista, è un linguaggio misto, essendo sia compilato sia interpretato, in fasi diverse 90 15 Fondamenti di Informatica 1 Settimana 1 Portabilità Efficienza ✔ I programmi scritti in un linguaggio interpretato ✔ I programmi scritti in un linguaggio interpretato sono poco efficienti sono portabili ✔ I programmi scritti in un linguaggio compilato – sono portabili a livello di file sorgente, ma è necessario compilare il programma su ogni diversa CPU – non sono portabili a livello di file eseguibile, perché esso contiene codice macchina per una particolare CPU ✔ I programmi scritti in linguaggio Java sono portabili, oltre che a livello di file sorgente, anche ad un livello intermedio, il livello del bytecode – l’intero processo di traduzione in linguaggio macchina deve essere svolto ad ogni esecuzione ✔ I programmi scritti in un linguaggio compilato sono molto efficienti – l’intero processo di traduzione in linguaggio macchina viene svolto prima dell’esecuzione, una volta per tutte ✔ I programmi scritti in linguaggio Java hanno un’efficienza intermedia – parte del processo di traduzione viene svolto una volta per tutte (dal compilatore) e parte viene svolto ad ogni esecuzione (dall’interprete) – possono essere compilati una sola volta ed eseguiti da interpreti diversi su diverse CPU 91 92 Portabilità ed efficienza ✔ Se si vuole soltanto la portabilità, i linguaggi interpretati sono la scelta migliore ✔ Se si vuole soltanto l’efficienza, i linguaggi compilati sono la scelta migliore ✔ Se si vogliono perseguire entrambi gli obiettivi, come quasi sempre succede, il linguaggio Java può essere la scelta vincente 93 94 Un programma che elabora numeri public class Coins1 { public static void main(String[] args) { int lit = 15000; // lire italiane double euro = 2.35; // euro Tipi di dati numerici // calcola il valore totale double totalEuro = euro + lit / 1936.27; // stampa il valore totale System.out.print("Valore totale in euro "); System.out.println(totalEuro); } } 95 Marcello Dalpasso 96 16 Fondamenti di Informatica 1 Settimana 1 Un programma che elabora numeri I numeri in virgola mobile ✔ Questo programma elabora due tipi di numeri ✔ I numeri frazionari vengono di solito rappresentati – numeri interi per le lire italiane, che non prevedono l’uso di decimi e centesimi e quindi non hanno bisogno di una parte frazionaria – numeri frazionari (“in virgola mobile”) per gli euro, che prevedono l’uso di decimi e centesimi e assumono valori con il separatore decimale ✔ I numeri interi (positivi e negativi) si rappresentano in Java con il tipo di dati int ✔ I numeri in virgola mobile (positivi e negativi, a precisione doppia) si rappresentano in Java con il tipo di dati double nei computer come numeri in virgola mobile – si rappresentano con la sequenza delle loro cifre significative e con l’indicazione della posizione del separatore decimale • 250 e 2,5 hanno le stesse cifre significative (25), ma diverse posizioni del separatore decimale – è molto facile moltiplicare o dividere per 10, in quanto cambia solo la posizione della virgola (che è mobile) – equivale alla rappresentazione esponenziale (2,5 × 102) – in realtà si usa la rappresentazione in base 2 anziché 10 97 98 I commenti Perché usare due tipi di numeri? ✔ In realtà sarebbe possibile usare numeri in virgola mobile anche per rappresentare i numeri interi, ma ecco due buoni motivi per non farlo – “filosofia”: indicando esplicitamente che per le lire italiane usiamo un numero intero, rendiamo evidente il fatto che non esistono i decimali per le lire italiane • è importante rendere comprensibili i programmi! – “pratica”: i numeri interi rappresentati come tipo di dati int sono più efficienti, perché occupano meno spazio in memoria e sono elaborati più velocemente ✔ Nel programma sono presenti anche dei commenti, che ✔ ✔ ✔ ✔ vengono ignorati dal compilatore, ma che rendono il programma molto più comprensibile // lire italiane Un commento inizia con una doppia barra // e termina alla fine della riga Nel commento si può scrivere qualsiasi cosa Se il commento si deve estendere per più righe, è molto scomodo usare tante volte la sequenza // Si può iniziare un commento con /* e terminarlo con */ // questo e’ un commento // lungo,inutile... // ... e anche scomodo /* questo e’ un commento lungo ma inutile... */ 99 Alcune note sintattiche L’uso delle variabili ✔ L’operatore che indica la divisione è /, quello che lit / 1936.27 indica la moltiplicazione è * ✔ Quando si scrivono numeri in virgola mobile, bisogna usare il punto come separatore decimale, 1936.27 invece della virgola (uso anglosassone) ✔ Quando si scrivono numeri, non bisogna indicare 15000 il punto separatore delle migliaia ✔ I numeri in virgola mobile si possono anche esprimere in notazione esponenziale 1.93E3 // vale 1.93 × 103 101 Marcello Dalpasso 100 ✔ Il programma fa uso di variabili di tipo numerico – lit di tipo int, euro e totalEuro di tipo double ✔ Le variabili sono spazi di memoria, identificati da un nome, che possono conservare valori di un determinato tipo ✔ Ciascuna variabile deve essere definita, int lit; indicandone il tipo ed il nome ✔ Una variabile può contenere soltanto valori del suo stesso tipo ✔ Nella definizione di una variabile, è possibile assegnarle un valore iniziale int lit = 15000; 102 17 Fondamenti di Informatica 1 Settimana 1 L’uso delle variabili I nomi delle variabili ✔ Il programma poteva risolvere lo stesso problema ✔ La scelta dei nomi per le variabili è molto importante, ed è anche senza fare uso di variabili public class Coins2 { public static void main(String[] args) { System.out.print("Valore totale in euro "); System.out.println(2.35 + 15000 / 1936.27); } } ma sarebbe stato molto meno comprensibile e modificabile con difficoltà bene scegliere nomi che descrivano adeguatamente la funzione della variabile ✔ In Java, un nome (di variabile, di metodo, di classe…) può essere composto da lettere, da numeri e dal carattere di sottolineatura, ma – deve iniziare con una lettera – non può essere una parola chiave del linguaggio – non può contenere spazi ✔ Le lettere maiuscole sono diverse dalle minuscole! Ma è buona norma non usare nello stesso programma nomi di variabili che differiscano soltanto per una maiuscola 103 104 Definizione di variabili ✔ Sintassi: nomeTipo nomeVariabile; nomeTipo nomeVariabile = espressione; ✔ Scopo: definire la nuova variabile nomeVariabile, di tipo nomeTipo, ed eventualmente assegnarle il valore iniziale espressione ✔ Di solito in Java si usano le seguenti convenzioni Assegnazioni – i nomi di variabili e di metodi iniziano con una lettera minuscola lit main Coins1 – i nomi di classi iniziano con una lettera maiuscola – i nomi composti, in entrambi i casi, si ottengono attaccando le parole successive alla prima con la maiuscola totalEuro MoveRectangle 106 105 L’uso delle variabili L’uso delle variabili ✔ Abbiamo visto come i programmi usino le public class Coins6 { public static void main(String[] args) { int lit = 15000; // lire italiane double euro = 2.35; // euro double dollars = 3.05; // dollari // calcola il valore totale // sommando successivamente i contributi double totalEuro = lit / 1936.27; totalEuro = totalEuro + euro; totalEuro = totalEuro + dollars * 0.93; System.out.print("Valore totale in euro "); System.out.println(totalEuro); } } variabili per memorizzare i valori da elaborare e i risultati dell’elaborazione ✔ Le variabili sono posizioni in memoria che possono conservare valori di un determinato tipo ✔ Il valore memorizzato in una variabile può essere modificato, non soltanto inizializzato… ✔ Il cambiamento del valore di una variabile si ottiene con un enunciato di assegnazione 107 Marcello Dalpasso 108 18 Fondamenti di Informatica 1 Settimana 1 L’uso delle variabili L’assegnazione ✔ In questo caso il valore della variabile totalEuro ✔ Analizziamo l’enunciato di assegnazione cambia durante l’esecuzione del programma totalEuro = totalEuro + euro; – per prima cosa la variabile viene inizializzata contestualmente alla sua definizione ✔ Cosa significa? Non certo che totalEuro è uguale a se stessa più qualcos’altro… double totalEuro = lit / 1936.27; ✔ L’enunciato di assegnazione significa – poi la variabile viene incrementata, due volte Calcola il valore dell’espressione a destra del segno = e scrivi il risultato nella posizione di memoria assegnata alla variabile indicata a sinistra del segno = totalEuro = totalEuro + euro; totalEuro = totalEuro + dollars * 0.93; mediante enunciati di assegnazione 109 L’assegnazione euro totalEuro Assegnazione o definizione? ✔ Attenzione a non confondere la definizione di una variabile con un enunciato di assegnazione! 2.35 7.746853486342298 LEGGI double totalEuro = lit / 1936.27; totalEuro = totalEuro + euro; ✔ La definizione di una variabile inizia specificando LEGGI SCRIVI 110 il tipo della variabile, l’assegnazione no totalEuro + euro ✔ Una variabile può essere definita una volta sola, mentre le si può assegnare un valore molte volte ✔ Il compilatore segnala come errore il tentativo di CALCOLA definire una variabile una seconda volta 10.096853486342297 double euro = 2; double euro = euro + 3; 111 euro is already defined 112 Assegnazione Incremento di una variabile ✔ Sintassi: ✔ L’incremento di una variabile è l’operazione che consiste nell’aumentarne il valore di uno nomeVariabile = espressione; ✔ Scopo: assegnare il nuovo valore espressione alla variabile nomeVariabile ✔ Nota: purtroppo Java (come C e C++) utilizza il segno = per indicare l’assegnazione, creando confusione con l’operatore di uguaglianza (che vedremo essere un doppio segno =, cioè ==); altri linguaggi usano simboli diversi per l’assegnazione (ad esempio, il linguaggio Pascal usa :=) 113 Marcello Dalpasso int counter = 0; counter = counter + 1; ✔ Questa operazione è talmente comune nella programmazione, che il linguaggio Java fornisce un operatore apposito per l’incremento counter++; e per il decremento counter--; 114 19 Fondamenti di Informatica 1 Settimana 1 Variabili non inizializzate ✔ È buona regola fornire sempre un valore di inizializzazione nella definizione di variabili Intervallo ✔ Cosa succede altrimenti? int lit; – la definizione di una variabile “crea” la variabile, cioè le riserva uno spazio nella memoria primaria (la quantità di spazio dipende dal tipo della variabile) – tale spazio di memoria non è “vuoto”, una condizione che non si può verificare in un circuito elettronico, ma contiene un valore “casuale” (in realtà contiene l’ultimo valore attribuito a quello spazio da un precedente programma… valore che a noi non è noto) 115 116 Variabili non inizializzate Variabili non inizializzate ✔ Se si usasse il valore di una variabile prima di averle ✔ Questo problema provoca insidiosi errori di assegnato un qualsiasi valore, il programma si troverebbe ad elaborare quel valore che “casualmente” si trova nello ERRORE spazio di memoria riservato alla variabile public class Coins3 // NON FUNZIONA! { public static void main(String[] args) { int lit; double euro = 2.35; double totalEuro = euro + lit / 1936.27; System.out.print("Valore totale in euro "); System.out.println(totalEuro); } } esecuzione in molti linguaggi di programmazione – il compilatore Java, invece, segnala come errore l’utilizzo di variabili a cui non sia mai stato assegnato un valore (mentre non è un errore la sola definizione...) Coins3.java:5: variable lit might not have been initialized – questi errori non sono sintattici, bensì logici, ma vengono comunque individuati dal compilatore, perché si tratta di errori semantici (cioè di comportamento del programma) individuabili in modo automatico 117 118 Assegnazioni con conversione ✔ In un’assegnazione, il tipo di dati dell’espressione e della Conversioni fra diversi tipi di dati variabile a cui la si assegna devono essere compatibili – se i tipi non sono compatibili, il compilatore segnala un errore (non sintattico ma semantico) ✔ I tipi non sono compatibili se provocano una possibile perdita di informazione durante la conversione ✔ L’assegnazione di un valore di tipo numerico intero ad una variabile di tipo numerico in virgola mobile non può provocare perdita di informazione, quindi è ammessa int intVar = 2; double doubleVar = intVar; 119 Marcello Dalpasso OK 120 20 Fondamenti di Informatica 1 Settimana 1 Tipi di dati numerici incompatibili double doubleVar = 2.3; int intVar = doubleVar; possible loss of precision found : double required: int ✔ In questo caso si avrebbe una perdita di informazione, perché la (eventuale) parte frazionaria di un valore in virgola mobile non può essere memorizzata in una variabile di tipo intero ✔ Per questo motivo il compilatore non accetta un enunciato di questo tipo, segnalando l’errore semantico ed interrompendo la compilazione Conversioni forzate (cast) ✔ Ci sono però casi in cui si vuole effettivamente ottenere la conversione di un numero in virgola mobile in un numero intero ✔ Lo si fa segnalando al compilatore l’intenzione esplicita di accettare l’eventuale perdita di informazione, mediante un cast (“forzatura”) double doubleVar = 2.3; int intVar = (int)doubleVar; OK ✔ Alla variabile intVar viene così assegnato il valore 2, la parte intera dell’espressione 121 122 Conversioni con arrotondamento Conversioni con arrotondamento ✔ La conversione forzata di un valore in virgola ✔ Questo semplice algoritmo per arrotondare i mobile in un valore intero avviene con troncamento, trascurando la parte frazionaria ✔ Spesso si vuole invece effettuare tale conversione con arrotondamento, convertendo all’intero più vicino ✔ Ad esempio, possiamo sommare 0.5 prima di fare la conversione double rate = 2.95; int intRate = (int)(rate + 0.5); System.out.println(intRate); 3 numeri in virgola mobile funziona però soltanto per numeri positivi, quindi non è molto valido… double rate = -2.95; int intRate = (int)(rate + 0.5); System.out.println(intRate); ✔ Un’ottima soluzione è messa a disposizione dal metodo round della classe Math della libreria standard, che funziona bene per tutti i numeri double rate = -2.95; int intRate = (int)Math.round(rate); System.out.println(intRate); 123 Il metodo Math.round -3 124 Il metodo Math.round Seguitela anche voi! ✔ Come si fa a capire che System.out.println è un double rate = -2.95; int intRate = (int)Math.round(rate); System.out.println(intRate); ✔ C’è una differenza sostanziale tra il metodo round e, ad esempio, il metodo println già visto – println agisce su un oggetto (ad esempio, System.out) – round non agisce su un oggetto (Math è una classe) ✔ Il metodo Math.round è un metodo statico 125 Marcello Dalpasso -2 metodo applicato ad un oggetto, mentre Math.round no? ✔ La sintassi è identica…Math sembra un oggetto! ✔ Tutte le classi, gli oggetti e i metodi della libreria standard seguono una rigida convenzione – i nomi delle classi (Math, System) iniziano con una lettera maiuscola – i nomi di oggetti (out) e metodi (println, round) iniziano con una lettera minuscola • oggetti e metodi si distinguono perché solo i metodi sono sempre seguiti dalle parentesi tonde 126 21 Fondamenti di Informatica 1 Settimana 1 Invocazione di metodo statico ✔ Sintassi: Costanti NomeClasse.nomeMetodo(parametri) ✔ Scopo: invocare il metodo statico nomeMetodo definito nella classe NomeClasse, fornendo gli eventuali parametri richiesti ✔ Nota: un metodo statico non viene invocato con un oggetto, ma con un nome di classe 128 127 L’uso delle costanti L’uso delle costanti ✔ Così come si usano nomi simbolici descrittivi per ✔ Un programma per il cambio di valuta le variabili, è opportuno assegnare nomi simbolici anche alle costanti utilizzate nei programmi public class Convert1 { public static void main(String[] args) { double dollars = 2.35; int lit = (int)(dollars * 2125); } } ✔ Chi legge il programma potrebbe legittimamente chiedersi quale sia il significato del “numero magico” 2125 usato nel programma per convertire i dollari in lire italiane... public class Convert2 { public static void main(String[] args) { final int LIT_PER_DOLLAR = 2125; double dollars = 2.35; int lit = (int)(dollars * LIT_PER_DOLLAR); } } ✔ Un primo vantaggio molto importante aumenta la leggibilità 129 L’uso delle costanti Definizione di costante ✔ Sintassi: ✔ Un altro vantaggio: se il valore della costante deve cambiare (nel nostro caso, perché varia il tasso di cambio dollaro/lira), la modifica va fatta in un solo punto del codice! public class Convert3 { public static void main(String[] args) { final int LIT_PER_DOLLAR = 2135; double dollars1 = 2.35; int lit1 = (int)(dollars1 * LIT_PER_DOLLAR); double dollars2 = 3.45; int lit2 = (int)(dollars2 * LIT_PER_DOLLAR); } } 131 Marcello Dalpasso 130 final nomeTipo NOME_COSTANTE = espressione; ✔ Scopo: definire la costante NOME_COSTANTE di tipo nomeTipo, assegnandole il valore espressione, che non potrà più essere modificato ✔ Nota: il compilatore segnala come errore semantico il tentativo di assegnare un nuovo valore ad una costante, dopo la sua inizializzazione ✔ Di solito in Java si usa la seguente convenzione – i nomi di costanti sono formati da lettere maiuscole • i nomi composti si ottengono attaccando le parole successive alla prima con un carattere di sottolineatura 132 22 Fondamenti di Informatica 1 Settimana 1 Intervallo Operazioni aritmetiche 133 134 Operazioni aritmetiche Operazioni aritmetiche ✔ L’operatore di moltiplicazione va sempre indicato ✔ Quando entrambi gli operandi sono numeri interi, esplicitamente, non può essere sottinteso ✔ Le operazioni di moltiplicazione e divisione hanno la precedenza sulle operazioni di addizione e sottrazione, cioè vengono eseguite prima ✔ È possibile usare coppie di parentesi tonde per indicare in quale ordine valutare sotto-espressioni a + b / 2 ≠ (a + b) / 2 ✔ In Java non esiste il simbolo di frazione, le frazioni vanno espresse “in linea”, usando l’operatore di divisione a + b (a + 2 b) / 2 la divisione ha una caratteristica particolare, che può essere utile ma che va usata con attenzione – calcola il quoziente intero, scartando il resto! 7.0 / 4.0 7 / 4 1 1,75 7 / 4.0 7.0 / 4 ✔ Il resto della divisione tra numeri interi può essere calcolato usando l’operatore %, che non esiste in algebra ed il cui simbolo è stato scelto perché è simile all’operatore di divisione 7 % 4 3 135 136 Divisione fra interi Funzioni più complesse public class Coins7 { public static void main(String[] args) { double euro = 2.35; final int CENT_PER_EURO = 100; int centEuro = (int)(euro * CENT_PER_EURO); int intEuro = centEuro / CENT_PER_EURO; centEuro = centEuro % CENT_PER_EURO; System.out.print(intEuro); System.out.print(" euro e "); System.out.print(centEuro); System.out.println(" centesimi"); } } ✔ Non esistono operatori per calcolare funzioni più 2 euro e 35 centesimi 137 Marcello Dalpasso complesse, come l’elevamento a potenza ✔ La classe Math della libreria standard mette a disposizione metodi statici per il calcolo di tutte le funzioni algebriche e trigonometriche, richiedendo parametri double e restituendo risultati double – Math.pow(x, y) restituisce xy (il nome pow deriva da power, potenza) – Math.sqrt(x) restituisce la radice quadrata di x (il nome sqrt deriva da square root, radice quadrata) – Math.log(x) restituisce il logaritmo naturale di x – Math.sin(x) restituisce il seno di x espresso in radianti 138 23 Fondamenti di Informatica 1 Settimana 1 Combinare assegnazioni e aritmetica Numeri binari ✔ Abbiamo già visto come in Java sia possibile ✔ I numeri che siamo abituati ad utilizzare sono espressi con combinare in un unico enunciato un’assegnazione ed un’espressione aritmetica che coinvolge la variabile a cui si assegnerà il risultato totalEuro = totalEuro + dollars * 0.93; ✔ Questa operazione è talmente comune nella programmazione, che il linguaggio Java fornisce una scorciatoia totalEuro += dollars * 0.93; che esiste per tutti gli operatori aritmetici x = x * 2; x *= 2; la notazione posizionale in base decimale – base decimale perché usiamo dieci cifre diverse (da 0 a 9) – notazione posizionale perché cifre uguali in posizioni diverse hanno significato diverso (si dice anche che hanno peso diverso, cioè pesano diversamente nella determinazione del valore del numero espresso 434 = 4·102 + 3·101 + 4·100 – il peso di una cifra è uguale alla base del sistema di numerazione (10, in questo caso), elevata alla potenza uguale alla posizione della cifra nel numero, posizione che si incrementa da destra a sinistra a partire da 0 – la parte frazionaria, a destra del simbolo separatore, si valuta con potenze negative 4,34 = 4·100 + 3·10-1 + 4·10-2 139 140 Numeri binari Numeri binari ✔ I computer usano invece numeri binari, cioè ✔ La conversione di un numero da base decimale a numeri rappresentati con notazione posizionale in base binaria – la base binaria usa solo due cifre diverse, 0 e 1 – la conversione da base binaria a decimale è semplice (1101)2 = (1·23 + 1·22 + 0·21 + 1·20)10 = (13)10 (1,101)2 = (1·20 + 1·2-1 + 0·2-2 + 1·2-3)10 = (1,625)10 ✔ I numeri binari sono più facili da manipolare per i computer, perché è meno complicato costruire circuiti logici che distinguono tra “acceso” e “spento”, piuttosto che fra dieci livelli diversi di voltaggio base binaria è, invece, più complessa ✔ Innanzitutto, la parte intera del numero va elaborata indipendentemente dalla eventuale parte frazionaria – la parte intera del numero decimale viene convertita nella parte intera del numero binario – la parte frazionaria del numero decimale viene convertita nella parte frazionaria del numero binario – la posizione del punto separatore rimane invariata 141 142 Numeri binari Numeri binari ✔ Per convertire la sola parte intera, si divide il numero per ✔ Per convertire la sola parte frazionaria, si moltiplica il 2, eliminando l’eventuale resto e continuando a dividere per 2 il quoziente ottenuto fino a quando non si ottiene 100 / 2 = 50 resto 0 quoziente uguale a 0 ✔ Il numero binario si ottiene 50 / 2 = 25 resto 0 25 / 2 = 12 resto 1 scrivendo la serie dei resti 12 / 2 = 6 resto 0 delle divisioni, iniziando 6 / 2 = 3 resto 0 3 / 2 = 1 resto 1 dall’ultimo resto ottenuto 1 / 2 = 0 resto 1 ✔ Attenzione: non fermarsi quando si ottiene quoziente 1, ma proseguire fino a 0 (100)10 = (1100100)2 numero per 2, sottraendo 1 dal prodotto se è maggiore di 1 e continuando a moltiplicare per 2 il risultato così ottenuto fino a quando non si ottiene un risultato uguale a 0 oppure un risultato già ottenuto in precedenza 0,35 · 2 = 0,7 ✔ Il numero binario si ottiene scrivendo la 0,7 · 2 = 1,4 0,4 · 2 = 0,8 serie delle parti intere dei prodotti 0,8 · 2 = 1,6 ottenuti, iniziando dal primo 0,6 · 2 = 1,2 ✔ Se si ottiene un risultato già ottenuto in 0,2 · 2 = 0,4 precedenza, il numero sarà periodico, anche se non lo era in base decimale 143 144 Marcello Dalpasso (0,35)10 = (0,010110)2 24 Fondamenti di Informatica 1 Settimana 1 Numeri binari Le reti di computer ✔ Per programmare in Java non c’è bisogno di conoscere i ✔ Alcuni computer sono unità autosufficienti (stand- numeri binari, ma tale conoscenza fa parte della cultura di base dell’informatica ✔ Perché il massimo numero rappresentabile con una variabile di tipo int è 2147483647? – una variabile di tipo int occupa uno spazio in memoria pari a 32 bit, cioè il suo valore viene rappresentato con 32 cifre binarie – il primo bit rappresenta il segno (0 ⇒ positivo, 1 ⇒ negativo) alone), mentre altri sono interconnessi mediante reti di comunicazione (reti telematiche) ✔ I computer di casa sono di solito stand-alone o vengono interconnessi solo saltuariamente con un modem (modulatore-demodulatore) tramite la rete telefonica – il massimo numero è 01111111111111111111111111111111 che equivale a 231-1 = 2147483647 145 146 Le reti di computer Le reti di computer ✔ I computer di laboratori e uffici sono di solito ✔ Attraverso le connessioni di rete, un computer può connessi in modo permanente ad una rete locale (LAN, Local Area Network) ✔ Alcune reti locali sono poi connesse a reti telematiche a grande distanza (WAN, Wide Area Network), come la rete Internet scambiare informazioni con altri computer, nella stanza adiacente o a migliaia di chilometri ✔ Uno degli esempi più eclatanti di trasmissione di informazioni a distanza sulla rete mondiale Internet è il cosiddetto World-Wide Web (WWW), o semplicemente web ✔ Un altro servizio informatico consentito dalle reti telematiche è lo scambio di messaggi di posta elettronica (e-mail, electronic mail) 147 148 Minicomputer e Workstation Minicomputer e Workstation ✔ Nei primi vent’anni di utilizzo, i computer furono ✔ Il primo minicomputer venne venduto nel 1965 dalla utilizzati soltanto in grandi aziende degli USA – erano enormemente costosi ma fornivano un servizio insostituibile ✔ A metà degli anni ‘60 furono disponibili i circuiti integrati, che provocarono una rivoluzione in campo elettronico, consentendo la produzione di computer a costi accettabili per un maggior numero di utenti, ricercatori universitari e tecnici di aziende (prevalentemente di ingegneria) 149 Marcello Dalpasso Digital Equipment Corporation (DEC) con il nome PDP8, iniziando una fortunata serie di computer ✔ Il PDP-8 era contenuto in un unico armadietto ✔ Nel 1978 la DEC produsse il primo minicomputer a 32 bit, il VAX, capostipite di una serie gloriosa di computer ✔ Questi computer venivano venduti con pochissimo software e quasi sempre gli utenti dovevano essere buoni programmatori ✔ Un altro minicomputer molto famoso è l'IBM AS/400 150 25 Fondamenti di Informatica 1 Settimana 1 Minicomputer e Workstation Minicomputer e Workstation ✔ I minicomputer, come i più grandi mainframe, venivano ✔ Le workstation usano il sistema operativo Unix utilizzati da molti utenti contemporaneamente, secondo un sistema di time-sharing (ripartizione di tempo) ✔ Nei primi anni ‘80, con la comparsa dei terminali grafici, con esigenze di calcolo più stringenti, tali sistemi creavano sempre più disagi agli utenti ✔ La tecnologia progredì fino alla produzione di computer che potevano stare sulla scrivania, con costi abbastanza bassi da consentirne l’utilizzo personale, per un solo utente ✔ Nacque la prima workstation (stazione di lavoro), prodotta da Sun Microsystems ✔ Ogni costruttore ha sviluppato una propria versione di Unix, ma le differenze sono minime ✔ Questo ha favorito lo sviluppo di software in modo più economico, perché lo stesso software può essere venduto per più piattaforme ✔ Tutte le workstation adottano lo standard grafico X Window System, sviluppato dal MIT 151 152 Scegliere bene i nomi delle variabili Scegliere bene i nomi delle variabili public class Coins4 { public static void main(String[] args) { int a = 15000; double b = 2.35; double c = b + a / 1936.27; } } ✔ È molto importante scegliere nomi delle variabili che descrivano adeguatamente il loro compito – è un ottimo metodo per scrivere codice che si documenta da solo! – non è molto elegante dover inserire commenti soltanto per descrivere la funzione svolta da una variabile – è meglio usare i commenti soltanto per descrivere i passaggi meno intuitivi dell’algoritmo – troppi commenti rendono il programma poco leggibile! – se si modifica il programma, bisogna poi modificare anche i commenti… altrimenti è meglio eliminarli! public class Coins5 { public static void main(String[] args) { int lit = 15000; double euro = 2.35; double totalEuro = euro + lit / 1936.27; } } 153 154 Prendere confidenza con il computer Accedere al computer ✔ Per molti di voi il laboratorio didattico di questo ✔ In un computer di uso personale spesso non è corso costituisce il primo approccio al computer ✔ I primi passi da compiere per acquisire confidenza con il nuovo strumento di lavoro sono: – – – – – – accedere al computer (fare log-in) capire i concetti di file e di cartella (directory) individuare il compilatore e l’interprete Java scrivere un programma Java compilare un programma Java eseguire programmi invece sempre controllato ed è necessario eseguire la procedura di accesso (login) ✔ La procedura di accesso dipende dal sistema operativo, ma in generale richiede l’inserimento di un nome utente (account) e di una password 155 Marcello Dalpasso necessaria nessuna procedura di accesso ✔ Nei computer del laboratorio didattico l’accesso è 156 26 Fondamenti di Informatica 1 Settimana 1 File Directory ✔ Come tutte le altre informazioni in un computer, i ✔ I file sono conservati all’interno di cartelle o programmi sono memorizzati in file (“archivi”) nella memoria secondaria ✔ Un file ha un nome e un contenuto directory ✔ Una cartella può contenere – i nomi di file devono rispondere a regole che dipendono dal sistema operativo – di solito i nomi di file terminano con una parte, chiamata estensione, che è separata da un punto ✔ Un programma Java deve essere memorizzato in un file con estensione .java – zero o più file e – zero o più altre cartelle ✔ È quindi possibile creare cartelle all’interno di altre cartelle, dando origine ad una struttura gerarchica – ad esempio, Test.java 157 158 Individuare il compilatore Java Sequenze di “escape” ✔ Il modo di utilizzo del compilatore Java dipende ✔ Proviamo a stampare una stringa che contiene Hello, "World"! delle virgolette dal sistema operativo – – – – si seleziona con il mouse un’icona sullo schermo si seleziona una voce in un menu di comandi si compone il nome di un comando sulla tastiera si utilizza un ambiente integrato per lo sviluppo software (IDE, Integrated Development Environment) ✔ Nel nostro corso useremo i comandi da tastiera del JDK (Java Development Kit) di Sun Microsystems // NON FUNZIONA! System.out.println("Hello, "World"!"); ✔ Il compilatore identifica le seconde virgolette come la fine della prima stringa "Hello, ", ma poi non capisce il significato della parola World ✔ Basta inserire una barra rovesciata \ (backslash) prima delle virgolette all’interno della stringa System.out.println("Hello, \"World\"!"); 159 Sequenze di “escape” Sequenze di “escape” ✔ Un’altra sequenza di escape che si usa è \n, // FUNZIONA! System.out.println("Hello, \"World\"!"); ✔ Il carattere backslash all’interno di una stringa non rappresenta se stesso, ma si usa per codificare altri caratteri che sarebbe difficile inserire in una stringa, per vari motivi (sequenza di escape) ✔ Allora, come si fa ad inserire veramente un carattere backslash in una stringa? che rappresenta il carattere di “nuova riga” o “andare a capo” System.out.println("*\n**\n***\n"); System.out.println("*"); System.out.println("**"); System.out.println("***"); * ** *** ✔ Le sequenze di escape si usano anche per – si usa la sequenza di escape \\ inserire caratteri di lingue straniere o simboli che non si trovano sulla tastiera System.out.println("File C:\\autoexec.bat"); File C:\autoexec.bat 161 Marcello Dalpasso 160 162 27 Fondamenti di Informatica 1 Settimana 1 Sequenze di “escape” Errori di battitura o di ortografia ✔ Ad esempio, per scrivere parole italiane con ✔ Gli errori di battitura possono essere molto lettere accentate senza avere a disposizione una tastiera italiana difficili da identificare System.out.println("Perch\u00E9?"); ✔ Queste sequenze di escape utilizzano la codifica standard Unicode Perché? http://www.unicode.org per rappresentare i caratteri di tutti gli alfabeti del mondo con 4 caratteri esadecimali (codifica a 16 bit, 65536 simboli diversi) 163 maiuscola public class Hello { public static void Main(String[] args) { System.out.println("Hello, World!"); } } ✔ In questo caso il compilatore non segnala alcun errore di sintassi, perché Main è un nome valido per un metodo 164 Errori di battitura o di ortografia ✔ Viene invece segnalato un errore in esecuzione C:\>java Hello Exception in thread "main" java.lang.NoSuchMethodError: main ✔ L’interprete Java che esegue la classe compilata Hello inizia cercando di eseguire il metodo main – segnala un errore perché il metodo main non esiste – il metodo Main non può essere utilizzato al posto del metodo main – l’interprete non fa ipotesi, non cerca nomi simili 165 Marcello Dalpasso 166 28