PDA

View Full Version : [JAVA] soluzione per stack + gestione delle eccezzioni


Fenomeno85
25-03-2006, 12:32
Allora ho creato uno stack ... come sembra come soluzione??

/**
*Questa classe serve per gestire una lista di tipo LIFO
*/

public class StackLifo{
/* array dello stack */
private int []pila;
/* puntatore alla prima cella libera */
private int cellaLibera;
/* costruttore senza parametri */
public StackLifo () {
this (100);
}
/**
*Costruttore con parametri
*@param: dimensione dello stack
*/
public StackLifo (int dim) {
if (dim <= 0){
System.out.println ("La dimensione non e' corretta (dim > 0) . Viene assegnato il valore di 100");
dim = 100;
}
this.pila = new int [dim];
}
/**
*Il metodo push permette di inserire un valore nello stack.
*@param: valore intero
*/
public void push(int value) throws FullStackLifoException{
if (this.cellaLibera == this.pila.length){
throw new FullStackLifoException ();
}
System.out.println ("Inserito il valore: "+value);
this.pila[cellaLibera] = value;
this.cellaLibera ++;
}
/**
*Il metodo pop permette di estrarre un valore nello stack.
*/
public int push() throws EmptyStackLifoException{
if (this.cellaLibera == 0){
throw new EmptyStackLifoException ();
}
this.cellaLibera --;
return this.pila[cellaLibera];
}
}



/* Programma che utilizza uno stack */

public class GestioneLista {
public static void main (String[] arg){
StackLifo pila;
pila = new StackLifo(10);
/* inseriamo finche non saturiamo la lista */
for (int i=0; i<12; i++){
try{
pila.push(i);
}
catch (FullStackLifoException e){
System.out.println (e.toString());
}
}
/* svuotiamo finche non cerchiamo di estarre dalla lista vuota */
int x=0;
for (int i=0; i<12; i++){
try{
x = pila.pop();
System.out.println ("Estratto: "+x);
}
catch (EmptyStackLifoException e){
System.out.println (e.toString());
}
}

}
}



/**
*Questa eccezione è invocata quando la lista è vuota e si cerca di estarre dati
*/

public class EmptyStackLifoException extends Exception {
/* costruttore */
public EmptyStackLifoException (){
super ("Lista vuota");
}
/* override del metodo toString */
public String toString (){
return getMessage ();
}
}



/**
*Questa eccezione serve per gestire il caso che si cerchi di andare a scrivere
*fuori dallo stack
*/

public class FullStackLifoException extends Exception {
/* costruttore */
public FullStackLifoException (){
super ("Coda piena");
}
/* override del metodo to String */
public String toString (){
return getMessage();
}
}


Allora funziona funziona .. però dato che è il mio primo programma che gestisce anche le eccezzioni volevo sapere se l'approccio è corretto.
Alcune delucidazioni in merito...
ho fatto nella funziona push un lancio di eccezzione nel caso che si cerca di estarre dati ... fin qui ... tutto ok ... anche se io ho ancora in mente l'aspetto procedurale e quindi mi viene in mente sempre di controllare con gli if e non lanciare mai eccezzioni :( tralasciamo questo fatto ... allora ma dato che la funzione fa un ritorno di un valore intero ... come mai non mi dice nulla quando lancio questa eccezzione nel main??

Comunque è giusto questo approccio? cioè nei medoti della classe io lancio solo l'eccezzione e poi per propagazione la piglio nel main? :stordita:

~§~ Sempre E Solo Lei ~§~

andbin
25-03-2006, 13:47
Ma ... esiste già la classe java.util.Stack!! ;)

Comunque, a parte questo, la tua implementazione non mi sembra molto chiara!
Prima di tutto io lancerei una eccezione di tipo IllegalArgumentException (o un suo derivato) se si tenta di creare lo stack con una dimensione negativa. Mandare fuori qualcosa su System.out a quel livello non mi sembra una buona cosa.

