Numeri, espressioni, calcoli, caratteri, input Interi e decimali Definizione di costanti Espressioni Funzioni matematiche Classi involucro Il tipo char Acquisizione di input Laboratorio di Programmazione Luca Tesei 1 Una classe Borsellino /** Realizza un borsellino per le monete. Registra il numero di monete e calcola il valore totale */ public class Purse { /** Costruisce un borsellino vuoto */ public Purse() { } /** Aggiunge monete di tipo "nickel" al borsellino @param count il numero di nickel da aggiungere */ public void addNickels(int count) { } Laboratorio di Programmazione Luca Tesei 2 Classe Borsellino cont’d /** Aggiunge monete di tipo "dime" al borsellino @param count il numero di dime da aggiungere */ public void addDimes(int count) { } /** Aggiunge monete di tipo "quarter" al borsellino @param count il numero di quarter da aggiungere */ public void addQuarters(int count) { } /** Ispeziona il valore totale delle monete nel borsellino @returns la somma dei valori di tutte le monete attualmente presenti */ public double getTotal() { } } Laboratorio di Programmazione Luca Tesei 3 Esempio d’uso Purse myPurse = new Purse(); myPurse.addNickels(3); myPurse.addDimes(1); myPurse.addQuarters(2); double totalValue = myPurse.getTotal(); ● totalValue conterrà 0,75 cioè il valore in dollari delle monete contenute nel borsellino Laboratorio di Programmazione Luca Tesei 4 Numeri interi e numeri decimali ● ● ● ● ● Per rappresentare quantità che si contano naturalmente con multipli di 1 (positivi o negativi) usiamo variabili di tipo intero (int) Nell’esempio del borsellino int è il tipo dei parametri dei metodi addXXX Questo perché è naturale considerare le monete come quantità indivisibili e quindi quantificate con un numero intero Il metodo getTotal() invece restituisce un double Questo perché è naturale per un valore che rappresenta una quantità di dollari avere dei decimali Laboratorio di Programmazione Luca Tesei 5 Primi passi per l’implementazione di Purse Ogni oggetto di tipo Purse può essere descritto dalla quantità di nickels, dimes e quarters che contiente ● Inseriamo quindi tre variabili istanza di tipo int per rappresentare queste quantità ... private int nickels; private int dimes; private int quarters; ● Laboratorio di Programmazione Luca Tesei 6 Primi passi per l’implementazione di Purse public double getTotal() { return nickels * 0.05 + dimes * 0.1 + quarters * 0.25; } ● L’ * indica la moltiplicazione (perché • o × non si trovano generalmente nelle tastiere) ● L’espressione dopo return segue le regole di associatività e precedenza tipiche dell’aritmetica (la grammatica di Java per le espressioni segue le regole che abbiamo visto a Programmazione) ● Il valore ottenuto è un numero in virgola mobile poiché moltiplicando un intero per un numero decimale si ottiene un numero decimale, in generale Laboratorio di Programmazione Luca Tesei 7 Costanti numeriche ● ● ● ● Nelle costanti numeriche che si possono scrivere nel codice la virgola deve essere indicata come punto decimale Si può usare anche la notazione esponenziale Ad esempio 5,0 × 10-3 si scrive come 5.0E-3 Cioè si usa il punto decimale e si scrive E seguito dall’esponente di × 10 Laboratorio di Programmazione Luca Tesei 8 Numeri interi ● ● ● ● Un numero intero è un numero senza decimali che può essere sia positivo che negativo Il tipo base Java corrispondente ai numeri interi è int Una variabile int può contenere i numeri interi da –2147483648 a +2147483647 31 bit + 1 bit per il segno = 32 bit di memoria allocati per ogni variabile int Laboratorio di Programmazione Luca Tesei 9 Numeri interi Esistono altri tipi base di interi che possono rappresentare meno o più numeri di int • short: 16 bit - Range: da -215 a 215-1 • byte: 8 bit - Range da –27 a 27-1 • long: 64 bit - Range da –263 a 263 –1 ● Laboratorio di Programmazione Luca Tesei 10 Numeri in virgola mobile ● ● ● ● ● Possono contenere cifre decimali Contengono un certo numero di cifre significative e la posizione della virgola Es. 250 25 0.25 0.025 hanno tutti le stesse cifre significative (25), ciò che cambia è la posizione della virgola (da qui “virgola mobile”) Naturalmente la rappresentazione in realtà è in base 2 In java la virgola è rappresentata dal punto decimale come nella notazione anglosassone (come tutte le calcolatrici del resto) Laboratorio di Programmazione Luca Tesei 11 Numeri in virgola mobile • double può rappresentare circa 15 cifre significative: è il tipo con maggiore precisione (“doppia precisione”) • float può rappresentare circa 7 cifre significative: precisione spesso insufficiente, ma calcoli più veloci ● Per precisione si intende la grandezza degli errori dovuti all’ arrotondamento che inevitabilmente si commettono con l’uso di questi numeri Laboratorio di Programmazione Luca Tesei 12 Precisione public class ProvaPrecisione { public static void main(String [] argv) { double originalPrice = 3E14; double discountedPrice = originalPrice – 0.05; double discount = originalPrice – discountedPrice; // dovrebbe essere 0.05 System.out.println(discount); // stampa 0.0625 – Errore dovuto //all’arrotondamento da rappresentazione } } Laboratorio di Programmazione Luca Tesei 13 Numeri rappresentabili ● ● Il tipo float può rappresentare il range dei numeri, positivi o negativi, con valore assoluto che va da 2-149 a (2-2-23)•2127 Il tipo double può rappresentare il range dei numeri, positivi o negativi, con valore assoluto che va da 2-1074 a (2-2-52)•21023 Laboratorio di Programmazione Luca Tesei 14 Numeri a lunghezza e precisione arbitraria ● ● Il pacchetto java.math contiene una classe BigInteger i cui oggetti possono rappresentare numeri interi di lunghezza arbitraria Lo stesso pacchetto contiene una classe BigDecimal i cui oggetti possono rappresentare numeri a virgola mobile con precisione arbitraria Laboratorio di Programmazione Luca Tesei 15 Numeri a lunghezza e precisione arbitraria • • Per questi numeri non si possono usare i normali operatori + * - / = I corrispondenti metodi add, multiply, subtract, divide ed equals sono forniti dalle relative classi: BigInteger a = new BigInteger(“123456789”); BigInteger b = new BigInteger(“987654321”); BigInteger c = a.multiply(b); System.out.println(c); // stampa 121932631112635269 • Naturalmente i calcoli con questi numeri sono più lenti di quelli fatti con i numeri dei tipi base Laboratorio di Programmazione Luca Tesei 16 Costruttore di Purse Public Purse() { nickels = 0; dimes = 0; quarters = 0; } ● Il costruttore di default farebbe esattamente la stessa cosa, ma lo specifichiamo per chiarezza Laboratorio di Programmazione Luca Tesei 17 Implementazione di addNickels public void addNickels(int count) { nickels = nickels + count; } ● È la tipica istruzione di incremento di un valore ● L’assegnamento prima valuta la parte a sinistra dell’= e quindi considera il valore corrente della variabile istanza intera nickels al quale aggiunge il valore di count ● Il valore così ottenuto sarà assegnato alla variabile istanza nickels, cioè sarà il suo valore dopo l’esecuzione dell’istruzione (si può pensare che sia il valore che nickels ha dopo il ; finale) Laboratorio di Programmazione Luca Tesei 18 Altre istruzioni di incremento In Java, come in C, esiste una forma abbreviata per l’incremento nickels = nickels + count; può essere scritta equivalentemente come nickels += count; ● La stessa abbreviazione si può usare anche per gli altri operatori (*, /, -): P *= q; // equivalente a p = p * q; ● Laboratorio di Programmazione Luca Tesei 19 Incremento di 1 Un’istruzione che ricorre molto frequentemente nei programmi è l’incremento o il decremento di una variabile intera di una unità ● In Java, come in C, esistono abbreviazioni speciali per questi casi: i++; // equivalente a i = i + 1; e a i +=1; i--; // equivalente a i = i – 1; e a i -=1; ● Laboratorio di Programmazione Luca Tesei 20 Costanti public double getTotal() { return nickels * 0.05 + dimes * 0.1 + quarters * 0.25; } ● ● La maggior parte del codice si documenta da sé, ma in questo caso i numeri 0.05, 0.1 e 0.25 compaiono senza nessuna spiegazione È buona regola evitare di inserire nel codice questi “numeri magici” Laboratorio di Programmazione Luca Tesei 21 Costanti ● ● ● ● Le costanti possono essere pensate come dei nomi a cui è associato un valore Tale associazione rimane valida per tutta la vita della costante e non cambia mai In genere, per convenzione, le costanti sono scritte tutte maiuscole e si usa l’underscore come separatore nel caso che il nome sia composto da più parole In Java una costante si dichiara come una variabile (di frame) usando la parola chiave final e inizializzando il valore nella dichiarazione Laboratorio di Programmazione Luca Tesei 22 Costanti public double getTotal() { final double NICKEL_VALUE = 0.05; final double DIME_VALUE = 0.1; final double QUARTER_VALUE = 0.25; return nickels * NICKEL_VALUE + dimes * DIME_VALUE + quarters * QUARTER_VALUE; } Laboratorio di Programmazione Luca Tesei 23 final ● ● In generale in Java la parola chiave final indica un qualcosa che non può essere più modificato (vedremo che esistono, oltre alle variabili, anche classi final, cioè che non possono essere estese) Il compilatore dà errore se si cerca di modificare una variabile final. Laboratorio di Programmazione Luca Tesei 24 Costanti ● ● ● ● La dichiarazione di una variabile con lo specificatore final ha lo stesso effetto di una qualsiasi altra definizione di variabile Viene cioè allocata la nuova variabile sul frame corrente dell’attivazione corrente Al momento della chiusura del blocco del frame in cui è stata definita essa scompare E’ il controllo del compilatore che la rende non modificabile Laboratorio di Programmazione Luca Tesei 25 Costanti ● ● ● In genere però le costanti sono utili in diversi metodi della stessa classe Per evitare di dover ridefinire le variabili final in ogni metodo che le usa (ed evitare anche errori se il valore viene modificato solo in alcuni metodi, ad esempio in un’altra versione del programma) possiamo pensare di associare le costanti direttamente alla classe Per definire costanti che si riferiscono ad una classe si può usare lo specificatore static Laboratorio di Programmazione Luca Tesei 26 static ● ● ● ● Lo specificatore static deriva dal C e il suo nome può risultare fuorviante In Java, se nella definizione di una classe viene inserita una variabile istanza con lo specificatore static, quella variabile istanza va considerata come elemento della classe In genere le variabili istanza formano lo stato di ogni oggetto della classe che viene creato Le variabili istanza static invece non vanno a far parte dello stato degli oggetti della classe, ma fanno parte della definizione della classe stessa Laboratorio di Programmazione Luca Tesei 27 static ● ● ● ● Esiste una sola copia di una variabile istanza static di una classe e si riferisce all’intera classe Per riferirla e/o modificarla si usa la notazione NomeClasse.nomeVariabileIstanzaStatic Alle variabili istanza static possono essere associati tutti i possibili specificatori di accesso: public, private e protected Inoltre possono essere final, cioè costanti di classe Laboratorio di Programmazione Luca Tesei 28 Esempio ● ● ● ● Vedremo più avanti degli esempi in cui sono utili variabili static di classe Per adesso useremo questa possibilità solo per specificare costanti Nel nostro caso le costanti che indicano il valore di ogni moneta sembrano essere utili solo nel contesto della classe Purse e quindi le dichiariamo private Molte classi delle API hanno invece delle costanti pubbliche che si possono usare Laboratorio di Programmazione Luca Tesei 29 Esempio public class Purse { ... private static final double NICKEL_VALUE = 0.05; private static final double DIME_VALUE = 0.1; private static final double QUARTER_VALUE = 0.25; ... } Laboratorio di Programmazione Luca Tesei 30 Esempio ● All’interno dei metodi della classe si possono riferire le variabili static (sia final che non) semplicemente con il loro nome (nel caso di conflitto va invece specificato il nome completo (cioè NomeClasse.nomeVariabile), ad esempio Purse.NICKEL_VALUE public double getTotal() { return nickels * NICKEL_VALUE + dimes * DIME_VALUE + quarters * QUARTER_VALUE; } Laboratorio di Programmazione Luca Tesei 31 Operazioni fra interi e decimali ● ● ● ● In Java gli operatori + - * / si possono combinare come si vuole insieme a costanti numeriche, variabili di frame, variabili istanza e chiamate di metodi per ottenere espressioni aritmetiche Gli operandi possono essere sia numeri interi (byte, short, int, long) che numeri in virgola mobile (float, double) Il risultato è un intero solo se tutti gli operandi sono interi Basta che un solo operando si in virgola mobile perché il valore di tutta l’espressione sia in virgola mobile Laboratorio di Programmazione Luca Tesei 32 Espressioni aritmetiche La grammatica per le espressioni aritmetiche che si possono scrivere in Java è la seguente: EE+T|E–T|T TT*F|T/F|F F -<Op> | <Op> <Op> (E) | <Num> | <Ide> | <DotExpr> ● La grammatica implementa le regole tipiche di associatività e precedenza degli operatori ● F è un ulteriore livello di precedenza per l’operatore unario – (che lega più di tutti) usato per cambiare il segno a un operando ● Laboratorio di Programmazione Luca Tesei 33 Espressioni aritmetiche ● ● ● <Num> è un simbolo non terminale che genera tutte le possibili costanti numeriche (intere e decimali, con o senza notazione esponenziale) <Ide> è un simbolo non terminale che genera tutti i possibili identificatori Java <DotExpr> è un simbolo non terminale che genera tutte le possibili espressioni formate da nomi e/o chiamate di metodi separate da punti (ad esempio myPurse.getTotal() rappresenta un double, this.nickels rappresenta un int all’interno di un metodo della classe Purse ) Laboratorio di Programmazione Luca Tesei 34 Espressioni aritmetiche ● Esempi: –7 * 4 valore 28 (int) – 11 + 2.0 / 4 valore 11.5 (double) – (11 + 2.0) / 4 valore 3.25 (double) – this.nickels * this.getTotal() – 3 * 7 supponendo che il valore della variabile istanza nickel dell’oggetto this sia 3 (int) e che il totale this.getTotal() sia 12.5 (double) si ottiene un valore double a causa del valore double dell’operando this.getTotal(). Il valore è 16.5 Laboratorio di Programmazione Luca Tesei 35 Divisione ● ● ● ● ● ● Bisogna prestare un’attenzione particolare al simbolo / In Java esso rappresenta sia la divisione usuale che la divisione intera Viene applicata la divisione intera se entrambi gli operandi sono interi La divisione intera restituisce solo la parte intera del risultato! 7 / 4 valore 1! Non 1.75! 7 / 4.0 valore 1.75 (4.0 non intero) Laboratorio di Programmazione Luca Tesei 36 Resto della divisione intera ● ● ● Il simbolo % è un operatore binario che si può applicare solo fra due interi Calcola il resto della divisione intera fra il primo e il secondo 7 % 4 valore 3 Laboratorio di Programmazione Luca Tesei 37 Errore comune L’overloading del simbolo / porta spesso ad errori logici difficili da individuare ● Ad esempio: ... int p1 = 21; // punteggio prima prova int p2 = 24; // punteggio seconda prova int p3 = 22; // punteggio terza prova double media = (p1 + p2 + p3) / 3; System.out.println(media); /* Stampa 22.0! Non 22.3333333!! */ ● Laboratorio di Programmazione Luca Tesei 38 Errore comune Per ottenere il risultato che vogliamo bisogna fare in modo che almeno uno degli operandi sia un double // Se un intero viene assegnato a una variabile // di tipo double viene convertito a double double totale = p1 + p2 + p3; // totale è un valore double double media = totale / 3; ● Oppure double media = (p1 + p2 + p3) / 3.0; Laboratorio di Programmazione Luca Tesei 39 Metodi static ● ● ● ● La classe java.lang.Math (consultare le API) è una collezione di costanti e metodi static Abbiamo già visto che una variabile istanza dichiarata come static si riferisce alla classe e ne esiste un’unica copia (non viene inserita nello stato degli oggetti della classe che vengono creati) Anche un metodo può essere dichiarato come static e, analogamente, esso si riferisce alla classe È analogo a una funzione del C Laboratorio di Programmazione Luca Tesei 40 Metodi static ● ● ● ● Un metodo static non può essere invocato su un oggetto della classe L’unico modo per mandare in esecuzione il metodo static è quello di scrivere NomeClasse.nomeMetodo(parametri); All’interno di un metodo statico non è disponibile il parametro implicito this (poiché non c’è nessun oggetto su cui il metodo è stato invocato) Per il resto il meccanismo di esecuzione è analogo a quello dei metodi non statici (in particolare la creazione di una nuova attivazione e il meccanismo di passaggio e gestione dei parametri espliciti) Laboratorio di Programmazione Luca Tesei 41 Funzioni e costanti matematiche ● ● ● ● ● ● Definite nella classe java.lang.Math come costanti e metodi static Pi greco: Math.PI Base dei logaritmi naturali: Math.E Radice quadrata: double radiceDi2 = Math.sqrt(2); Coseno: double cosenoDiPiGrecoMezzi = Math.cos(Math.PI / 2); Consultare le API per vedere tutte le altre funzioni disponibili Laboratorio di Programmazione Luca Tesei 42 Conversioni di tipi Il compilatore esegue alcune conversioni di tipo implicitamente: ● Quando un valore intero viene assegnato ad una variabile double o float, il valore viene convertito in double o float automaticamente ... double pippo = 4; // 4 è una costante intera System.out.println(pippo); // Stampa 4.0 ● 4.0 è la rappresentazione di una costante a virgola mobile (c’è il punto decimale) ● Laboratorio di Programmazione Luca Tesei 43 Conversioni esplicite La conversione precedente viene eseguita automaticamente perché non comporta nessuna perdita di informazione (i numeri interi hanno i loro corrispondenti nei numeri a virgola mobile) ● Quando un assegnamento, invece, può provocare una perdita di informazione viene segnalato dal compilatore come errore ● Una errore di questo genere si ha, ad esempio, quando si tenta di assegnare un valore a virgola mobile ad una variabile intera int prova = 3.5; // Errore di // compilazione ● Laboratorio di Programmazione Luca Tesei 44 Conversioni esplicite Per forzare il compilatore ad accettare l’assegnamento (se si vuole accettare la perdita di informazione che ne deriva) si deve fare una conversione di tipo esplicita ● Questa operazione si chiama casting int prova = (int)3.5; // accettato ● L’effetto di questo casting è di buttare via la parte decimale del numero a virgola mobile e di assegnare a prova solo la parte intera 3 ● Laboratorio di Programmazione Luca Tesei 45 Casting ● ● ● ● Il casting si può fare fra diversi tipi base Ogni volta che si fa si accetta la possibilità di perdere informazione Ad esempio, facendo un casting da double a float si potranno perdere alcune cifre significative Così come facendo un casting da int a short Laboratorio di Programmazione Luca Tesei 46 Casting L’operatore di casting (il tipo tra parentesi) lega più degli operatori aritmetici double total = 3.456; int prova = (int) total * 100; ● Esegue il casting su total e il valore di prova sarà 300 int prova = (int)(total * 100); ● Esegue il casting sul valore della moltiplicazione e il valore di prova sarà 345 ● Laboratorio di Programmazione Luca Tesei 47 Arrotondamenti Il casting da valori a virgola mobile a interi produce come risultato la parte intera del valore, anche se il valore è molto prossimo al valore intero successivo int prova = (int) 4.99; // prova vale 4 ● Per eseguire gli arrotondamenti secondo la regola usuale (se il primo decimale è da 0 a 4 si prende la parte intera, altrimenti la parte intera + 1) si può usare il metodo static Math.round (consultare le API: il valore restituito da Math.round è un long! Quindi bisogna fare un ulteriore casting se si vuole assegnare il risultato ad un int) ● Laboratorio di Programmazione Luca Tesei 48 Classi involucro ● ● ● ● Ognuno dei tipi base di Java ha una classe corrispondente nel pacchetto java.lang (consultare le API) Queste classi vengono dette classi involucro Gli oggetti di queste classi possono un valore del tipo base corrispondente La vera utilità sta nelle costanti e nei metodi statici che forniscono Laboratorio di Programmazione Luca Tesei 49 Classe Integer ● ● ● ● ● Prendiamo ad esempio la classe java.lang.Integer Un oggetto di questa classe può contenere un valore intero Tale valore non si trova in una variabile di frame come i soliti int Si trova nello heap all’interno dell’oggetto corrispondente Costanti static utili della classe: – – Integer.MIN_VALUE (minimo numero int rappresentabile Integer.MAX_VALUE (massimo int rappresentabile) Laboratorio di Programmazione Luca Tesei 50 Classe Integer Metodi statici pubblici utili della classe Integer public static int parseInt(String s) ● Cerca di interpretare il contenuto della stringa s come la rappresentazione di una costante intera: • Integer.parseInt(“15”) restituisce l’intero 15 ● Laboratorio di Programmazione Luca Tesei 51 Classe Integer ● ● ● ● Se la stringa contiene dei caratteri che non possono essere considerati la rappresentazione di un intero allora il metodo parseInt lancerà un’eccezione Le eccezioni sono il meccanismo di base di Java per gestire gli errori Per adesso non gestiamo questa eccezione, vedremo più avanti come si fa Se un’eccezione non viene gestita (il termine giusto sarebbe “catturata”) il programma termina con errore indicando quale eccezione si è verificata e la pila di attivazioni corrente (ci permette di risalire al punto preciso del programma in cui si è verificata) Laboratorio di Programmazione Luca Tesei 52 Lettura di dati in input • Vediamo due modi per acquisire dei dati di input dall’utente: 1. Tramite una finestra grafica di dialogo 2. Tramite lo standard input (la console, ma in generale può essere un qualunque file) – I dati in input rendono il programma interattivo e possono fare in modo che il comportamento dello stesso programma sia diverso se vengono dati input diversi Laboratorio di Programmazione Luca Tesei 53 Finestra di dialogo Possiamo chiedere all’utente di inserire una stringa e possiamo trattare l’oggetto corrispondente nel nostro programma ● La classe che ci serve per far apparire la finestra è javax.swing.JOptionPane (consultare API) ● Questa classe ha diversi metodi static showInputDialog che restituiscono un oggetto String ● Per far apparire la finestra e ottenere l’input: String input = JOptionPane.showInputDialog( “Quanti nickel hai?”); ● Laboratorio di Programmazione Luca Tesei 54 Finestra di dialogo ● La stringa che passiamo come parametro sarà visualizzata sulla finestra Laboratorio di Programmazione Luca Tesei 55 Finestra di dialogo ● ● ● ● L’utente è libero di digitare qualunque cosa nel campo di input Poi potrà fare click sui pulsanti OK o Annulla Se l’utente fa click su Annulla viene restituito il valore null e la variabile String input varrà quindi null Se l’utente fa click su OK viene creato un oggetto String che contiene la stringa inserita e il suo riferimento viene assegnato alla variabile input Laboratorio di Programmazione Luca Tesei 56 Esempio di uso import javax.swing.JOptionPane; public class InputTest { public static void main(String argv[]) { String input = JOptionPane.showInputDialog( "Quanti nickel hai?"); // Utilizzo il metodo parseInt per ottenere // il numero intero digitato int nickels = Integer.parseInt(input); System.out.println(nickels); // Nei programmi che usano la grafica si deve usare // questa chiamata per terminare il programma System.exit(0); } } Laboratorio di Programmazione Luca Tesei 57 Esempio ● ● ● ● Naturalmente si dovrebbe gestire sia il caso in cui l’utente fa click su Annulla sia il caso in cui quello che digita non è un intero Ancora non abbiamo gli strumenti per farlo Per adesso ci accontentiamo di un programma che, se qualcosa va storto, termina con errore Ricordarsi sempre di inserire System.exit(0); come ultima istruzione del main, altrimenti il programma resta in esecuzione (il gestore della grafica rappresenta un processo della nostra applicazione che rimane attivo fino a quando non lo si chiude esplicitamente con il metodo static System.exit) Laboratorio di Programmazione Luca Tesei 58 Il tipo base char ● ● ● ● ● Il tipo base char rappresenta i caratteri Come sappiamo Java gestisce tutto il set di caratteri Unicode Per indicare un carattere basta inserirlo tra due apici singoli: ‘a’ Ogni sequenza di escape corrisponde a un carattere ‘\n’, ‘\t’, ‘\u009F’ Un carattere ha associato un valore numerico reperibile con Character.getNumericValue Laboratorio di Programmazione Luca Tesei 59 Caratteri e Stringhe ● ● ● ● ● ● ‘h’ è un char “h” è una stringa, quindi un oggetto dello Heap, che contiene un solo carattere ‘h’ “Pippo”.charAt(0) ritorna il carattere ‘P’ Nelle stringhe i caratteri sono numerati da 0 in su “Pippo”.length() ritorna 5, la lunghezza della stringa Consultare le API Laboratorio di Programmazione Luca Tesei 60 Input da console ● ● ● Oltre che da una finestra di dialogo l’input può essere prelevato da uno stream di ingresso In Java, così come in C e in altri linguaggi, esiste uno stream apposito per questo che viene chiamato standard input Conosciamo già System.out, che è lo standard output, e sappiamo che è un oggetto della classe java.io.PrintStream • System.in è un oggetto della classe java.io.InputStream ed è lo standard input Laboratorio di Programmazione Luca Tesei 61 Ottenere l’input ● ● ● ● Un oggetto della classe InputStream, quale è System.in, è in grado di leggere un byte per volta dallo stream che rappresenta Non è molto comodo Quello che vorremmo è poter ottenere, come con la finestra di dialogo, una stringa di input Per prima cosa bisogna incapsulare l’oggetto System.in, di tipo InputStream, in un oggetto della classe java.io.InputStreamReader Laboratorio di Programmazione Luca Tesei 62 Ottenere l’input ● ● ● ● Un oggetto della classe InputStreamReader interpreta i byte di un oggetto InputStream come caratteri (tipo base char di Java) È un passo avanti per arrivare al nostro obiettivo I costruttori di questi oggetti richiedono sempre come argomento un’oggetto della classe InputStream Possiamo quindi usare System.in Laboratorio di Programmazione Luca Tesei 63 Ottenere l’input InputStreamReader reader = new InputStreamReader(System.in); • reader può restituire l’input sotto forma di un carattere per volta (guardare le API e scoprire come mai il metodo read restituisce un int piuttosto che un char) ● ● Possiamo ottenere di meglio Gli oggetti della classe java.io.BufferedReader possono restituire stringhe formate da caratteri di uno stream di caratteri Laboratorio di Programmazione Luca Tesei 64 Ottenere l’input BufferedReader console = new BufferedReader(reader); ● ● Il costruttore richiede un oggetto della classe java.io.Reader, di cui InputStreamReader è una sottoclasse Possiamo quindi passare il nostro oggetto System.in, incapsulato nell’oggetto reader di tipo InputStreamReader, al costruttore e ottenere l’oggetto riferito da console Laboratorio di Programmazione Luca Tesei 65 Ottenere l’input ● ● Sugli oggetti della classe BufferedReader è possibile chiamare il metodo readLine() che restituisce una stringa contentente una linea di testo Questo è quello che volevamo ottenere Laboratorio di Programmazione Luca Tesei 66 Ottenere l’input Ricapitolando: InputStreamReader reader = new InputStreamReader(System.in); ● BufferedReader console = new BufferedReader(reader); Oppure BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); ● Laboratorio di Programmazione Luca Tesei 67 Ottenere l’input A questo punto: String input = console.readLine(); ● ● ● ● Aspetta fino a quando l’utente non digita una linea di testo e preme Invio La linea scritta è contenuta nella stringa riferita da input A questo punto possiamo fare il parsing della stringa con i metodi delle classi involucro se ci aspettiamo l’inserimento di un valore di un certo tipo (es Integer.parseInt) Laboratorio di Programmazione Luca Tesei 68 IOException ● ● ● ● ● Abbiamo già visto che il metodo Integer.parseInt può sollevare un’eccezione se la stringa passata non contiene le cifre di un intero Anche il metodo readLine della classe BufferedReader può sollevare un’eccezione se qualcosa va storto con il reperimento dell’input L’eccezione è del tipo IOException L’eccezione IOException è un’eccezione che deve essere gestita obbligatoriamente Nel caso non la si voglia gestire si deve esplicitare che il metodo che stiamo scrivendo la può sollevare Laboratorio di Programmazione Luca Tesei 69 Throws ● Nel nostro caso il metodo che chiama readLine è il main Siccome ancora non abbiamo visto come gestire l’eccezione dobbiamo esplicitamente dichiarare che non la gestiamo scrivendo public static void main(String[] argv) throws IOException { ● ... } Laboratorio di Programmazione Luca Tesei 70 Un programma di esempio import java.io.*; public class InputDaConsole { public static void main(String argv[]) throws IOException { BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Quanti nickels hai?"); String input = console.readLine(); int nickels = Integer.parseInt(input); System.out.println("Hai scritto " + nickels); } } Laboratorio di Programmazione Luca Tesei 71 Classe Scanner ● ● ● ● Dalla versione 1.5 della jdk è disponibile una classe java.util.Scanner Un oggetto di questa classe permette di scorrere un flusso di caratteri o una stringa riconoscendo interi, float, double o stringhe che fanno match con una data espressione regolare Nella sua versione di default i separatori sono gli spazi bianchi Si vedano le API per maggiori dettagli Laboratorio di Programmazione Luca Tesei 72 Esercizio ● ● Riscrivere il costruttore della classe Purse in modo che chieda in input il numero di monete iniziali Aggiungere alla classe Purse un metodo che restituisca il totale in dollari e in penny (100 penny = 1 dollaro) (Suggerimento: usare la divisione intera e il resto della divisione intera) Laboratorio di Programmazione Luca Tesei 73 Esercizio ● ● ● ● Scrivere una classe RisolutoreEquazione2Grado Il costruttore deve chiedere in input i coefficienti a, b, c dell’equazione Implementare i due metodi per dare le due soluzioni: – public double getFirstSolution() – public double getSecondSolution() Scrivere una classe test Laboratorio di Programmazione Luca Tesei 74 Esercizio ● ● ● ● ● Scrivere un programma che assista un cassiere nel dare il resto Input: sommaDaPagare e sommaRicevuta La differenza sommaRicevuta – sommaDaPagare rappresenta il resto da dare Il resto deve essere corrisposto usando le seguenti banconote/monete: 1 dollaro, 1 Quarter, 1 Dimes, 1 Nickel, 1 Penny Il programma deve indicare quante monete di ogni tipo il cassiere deve dare --continua Laboratorio di Programmazione Luca Tesei 75 Esercizio cont’d ● ● Il programma deve fornire una soluzione che corrisponda all’erogazione del minimo numero possibile di banconote/monete Esempio Cassiere harry = new Cassiere(); harry.setSommaDaPagare(8.37); harry.riceve(10); int dollars = harry.returnDollars(); // Restituisce 1 int quarters = harry.returnQuarters(); // Restituisce 2 int dimes = harry.returnDimes(); // Restituisce 1 int nickels = harry.returnNickels(); // Restituisce 0 int pennies = harry.returnPennies(); // Restituisce 3 Laboratorio di Programmazione Luca Tesei 76 Esercizio ● Scrivere un programma che legge un numero intero e poi stampa le sue cifre, una ad una, in ordine inverso ● Esempio: se leggo 78349 ● Deve stampare ● 9 ● 4 ● 3 ● 8 ● 7 Laboratorio di Programmazione Luca Tesei 77 Esercizio ● ● ● Scrivere un programma che calcoli la data della domenica di Pasqua, che è la prima domenica dopo la prima luna piena di primavera, di un qualunque anno. Si usi il seguente algoritmo ideato da Carl Friedrich Gauss nel 1800: Sia y l’anno (1800, 2001, ...) ● Dividi y per 19 ottenendo il resto a. Ignora il quoziente ● Dividi y per 100 ottenendo il quoziente b e il resto c ● Continua Laboratorio di Programmazione Luca Tesei 78 Esercizio cont’d ● ● ● ● ● ● Dividi b per 4 ottenendo quoziente d e resto e Dividi 8 * b + 13 per 25 ottenendo il quoziente g. Ignora il resto. Dividi 19 * a + b - d - g + 15 per 30 ottenendo il resto h. Ignora il quoziente. Dividi c per 4 , ottenendo il quoziente j e il resto k Dividi a + 11 * h per 319, ottenendo il quoziente m. Ignora il resto Continua Laboratorio di Programmazione Luca Tesei 79 Esercizio cont’d ● ● ● ● ● Dividi 2 * e + 2 * j - k - h + m + 32 per 7 ottenendo il resto r. Ignora il quoziente Dividi h - m + r + 90 per 25, ottenendo il quoziente n. Ignora il resto Dividi h - m + r + n + 19 per 32 ottenendo il resto p. Ignora il quoziente Pasqua cade il giorno p del mese n Scrivere una classe Year con metodi getEasterDay() e getEasterMonth() Laboratorio di Programmazione Luca Tesei 80