javac Hello.java Hello.java:3: cannot resolve symbol symbol : variable aut location: class java.lang.System System.aut.println("Hello, World!"); ^ 1 error posizione (numero di riga) posizione (nella riga) diagnosi">

La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Errori di programmazione. Lattività di programmazione, come ogni altra attività di progettazione, è soggetta ad errori di vario tipo errori di sintassi.

Presentazioni simili


Presentazione sul tema: "Errori di programmazione. Lattività di programmazione, come ogni altra attività di progettazione, è soggetta ad errori di vario tipo errori di sintassi."— Transcript della presentazione:

1 Errori di programmazione

2 Lattività di programmazione, come ogni altra attività di progettazione, è soggetta ad errori di vario tipo errori di sintassi o di compilazione errori logici o di esecuzione System. aut.println("Hello, World!"); System.out.println("Hello, World !) ; System.out.println("Hell, World!"); System.out.println("Hello, World!");

3 Errori di sintassi In questo caso il compilatore riesce agevolmente ad individuare e segnalare lerrore di sintassi, perché identifica il nome di un oggetto (simbolo) che non è stato definito (aut) e sul quale non è in grado di decidere System.aut.println("Hello, 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 posizione (numero di riga) posizione (nella riga) diagnosi

4 Errori di sintassi 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 System.out.println("Hello, World!); 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 virgolette mancanti

5 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 lha inserita allinterno 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

6 Errori logici Questo errore, invece, non viene segnalato dal compilatore, che non può sapere che cosa il programmatore abbia intenzione di far scrivere al programma sulloutput standard la compilazione va a buon fine si ha un errore durante lesecuzione del programma, perché viene prodotto un output diverso dal previsto System.out.println("Hell, World!"); C:\>java Hello Hell, World! manca un carattere

7 Errori logici Sono molto più insidiosi degli errori di sintassi il programma viene compilato correttamente, ma non fa quello che dovrebbe fare Leliminazione degli errori logici richiede molta pazienza, eseguendo il programma ed osservando con attenzione i risultati prodotti è necessario collaudare i programmi, come qualsiasi altro prodotto dellingegneria Si usano programmi specifici (debugger) per trovare gli errori logici (bug) in un programma

8 Tipi di dati numerici

9 Un programma che elabora numeri public class Coins1 { public static void main(String[] args) { int lit = 15000; // lire italiane double euro = 2.35; // euro // calcola il valore totale double totalEuro = euro + lit / ; // stampa il valore totale System.out.print("Valore totale in euro "); System.out.println(totalEuro); }

10 Un programma che elabora numeri Questo programma elabora due tipi di numeri numeri interi per le lire italiane, che non prevedono luso di decimi e centesimi e quindi non hanno bisogno di una parte frazionaria numeri frazionari (in virgola mobile) per gli euro, che prevedono luso 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

11 I numeri in virgola mobile I numeri frazionari vengono di solito rappresentati nei computer come numeri in virgola mobile si rappresentano con la sequenza delle loro cifre significative e con lindicazione 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 × 10 2 ) in realtà si usa la rappresentazione in base 2 anziché 10

12 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

13 I commenti Nel programma sono presenti anche dei commenti, che vengono ignorati dal compilatore, ma che rendono il programma molto più comprensibile 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 */ // lire italiane /* questo e un commento lungo ma inutile... */ // questo e un commento // lungo,inutile... //... e anche scomodo

14 Alcune note sintattiche Loperatore che indica la divisione è /, quello che indica la moltiplicazione è * Quando si scrivono numeri in virgola mobile, bisogna usare il punto come separatore decimale, invece della virgola (uso anglosassone) Quando si scrivono numeri, non bisogna indicare il punto separatore delle migliaia I numeri in virgola mobile si possono anche esprimere in notazione esponenziale lit / E3 // vale 1.93 × 10 3

15 Luso delle variabili 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, 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; int lit = 15000;

16 Luso delle variabili Il programma poteva risolvere lo stesso problema anche senza fare uso di variabili ma sarebbe stato molto meno comprensibile e modificabile con difficoltà public class Coins2 { public static void main(String[] args) { System.out.print("Valore totale in euro "); System.out.println( / ); }

17 I nomi delle variabili La scelta dei nomi per le variabili è molto importante, ed è 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

18 Definizione di variabili Sintassi: 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 i nomi di variabili e di metodi iniziano con una lettera minuscola 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 nomeTipo nomeVariabile; nomeTipo nomeVariabile = espressione; lit MoveRectangletotalEuro mainCoins1

19 Intervallo

20 Assegnazioni

21 Luso delle variabili Abbiamo visto come i programmi usino le variabili per memorizzare i valori da elaborare e i risultati dellelaborazione 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

22 Luso delle variabili public class Coins3 { 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 / ; totalEuro = totalEuro + euro; totalEuro = totalEuro + dollars * 0.93; System.out.print("Valore totale in euro "); System.out.println(totalEuro); }

23 In questo caso il valore della variabile totalEuro cambia durante lesecuzione del programma per prima cosa la variabile viene inizializzata contestualmente alla sua definizione poi la variabile viene incrementata, due volte mediante enunciati di assegnazione Luso delle variabili double totalEuro = lit / ; totalEuro = totalEuro + euro; totalEuro = totalEuro + dollars * 0.93;

24 Analizziamo lenunciato di assegnazione Cosa significa? Non certo che totalEuro è uguale a se stessa più qualcosaltro… Lenunciato di assegnazione significa Calcola il valore dellespressione a destra del segno = e scrivi il risultato nella posizione di memoria assegnata alla variabile indicata a sinistra del segno = Lassegnazione totalEuro = totalEuro + euro;

25 Lassegnazione euro totalEuro totalEuro + euro LEGGI SCRIVI CALCOLA

26 Assegnazione o definizione? Attenzione a non confondere la definizione di una variabile con un enunciato di assegnazione! La definizione di una variabile inizia specificando il tipo della variabile, lassegnazione no 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 definire una variabile una seconda volta double totalEuro = lit / ; totalEuro = totalEuro + euro; double euro = 2; double euro = euro + 3; euro is already defined

27 Assegnazione Sintassi: Scopo: assegnare il nuovo valore espressione alla variabile nomeVariabile Nota: purtroppo Java (come C e C++) utilizza il segno = per indicare lassegnazione, creando confusione con loperatore di uguaglianza (che vedremo essere un doppio segno =, cioè ==); altri linguaggi usano simboli diversi per lassegnazione (ad esempio, il linguaggio Pascal usa :=) nomeVariabile = espressione;

28 Variabili non inizializzate

29 È buona regola fornire sempre un valore di inizializzazione nella definizione di variabili Cosa succede altrimenti? 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 lultimo valore attribuito a quello spazio da un precedente programma… valore che a noi non è noto) int lit;

30 Variabili non inizializzate Se si usasse il valore di una variabile prima di averle assegnato un qualsiasi valore, il programma si troverebbe ad elaborare quel valore che casualmente si trova nello spazio di memoria riservato alla variabile public class Coins4 // NON FUNZIONA! { public static void main(String[] args) { int lit; double euro = 2.35; double totalEuro = euro + lit / ; System.out.print("Valore totale in euro "); System.out.println(totalEuro); } ERRORE

31 Variabili non inizializzate Questo problema provoca insidiosi errori di esecuzione in molti linguaggi di programmazione il compilatore Java, invece, segnala come errore lutilizzo di variabili a cui non sia mai stato assegnato un valore (mentre non è un errore la sola definizione...) 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 Coins4.java:5: variable lit might not have been initialized

32

33 Costanti

34 Luso delle costanti Un programma per il cambio di valuta 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 Convert1 { public static void main(String[] args) { double dollars = 2.35; int lit = (int)(dollars * 2125); }

35 Luso delle costanti Così come si usano nomi simbolici descrittivi per le variabili, è opportuno assegnare nomi simbolici anche alle costanti utilizzate nei programmi Un primo vantaggio molto importante aumenta la leggibilità 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); }

36 Luso delle costanti 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); }

37 Definizione di costante Sintassi: 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 final nomeTipo NOME_COSTANTE = espressione;

38 public class Coins { public static void main(String[] args) { int a = 15000; double b = 2.35; double c = b + a / ; } Scegliere bene i nomi delle variabili public class Coins { public static void main(String[] args) { int lit = 15000; double euro = 2.35; double totalEuro = euro + lit / ; }

39 Scegliere bene i nomi delle variabili È 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 dellalgoritmo troppi commenti rendono il programma poco leggibile! se si modifica il programma, bisogna poi modificare anche i commenti… altrimenti è meglio eliminarli!

40 Operazioni aritmetiche

41 Loperatore di moltiplicazione va sempre indicato 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 In Java non esiste il simbolo di frazione, le frazioni vanno espresse in linea, usando loperatore di divisione (a + b) / 2a + b / 2 (a + b) / 2

42 Operazioni aritmetiche Quando entrambi gli operandi sono numeri interi, la divisione ha una caratteristica particolare, che può essere utile ma che va usata con attenzione calcola il quoziente intero, scartando il resto! Il resto della divisione tra numeri interi può essere calcolato usando loperatore %, che non esiste in algebra ed il cui simbolo è stato scelto perché è simile alloperatore di divisione 7 / / / / 4 1,75 7 % 47 % 43

43 Divisione fra interi public class Coins5 { 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"); } 2 euro e 35 centesimi

44 Funzioni più complesse Non esistono operatori per calcolare funzioni più complesse, come lelevamento 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 x y (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

45 Combinare assegnazioni e aritmetica Abbiamo già visto come in Java sia possibile combinare in un unico enunciato unassegnazione ed unespressione aritmetica che coinvolge la variabile a cui si assegnerà il risultato Questa operazione è talmente comune nella programmazione, che il linguaggio Java fornisce una scorciatoia che esiste per tutti gli operatori aritmetici totalEuro = totalEuro + dollars * 0.93; totalEuro += dollars * 0.93; x = x * 2; x *= 2;

46 Incremento di una variabile Lincremento di una variabile è loperazione che consiste nellaumentarne il valore di uno Questa operazione è talmente comune nella programmazione, che il linguaggio Java fornisce un operatore apposito per lincremento e per il decremento int counter = 0; counter = counter + 1; counter++; counter--;

47 Intervallo

48 Conversioni fra diversi tipi di dati

49 Assegnazioni con conversione In unassegnazione, il tipo di dati dellespressione e della variabile a cui la si assegna devono essere compatibili s e 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 Lassegnazione 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; OK

50 Tipi di dati numerici incompatibili 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 lerrore semantico ed interrompendo la compilazione possible loss of precision found : double required: int double doubleVar = 2.3; int intVar = doubleVar;

51 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 lintenzione esplicita di accettare leventuale perdita di informazione, mediante un cast (forzatura) Alla variabile intVar viene così assegnato il valore 2, la parte intera dellespressione double doubleVar = 2.3; int intVar = (int)doubleVar; OK

52 Conversioni con arrotondamento La conversione forzata di un valore in virgola mobile in un valore intero avviene con troncamento, trascurando la parte frazionaria Spesso si vuole invece effettuare tale conversione con arrotondamento, convertendo allintero 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

53 Conversioni con arrotondamento Questo semplice algoritmo per arrotondare i numeri in virgola mobile funziona però soltanto per numeri positivi, quindi non è molto valido… Unottima 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)(rate + 0.5); System.out.println(intRate); -2 double rate = -2.95; int intRate = (int)Math.round(rate); System.out.println(intRate); -3

54 Il metodo Math.round 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 double rate = -2.95; int intRate = (int)Math.round(rate); System.out.println(intRate);

55 Il metodo Math.round Come si fa a capire che System.out.println è un 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 Seguitela anche voi!

56 Invocazione di metodo statico Sintassi: 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 NomeClasse.nomeMetodo(parametri)

57 Rappresentazione dei numeri

58 Numeri binari I numeri che siamo abituati ad utilizzare sono espressi con 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 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 434 = 4· · ·10 0 4,34 = 4· · ·10 -2

59 Numeri binari I computer usano invece numeri binari, cioè 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 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 (1101) 2 = (1· · · ·2 0 ) 10 = (13) 10 (1,101) 2 = (1· · · ·2 -3 ) 10 = (1,625) 10

60 Numeri binari La conversione di un numero da base decimale a 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

61 Numeri binari Per convertire la sola parte intera, si divide il numero per 2, eliminando leventuale resto e continuando a dividere per 2 il quoziente ottenuto fino a quando non si ottiene quoziente uguale a 0 Il numero binario si ottiene scrivendo la serie dei resti delle divisioni, iniziando dallultimo resto ottenuto Attenzione: non fermarsi quando si ottiene quoziente 1, ma proseguire fino a / 2 = 50 resto 0 50 / 2 = 25 resto 0 25 / 2 = 12 resto 1 12 / 2 = 6 resto 0 6 / 2 = 3 resto 0 3 / 2 = 1 resto 1 1 / 2 = 0 resto 1 (100) 10 = ( ) 2

62 Numeri binari Per convertire la sola parte frazionaria, si moltiplica il 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 Il numero binario si ottiene scrivendo la serie delle parti intere dei prodotti ottenuti, iniziando dal primo Se si ottiene un risultato già ottenuto in precedenza, il numero sarà periodico, anche se non lo era in base decimale 0,35 · 2 = 0,7 0,7 · 2 = 1,4 0,4 · 2 = 0,8 0,8 · 2 = 1,6 0,6 · 2 = 1,2 0,2 · 2 = 0,4 (0,35) 10 = (0,010110) 2

63 Numeri binari Per programmare in Java non cè bisogno di conoscere i numeri binari, ma tale conoscenza fa parte della cultura di base dellinformatica Perché il massimo numero rappresentabile con una variabile di tipo int è ? 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) il massimo numero è che equivale a =

64

65 Stringhe

66 Il tipo di dati stringa I tipi di dati più importanti nella maggior parte dei programmi sono i numeri e le stringhe Una stringa è una sequenza di caratteri, che in Java (come in molti altri linguaggi) vanno racchiusi tra virgolette le virgolette non fanno parte della stringa Possiamo dichiarare e inizializzare variabili di tipo stringa Possiamo assegnare un valore ad una variabile di tipo stringa String name = "John"; "Hello" name = "Michael";

67 Il tipo di dati stringa Diversamente dai numeri, le stringhe sono oggetti infatti, il tipo di dati String inizia con la maiuscola! invece, int e double iniziano con la minuscola… Una variabile di tipo stringa può quindi essere utilizzata per invocare metodi della classe String ad esempio, il metodo length restituisce la lunghezza di una stringa, cioè il numero di caratteri presenti in essa (senza contare le virgolette) String name = "John"; int n = name.length(); 4

68 Il tipo di dati stringa Il metodo length della classe String non è un metodo statico infatti per invocarlo usiamo un oggetto della classe String, e non il nome della classe stessa Una stringa di lunghezza zero, che non contiene caratteri, si chiama stringa vuota e si indica con due caratteri virgolette consecutivi, senza spazi interposti // NON FUNZIONA! String s = "John"; int n = String.length(s); // FUNZIONA String s = "John"; int n = s.length(); String empty = ""; System.out.println(empty.length()); 0

69 Estrazione di sottostringhe Per estrarre una sottostringa da una stringa si usa il metodo substring il primo parametro di substring è la posizione del primo carattere che si vuole estrarre il secondo parametro è la posizione successiva allultimo carattere che si vuole estrarre String greeting = "Hello, World!"; String sub = greeting.substring(0, 4); // sub contiene "Hell" Heoll,Wodlr! Attenzione alla minuscola!

70 Estrazione di sottostringhe La posizione dei caratteri nelle stringhe viene stranamente numerata a partire da 0 anziché da 1 in linguaggi precedenti, come il C e il C++, questa era unesigenza tecnica, mentre in Java non lo è più e si è mantenuta questa strana caratteristica soltanto per uniformità con tali linguaggi molto diffusi Alcune cose da ricordare la posizione dellultimo carattere corrisponde alla lunghezza della stringa meno 1 la differenza tra i due parametri di substring corrisponde alla lunghezza della sottostringa estratta

71 Estrazione di sottostringhe Il metodo substring può essere anche invocato con un solo parametro In questo caso il parametro fornito indica la posizione del primo carattere che si vuole estrarre, e lestrazione continua fino al termine della stringa String greeting = "Hello, World!"; String sub = greeting.substring(7); // sub contiene "World!" Heoll,Wodlr!

72 Estrazione di sottostringhe Cosa succede se si fornisce un parametro errato a substring? Il programma viene compilato correttamente, ma viene generato un errore in esecuzione // NON FUNZIONA! String greeting = "Hello, World!"; String sub = greeting.substring(0, 14); Exception in thread main java.lang.StringIndexOutOfBoundsException String index out of range: 14

73 Concatenazione di stringhe Per concatenare due stringhe si usa loperatore + Loperatore di concatenazione è identico alloperatore di addizione se una delle espressioni a sinistra o a destra delloperatore + è una stringa, laltra espressione viene convertita in stringa e si effettua la concatenazione String s1 = "li"; String s2 = "re"; String s3 = s1 + s2; // s3 contiene lire int lit = 15000; String s = lit + s3; // s contiene "15000lire"

74 Concatenazione di stringhe Osserviamo che la concatenazione prodotta non è proprio quella che avremmo voluto, perché manca uno spazio tra e lire loperatore di concatenazione non aggiunge spazi! (meno male, diremo la maggior parte delle volte…) Leffetto voluto si ottiene così int lit = 15000; String litName = "lire"; String s = lit + litName; // s contiene "15000lire" String s = lit + " " + litName; Non è una stringa vuota, ma una stringa con un solo carattere, uno spazio (blank)

75 Concatenazione di stringhe La concatenazione è molto utile per ridurre il numero di enunciati usati per stampare i risultati dei programmi Bisogna fare attenzione a come viene gestito il concetto di andare a capo (cioè alla differenza tra print e println) int total = 10; System.out.print("Il totale è "); System.out.println(total); int total = 10; System.out.println("Il totale è " + total);

76 Sequenze di escape Proviamo a stampare una stringa che contiene delle virgolette 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 allinterno della stringa // NON FUNZIONA! System.out.println("Hello, "World"!"); Hello, "World"! System.out.println("Hello, \"World\"!");

77 Sequenze di escape Il carattere backslash allinterno 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? si usa la sequenza di escape \\ // FUNZIONA! System.out.println("Hello, \"World\"!"); System.out.println("File C:\\autoexec.bat"); File C:\autoexec.bat

78 Sequenze di escape Unaltra sequenza di escape che si usa è \n, che rappresenta il carattere di nuova riga o andare a capo Le sequenze di escape si usano anche per inserire caratteri di lingue straniere o simboli che non si trovano sulla tastiera System.out.println("*\n**\n***\n"); * ** *** System.out.println("*"); System.out.println("**"); System.out.println("***");

79 Sequenze di escape Ad esempio, per scrivere parole italiane con lettere accentate senza avere a disposizione una tastiera italiana Queste sequenze di escape utilizzano la codifica standard Unicode per rappresentare i caratteri di tutti gli alfabeti del mondo con 4 caratteri esadecimali (codifica a 16 bit, simboli diversi) System.out.println("Perch\u00E9?"); Perché?

80 Intervallo

81 Elaborazioni con stringhe

82 Alcuni metodi utili di String Un problema che capita spesso di affrontare è quello della conversione di una stringa per ottenerne unaltra tutta in maiuscolo o tutta in minuscolo La classe String mette a disposizione due metodi toUpperCase converte tutto in maiuscolo toLowerCase converte tutto in minuscolo String s = "Hello"; String ss = s.toUpperCase() + s.toLowerCase(); // ss vale "HELLOhello"

83 Alcuni metodi utili di String Si noti che lapplicazione di uno di questi metodi alla stringa s non altera il contenuto della stringa s, ma restituisce una nuova stringa In particolare, nessun metodo della classe String modifica loggetto con cui viene invocato! si dice perciò che gli oggetti della classe String sono oggetti immutabili String s = "Hello"; String ss = s.toUpperCase() + s.toLowerCase(); // s vale ancora "Hello" !

84 Esempio Scriviamo un programma che genera la password per un utente, con la regola seguente si prendono le iniziali dellutente, le si rendono minuscole e si concatena letà dellutente espressa numericamente (in realtà questa regola non è assolutamente da usare, perché è prevedibile e quindi poco sicura!) Utente: Marcello Dalpasso Età: 35 Password: md35

85 Esempio public class MakePassword { public static void main(String[] args) { String firstName = "Marcello"; String lastName = "Dalpasso"; int age = 35; // estrai le iniziali String initials = firstName.substring(0, 1) + lastName.substring(0, 1); // converti in minuscolo e concatena letà String pw = initials.toLowerCase() + age; // stampa la password System.out.println("La password è " + pw); }

86 Conversione di stringhe in numeri A volte si ha una stringa che contiene un valore numerico e si vuole assegnare tale valore ad una variabile di tipo numerico, per poi elaborarlo Il compilatore segnala lerrore semantico perché non si può convertire automaticamente una stringa in un numero, dato che non vi è certezza che il suo contenuto rappresenti un valore numerico String password = "md35"; String ageString = password.substring(2); // ageString contiene "35" // NON FUNZIONA! int age = ageString; incompatible types found : java.lang.String required: int

87 Conversione di stringhe in numeri La conversione corretta si ottiene invocando il metodo statico parseInt della classe Integer La conversione di un numero in virgola mobile si ottiene, analogamente, invocando il metodo statico parseDouble della classe Double int age = Integer.parseInt(ageString); // age contiene il numero 35 String numberString = "34.3"; double number = Double.parseDouble(numberString); // number contiene il numero 34.3

88 Per convertire un numero in stringa si può concatenare il numero con la stringa vuota È però più elegante utilizzare il metodo toString delle classi Integer e Double, rispettivamente per numeri interi e numeri in virgola mobile Conversione di numeri in stringhe int ageNumber = 10; String ageString = "" + ageNumber; // ageString contiene "10" int ageNumber = 10; String ageString = Integer.toString(ageNumber);

89 A volte la conversione automatica di numeri in stringhe, eseguita con la concatenazione o con i metodi toString, non fornisce il risultato voluto Ad esempio, quando si elaborano valori monetari Problemi nelle conversioni double euro = ; final double TAX_RATE = 17.5; System.out.println("Reddito: " + euro + " euro"); double tax = euro * TAX_RATE / 100; System.out.println("Tassa: " + tax + " euro"); Reddito: euro Tassa: euro I millesimi di euro non esistono, sarebbe meglio scrivere

90 Per effettuare conversioni di numeri in stringhe in modo controllato (cioè non automatico), si può usare la classe java.text.NumberFormat Conversioni sotto controllo double euro = ; final double TAX_RATE = 17.5; System.out.println("Reddito: " + euro + " euro"); double tax = euro * TAX_RATE / 100; NumberFormat formatter = NumberFormat.getNumberInstance(); formatter.setMaximumFractionDigits(2); formatter.setMinimumFractionDigits(2); String taxStr = formatter.format(tax); System.out.println("Tassa: " + taxStr + " euro");

91 Per prima cosa otteniamo un oggetto NumberFormat invocando un metodo statico Poi impostiamo il numero massimo di cifre decimali e anche il numero minimo (altrimenti 4.30 viene stampato come 4.3) Infine, effettuiamo la conversione invocando il metodo format delloggetto formatter Conversioni sotto controllo NumberFormat formatter = NumberFormat.getNumberInstance(); formatter.setMaximumFractionDigits(2); formatter.setMinimumFractionDigits(2); String taxStr = formatter.format(tax);

92 Nel caso specifico dei valori monetari, una valida alternativa è lutilizzo di un particolare oggetto di tipo NumberFormat che contiene già le impostazioni corrette per convertire i valori monetari in una stringa tale oggetto si ottiene invocando un metodo statico La stringa che viene stampata rispetta il formato monetario della divisa (currency) locale Conversione di valori monetari NumberFormat currency = NumberFormat.getCurrencyInstance(); System.out.println(currency.format(1025.3)); L In Italia viene stampato un numero intero, con il punto come separatore delle migliaia e con il prefisso L.

93 Preparare i casi di prova Come si può collaudare un programma? non è possibile provare tutti i possibili valori dei dati in ingresso, e non avrebbe neanche senso farlo bisogna invece cercare di provare tutti i possibili casi, i possibili gruppi di valori per far questo, bisogna predisporre dei casi di prova (test cases) per collaudare il programma bisogna anche verificare il funzionamento del programma nei casi di input non corretto per ogni caso di prova bisogna calcolare manualmente loutput corretto del programma

94 Preparare i casi di prova (continua) per i casi di prova di input non corretto, bisogna determinare le segnalazioni derrore previste se il programma fallisce in un caso di prova, bisogna identificare e correggere lerrore nel programma; quindi, bisogna eseguire di nuovo tutti i casi di prova correggendo un errore se ne possono introdurre altri! progettare i casi di prova prima di scrivere il codice progettare i casi di prova aiuta a capire meglio lalgoritmo dopo aver scritto il codice, si tende (inconsciamente?) a collaudare di meno le parti di codice che si ritengono più deboli...

95 Errori di arrotondamento Gli errori di arrotondamento sono un fenomeno naturale nel calcolo in virgola mobile eseguito con un numero finito di cifre significative calcolando 1/3 con due cifre significative, si ottiene 0,33 moltiplicando 0,33 per 3, si ottiene 0,99 e non 1 Siamo abituati a valutare questi errori pensando alla rappresentazione dei numeri in base decimale, ma i computer rappresentano i numeri in virgola mobile in base binaria e a volte si ottengono dei risultati inattesi!

96 Errori di arrotondamento Qui lerrore inatteso è dovuto al fatto che 4,35 non ha una rappresentazione esatta nel sistema binario, proprio come 1/3 non ha una rappresentazione esatta nel sistema decimale 4,35 viene rappresentato con un numero appena un po inferiore a 4,35, che, quando viene moltiplicato per 100, fornisce un numero appena un po inferiore a 435, quanto basta però per essere troncato a 434 È sempre meglio usare Math.round double f = 4.35; int n = (int)(100 * f); System.out.println(n);

97

98 Concatenazione di stringhe La concatenazione è molto utile per ridurre il numero di enunciati usati per stampare i risultati dei programmi Bisogna fare attenzione a come viene gestito il concetto di andare a capo (cioè alla differenza tra print e println) int total = 10; System.out.print("Il totale è "); System.out.println(total); int total = 10; System.out.println("Il totale è " + total);

99 Ricevere dati in ingresso

100 I dati in ingresso ai programmi I programmi visti finora non sono molto utili, visto che eseguono sempre la stessa elaborazione ad ogni esecuzione Il programma MakePassword genera sempre la password md35 se si vuole che generi la password per un altro utente (o per lo stesso utente invecchiato…), è necessario modificare il codice sorgente (in particolare, le inizializzazioni delle variabili) e compilarlo di nuovo I programmi utili hanno bisogno di ricevere dati in ingresso dallutente

101 Linput standard dei programmi Il modo più semplice e immediato per fornire dati in ingresso ad un programma consiste nellutilizzo della tastiera altri metodi fanno uso del mouse, del microfono… Abbiamo visto che tutti i programmi Java hanno accesso al proprio output standard, tramite loggetto System.out di tipo PrintStream Analogamente, linterprete Java mette a disposizione dei programmi in esecuzione il proprio input standard (flusso di input), tramite loggetto System.in di tipo InputStream

102 La classe JOptionPane Sfortunatamente, la classe InputStream non possiede metodi comodi per la ricezione di dati numerici e stringhe PrintStream ha invece il comodissimo metodo print Per ovviare a questo limite, è possibile usare la classe JOptionPane, che dispone di un metodo statico showInputDialog che apre una finestra di dialogo che può ricevere una stringa inserita dallutente Il metodo showInputDialog restituisce una stringa, se vogliamo ricevere un dato numerico, la stringa dovrà essere convertita esplicitamente in un numero

103 Leggere linput con la classe JOptionPane

104 Il metodo showInputDiolaog di JOptionPane Prima di tutto bisogna creare una variabile di tipo String alla quale assegnare il valore reso invocando il metodo showInputDiolaog Durante lesecuzione del metodo verrà aperta una finestra con il messaggio come intestazione e due bottoni. Lutente può scrivere una stringa nella finestra e chiuderla con uno dei bottoni Se si usa OK il programma riceve la stringa (eventualmente di lunghezza nulla), se si usa cancel viene restituito un riferimento null String line; line = JOptionPane.showInputDialog(messaggio);

105 Esempio import javax.swing.JOptionPane; public class ProvaJOP { public static void main (String[] arg) { String dato; dato = JOptionPane.showInputDialog ("Dammi una stringa"); System.out.println("Hai scritto: " + dato); dato = JOptionPane.showInputDialog ("Dammi un numero intero"); int i = Integer.parseInt(dato); System.out.println("Hai scritto: " + i); dato = JOptionPane.showInputDialog ("Dammi un numero in virgola mobile"); double d = Double.parseDouble(dato); System.out.println("Hai scritto: " + d); System.exit(0); }

106 LENIAC e gli albori dellinformatica LENIAC ( Electronic Numerical Integrator And Computer ) fu il primo computer elettronico, realizzato alluniversità di Pennsylvania nel 1946 Occupava una grande stanza ed era costituito da molti armadi con circa valvole (analoghe ai transistori), parecchie delle quali si bruciavano ogni giorno e dovevano essere sostituite Veniva programmato collegando cavi su appositi pannelli, simili a quelli dei centralini telefonici, ed andava nuovamente programmato in tal modo per ogni specifico problema

107 LENIAC e gli albori dellinformatica

108 Il progetto fu finanziato dalla Marina statunitense per il calcolo di tavole balistiche da usare per la stima della traiettoria di un proiettile in funzione della resistenza del vento, della velocità iniziale e delle condizioni atmosferiche Questo problema richiedeva la soluzione numerica di equazioni differenziali (numerical integrator) Questi calcoli venivano precedentemente svolti da esseri umani, detti computer, letteralmente calcolatori (manuali...) Più tardi lENIAC venne usato per catalogare i dati del servizio demografico statunitense

109

110 Le fasi della programmazione

111 Lattività di programmazione si esegue in tre fasi scrittura del programma (codice sorgente) compilazione del codice sorgente 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

112 Individuare il compilatore Java Il modo di utilizzo del compilatore Java dipende dal sistema operativo si seleziona con il mouse unicona 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

113 La compilazione del sorgente Compilando il codice sorgente di un programma (gli enunciati in linguaggio Java) si ottiene un particolare formato di codice eseguibile, detto bytecode, che è codice macchina per la Java Virtual Machine (JVM) javac Hello.java genera Hello.class Quindi il bytecode non è codice direttamente eseguibile, dato che la JVM non esiste… Il file con il codice bytecode contiene una traduzione delle istruzioni del programma

114 Lesecuzione del programma Per eseguire un programma si usa linterprete Java, un programma eseguibile sul computer dellutente che 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 lesecuzione (ad esempio, la classe System) java Hello scrive Hello, World! sullo standard output

115 La Java Virtual Machine CPU reale Interprete Java CPU virtuale (JVM) bytecode codice macchina

116 La libreria di classi standard Per scrivere sullo standard output è necessario interagire con il sistema operativo, unoperazione 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 allinterno di librerie standard, che sono raccolte di classi Non è necessario avere a disposizione il codice sorgente di queste classi, né capirlo! Comodo...

117 Il processo di programmazione in Java codice sorgente compilatore file di bytecode librerie interprete programma in esecuzione JDK - Java Development Kit E se qualcosa non funziona?

118 eventualmente usa debugger jdb Hello fine errori di logica? errori di sintassi? Modifica-Compila-Collauda inizio Si No crea o modifica programma edit Hello.java compila programma javac Hello.java collauda programma java Hello

119 Compilatore e/o interprete Per passare dalla scrittura del file sorgente in linguaggio Java allesecuzione del programma su una particolare CPU, si usano il compilatore e linterprete Con la maggior parte degli altri linguaggi di programmazione ad alto livello, invece, si usa soltanto il compilatore oppure soltanto linterprete 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 leventuale ausilio di un caricatore, loader, che interagisce con una libreria) con linguaggi interpretati come BASIC e PERL, linterprete traduce al volo il file sorgente in codice eseguibile e lo esegue, senza creare un file eseguibile

120 compilatore (caricatore) Il processo di programmazione codice sorgente compilatore file di bytecode librerie interprete programma in esecuzione codice sorgente librerie interprete programma in esecuzione codice sorgente librerie programma in esecuzione file eseguibile linguaggio Java linguaggi compilati linguaggi interpretati

121 Compilatore e/o interprete Il fatto che un linguaggio sia compilato o interpretato influisce fortemente su quanto è facile eseguire lo stesso programma su computer aventi diverse CPU (portabilità) veloce lesecuzione di un programma (efficienza) Entrambi questi aspetti sono molto importanti 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

122 Portabilità I programmi scritti in un linguaggio interpretato 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 possono essere compilati una sola volta ed eseguiti da interpreti diversi su diverse CPU

123 Efficienza I programmi scritti in un linguaggio interpretato sono poco efficienti lintero processo di traduzione in linguaggio macchina deve essere svolto ad ogni esecuzione I programmi scritti in un linguaggio compilato sono molto efficienti lintero processo di traduzione in linguaggio macchina viene svolto prima dellesecuzione, una volta per tutte I programmi scritti in linguaggio Java hanno unefficienza intermedia parte del processo di traduzione viene svolto una volta per tutte (dal compilatore) e parte viene svolto ad ogni esecuzione (dallinterprete)

124 Portabilità ed efficienza Se si vuole soltanto la portabilità, i linguaggi interpretati sono la scelta migliore Se si vuole soltanto lefficienza, 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


Scaricare ppt "Errori di programmazione. Lattività di programmazione, come ogni altra attività di progettazione, è soggetta ad errori di vario tipo errori di sintassi."

Presentazioni simili


Annunci Google