PDA

View Full Version : [Java] convertitore che non converte


ZuMBi
06-02-2007, 22:23
premetto, non conosco java.
per forza di cose però mi vedo costretto a scrivere un programma. :muro:
ecco quello che sono riuscito a mettere insieme fino ad ora.
il problema principale è che non ho idea di come gestire la parte relativa alla conversione.
se qualcuno potesse aiutarmi a completarlo gliene sarei davvero grato.
sottolineo che sono alla ricerca della massima semplicità, niente di troppo "avanzato".

nin
10-02-2007, 23:55
Un up per un amico che aiuterei volentieri se potessi :)

Apix_1024
11-02-2007, 00:05
up per due compaesani in mezzo a tutti questi utenti!!! :D :D

PGI-Bis
11-02-2007, 01:13
Puoi creare una classe tipo:

public class ConvertitoreUnità {
private final double FATTORE_DI_CONVERSIONE;

public ConvertitoreUnità(double fattoreDiConversione) {
FATTORE_DI_CONVERSIONE = fattoreDiConversione;
}

public double converti(double valore) {
return valore * FATTORE_DI_CONVERSIONE;
}

public double inverti(double valore) {
return valore / FATTORE_DI_CONVERSIONE;
}
}

Poi crei tre convertitori: pascalPascal, pascalBar, pascalMMHG. Li associ nella mappa a tre chiavi, "Pascal", "Bar" e "MMHG". Facciamo finta che questi siano i valore contenuti nel modello delle JComboBox. Dato il valore "i" del campo di testo in formato numerico, applichi prima l'inversa per ottenere la conversione ad una misura comune (Pascal):

Convertitore c = mappaConvertitore.get(startC.getSelectedValue());
double valoreIntermedio = c.inverit(i);

Poi prendi il convertitore associato al valore corrente della seconda JComboBox:

Convertitore c = mappaConvertitore.get(endC.getSelectedValue());

e applichi la conversione da Pascal a quello che deve essere:

double valoreConvertito = c.converti(valoreIntermedio);

Probabilmente è meglio se usi dei BigDecimal, così eviti valori strambi.

ZuMBi
11-02-2007, 18:50
scusa la mia ingoranza ma...

1 - cosa intendi per mappa?
2 - la classe dove la devo inserire? in una altro file, nello stesso file (ma dove!?)
3 - in che senso creare tre convertitori?

ovviamente grazie per la risposta.

PGI-Bis
11-02-2007, 19:19
Per creare tre convertitori intendo:

ConvertitoreUnità pascalPascal = new ConvertitoreUnità(1);
ConvertitoreUnità pascalBar = new ConvertitoreUnità(0.0001);
ConvertitoreUnità pascalMMHG = new ConvertitoreUnità(0.0075);

Per mappa l'omonima struttura dati. Ad esempio:

Map<String, ConvertitoreUnità> mappaConvertitoriPressione =
new HashMap<String, ConvertitoreUnità>();

Dichiara questa mappa come campo private della classe "convertitore"

Nella mappa metti i tre riferimenti ai converititori di pressione suddetti. Per la chiave puoi usare gli stessi valori che userai per le caselle combinate (JComboBox della pressione). Ad esempio:

mappaConvertitoriPressione.put("Pascal (Pa)", pascalPascal);
mappaConvertitoriPressione.put("Bar", pascalBar);
mappaConvertitoriPressione.put("Millimetri di mercurio (mmHg)", pascalMMHG);

Metti la creazione dei tre converitori e la loro associazione nella mappa dei convertitori di pressione nel costruttore di "convertitore".

Nel metodo actionPerformed, nel blocco if che corrisponde alla richiesta di conversione della pressione (if(source == convert)) devi:

1. determinare se è richiesta una conversione della pressione.

Puoi farlo guardando se il modello delle caselle combinate è quello della pressione

2. Ottenere il convertitore corrispondente al valore immesso nella prima casella combinata:

ConvertitoreUnità conv = mappaConvertitoriUnità.get((String)startc.getSelectedItem());

3. invertire il valore numerico presente nel campo di testo dove l'utente scrive

