![]() |
Università
|
Diploma in Ingegneria Informatica
|
A.A. 2001/2002
Versione 1.17 18/01/2002
Si progetti in UML un sistema di classi che descriva un anno di corso del diploma. Il sistema deve includere le seguenti entità:
Realizzare una classe Bits che gestisce sequenze di 32 bit, singolarmente manipolabili, attraverso una rappresentazione interna con un valore intero. A tale scopo si implementino i seguenti metodi pubblici:
Definire una classe Square che memorizza quadrati di numeri interi. Prevedere nella classe:
Realizzare una classe Biglietto che rappresenta un biglietto di autobus urbano a tariffa unica. La classe include:
Si realizzi la classe Cruci che rappresenta un cruciverba. La classe ha un costruttore che riceve i parametri n numero delle righe, m numero delle colonne, e un array di coppie di coordinate che rappresenta l'insieme delle caselle nere. Una coppia è rappresentata da un oggetto di classe Coppia, opportunamente definita. Cruci fornisce i seguenti servizi:
Si modifichi la classe Bits dell'esercizio 1.2 nella classe EBits in modo da renderla estendibile, e la si estenda con la classe SBits avente le seguenti caratteristiche:
Si definisca l'interfaccia SuFigura che rappresenta le azioni comuni su una figura geometrica, e precisamente i metodi:
Si definisca quindi una classe astratta Figura che implementa in parte SuFigura e che memorizza la posizione del centro della figura (oggetto di classe PointE) e realizza il solo metodo move.
Dalla classe Figura si derivino le classi Poligono e Cerchio. La classe Poligono memorizza il numero dei lati e i vertici, questi ultimi in un array di oggetti di classe PointE che esprimono le componenti cartesiane dei vettori che collegano il centro del poligono (un punto interno, mediano di una diagonale; si assuma il poligono convesso) e i vertici stessi; implementa inoltre tutti i metodi non ereditati (una versione semplificata show stampa su STDOUT le posizioni del centro e dei vertici) e il metodo perim che calcola il perimetro. La classe Cerchio memorizza il raggio del cerchio (il centro coincide con il centro geometrico) e implementa i metodi non ereditati (si noti che rot è in questo caso un'operazione nulla; una versione semplificata show stampa su STDOUT le posizioni del centro e il raggio) e i metodi perim che calcola il perimetro e area che calcola l'area.
Dalla classe Poligono si derivino le classi Rettangolo e Triangolo. La classe Rettangolo ridefinisce il metodo perim per tener conto dell'eguale lunghezza di due lati opposti, e implementa il metodo area. La classe Triangolo definisce il metodo area applicando la formula di Erone (area=sqrt(p*(p-a)*(p-b)*(p-c)) p semiperimetro).
Dalla classe Rettangolo si derivi la classe Quadrato che ridefinisce sia il metodo perim che area per tener conto della eguaglianza dei lati.
Si consideri la seguente interfaccia:
public interface FormattedOutput { public String out(String format); }Il metodo out restituisce in una stringa una rappresentazione formattata del valore (principale) contenuto nell'oggetto che implementa l'interfaccia. La stringa format descrive le modalità di composizione della stringa di output secondo una convenzione derivata da quella utilizzata dalla funzione printf del linguaggio C e precisamente:
simbolo | opzionale | significato |
---|---|---|
- | si | allineamento a sinistra |
numero | si | minimo numero di caratteri che forma
la stringa di output: se i caratteri significativi sono meno, vengono aggiunti spazi a destra o a sinistra a seconda dell'allineamento |
. [punto] | si | separa il numero precedente dal seguente |
numero | si | nel caso di una stringa, è
il massimo numero di caratteri da rappresentare in output; nel caso di un numero, la precisione (numero massimo di cifre per un intero, numero di decimali per un floating point) |
carattere di conversione | no | d intero decimale o intero ottale: la stringa di output ha uno 0 iniziale obbligatorio x intero esadecimale: la stringa di output ha un prefisso 0x obbligatorio c singolo carattere s stringa: o l'intera stringa oggetto oppure un suo prefisso lungo quanto la precisione, se specificata f float rappresentato come [-]mmm.nnnn ove i decimali sono in numero pari alla precisione (6 se non indicata); per i complessi il formato è valido per ciascuna delle due componenenti ovvero [-]mmm.nnnn±mmm.nnnnj e floating rappresentato come [-]m.nnnnnne[±]xx (decimali come sopra) |
Tenendo presente che le classi wrapper di Java non sono estendibili, definire, con i metodi strettamente necessari, le seguenti classi wrapper che implementano l'interfaccia FormattedOutput:
In ciascuna classe il metodo out deve sollevare un'eccezione se la stringa di formato è illegale.
Definire infine infine la classe Format che implementa il metodo statico:
public static String out(String formatStr, FormattedOutput[] values);che riceve nel parametro formatStr una stringa contenente sequenze di caratteri normali (compresi spazi) alternate a stringhe di formato precedute dal carattere speciale % (il carattere normale % viene rappresentato con %%). Ad esempio:
Definire un package Utility che include la classe
Wrapper che ha 2 tipi di metodi statici:
Object wrap(basictype val);
basictype unwrap(Object obj, basictype dummy);
ove basetype è uno dei tipi base (boolean, char, byte,
short, int, long, float, double).
I due tipi di metodi sono overloaded, con una
variante per ciascun tipo base.
Il metodo wrap
incapsula in un oggetto, di una adeguata
classe wrapper, il valore di tipo base
passato come parametro e restituisce l'oggetto come
valore di ritorno.
Un metodo unwrap estrae il valore
da un oggetto di classe wrapper, purché compatibile, e
lo restituisce come valore per quel particolare tipo base.
Se l'oggetto wrapper non è quello esattamente
corrispondente al tipo base, viene
tentata se possibile una conversione, altrimenti viene
sollevata l'eccezione java.lang.IllegalArgumentException.
Il parametro aggiuntivo dummy consente di definire
contratti diversi per le varianti overloaded.
Nel package Prove definire la classe ProvaWrapper
il cui metodo main, in un ciclo, acquisisce da stdin
un valore di uno dei tipi base, secondo la seguente convenzione:
tipo | esempi |
---|---|
boolean | false true |
char | 'c' '$' '\'' (l'apice) '\\' (la barra rovescia) |
byte | 12B |
short | -35S |
int | 24I 24 |
long | -31L 27l |
float | .5f -2.4F 0.056f |
double | -2.1D .5D |
Utilizzando la classe StreamTokenizer, nel ciclo viene identificato il tipo e successivamente chiamato il corrispondente metodo wrap con il valore acquisito, e l'oggetto tornato viene inserito in un oggetto di tipo java.util.Vector. Quando il vettore contiene 10 elementi, viene svuotato e i valori memorizzati vengono visualizzati, in ordine inverso a quello di inserimento, su stdout.
Estendere la classe BufferedReader per operare un filtraggio
su file in formato HTML atto ad eliminare i tag e i commenti, ovvero
tutte le sequenze del tipo:
<...<...<...>...>...> (bilanciate)
<!--...........-->
Es:
<H3>Testo 1<!--Testo 2<BR><P> Testo 3 --> Testo 4 Testo 5<BR>Testo 6viene trasformato in:
Testo 1 Testo 4 Testo 5Testo 6Prevedere un metodo main di collaudo.
Si realizzi la classe IntegerConvert che definisce 2 metodi statici:
public static void str2Int(Reader in, DataOutputStream out)
throws ....
public static void int2Str(DataInputStream in, Writer out);
throws ....
Il primo metodo riceve in input un testo costituito da numeri esadecimali
a massimo 8 cifre: le cifre sono rappresentate nello stream da
caratteri ASCII a 7 bit, 1 byte per carattere, in campi da 8 byte. Se un
numero è rappresentato da meno di 8 cifre, vengono aggiunti caratteri
spazio a destra del numero a completare il campo. Il valore rappresentato
va convertito in intero: a questo scopo si applichi la formula base della
notazione posizionale in forma fattorizzata,
che per un numero positivo (<= $7fffffff) è
data da:
a = a7*167 + a6*166 + ... +
a1*16 + a0 =
((...(a7*16 + a6) *16 + a5)*16 + ... +
a1)*16 + a0
che ripete l'operazione elementare:
(pi << 4) + ai
(ricavare un'analoga espressione per i numeri negativi).
I valori convertiti vanno salvati nello stream di output nella rappresentazione interna. L'altro metodo effettua l'operazione opposta. Scrivere un metodo main di collaudo che effettua letture e scritture su file.
Si realizzi la classe Rombo che memorizza in un array a 4 componenti le coordinate dei vertici di un rombo, rappresentate da oggetti di classe Point. La classe Rombo, oltre ad includere il costruttore di default che inizializza l'oggetto a rappresentare il quadrato di lato unitario, con un vertice nell'origine e 2 lati sui 2 semiassi cartesiani positivi, include un costruttore che riceve 4 oggetti Point che rappresentano i 4 vertici, e uno che riceve in una stringa il nome di un file e ricava le coordinate dei 4 vertici dal contenuto del file indicato. In quest'ultimo caso, la lettura dal file avviene utilizzando un oggetto di classe PointInputStream: questa classe estende la classe DataInputStream con costruttori analoghi a quest'ultima e con in più il metodo readPoint che restituisce un nuovo oggetto Point leggendone le due coordinate mediante i metodi della classe DataInputStream da cui eredita. La classe Rombo include inoltre il metodo toString, che ha l'usuale significato, e un metodo vertici che restituisce, come ObjectIterator, un oggetto di classe RomboEnum, definita come classe locale al metodo vertici. Tale oggetto realizza l'iterazione dei vertici del rombo cui è associato assumendo che l'oggetto che rappresenta quest'ultimo sia immutabile (una volta inizializzato non si può modificare ma solo leggere). Si aggiunga alla classe Rombo un metodo main di collaudo.
Realizzare una classe OrderedStrings che mantiene in un array un insieme di n stringhe prelevate da un file (una stringa per riga), ove si assumono già ordinate sulla base dei primi 3 caratteri della prima parola e dei primi 3 della seconda; l'ordinamento tra caratteri nella stessa posizione, e nei casi di non egual numero di caratteri coinvolti, è l'usuale (confronto lessicografico). Si preveda nella classe un metodo di ricerca di una stringa che utilizzi una ricerca binaria e un metodo main di collaudo. Per i confronti si pensi di implementare opportunamente l'interfaccia FI2.Util.Comparable.
Si realizzi con la classe Interp un semplice interprete di una macchina a stack. La macchina dispone di uno stack e di un insieme di NVAR variabili, entrambi per valori floating point in doppia precisione. Le primitive della macchina sono le seguenti:
pushi val | push del valore val |
pushv i | push del contenuto della variabile i (0..i..NVAR-1) |
popv i | pop dallo stack alla variabile i |
add | pop+pop -> push |
sub | -(pop-pop) -> push |
mul | pop*pop -> push |
div | 1/(pop/pop) -> push |
printv i | output su STDOUT del contenuto della variabile i |
prints | output su STDOUT del top dello stack (senza rimozione) |
exit | Uscita dall'interprete |
Implementare con la classe StringStack l'interfaccia Stack in modo da far uso di uno StringBuffer per memorizzare in forma LIFO elementi costituiti da singoli caratteri. Aggiungere nella classe implementata un metodo print che effettui su STDOUT un output 'significativo' dello stack (mettendo, in particolare, in evidenza il top dello stack). e un metodo di svuotamento dello stack. Realizzare inoltre un metodo statico String reverse(String s) che restituisce la versione speculare della stringa parametro, utilizzando un oggetto di classe StringStack. Aggiungere un metodo main di collaudo.
Si voglia realizzare un metodo di verifica ed evidenziazione del bilanciamento di
parentesi rotonde in un'espressione generica. A tale scopo si realizzi nella classe
CheckBalance il metodo ricorsivo:
public static void check()
che nel campo statico di classe expr riceve,
come stringa, l'espressione da esaminare, nel campo
startix la posizione nella riga da cui iniziare
la verifica, e che usa uno stack di interi.
Il metodo effettua un ciclo entro il quale, a partire
dalla posizione startix, ricerca la prima '('
non preceduta da ')': se la trova, salva la posizione
della parentesi aperta sullo stack, avanza
startix alla posizione che segue immediatamente
quella della parentesi e si richiama ricorsivamente; al ritorno,
effettua un pop dallo stack della posizione
salvata e, se startix 'punta' ad una parentesi chiusa,
stampa su STDOUT le posizioni relative alla coppia di parantesi
(per quella aperta, ricavata dallo stack, per quella
chiusa, da startix), avanza quindi di una posizione
startix e ricicla. Se dal ritorno della chiamata
ricorsiva startix è posizionato oltre la
fine della stringa, il metodo termina con una segnalazione
di errore di parentesi aperta non bilanciata. Dal ciclo
si esce se non vengono trovate altre parentesi aperte o
se si trova una parentesi chiusa prima di una aperta e la chiamata
non corrisponde al primo livello di ricorsione: in quest'ultimo
caso il metodo, prima di terminare,
avanza startix in modo da 'puntare' alla
parentesi chiusa. Se il livello di ricorsione è
il primo, il ciclo prosegue dopo una segnalazione
di parentesi chiusa non bilanciata e l'avanzamento
di una posizione di startix.
Il metodo:
public static void runCheck(String ex)
avvia il procedimento impostando la stringa-espressione
(ricevuta nel parametro ex) e il valore iniziale di
startix.
Aggiungere un metodo main
di collaudo che richieda da STDIN, una dopo l'altra,
le espressioni da verificare.
Si implementi l'interfaccia Queue con la classe TableQueue che
utilizza una particolare struttura di dati descritta nel seguito.
Si definisca la classe TbNode con 2 campi, un Object
che rappresenta l'elemento inserito nella struttura di dati, e un indice
(next) che rappresenta la posizione, in un array QTab
di TbNode, del nodo successore. L'array-tabella QTab
è composta da NELEM nodi ed è inizializzata in modo che
tutti i nodi, non associati ad elementi, siano collegati in forma
di stack a partire dal nodo di posizione 0. In ogni istante
la posizione del top dello stack è rappresentata
dal campo top in TableQueue. Con i nodi
prelevabili dallo stack viene costituita una coda in forma
concatenata, per la quale il campo head fornisce, in ogni
istante, la posizione del primo elemento e il campo tail
quella dell'ultimo. Se la coda è vuota entrambi i campi valgono
NULLPOS (pari a -1). L'inserimento di un elemento in coda
corrisponde ad estrarre un nodo dallo stack, associarlo
all'elemento e inserirlo in fondo alla coda, diventandone il nuovo
nodo terminale. L'estrazione corrisponde, se la coda non è
vuota, alla rimozione del nodo in testa alla coda e alla
sua restituzione allo stack dei nodi liberi. Aggiungere
un metodo main di collaudo.
Si implementi l'interfaccia Queue con la classe FileQueue che
realizza in forma circolare su file una coda di dimensioni massime prefissate
(MAXELEM). Ogni elemento della coda è rappresentato da un blocco di
256 byte. Il costruttore FileQueue(String name),
se il file name non esiste, lo crea e lo inizializza a coda vuota.
L'inserimento di un oggetto corrisponde all'inserimento nella coda sul file
di un byte che rappresenta una lunghezza (0..255),
seguito da una stringa di caratteri ASCII a 7 bit
che rappresenta la stringa ritornata dalla chiamata toString
applicata all'oggetto passato come parametro, troncata ai primi
255 caratteri se più lunga di tale quantità.
L'estrazione ritorna un oggetto stringa con il contenuto
dell'elemento (tenuto conto del valore di lunghezza associato).
Utilizzare la classe FileQueue per realizzare una forma
semplificata di spooling di file di testo su STDOUT. Si realizzi
a tale scopo una classe Sp con un metodo main che
inserisce in un FileQueue di nome prefissato il nome del
file da visualizzare, passato come parametro sulla linea di comando.
Si realizzi inoltre la classe Spool il cui metodo main
in un ciclo effettui l'estrazione dal FileQueue usato da Sp
di ciascuno dei singoli nomi di file presenti,
visualizzandone poi l'intero contenuto su STDOUT
attraverso le funzioni dell'oggetto FI2.Util.FI2Sys.
Nel ciclo è prevista una sospensione
per 20 s prima di visualizzare il successivo, finché la
coda si svuota, cosa che fa terminare il metodo main. Per l'attesa
si utilizzi il metodo Thread.currentThread.sleep(long milliseconds).
Si trascurino problemi di interferenza tra Sp e Spool,
assumendo che i loro metodi main non operino mai in concorrenza.
Applicando la tecnica dell'adattatore, utilizzare la classe LinkedQueue per realizzare la classe PointQueue che memorizza in una coda esclusivamente oggetti di tipo Point. Gli oggetti rappresentano i vertici di una spezzata sul piano: definire una classe Spezzata che, nel suo metodo main, riceve da STDIN le coordinate di una sequenza di punti, li memorizza temporaneamente in una coda di tipo PointQueue e, su sollecitazione dell'input, li estrae tutti e li copia in un array di dimensioni opportune, verificando se la spezzata ha almeno due segmenti che si intersecano e fornendo la risposta su STDOUT, prima di ricominciare l'acquisizione di una nuova sequenza di punti.
Si consideri la seguente classe:
public class ContainerHelper { public static final int SETEMPTYCOM = 0; public static final int SETDOUBLECOM = 1; // codici comandi di attivazione private ContainerActivator act; /**[c] * costruttore base * @param a attivatore da associare */ public ContainerHelper (ContainerActivator a) { act = a; } /**[m] * metodo di impostazione dell'attivatore * @param a attivatore da associare */ public void setActivator(ContainerActivator a) { act = a; } /**[m] * metodo di attivazione dell'attivatore * @param command indice del metodo da attivare * @return Container nuovo contenitore dopo l'operazione * attivata (coincide con il contenitore originario * se con approccio ad oggetti mutabili) */ public Container activate(int command) { switch(command) { case SETEMPTYCOM: return act.setEmpty(); case SETDOUBLECOM: return act.setDouble(); default: return null; } //switch } //[m] activate } //{c} ContainerHelperGli oggetti di classe ContainerHelper consentono di attivare in modo indiretto i metodi di oggetti che implementano la seguente interfaccia:
public interface ContainerActivator { /**[m][a] * svuotamento del contenitore * @return Container il contenitore stesso se * oggetto mutabile, un nuovo contenitore vuoto * se immutabile */ public Container setEmpty(); /**[m][a] * raddoppio degli elementi del contenitore - * i riferimenti di quelli presenti vengono * copiati se con approccio non mutabile * @return Container il contenitore stesso se * oggetto mutabile, un nuovo contenitore vuoto * se immutabile */ public Container setDouble(); } //{c} ContainerActivatorRealizzare la classe LisArrayStack che estende la classe FI2.Linear.ArrayStack in modo da implementare l'interfaccia FI2.Set.Container e includere un attivatore di classe ContainerHelper. Quest'ultimo viene inizializzato in fase di costruzione come unico oggetto di una classe anonima (definita quindi nel costruttore di LisArrayStack) che implementa opportunamente i metodi dell'interfaccia ContainerActivator. Nel realizzare l'implementazione di Container si tenga presente ai limiti posti dalla classe ArrayStack.
Si estenda la classe FI2.Linear.ArrayQueue al fine di implementare l'interfaccia Deque. Se necessario partire da una versione modificata ArrayQueueE più adatta ad una successiva estensione.
Con la tecnica dell'adattatore applicata alla classe FI2.Linear.ArrayQueue, definire la classe TempQueue dotata dei seguenti metodi (oltre ai costruttori):
Con la tecnica dell'esercizio 4.5 (TableQueue) realizzare un'implementazione di List: derivare il metodo di collaudo da quello di ArrayList con i minimi cambiamenti e collaudare la classe con bubble-sort.
Si voglia realizzare in forma concatenata una rappresentazione di un linguaggio
a liste innestabili (si pensi al LISP o al LOGO): l'input è costituito
da frasi in cui sono identificabili parole e numeri inseriti in parentesi
rotonde innestabili. Ad esempio:
aldo bruno (carlo ((dino 35 elmo) franco(giulio ()ileo) 12)) lucio
Ogni elemento nella frase è rappresentato da un nodo di una struttura
concatenata. Il nodo ha 2 riferimenti: una sottolista (subl)
e il nodo successore (succ). Se un elemento è atomico (parola
o numero) è rappresentato da un nodo in cui il riferimento subl
è nullo; se l'elemento è una parentesi aperta, il campo succ
riferisce il nodo che rappresenta l'elemento che segue, nella frase, la corrispondente
parentesi chiusa, mentre il campo subl riferisce il primo elemento
contenuto nella sottolista aperta dalla parentesi e che inizia una successione
di nodi che termina con il nodo che rappresenta la corrispondente parentesi
chiusa; se l'elemento è una parentesi chiusa, il campo succ,
come per un elemento atomico, riferisce il nodo seguente nella frase.
Per la frase sopra si avrebbe:
sistemare la figura +----+-+-+ +-----+-+-+ +--+-+-+ +-----+-+-+ |aldo|^| |-- >|bruno|^| |-- >|(1| | |-- >|lucio|^|^| +----+-+-+ +-----+-+-+ +--+-+-+ +-----+-+-+ | ^ +----------------------------+ | | | | +---------+ v | +-----+-+-+ +--+-+-+ +--+-+-+ |carlo|^| |-- >|(2| | |-- >|)1|^| | +-----+-+-+ +--+-+-+ +--+-+-+ | ^ +---------------+ | | +--------------------------+ v | +--+-+-+ +------+-+-+ +--+-+-+ +--+-+-+ +--+-+-+ |(3| | |-- >|franco|^| |-- >|(4| | |-- >|12|^| |-- >|)2|^| | +--+-+-+ +------+-+-+ +--+-+-+ +--+-+-+ +--+-+-+ | ^ | ^ | | | | | | | +-----------------------------------------------------+ +-+ | +-------------------+ | | +---------------------------+ | | v | v | +----+-+-+ +--+-+-+ +----+-+-+ +--+-+-+ +------+-+-+ +--+-+-+ +----+-+-+ +--+-+-+ |dino|^| |-- >|35|^| |-- >|elmo|^| |-- >|)3|^| | |giulio|^| |-- >|(5| | |-- >|ileo|^| |-- >|)4|^| | +----+-+-+ +--+-+-+ +----+-+-+ +--+-+-+ +------+-+-+ +--+-+-+ +----+-+-+ +--+-+-+ | ^ | | | +-------+ v | +--+-+-+ |)5|^| | +--+-+-+ (Nella figura le parentesi sono state corredate dal numero di livello)Definire la classe PLNode che rappresenta il nodo della lista e la classe ParList che rappresenta la struttura di dati 'lista con parentesi'. Prevendere in quest'ultima classe:
aldo bruno ----carlo -------- ------------dino 35 elmo --------franco ------------giulio ---------------- ------------ileo --------12 ---- lucio(Si tratta di un esercizio piuttosto elaborato ma istruttivo).
Estendere la classe ArrayList con la classe IAPS in modo che includa il metodo remElements che restituisce un oggetto di classe APSIter che implementa l'interfaccia java.util.Iterator di Java 1.2. È necessario apportare modifiche nella classe ArrayList per definire la classe APSIter come classe interna ad IAPS?
Adattare l'esempio di bubble-sort in modo da ordinare oggetti di classe java.awt.Color, che rappresenta un colore a 24 bit, sulla base della luminosità (brightness) del colore (si veda per questo la rappresentazione HSB del colore).
Realizzare un programma in grado di interpretare un testo che contiene comandi per la creazione di oggetti grafici in una finestra. La sintassi prevede che il testo d'ingresso, un comando per riga, possa includere i seguenti comandi:
Comando | Significato |
---|---|
B <stringa> | bottone con etichetta |
L <stringa> | label |
F <stringa> | text field con valore iniziale |
T <stringa> | text area con valore iniziale |
C <stringa> | checkbox con valore |
Realizzare un programma con un'interfaccia grafica dotata di 4 bottoni etichettati come 'cerchio', 'rettangolo', 'rombo', 'triangolo'. La pressione su uno dei bottoni aggiunge, in un'area grafica sottostante, un corrispondente oggetto geometrico in posizione e dimensioni casuali (in un range stabilito). Se si preme il mouse all'interno dell'area dell'oggetto geometrico, questo viene selezionato e deselezionato, e si può spostare con il mouse con un'azione di dragging. La memorizzazione dei descrittori degli oggetti geometrici deve avvenire in una Sequence.
(Suggerimenti: definire in un'interfaccia DrawMovable i metodi che gli oggetti grafici devono implementare (draw per il disegno, move per la traslazione, contains per verificare se un punto è all'interno di una figura. Ove possibile, usare la classe PointE. Inserire in una classe astratta SelFigure, che gli oggetti grafici estendono, la memorizzazione dello stato di 'selezionato'. Il metodo draw disegna, per ogni oggetto grafico, se stesso in un colore che dipende dalla selezione. Per il rombo e per il triangolo sfruttare le caratteristiche della classe Polygon di Java. L'area grafica è un (derivato di un) Canvas su cui sono registrati gli ascoltatori per il mouse. Il metodo paint chiama il metodo draw di tutti gli oggetti nella sequenza.)
Realizzare un oggetto LevelBar che rappresenta una barra di livello per un misuratore generico. Prevedere un metodo di aggiornamento del valore rappresentato che consenta di precisare anche una descrizione dell'unità di misura e il range dei valori ammessi, in modo che la barra faccia vedere il valore attuale anche mediante un numero di percentuale (rispetto al fondoscala).
Rappresentare con un albero binario lo split di finestre sullo schermo. A partire da una finestra che occupa tutto lo schermo, ogni finestra può essere suddivisa in due e le due finestre che si ottengono vanno ad occupare complessivamente l'area della finestra genitrice. Si veda in figura la corrispondenza tra un layout e il relativo albero.
+------------------+ |a-a1 | | | +---------+--------+ a (a1 a2 (b1 b2 (c1 c2))) |a2-b1 |b2-c1 | | | | | +--------+ | |c2 | | | | +---------+--------+Prevedere primitive di split, fuse (il contrario di split), di rappresentazione grafica (in scala) del layout delle finestre.
Utilizzando la tecnica figlio-fratello per la rappresentazione di alberi generici con alberi binari, costruire l'immagine di un directory, di pathname fornito come parametro, collocando come elementi dati dell'albero oggetti di classe java.io.File. Realizzare il metodo showDir che, fornito un nodo dell'albero che rappresenta un directory, visualizzi il listato del contenuto di quest'ultimo (come il comando DIR del DOS ma in modo semplificato).
Implementare l'interfaccia ExpandBinaryTree con il supporto di un array: i nodi dell'albero contengono 3 indici che rappresentano le posizioni dei nodi figli nell'array e quella del padre. L'array è inizializzato come uno stack (concatenato) di nodi liberi; ogni volta che un nuovo nodo viene inserito, viene prelevato dallo stack e ad esso restituito quando viene rimosso dall'albero.
Definire un'implementazione dell'interfaccia Comparator per confrontare oggetti di classe java.util.Date. Utilizzare questo comparatore per eseguire un selection sort di n valori di classe Date.
Realizzare uno scheduler temporale che riceve da stdin l'indicazione di un evento rappresentato da un istante temporale (espresso in qualche modo coerente) e una stringa descrittiva. Lo scheduler è costituito da due thread: uno riceve in un ciclo gli eventi da stdin e li inserisce in una CdP in ordine temporale crescente, l'altro thread in un ciclo valita a cadenza temporale fissa T se l'istante inferiore indicato nella CdP è scaduto e, in caso affermativo, lo estrae dalla coda e ne fornisce segnalazione su stdout.
La classe DescTable include un vettore (descs) di n oggetti di classe Desc, preallocati nel costruttore di base, e una coda a priorità inizialmente vuota. La classe Desc rappresenta un descrittore includente un intero di identificazione (pid), un intero che rappresenta una priorità (prio), e una variabile di stato (state) che può assumere uno dei valori UNDEFINED, CREATED, ACTIVATED, SUSPENDED, TOBEKILLED, KILLED. Nel vettore descs gli n descrittori vengono inizializzati con lo stato UNDEFINED e con pid pari all'indice del corrispondente elemento del vettore. La classe DescTable realizza i seguenti metodi:
public int create(int pr) throws FullException;
Cerca il primo descrittore libero (stato UNDEFINED o KILLED) e,
se lo trova, lo alloca (trasformando lo stato in CREATED), vi assegna
la priorità pr e ne restituisce il pid.
Se tutti i descrittori sono allocati, solleva l'eccezione indicata.
public void activate(int pid) throws InvalidArgumentException
Se lo stato del descrittore identificato da pid % n è CREATED o
SUSPENDED, inserisce il descrittore nella CdP usando la priorità in
modo da ordinare i descrittori per priorità decrescente; in caso
contrario solleva l'eccezione indicata.
public int suspend() throws EmptyException
Estrae il descrittore di massima priorità dalla CdP. Se il suo stato è
TOBEKILLED, lo trasforma in KILLED, incrementa del valore n il suo pid
e restituisce il valore NOPID = -1. Altrimenti (lo stato deve essere in questo caso
ACTIVATED), trasforma lo stato in SUSPENDED e restituisce il valore
del pid. Se invece la coda è vuota, solleva l'eccezione indicata.
public void kill(int pid) throws InvalidArgumentException
Se lo stato del descrittore identificato da pid % n è UNDEFINED o KILLED,
solleva l'eccezione indicata. Altrimenti se lo stato è ACTIVATED, estrae il
descrittore dalla CdP (ove è certamente presente, sebbene in generale non
con la massima priorità). Dopo questa estrazione oppure (senza estrazione)
se lo stato era CREATED, lo trasforma in KILLED e incrementa del valore n
il suo pid. Se lo stato era originariamente SUSPENDED, lo trasforma
in TOBEKILLED.
Si noti che l'incremento di pid fa in modo che lo stesso descrittore abbia pid distinti se viene osservato in due momenti diversi in entrambi i quali è nello stato CREATED , ACTIVATED o SUSPENDED ma avendo subito tra questi due istanti un kill e un nuovo create. Dal pid si può comunque ricavare l'indice dell'elemento nel vettore attraverso l'operazione di modulo (pid % n).
Aggiungere un metodo main di controllo che, allocata una tabella di classe DescTable di n=10 elementi, ne crea e attiva 6 e poi esegue 20 volte un ciclo con cadenza temporale prefissata: ad ogni ciclo decide a caso di useguire uno dei 4 metodi. Se viene eseguito un suspend, il pid restituito viene inserito in una coda FIFO; se viene eseguito un activate, il pid del descrittore da attivare viene estratto dalla testa della coda FIFO; se viene eseguito un kill, viene scelto un pid a caso tra i 6 attivati, gestendo l'eventuale eccezione.