Paola Magillo, Univestita' di Genova,
Corso di Programmazione II per SMID, a.a. 2005-2006.
Lezione 12:
CASO DI STUDIO: GESTIONE DI UNA BIBLIOTECA - PARTE I
Vediamo un esempio che verra' poi usato nell'esame.
La biblioteca tiene traccia dei libri presenti e dei libri
dati in prestito.
Ogni libro ha associate le seguenti informazioni:
autore, titolo, numero di copie totali possedute dalla biblioteca,
numero di copie attualmente date in prestito
(dove il numero di copie date in prestito
ovviamente non puo' essere maggiore
del numero di copie possedute).
Internamente al sistema un libro ha anche un codice numerico
che serve come identificatore.
La biblioteca permette le seguenti operazioni:
-
dare in prestito una copia di un libro
-
ricevere in restituzione una copia prestata di un libro
-
acquisire un nuovo libro in un certo numero di copie
-
dismettere un libro dalla biblioteca
Nella lezione 13 la biblioteca avra' anche un'interfaccia grafica,
qui non ce ne occupiamo ancora.
Tutte le classi che costituiscono questo esempio
sono predisposte per essere documentate con Javadoc (vedere
lezione 11).
Scaricare tutti i file java nella directory corrente e poi digitare
"javadoc *.java", genera documentazione per tutte le classi,
il file da cui partire (con l'indice) e' poi quello di nome "index.html".
- classi per la biblioteca
- classi per leggere e scrivere la biblioteca su file
- classi per interfaccia grafica (nella prossima lezione)
Classi per la biblioteca
- Classe Libro: tiene le informazioni generali di un libro
(titolo, autore).
- Classe LibroInBiblioteca: sotto-classe di Libro,
aggiunge le informazioni relative alla presenza del libro
nella biblioteca (numero di copie totali, numero di
copie prestate).
- Classe Biblioteca: tiene un insieme di libri implementato
ad array, permette operazioni di prestito, restituzione,
acquisizione e dismissione di un libro.
Classe Libro
Sorgente
Rappresenta un libro indipendentemente dalla biblioteca.
Attributi pubblici: titolo (stringa), autore (stringa).
Metodi pubblici:
- Libro(String aut, String tit) -- costruttore,
prende in argomento le stringhe da usare come titolo e come autore.
Classe LibroInBiblioteca
Sorgente.
Sotto-classe di libro, rappresenta un libro nella biblioteca.
Attributi (non sono pubblici):
numero di copie totali presenti in biblioteca (intero),
numero di copie prestate (intero).
Metodi pubblici:
-
LibroInBiblioteca(String aut, String tit, int num) -- costruttore,
prende in argomento le stringhe da usare come titolo e come autore,
il numero di copie totali;
inizializza a zero il numero di copie prestate.
-
int copieTotali() -- restituisce quante copie sono possedute
dalla biblioteca.
-
int copiePrestate() -- restituisce quante copie sono state
prestate.
-
boolean prestaCopia() -- aumenta di 1 il numero di copie prestate,
se questo rimane minore o uguale al numero di copie totali,
e restituisce true; altrimenti non fa nulla e restituisce false.
-
boolean restituisciCopia() -- diminuisce di 1 il numero di
copie prestate, se questo rimane maggiore o uguale a zero,
e restituisce true; altrimenti non fa nulla e restituisce false.
Classe Biblioteca
Sorgente.
All'interno della biblioteca i libri sono tenuti in un array.
Al momento della creazione della biblioteca
questo array e' dimensionato a un certa capacita',
la quale e' il numero massimo di libri che la biblioteca
potra' contenere.
In generale la biblioteca conterra'
meno libri della sua capacita' (inizialmente nessuno).
I libri presenti occupano posizioni consecutive nell'array,
a partire dall'indice 0 fino all'indice N-1 (dove N = numero
di libri presenti).
Le posizioni non occupate (dalla posizione N in poi)
contengono l'oggetto nullo.
Quando viene acquisito un nuovo libro, questo viene inserito in
fondo alla parte di array attualmente usata, cioe' in posizione N
(dove N = numero di libri ESCLUSO il nuovo libro da inserire).
Quando viene dismesso un libro, la sua posizione nell'array
(sia K) resterebbe libera, creando un "buco" nella parte di array
occupata. Per evitare questo, il libro che occupa la posizione
N-1 (dove N = numero
di libri presenti INCLUSO il vecchio libro da cancellare)
viene spostato in posizione K.
La posizione da cancellare ora e' N-1, percio' liberandola non
si creano buchi nell'array.
Attributi (privati):
- LibroInBiblioteca libri[] = array dei libri
- int capacita = quanti libri puo' contenere la biblioteca
= numero totale di posizioni nell'array
- int numero = numero di libri presenti
= numero di posizioni nella parte di array occupata da libri
Tutti questi attributi sono privati per impedire
che vengano modificati in modo incontrollato.
Costruttori:
-
Biblioteca() -- crea biblioteca vuota, con capacita' 100 libri.
-
Biblioteca(int cap) -- crea biblioteca vuota, con capacita' assegnata;
se cap e' minore di 100 viene automaticamente portato a 100.
Metodi (pubblici) che leggono la situazione della biblioteca:
-
int laCapacita() -- fornisce il numero massimo di libri
(capacita' della biblioteca).
-
int numeroLibri() -- restituisce il numero di
libri presenti in biblioteca.
-
libroPerCodice(int cod) -- restituisce il libro che
si trova alla posizione cod nell'array,
se non esiste restituisce null.
Tutte le informazioni relative al libro si ottengono agendo sull'oggetto
restituito da libroPerCodice
(dopo aver controllato che non sia null):
Titolo e autore del libri si ottengono accedendo agli attributi
pubblici del libro.
Numero di copie del libro totali e prestate
si ottengono usando le funzioni della classe LibroInBiblioteca.
Metodi (pubblici) che modificano la situazione della biblioteca:
-
boolean cambiaCapacita(int cap) -- cambia la capacita' della
biblioteca, viene eseguito solo se la biblioteca e' ancora vuota;
ritorna true se ha successo e false altrimenti.
-
boolean nuovoLibro(String aut, String tit, int num) --
acquisisce un nuovo nella biblioteca, con titolo e autore e
numero di copie totali dati, se nell'array c'e' ancora posto,
e restituisce true; se invece
nell'array non c'e' piu' posto, non fa nulla e restituisce false.
-
void prestaLibro(int cod) -- presta una copia
del libro presente nell'array alla posizione cod,
solleva eccezione se il libro in quella posizione non esiste,
o se tutte le copie sono state gia' prestate.
-
void restitLibro(int cod) -- riceve in restituzione una
copia del libro di codice cod,
solleva eccezione se il libro in quella posizione non esiste,
o se nessuna copia e' stata prestata.
-
boolean dismettiLibro(int cod) -- dismette dal biblioteca
il libro presente nell'array alla posizione cod, se esiste,
e restituisce true;
se invece il libro non esiste, non fa nulla e restituisce false.
Nota: il libro viene dismesso anche se ha ancora copie prestate.
Lettura e scrittura della biblioteca
Scegliamo di definire noi una sintassi per la biblioteca
su file e le relative funzioni di lettura / scrittura.
Sintassi per la biblioteca
- parola chiave "BIBLIO"
- capacita' (intero)
- per ogni libro:
- parola chiave "AUT:"
- autore (stringa)
- parola chiave "TIT:"
- titolo (stringa)
- parola chiave "NUM:"
- numero totale di copie (intero)
- parola chiave "PST:"
- numero di copie attualmente prestare (intero)
I vari elementi sopra elencati sono separati da spazi o ritorni a capo.
Esempio di file biblioteca:
BIBLIO 100
AUT: Publio Virgilio Marone TIT: Eneide NUM: 1 PST: 1
AUT: Dante Alighieri TIT: La Commedia NUM: 2 PST: 0
AUT: Alessandro Manzoni TIT: I Promessi Sposi NUM: 3 PST: 2
AUT: Ludovico Ariosto TIT: Orlando Furioso NUM: 1 PST: 0
Classi per leggere e scrivere biblioteca
-
BiblioIO -- classe che contiene solo le parole chiave,
come costanti; viene usata dalle due classi seguenti.
sorgente.
-
BiblioWriter -- classe che scrive una biblioteca.
-
BiblioReader -- classe che legge una biblioteca, sotto-classe
di MyReader (ved. lezione 10).
BiblioWriter
sorgente.
Metodi pubblici (inclusi i costruttori):
-
BiblioWriter(String name) -- crea writer aprendo in scrittura
il file di nome dato.
-
BiblioWriter(PrintStream ffdd) -- crea writer sul
file gia' aperto in scrittura, da usare per esempio
passando lo standard output System.out
-
boolean writeBook(Biblioteca bib, int i) --
scrive il libro i-esimo dalla biblioteca data
-
void write(Biblioteca bib) -- scrive tutta la biblioteca
Il main di prova crea una biblioteca, vi mette dei libri e la
scrive sul file "pippo.txt".
BiblioReader
sorgente.
Metodi pubblici (inclusi i costruttori):
-
BiblioReader(String name) -- crea reader aprendo in lettura
il file di nome dato, puo' sollevare eccezione (es. se il
file non esiste).
-
BiblioReader(InputStream ffdd) -- crea reader sul
file gia' aperto in lettura, per esempio
lo standard input System.in
-
boolean readBook(Biblioteca bib) -- legge libro e lo aggiunge
alla biblioteca data, non solleva eccezioni ma ritorna
true solo se tutto ok, altrimenti false
-
int read(Biblioteca bib) -- legge l'intera la biblioteca
aggiungendo tutti i libri che trova nel file,
ritorna il numero di libri letti.
Il main di prova legge una biblioteca dal file "pippo.txt"
e la scrive per verifica su standard output.
Gestione della biblioteca con interfaccia NON grafica
Aggiungiamo alla classe Biblioteca un main che fa le seguenti cose:
-
Guarda quanti parametri ci sono sulla command line (basta
guardare args.length)
-
Se nessuno, crea biblioteca vuota.
-
Se almeno uno, lo usa come nome file da cui caricare la biblioteca.
-
Poi entra in un ciclo infinito (basta scrivere "while (true)") dove
ad ogni giro:
- scrive su standard output "Che cosa scegli (N,D,P,R,S,X):"
- chiede da standard input una stringa
- guarda la stringa immessa:
se "N" chiede dati per nuovo libro
se "D" chiede numero di libro da dismettere e poi lo dismette
se "P" chiede numero di libro da prestare e poi lo presta
se "R" chiede numero di libro da restituire e poi lo restituisce
se "S" salva biblioteca riscrivendola sul file iniziale
(se c'erano parametri su command-line),
oppure su "pippo.txt" (o altro nome fissato)
se "X" esce (chiamando "System.exit(0)")
Usare le classi BiblioReader e BiblioWriter viste
prima
per leggere e scrivere la biblioteca da e su file.
Usare la classe MyReader vista in
lezione 10
per leggere da standard input. Per semplicita' assumere che
autore e titolo siano una sola stringa senza spazi.