Poi oltretutto hai invertito il significato di push e pop. push (dall'inglese: spingere) serve per inserire un elemento nello stack e pop serve per estrarre un elemento dallo stack, non il contrario!

Quando si crea una nuova eccezione normalmente è più che sufficiente implementare soltanto i due costruttori: quello senza argomenti e quello con argomento stringa:
public class MiaEccezione extends Exception {
public MiaEccezione() {
super();
}

public MiaEccezione(String s) {
super(s);
}
}

Fenomeno85
25-03-2006, 14:04
si che pirla che sono :D

provvedo a correggere :D


~§~ Sempre E Solo Lei ~§~

Mixmar
26-03-2006, 10:03
si che pirla che sono :D

provvedo a correggere :D


~§~ Sempre E Solo Lei ~§~

E comunque eccezione si scrive con una 'z' sola! :Prrr:

Fenomeno85
26-03-2006, 11:39
E comunque eccezione si scrive con una 'z' sola! :Prrr:

ok a parte questo :fiufiu: la metodologia è corretta?

poi altra cosa ... come faccio a lanciare l'eccezione sui valori passati?



~§~ Sempre E Solo Lei ~§~

anx721
26-03-2006, 12:26
L'approccio è corretto; non ho capito cos intendi con queste due domande:

1 - come faccio a lanciare l'eccezione sui valori passati?
2 - allora ma dato che la funzione fa un ritorno di un valore intero ... come mai non mi dice nulla quando lancio questa eccezzione nel main

Fenomeno85
26-03-2006, 18:01
L'approccio è corretto; non ho capito cos intendi con queste due domande:

1 - come faccio a lanciare l'eccezione sui valori passati?
2 - allora ma dato che la funzione fa un ritorno di un valore intero ... come mai non mi dice nulla quando lancio questa eccezzione nel main

1) praticamente facciamo che io ho

int ciapet (int val)

mi passano una stringa ... io come faccio a capire l'eccezzione?

che istruzioni devo mettere nella funzione?

2) allora l'istruzione era x = pila.pop ()

pop ritorno un intero ... però io lo faccio tornare solo se non viene chiamata l'eccezione ... mentre se c'è l'eccezione non faccio tornare nulla ... ma questo non produce nessun effetto su x o sbaglio??

3) tornando su quando alloco l'array ... te mi hai detto che non è corretto re-inizializzare con un valore che decido e far visualizzare un messaggio ... in quel caso la soluzione corretta quale sarebbe stata? ... ipotizziamo che mi ritrovo in situazioni del genere come mi devo comportare? ... richiedere il valore?

4) la cosa corretta sarebbe sempre controllare quando alloco e quindi mettere sempre tra try catch per queste istruzioni per vedere se non ho finito lo space? ... ipotizziamo che mi scatta l'eccezzione ... come mi comporto?? ritendo l'allocazione?? oppure chiudo e avviso che non è possibile allocare??

~§~ Sempre E Solo Lei ~§~

anx721
26-03-2006, 19:20
1) praticamente facciamo che io ho

int ciapet (int val)

mi passano una stringa ... io come faccio a capire l'eccezzione?

che intendi mi passaqno una stringa?!? i lmetodo prende un int e quindi da nessuna parte potrà essere invocato passando una stringa se no il compilatore ti striglia..non siamo mica in C...

che istruzioni devo mettere nella funzione?

2) allora l'istruzione era x = pila.pop ()

pop ritorno un intero ... però io lo faccio tornare solo se non viene chiamata l'eccezione ... mentre se c'è l'eccezione non faccio tornare nulla ... ma questo non produce nessun effetto su x o sbaglio??

Un'eccezione non viene ritornata ma provoca un'alterazione nel normale flusso del programma; quando viene lanciata il controllo del flusso passa al blocco catch corrispondente al primo blocco try che racchiude l'istruzione che ha causato l'eccezione, o provoca la terminazione del thread se tale blocco try non c'è.

3) tornando su quando alloco l'array ... te mi hai detto che non è corretto re-inizializzare con un valore che decido e far visualizzare un messaggio ... in quel caso la soluzione corretta quale sarebbe stata? ... ipotizziamo che mi ritrovo in situazioni del genere come mi devo comportare? ... richiedere il valore?

