Laboratorio VI: 12-Nov-2007                                                versione del 7-Nov-2007



Parte I Correzione degli errori sintattici e semantici segnalati dal compilatore
How to
Dopo aver scritto il codice di un metodo, si compila per verificarne la correttezza ed eventualmete correggerlo.
La compilazione genera, tipicamente, molti errori anche nel codice di programmatori esperti, quindi non bisogna scoraggiarsi.

Come correggere?

1/ Leggere attentamente il primo messaggio d'errore del compilatore. Spesso e' difficile da interpretare perche' puo' riferirsi a errori commessi molte righe prima della riga in cui e' segnalato (ad esempio nel caso di parentesi graffe mancanti o accoppiate non correttamente, o di caratteri ';' mancanti alla fine di un enunciato).

2/ Correggere solo il primo errore, salvare il file sorgente e ricompilare. Non correggere piu' di un errore alla volta, perche' spesso un errore genera piu' di un messaggio di errore e la correzione di un errore fa talvolta scomparire parecchi messaggi d'errore (purtroppo non sempre e' cosi'!).

3/ Attenzione a dove memorizzate il file sorgente! Accade spesso di memorizzare il file modificato in una directory diversa da quella in cui poi si compila. Il risultato e' che si continua a modificare il file sorgente, ma gli errori rimangono sempre uguali. La ragione e' che non viene compilato il file modificato, ma un file diverso.
Correggere gli errori sintattici
La seguente classe eseguibile Cryptic.java contiene sei errori sintattici. Scaricatela nella vostra directory di lavoro e compilatela.
La prima compilazione segnala solo tre errori: ma gli errori sono sei! Alcuni sono "nascosti" dai primi tre errori diagnosticati.
Correggete gli errori uno alla volta. Dopo la correzione dei primi due errori, la compilazione vi segnalera' 7 errori: non scoraggiatevi e cercate di capire i messaggi diagnostici del compilatore!
Quando avete corretto tutti gli errori, eseguite la classe. Che effetto ha l'esecuzione?

Il file Cryptic-commento.java commenta gli errori. La classe CrypticCorretta.java contiene il codice sorgente corretto: gli errori sono stati commentati. Consultateli solo se non riuscite nell'impresa da soli.

Parte II Linguaggio Java: decisioni e iterazioni
La mia soluzione
Estrarre lessemi da una stringa
I lessemi, o token, sono stringhe delimitate da caratteri definiti delimitatori. I caratteri delimitatori non possono essere usati nei token.
Esempio:
definiamo delimitatori i seguenti due caratteri '*' e '#'. Nella seguente stringa "uno*due#tre" possiamo identificare i tre token "uno", "due" e "tre", considerando delimitatori impliciti l'inizio e la fine della stringa.