String textValue = valuet.getText();
double value = Double.parseDouble(textValue);
value = conv.inverti(value);

3. Ottenere il convertitore corrispondente al valore immesso nella seconda casella combinata

conv = mappaConvertitoriUnità.get((String)endc.getSelectedItem());

4. convertire il valore numerico precedente:

value = conv.converti(value);

A questo punto value sarà il valore convertito dalla prima unità di misura alla seconda (teoricamente :D).


La classe ConvertitoreUnità la scrivi un file sorgente a sè stante, nella stessa cartella di "convertitore.java".

ZuMBi
11-02-2007, 19:24
ci lavoro un po' e vediamo cosa viene fuori.
grazie ancora per la disponibilità.

ZuMBi
11-02-2007, 19:59
Dichiara questa mappa come campo private della classe "convertitore"
dubbi su questo punto.
nel senso che non so come fare la dichiarazione.
abbi pazienza...;)

PGI-Bis
11-02-2007, 20:20
Nessun problema.

"campo" sta per variabile immediatamente dichiarata nel corpo della classe. Il corpo di una classe è quella parte del file sorgente che inizia subito dopo la prima parentesi graffa e termina subito prima della corrispondente parentesi graffia di chiusura. Ad esempio:

public class convertitore {//qui inizia il corpo
//qui è sempre corpo della classe

public convertitore() {//qui inizia il corpo del costruttore

/*qui finisce il corpo del costruttore*/}

//qui siamo ancora nel corpo della classe
/*qui finisce il corpo della classe*/}

Tutto quello che è scritto nella classe sta nel suo corpo, compreso il corpo del costruttore dunque tutto quanto è dichiarato nel corpo della classe. Non tutto è immediatamente dichiarato nel corpo. Ad esempio in:

public class convertitore {
private int campo = 10;

public convertitore() {
int variabileLocale = 25;
}
}

le dichiarazioni di variabile "int campo" e "int variabileLocale" sono entrambe contenute nel corpo della classe convertitore ma il contenimento della dichiarazione di variabile "variabileLocale" è mediato dal corpo del costruttore mentre il contenimento della dichiarazione di variabile "campo" è immediato cioè tra la dichiarazione di questa variabile e il corpo della classe non c'è un corpo intermedio.

L'immediatezza del contenimento di una dichiarazione di variabile rispetto al corpo della classe in cui è dichiarata è ciò che distingue un campo da una variabile locale.

Così quando dico "dichiara questa mappa come campo privato della classe convertitore" (più propriamente avrei dovuto dire come campo privato delle istanze della classe convertitore) intendo scrivi la dichiarazione di variabile:

private Map<String, ConvertitoreUnità> mappaConvertitoriUnità = eccetera

in modo che sia immediatamente contenuta nel corpo della classe convertitore. Convenzionalmente, come hai già fatto, le dichiarazioni di campo sono scritte subito dopo la parentesi di apertura del corpo della classe in cui intervengono.