Non te l'ho detto io ma la cosa è corretta...non ha senso richiedere il valore: lo stack puo essere usato in un qualsiasi contesto: chi ti dice che c'è l'utente che digita sulla console per reimmettere il valore...semplciemente puoi non fare nulla: se ti si passa un valore negativo quando vai ad istanziare l'array con un valore negativo partirà un'eccezione in quanto non si puo istanziare un array con dimensione negativa e quindi sei a posto. Se vuoi lanciare una tua specifica eccezione controlli direttamente se il valore è negativoe in tal caso lancia una tua eccezione.

4) la cosa corretta sarebbe sempre controllare quando alloco e quindi mettere sempre tra try catch per queste istruzioni per vedere se non ho finito lo space? ... ipotizziamo che mi scatta l'eccezzione ... come mi comporto?? ritendo l'allocazione?? oppure chiudo e avviso che non è possibile allocare??

quando allochi cosa? Lo stack? Hai finito quale space? O intendi allocare un nuovo elemeno nello stack? Nel primo caso lo spazio finisce se è terminata la memoria della jvm e non puoi farci nulla... Nel secondo caso non è necessario il blocco try: basta che implementi un metodo full() che ritorna un booleano che ti dice se lo stack è pieno, e analogamente un metodo empty() che ti ritorna true se lo stack è vuoto. prima di un'operazione controlli se puoi eseguirla con tali metodi.


infine..prima ti ho detto che l'aproccio era corretto, ora rileggendo meglio mi accorgo che non lo è del tutto. Le eccezioni che lanci se lo stack è pieno o vuoto estendono Exception: questo ti costringe a mettere ogni operazione sullo stack all'interno di un blocco try in quanto per le eccezioni normali vale la regola catch or declare. Ma se rifletti ci sono tante istruzioni java che possono lanciare un'eccezione senza che ciò ti constringa a racchiuderle in un blocco try. Pensa ad esempio a quando invochi un metodo su un oggetto null: scatta la NullPointerException, eppure non sei obbligato a mettere ogni invocazione di metodo all'interno di un try. E gli esempi sono tanti, ad esempio se provi ad accedere oltri i limiti di un array o se richiedi ad un Vector di 10 elementi di avere il suo undicesimo elemento scatta la ArrayIndexOutOfBoundsexception. In tutti questi casi vengono lanciate eccezioni, ma non sono eccezioni che estendono Exception, ma una sua sottoclasse, ovvero RuntimeException: la regola catch or declare infatti afferma che tutte le istruzioni che lanciano eccezioni CHE NON SONO RuntimeException devono essere incluse in un blocco try oppure il metodo deve dichiare di lanciare tali eccezioni. Questo significa che se le tue eccezioni di stack pieno o vuoto estendono RuntimeException invece di Exception puoi invocare quei metodi sullo stack senza chiuderli in un blocco try.

Con un minimo di esperienza riesci a capire quando un'eccezione deve essere runtime e quando no: le runtime exception solitamente indicano errori di programmazione e non dovrebbero essere catturate per gestirle in quanto un errore di programmazione è giusto che provochi il crash di un programma. per questo non 'cè ll'obbligo di gestirle. Tali errori di programmazione sono sempre evitabili dal programmatore: nel tuo caso ti basta verificare che lo stack non sia pieno prima di aggiungervi un elemento per evitare l'eccezione. Analogamente il progrmamtore puo sempre fare in modo di non invocare metodi su un oggetto nullo, può sempre fare in modo di non istanziare array con numeri negativi, ecc...per questo non è necessario catturare queste eccezioni. Le eccezioni non runtime invece generalmente rappresentano situazioni di errore o anomale non sempre verificabili dal progrmmatore. Ad esempio la lettura di un file può sempre andare male indipendentemente da come il programmatore implementa la cosa, per questo è obbligatorio catturare e gestire le IOException perche non sono evitabili a priori.

Fenomeno85
27-03-2006, 07:46
grazie mille ;)

~§~ Sempre E Solo Lei ~§~