Per estrarre token da una stringa, la libreria standard di Java (Java 2 Platform Standard Edition API specification, questo e' il suo nome per intero!) fornisce più di una classe.
Una e' gia' nota a questo corso: java.util.Scanner (introdotta da Java 5.0). Un'altra e' java.util.StringTokenizer (esistente in Java  1.4).

Scrivere la classe MyStringTokenizer.java, con la seguente interfaccia pubblica MyStringTokenizer.html.

Scrivere, successivamente, una classe di prova MyStringTokenizerTester.java che acquisisca un insieme di righe da standard input e per ciascuna riga separi i token, inviandoli successivamente a standard output separati dal carattere spazio.

Si provi la classe usando il re-indirizzamento dello standard input sullo stesso file MyStringTokenizer.java:
   $java MyStringTokenizerTester < MyStringTokenizer.java
MyStringTokenizer.java
MyStringTokenizerTester.java
massima comune sottostringa di due stringhe
(esercizio difficile!)
Si scriva una classe eseguibile MaxSottostringa.java che individui la sottostringa comune di lunghezza massima fra due stringhe.
Esempio: se le stringhe sono "PlutoPippoPaperino" e "FlautoPifferoClarino"
utoPi è la stringa comune di lunghezza massima (anche rino è una sottostringa comune, ma ha solo quattro caratteri, mentre utoPi ne ha cinque).

Inserire nelle classi un contatore per contare quante iterazioni vengono effettuate per ottenere il risultato.

Esercizione piu' facile:
Provare le tre soluzioni proposte e dire quale  soluzione e' piu' efficiente (cioe' ottiene il risultato con il minor numero di iterazioni).

Si provi la classe con le stringhe "TopolinoPlutoPippo" e "FlautoPifferoViolino".
Le soluzioni MaxSottostringa2 e MaxSottostringa3 forniscono una sola soluzione.
Capire come funzionano e modificarle in modo che gestiscano correttamente il caso di più sottostringhe di uguale lunghezza.
MaxSottostringa1.java
MaxSottostringa2.java
MaxSottostringa3.java

Parte III Linguaggio Java: Progettare le classi
La mia soluzione
money, money, money!
Scrivere un insieme di classi che registrino le transazioni economiche in valute internazionali effettuate da una ditta, quali pagamenti ricevuti ed effettuati.

Un registratore di transazioni economiche sia caratterizzato dai seguenti dati:
  • sequenza delle transazioni effettuate
  • saldo
 Una transizione economica sia caratterizzata dai seguenti dati:
  • data di effettuazione,
  • quantita' di danaro trattata
  • tipo di transazione: versamento o prelevamento.
Una quantità di denaro sia, a sua volta, caratterizzata dai seguenti dati:
  • tipo di valuta (es.: euro, dollaro, sterlina)
  • importo
  • rapporto di cambio verso l'euro.
Il programma deve fornire le seguenti funzionalità:
  • creare un nuovo registratore di transazioni con saldo iniziale nullo oppure non nullo
  • aggiungere una transazione, memorizzandola e aggiornando il saldo
  • fornire il saldo
  • fornire l'elenco delle transazioni effettuate nell'ordine in cui sono state registrate
Scrivere, successivamente una classe di prova che:
  • acquisisca i dati da standard input
  • stampi l'elenco delle operazioni
  • stampi il saldo
I dati, separati da spazi, siano introdotti nel seguente formato:
  • data   tipo_di_valuta   importo   rapporto_di_cambio_verso_euro   tipo_di_operazione.
Le righe che iniziano col carattere '*' sono righe di commento e, quindi, non contengono dati da acquisire.
Il file transazioni.txt fornisce un esempio di dati in ingresso al programma.
Si provi la classe di prova mediante redirezione dello standard input sul file transizioni.txt.

Progettare le classi:
usare i sostantivi per identificare le classi da codificare e i verbi per identificare i metodi.
Non c'e' una soluzione univoca, ovviamente! la mia soluzione e' nella directory money a fianco.
MoneyAmount.java
MoneyTransaction.java
MoneyTransactionRecorder.java
MoneyTransactionRecorderTester.java
Ancora triangoli nel piano
Codificare le classe MyTriangle2D.java e MyPoint2D.java con le seguenti interfacce pubbliche:
Per codificare la rotazione di un punto attorno a un generico punto R, e' necessario fare un po' di trigonometria. La trovate qui.

Per calcolare il baricentro di un triangolo, e' necessario ricordare alcune proprieta' dei triangoli che trovate qui.

Scrivere una semplice classe di prova che acquisisca i vertici di un triangolo, lo trasli e lo ruoti di quantita' introdotte dall'operatore e stampi a standard output i vertici del nuovo triangolo.

Se le vostre classi operano correttamente, provatele con la classe di prova DisplayLines.java fornita dal docente,  inserendo numeri interi compresi fra 0 e 100. La classe ha modeste capacita' grafiche e puo' visualizzare triangoli i cui vertici abbiano coordinate
  • 0 <= x <= 300
  • 0 <= y< = 300

La classe rappresenta i triangoli nel seguente quadrante:

Canvas

Gli angoli sono orientati come i figura.
MyPoint2D.java
MyTriangle2D.java
DisplayTriangles.java

Parte IV Linguaggio Java: progettare le classi e array
Una soluzione possibile
Archivio Studenti
Si scriva la classe ArchivioStudenti che realizza un archivio per la memorizzazione di dati relativi a studenti universitari. I dati memorizzati per ciascun studente siano: numero di matricola, nome, elenco di esami sostenuti con votazione conseguita.
Esempio di stampa dei dati di uno studente:
matr. 12345, nome: Marco Rossi
n. 2 esami sostenuti
1) Matematica A: 27
2) Fondamenti Informatica 1: 27
ArchivioStudenti.html fornisce l'interfaccia pubblica della classe.