ZuMBi
11-02-2007, 21:19
non riesco bene ad afferrare la funzione della nuova classe ConvertitoreUnita.
a questa classe viene delegato il compito di svolgere la conversione?
però non capisco che cosa devo metterci dentro.
purtroppo mi manca la logica stessa del java... :(

PGI-Bis
11-02-2007, 22:28
A scanso di equivoci, non hai un problema con il linguaggio. Nè hai un problema con la prospettiva orientata agli oggetti. Hai un problema... con me :D.

Non voglio trascinarti in un dibattito per cui la faccio breve. Ogni programma orientato agli oggetti è la traduzione della soluzione "umana" di un problema. La ragione per cui ConvertitoreUnità ti pare un alieno nel sistema è che la sua necessità sorge perchè io ho risolto il problema della conversione in un certo modo e la rappresentazione di questa mia soluzione richiede, appunto, che esista questo tipo di oggetti.

Essendo la mia soluzione, e non la tua, e non avendo discusso di come ho risolto il problema, mi pare assolutamente normale che ConvertitoreUnità ti sembri utile quanto una terza natica (che poeta, eh!? :D).

ConvertitoreUnità fa esattamente quello che hai notato: converte un valore da un'unità di misura ad un'altra e viceversa.

L'idea è che se ho tre unità di misura e ne scelgo una (pascal) come unità che tutti quanti i convertitori conoscono (cioè tutti sanno convertire da X a Pascal e da Pascal a X) allora anzichè avere bisogno di NxN convertitori che trasformano un valore da X a Y mi bastano N convertitori da X a Pascal. La conversione tra due unità di misura X e Y viene fatta applicando il convertitore da X a Pascal e poi applicando il convertitore da Pascal a X.

Se ogni converitore è in grado di cambiare l'unità di misura da X a Pascal e da Pascal a X (inverti e converti nella classe che ho proposto) e supponendo che per ogni ConvertitoreUnità:

1. "converti(valore)" trasformi un valore da Pascal alla specifica unità di misura del concreto ConverititoreUnità (Pascal, Bar, MMHg)
2. "inverti(valore)" trasformi un valore espresso nella specifica unità di misura del concreto ConvertitoreUnità (Pascal, Bar, MMHg) in Pascal

allora il problema converti un valore di pressione da un'unità di misura X ad un'unità di misura Y si risolve in:

1. prendo il convertitore che sa come trasformare i Pascal in X e viceversa
2. gli chiedo di convertire il valore espresso in X in Pascal (inverti)
3. prendo il convertitore che sa come trasformare i Pascal in Y e viceversa
4. gli chiedo di convertire il valore espresso in Pascal in Y

L'altro pezzo del problema è la classe che tu hai chiamato convertitore e che io vedo come l'oggetto che si occupa di raccogliere i dati ed eseguire la conversione. E' lui che la esegue: i vari ConvertitoreUnità hanno una capacità astratta di convertire ma concretamente non cambiano un bel niente. E' "convertitore" che passa da un valore ad un altro usando uno dei vari ConvertitoreUnità. E questo è quello che fa.

"convertitore" piglia un valore numerico V e due unità di misura X e Y. Deve trasformare il valore dalla prima (X) alla seconda (Y) unità di misura. Per farlo:

1. prende il convertitore corrispondente all'unità di misura X
2. gli passa il valore V chiedendogli di convertirlo in Pascal e ottenendo il valore VPa
3. prende il convertitore corrispondente all'unità di misura Y
4. gli passa il valore VPa chiedendogli di convertirlo in Y ottenendo Vy
5. presenta all'utente Vy

Il problema è, ribadisco, di condivisione della rappresentazione del problema risolto.

ZuMBi
12-02-2007, 22:40
a cosa possono essere dovuti questi errori?
G:\Documenti\programma esame borromei\convertitore.java:44: ';' expected
private mappa Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita> ();
^
G:\Documenti\programma esame borromei\convertitore.java:44: <identifier> expected
private mappa Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita> ();
^
G:\Documenti\programma esame borromei\convertitore.java:44: '(' expected
private mappa Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita> ();
^
G:\Documenti\programma esame borromei\convertitore.java:44: <identifier> expected
private mappa Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita> ();

PGI-Bis
12-02-2007, 22:50
tra private e Map<String, ... c'è una parola di troppo. Non:

private mappa Map<String, eccetera

ma

private Map<String, eccetera

nin
12-02-2007, 23:03
Perdonatemi..
up per due compaesani in mezzo a tutti questi utenti!!! :D :D

Eilà, conosco solo un fidentino che possiede un opteron e in effetti è un pazzo :D

Ciao Ariz :)

ZuMBi
12-02-2007, 23:05
permane questo...G:\Documenti\programma esame borromei\convertitore.java:44: <identifier> expected
private Map<String, ConvertitoreUnita>
ho scritto così:private Map<String, ConvertitoreUnita>

{

mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();

}

PGI-Bis
12-02-2007, 23:19
Le parentesi graffe non ci vanno.

private Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();

ZuMBi
12-02-2007, 23:36
se tolgo le parentesi persistono questi errori:G:\Documenti\programma esame borromei\convertitore.java:44: cannot find symbol
symbol : class Map
location: class convertitore
private Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();
^
G:\Documenti\programma esame borromei\convertitore.java:44: cannot find symbol
symbol : class HashMap
location: class convertitore
private Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();altra cosa...
quando dici di creare e associare i convertitori nella mappa intendi fare questo?private Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();

