PDA

View Full Version : esercizio java videoteca


Blade86
10-07-2007, 18:25
Salve a tutti,sono nuovo e ho un grosso problema con un esercizio java :muro: !!!
Potreste aiutarmi a svolgerlo? L'esercizio è il seguente:

Una videoteca memorizza le informazioni sui titoli disponibili in un file denominato “films.info”. Il file è organizzato in blocchi di righe, uno per ogni film, delimitati dalle stringhe “***inizio***” e “***fine***”. Le prime tre righe contengono il titolo del film e l’anno di produzione. Seguono gli attori protagonisti, in numero variabile, e il regista, secondo il seguente schema:

***inizio***
Titolo Film
Anno Produzione
***attori***
Nome Attore 1
Cognome Attore 1
Nome Attore2
Cognome Attore2

Nome Attore n
Cognome Attore n
***regia***
Nome Regista
Cognome Regista
***fine***

Scrivere un programma che, ricevuti in ingresso Cognome e Nome di un attore e Cognome e Nome di un regista, stampi la lista dei film interpretati dall’attore e diretti dal regista (titolo e anno di produzione).
Vi ringrazio per la vostra attenzione.

PGI-Bis
10-07-2007, 19:32
Postresti iniziare creando una rappresentazione del file "films.info". Intendo per rappresentazione del file un oggetto (in Java una categoria di oggetti, cioè una classe) che faccia da ponte tra i dati contenuti nel file films.info e il resto del sistema. Potrebbe essere una cosa di questo pseudo-tipo:

classe FilmFile
+Collection<Film> getFilms();

Un Film potrebbe essere:

classe Film
+String getTitolo();
+String getAnnoProduzione();
+Regista getRegista();
+Collection<Attore> getAttori();

Un Attore sarebbe:

classe Attore
+String getNome();
+String getCognome();

ed un Regista:

classe Regista
+String getNome();
+String getCognome();


Il sistema potrebbe prevedere l'esistenza di un Archivista a cui deleghi il compito di cercare delle occorrenze in un elenco di film:

classe Archivista
+Collection<Film> cerca(Attore a, Collection<Film> films);
+Collection<Film> cerca(Regista r, Collection<Film> films);

Il programma sarebbe quindi una semplice unione delle definizioni degli oggetti su proposti:

classe Programma:
+void setFilmFile(FilmFile file);
+void setArchivista(Archivista v);
+void cerca(Regista r, Attore a);

Il metodo "cerca" di Programma userebbe l'Archivista sulla collezione di Film nota al FilmFile per ricavare e stampare a video l'elenco di film diretti da r e interpretati da a.

Naturalmente è solo uno dei possibili modelli.

Blade86
10-07-2007, 20:24
ok. Ma se vorrei caricare it tutto in un ArrayList tramite i private final String MARCATORE_ .......... = "***.........***; come dovrei fare? e per fare il confronto fra Nome e Cognome attore, e Nome e Cognome regista?

PGI-Bis
10-07-2007, 20:48
Una volta che hai un modello che ti dica chi fa cosa, puoi passare ad esaminare il come.

Nel nostro caso, la domanda "e se volessi riempire un ArrayList tramite i marcatori eccetera eccetera", attiene a come faccia FilmFile a restituire la sua collezione di Film.

Altrimenti detto, FilmFile possiede un metodo getFilms() che restituisce un insieme di riferimenti Film ma come fa concretamente a restituire questi Film? Da dove li prende? E come li prende?

Bene. Come potrebbe funzionare il metodo getFilms() di FilmFile. FilmFile potrebbe avere un costruttore che prende come argomento un File. Quel File sarebbe il percorso del file "film.info". Il costruttore di FilmFile passerebbe poi ad analizzare il testo contenuto in quel file. Nota la forma in cui i singoli film, attori e registi sono conservati nel file (e qui possono entrare in gioco i tuoi marcatori di tipo Stringa), FilmFile creerebbe tanti oggetti Film quanti ne esistono nel file passatogli. Questi oggetti potrebbero essere immagazzinati in un ArrayList di Film. E il metodo getFilms() restituirebbe questo ArrayList (ArrayList è un Collection).

La questione del confronto è ancora un "come". Stavolta è "come fa Archivista a trovare tutti i Film che contengono un certo Attore" (metodo cerca(Attore, Collection<Film>)) e "come fa Archivista a trovare tutti i Film che contengono un certo Regista" (metodo cerca(Regista, Collection<Film>)).

La ricerca di un Attore nel metodo cerca(Attore attore, Collection<Film> films) di Archivista potrebbe essere semplicemente:

crea una lista di Film L inizialmente vuota
per ogni Film F nell'insieme films
-per ogni Attore A nell'insieme di attori di F
--se l'attore A coincide con l'attore cercato
---inserisci il film F nella lista L
---passa al prossimo film nell'insieme films
L contiene tutti i film recitati da attore, restituisci L

Idem per il regista.

Quando sarà il momento di cercare i Film di un certo attore, Programma prenderà la collezione di Film posseduta da FilmFile e la passerà al metodo cerca di Archivista insieme all'attore bersaglio. Archivista restituirà l'insieme di Film contenenti quell'attore. Lo stesso vale per il regista. La ricerca combinata attore+regista sarà fatta ottenendo da Archivista l'elenco di film in cui compare il regista e cercando poi in quell'elenco di film i film in cui compaia l'attore desiderato. Non è il modo più efficiente ma è sintetico.

Ti tornano i conti fin qui?

Blade86
10-07-2007, 21:33
si ok. Infatti avevo pensato una cosa del genere, però quando sono andato a caricare gli attori tramite i marcatori nell'ArrayList non me li dà, non potresti dirmi come si fà, io c'ho provato ma non và! in effetti il mio problema è forse quando carico faccio qualche errore. grazie

PGI-Bis
11-07-2007, 17:08
In che senso "come si fa"? :)

Si fa leggendo il file una linea per volta. Oppure lo leggi a blocchi. Prendi uno Scanner, ha un metodo hasNextLine che dice se il file contiene un'altra linea di testo e un metodo nextLine() che ti restituisce la linea di testo successiva.

Il formato è bizzarro ma non è particolarmente complicato.

la prima linea la scarti
la seconda è il titolo
la terza è l'anno di produzione
la quarta la scarti
finchè la linea non vale ***regia***
-la prima è il nome di un attore
-la seconda è il cognome di un attore
questa linea è il nome del regista
questa linea è il cognome del regista
questa linea è ***fine***

Applichi il procedimento finchè ci sono linee e sei a posto.

Blade86
12-07-2007, 09:40
private final String MARCATORE_ATTORI = "***attori***";
private final String MARCATORE_REGIA = "***regia***";



public void leggi(String file) throws Exception{
Scanner in = new Scanner(new FileReader(file));
Attori b = Attori.read(in);
while (b!=null){


if(in.hasNextLine() && in.nextLine().equals(MARCATORE_ATTORI)) {
while(in.hasNextLine()) {
String linea = in.nextLine();
if(linea.equals(MARCATORE_REGIA)) {
break;
} else {b.aggiungiattori(linea);


}

}
}
s.add(b);
}

il codice l'ho fatto così ma nn và!

PGI-Bis
12-07-2007, 11:36
Non va è un po' generico. Genera un'eccezione, non legge correttamente gli attori, li legge ma scarta il regista... tutto è possibile.

Supponendo che Attori.read(Scanner) sia una cosa di questo tipo:

return new Attore(scanner.nextLine(), scanner.nextLine());

mi suona strano il primo:

Attori b = Attori.read(in);

così come il

while(b != null)

L'if lo darei per buono. Se c'è un'altra linea e quella linea vale ***attori*** allora:

prendi una linea.
se la linea vale ***regia*** esci dal ciclo

l'else dovrebbe essere invece:

String nome = linea;
String cognome = in.nextLine();
s.add(new Attore(nome, cognome));

Blade86
12-07-2007, 13:11
Il fatto è : ho un ArrayList<Attore> attori e vorrei caricare la lista degli attori delimitati dai marcatori ***attori*** e ***regia*** nell'ArrayList e poi fare il confronto analizzando quello che c'è nell'ArrayList tramite il for generalizzato. Non è ke potresti postare questa parte del codice grazie!

PGI-Bis
12-07-2007, 13:32
Io posso anche incollarti il codice ma è difficile integrare una soluzione che è frutto di una visione estranea del problema. Ad esempio si potrebbe fare così:

package attoregisti;

import java.util.Collection;
import java.util.LinkedList;

public class FilmData {
private Regista regista;
private String titolo;
private String annoProduzione;
private LinkedList<Attore> attori = new LinkedList<Attore>();

public boolean validate() {
return regista != null && titolo != null && annoProduzione != null &&
attori.size() > 0;
}

public void addAttore(Attore a) {
attori.add(a);
}

public Collection<Attore> getAttori() {
return attori;
}

public Regista getRegista() {
return regista;
}

public void setRegista(Regista regista) {
this.regista = regista;
}

public String getTitolo() {
return titolo;
}

public void setTitolo(String titolo) {
this.titolo = titolo;
}

public String getAnnoProduzione() {
return annoProduzione;
}

public void setAnnoProduzione(String annoProduzione) {
this.annoProduzione = annoProduzione;
}


}

package attoregisti;

import java.io.*;
import java.util.*;

public class FilmFile {
private LinkedList<Film> films = new LinkedList<Film>();

public FilmFile(File file) throws IOException {
Scanner in = null;
try {
FilmData data = new FilmData();
in = new Scanner(file);
while(in.hasNextLine()) {
in.nextLine(); //***inizio***
data.setTitolo(in.nextLine());
data.setAnnoProduzione(in.nextLine());
String line = in.nextLine();
while(!(line = in.nextLine()).equals("***regia***")) {
String nomeAttore = line;
String cognomeAttore = in.nextLine();
data.addAttore(new Attore(nomeAttore, cognomeAttore));
}
data.setRegista(new Regista(in.nextLine(), in.nextLine()));
in.nextLine(); //***fine***
films.add(new Film(data));
data = new FilmData();
}
} finally {
if(in != null) {
in.close();
}
}
}

public Collection<Film> getFilms() {
return films;
}
}

Una versione più rispondente al formato intuibile, che consideri cioè la divisione del file in blocchi e gestisca eventuali malformazioni, sarebbe:

package attoregisti;

import java.util.LinkedList;

public class LineBuffer {
private int cursor = 0;
private LinkedList<String> lines = new LinkedList<String>();

public void append(String line) {
lines.add(line);
}

public void clear() {
cursor = 0;
lines.clear();
}

public String peekNext() {
return lines.get(cursor);
}

public String next() {
return lines.get(cursor++);
}

public void skip(int count) {
cursor += count;
}

public int remaining() {
return lines.size() - cursor + 1;
}

public boolean hasRemaining(int count) {
return cursor + count <= lines.size();
}

public boolean hasNext() {
return cursor < lines.size();
}

public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("[chunk start]\n");
for(String line : lines) {
buffer.append(line).append("\n");
}
buffer.append("[chunk end]");
return buffer.toString();
}
}