Si scriva, poi, la classe di prova ProvaArchivioStudenti la quale:

1/ istanzi un archivio leggendo i dati da standard input. I dati relativi a ciascun studente saranno inseriti in una riga, con i vari campi separati dal carattere '/',  con il seguente formato:
numero matricola / nome / nomeEsame1 votoEsame1 / nomeEsame2  votoEsame2 /  ...
Nel caso la riga sia vuota non si elabori la riga. Nel caso  il  primo carattere della riga sia pari a '*', la riga sia interpretata come una riga di commento e non come una riga di dati.
Il file studenti.txt e' un esempio di file di input contenente dati relativi ad alcuni studenti.

2/ scriva a standard output i dati relativi all'archivio. Il nome del file di output sia passato come argomento nella riga di comado.

3/ istanzi un nuovo archivio  e inserisca nell'archivio solo i dati degli studenti la cui media sia superiore a 27.

Suggerimento.

L'invocazione della classe di prova avverra' con re-indirizzamento dello standard 'input e output :
$ java ProvaArchivioStudenti < inputFile > outputFile
dove:
inputFile: nome del file di input che contiene i dati degli studenti
outputFile: nome del file di output in cui il programma scrive

STRUTTURE DATI

I dati gestiti nella classe ArchivioStudenti si riferiscono ad un insieme di studenti. Sara', quindi, opportuno definire un oggetto che memorizzi i dati relativi a un singolo studente. Questi sono nella nostra applicazione:  numero di matricola, nome, lista di esami sostenuti.
Si proceda, quindi, a definire, la classe Studente, che sara' usata nella classe ArchivioStudenti. Se non riuscite da soli, consultate la parte pubblica della classe, descritta nell' interfaccia  Studente.html.

La classe Studente deve memorizzare una lista di esami sostenuti. Sara', quindi, opportuno definire un oggetto che memorizzi i dati relativi a un singolo esame. Questi sono: denominazione e votazione conseguita.
Si proceda, quindi, a definire, la classe Esame. Se non riuscite da soli, consultate la parte pubblica della classe, descritta nell' interfaccia Esame.html.

Si usi nella classe ArchivioStudenti la tecnica degli array riempiti solo in parte con ridimensionamento dinamico.

STRUTTURA DEI FILE
Si possono usare due alternative:

- usare un file per ciascuna classe. Nei file le classi sono definite pubbliche (come nelle soluzioni fornite). Si definiscono, quindi, quattro file: Esame.java, Studente.java, ArchivioStudenti.java, ProvaArchivioStudenti.java.

- definire le classi Studente ed Esame nel file ArchivioStudenti.java. In questo caso, la classe ArchivioStudenti viene definita pubblica, mentre le classi Studente ed Esame sono definite senza specificatore di accesso. In un file si puo', infatti,  definire una sola classe pubblica!

OSSERVAZIONE
Notare che il costruttore public ArchivioStudento(Scanner in) gestisce internamente la lettura da file!

Nell'estrazione dei token mediante la classe Scanner, per usare come delimitatore il carattere '/', anzichè i caratteri whitespaces, si deve scrivere:

Scanner in = new Scanner(System.in);
in.useDelimiter("[/]+");
Esame.java
Studente.java
ArchivioStudenti.java
ProvaArchivioStudenti.java

Parte V
Consultare la documentazione di Java
Collegamenti
javaDocs
Nella documentazione di java in linea presso l'aula Taliercio consultare la documentazione relativa ai seguenti componenti della libreria standard:
- classe java.io.inputStream: che funzioni svolgono i metodi
   int read(byte[] b), long skip(long n)
- classe  java.util.Random: a che cosa serve e che metodi ha?
- classe java.awt.Graphics: che cosa fanno gli oggetti della classe? che cosa fa e che parametri ha il metodo void drawRect()?
- classe  java.io.DataInputStream:: a che cosa serve e che metodi ha? Che funzione svolgono i metodi readInt(), readDouble(), read(byte[] b) ?

Saper consultare rapidamente la documentazione java in linea nel sito dell'Aula Didattica Taliercio e' molto importante. Infatti in sede di prova pratica di esame, questa sarà la sola documentazione disponibile.
http://www.adt.unipd.it/guide/jdk1.4.1/docs/api/index.html