{
ConvertitoreUnita pascalPascal = new ConvertitoreUnita(1);
ConvertitoreUnita pascalBar = new ConvertitoreUnita(0.0001);
ConvertitoreUnita pascalMMHG = new ConvertitoreUnita(0.0075);
}

PGI-Bis
13-02-2007, 01:00
All'inizio del file sorgente, dopo la dichiarazione di package (se c'è, nel nostro caso non c'è) scrivi, in una linea a sè:

import java.util.*;

Questa dichiarazione farà sì che il compilatore, che ora ti dice che non riesce a capire cosa significhi "Map" riesca a risolvere quel nome riferendolo a java.util.Map.

Nell'ultima porzione di codice che hai incollato crei i tre convertitori. Manca l'associazione tra ognugno di quei converitori ed una chiave (una String) di identificazione nella mappa.

private Map<String, ConvertitoreUnita> mappaConvertitoriPressione = new HashMap<String, ConvertitoreUnita>();

{
ConvertitoreUnita pascalPascal = new ConvertitoreUnita(1);
ConvertitoreUnita pascalBar = new ConvertitoreUnita(0.0001);
ConvertitoreUnita pascalMMHG = new ConvertitoreUnita(0.0075);
mappaConvertitoriPressione.put("Pascal (Pa)", pascalPascal);
mappaConvertitoriPressione.put("Bar (ba)", pascalBar);
mappaConvertitoriPressione.put("Millimetri di mercurio (mmHg)", pascalMMHG);
}

ZuMBi
13-02-2007, 09:57
come non detto, avevo messo l'associazione dove non andava fatto.
adesso funziona tutto alla grande.
non so come ringraziarti.
ovviamente però ho alcune altre domandine da farti, non volermene ;)
in pratica quando vado ad inserire un valore che non sia numerico appare il messaggio d'errore.
il messaggio però rimane anche quando, successivamente, viene inserito un valore corretto; hai un'idea di come potrei fare per farlo scomparire?

PGI-Bis
13-02-2007, 12:57
Devi affinare il campo di testo che usi per inserire il valore numerico in modo tale da impedire la ricezione di valori non trasformabili in numeri.

Puoi usare un JFormattedTextField. Dove ora dichiari:

valuet = new JTextField();

cambi in:

valuet = new JTextField(new Float(0));

JFormattedTextField opera una convalida un po' primitiva dal punto di vista dell'interazione ma dovrebbe risolvere il problema "voglio che valuet.getText() restituisca una stringa che sia sempre trasformabile in float".

ZuMBi
14-02-2007, 00:16
un commentino ultra sintetico a questa rigaConvertitoreUnita conv = mappaConvertitoriPressione.get((String)startc.getSelectedItem());

PGI-Bis
14-02-2007, 12:05
Sempre nel caso della pressione, nella casella combinata startc hai una serie di stringhe che corrispondono alle chiavi dei convertitori di pressione nella mappa. La chiave è il valore che usi per recuperare qualcosa che immagazzini nella mappa (con mappa.put(chiave, valore)).

Nella casella combinata hai le stringhe:

"Pascal (Pa)"
"Millimetri di mercurio (mmHg)"
"Bar (ba)"

Avendo usato le stesse stringhe per i convertitori di pressione nella mappa:

mappaConvertitoriPressione.put("Pascal (Pa)", pascalPascal);
mappaConvertitoriPressione.put("Bar (ba)", pascalBar);
mappaConvertitoriPressione.put("Millimetri di mercurio (mmHg)", pascalMMHG);

ecco che, nel caso della pressione, ogni possibile valore corrente nella casella combinata ti consente di ricavare dalla mappa il ConvertitorePressione corrispondente.

String chiave = (String)startc.getSelectedValue();
ConvertitoreUnità c = mappaConvertitoriPressione.get(chiave);

condensato in:

ConvertitoreUnità c = mappaConvertitoriPressione.get((String)starc.getSelectedValue());