package attoregisti;

import java.util.Scanner;

public class FilmParser {

public FilmData parse(LineBuffer data) throws IllegalFormatException {
FilmData filmData = new FilmData();

if(!data.hasRemaining(2)) {
throw new IllegalFormatException(data, "not enough lines for header");
}

filmData.setTitolo(data.next());
filmData.setAnnoProduzione(data.next());

if(data.hasNext() && data.peekNext().equals("***attori***")) {
data.skip(1); //skip actors section identifier
while(data.hasNext() && !data.peekNext().equals("***regia***")) {
if(data.hasRemaining(2)) {
filmData.addAttore(new Attore(data.next(), data.next()));
} else {
throw new IllegalFormatException(data, "not enough lines for actor");
}
}
}

if(data.peekNext().equals("***regia***")) {
data.skip(1); //skip director section identifier
if(data.hasRemaining(2)) {
filmData.setRegista(new Regista(data.next(), data.next()));
} else {
throw new IllegalFormatException(data, "not enough lines for director");
}
}

if(filmData.validate()) {
return filmData;
} else {
throw new IllegalFormatException(data, "data is not a valid film chunk");
}
}
}

package attoregisti;

public class IllegalFormatException extends Exception {
private LineBuffer chunk;

public IllegalFormatException(LineBuffer chunk, String message) {
super(message);
this.chunk = chunk;
}

public String toString() {
return getMessage() + "\n" + chunk;
}
}

package attoregisti;

import java.io.*;
import java.util.*;

public class FilmFile {
private LinkedList<Film> films = new LinkedList<Film>();

public FilmFile(File file) throws IOException {
final String INIZIO = "***inizio***";
final String FINE = "***fine***";
Scanner in = null;
try {
in = new Scanner(file);
FilmParser parser = new FilmParser();
LineBuffer buffer = new LineBuffer();
while(in.hasNextLine()) {
String line = in.nextLine();
if(line.equals(INIZIO)) {
buffer = new LineBuffer();
} else if(line.equals(FINE)) {
try {
films.add(new Film(parser.parse(buffer)));
} catch(IllegalFormatException ex) {
ex.printStackTrace();
}
buffer.clear();
} else {
buffer.append(line);
}
}
} finally {
if(in != null) {
in.close();
}
}
}

public Collection<Film> getFilms() {
return films;
}
}

Ma non so quanto possa esserti utile averlo detto.

Blade86
12-07-2007, 14:22
non ti preoccupare adesso ho capito di + , ti ringrazio e alla prossima.