Newsgroup: it.comp.java
Titolo: matrice dinamica

Salve a tutti; stavo facendo un esercizio per imparare Java
(
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=132
).
Ho pensato di salvare i valori di ogni cella in una matrice (ammettiamo
che abbia i righe e j colonne), mi pareva la scelta più logica.
All'inizio ho provato a fare un array doppio di String, ma c'è il
problema che devo dare delle dimensioni predefinite e non posso quindi
variare le dimensioni in base all'input dell'utente. Ho goggleggiato un
po' e a quello che ho capito ci sono due solizioni possibili: usare una
linkedList o la classe vector. Sulla linkedList sinceramente ho molta
confusione in testa, per cui almeno all'inizio volevo provare con i
Vector e una volta risolto l'esercizio con questi riprendere in mano la
teoria e risolverlo anche nell'altro modo. Al momento riesco a risolvere
il problema solo se metto tutti valori delle celle in un vector
monodimensionale di dimensioni (i * j).
Con gli array era immediato accedere al valore di una cella, bastava
fare array[nr_riga][nr_colonna], con i Vector devo invece fare qualcosa
tipo Vector[((riga-1)*nr_colonne_totali) + colonna]; esiste un modo per
fare con i Vector una matrice in maniera simile a quanto succede con gli
array?

Alfonso (03/10/2010):

Un esercizio del genere secondo me è meglio farlo quando già si conosce
abbastanza bene il linguaggio, non in fase di apprendimento, anche
perchè l'idea di usare i container sarebbe dovuta venirti spontanea, e
non cercando su Google.
Ti sconsiglio di usare Vector: lavorando con un solo thread (mi sembra
il tuo caso) la sincronizzazione interna a Vector ha solo l'effetto di
rallentare la tua applicazione, anche se di poco. In questi casi
preferisco sempre usare ArrayList.
Tieni sempre presente che potresti allocare un array bidimensionale
anche successivamente alla sua dichiarazione, senza sapere subito quali
siano le sue dimensioni. Esempio:
String[][] spreadsheet=null;
//ottieni le due dimensioni w e h
spreadsheet=new String[w][h];
Comunque, personalmente in tutto questo avrei preferito usare un'altra
struttura: un HashMap<String,String> dove la chiave è l'indirizzo della
cella ("A1", "AZ34", "B4" ....) e il valore è il contenuto della cella.
HashMap<String,String> spreadsheet=new HashMap<String,String>();
In questo modo, quando effettuerai la normalizzazione dei valori,
ottenere il contenuto testuale di una cella è abbastanza banale:
String cellValue=spreadsheet.get(cellAddress);
Per facilitarti la vita (sia in fase di inserimento dei valori nella
tabella, sia quando prepari l'output) ti puoi preparare una funzione
statica che calcoli l'indirizzo della cella a partire dalle sue
coordinate fisiche:
public static String coordsToAddress(int row, int col) {
   //lascio a te l'implementazione
}
Quando dovrai implementare la funzione che calcolerà il valore di una
formula contenuta in una cella, ricordati di usare la ricorsione a tuo
vantaggio. Attenzione: il testo del problema afferma di assumere che
non vi siano riferimenti circolari, ma un programma di spreadsheet, per
quanto semplice, non può fare a meno di questo controllo.
Hope that helps.
-- 
Scientology: se la conosci la eviti, se la conosci non ti uccide.
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx
 - 
http://www.xenu.net
(per rispondere personalmente leva IlDitoDalCulo)
---> 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0 <---

 vantaggio. Attenzione: il testo del problema afferma di assumere che
li conviene usare un parser, ad esempio antlr (
http://www.antlr.org/
)
e' un buon programma per crearsene uno.
Ciao Jack

 quanto semplice, non può fare a meno di questo controllo.
a grandi linee penso di avere in mente i passaggi da fare per questo
controllo, certo da qui all'implementazione pratica ce ne corre... :D
Grazie mille per l'aiuto, provo ad andare avanti e in caso mi rifarò
vivo :D

 vivo :D
In bocca al lupo!


 preferisco sempre usare ArrayList.
Stavo cercando di usare ArrayList ma ho un problema che non riesco a
spiegarmi. Di seguito riporto i campi della classe spreadsheet, un int
per il numero di righe, uno per il numero di colonne e gli arrayList che
conterranno i dati. L'idea che ho avuto era : salvo una riga in un
ArrayList di stringhe(in questo caso tmp), quando questo è completo lo
aggiungo alla matrice, rappresentata da una ArrayList di ArrayList (in
questo caso celle).
public class spreadsheet{
	private int n_righe;
	private int n_col;
	private ArrayList<ArrayList<String>> celle = new
ArrayList<ArrayList<String>>();
	private ArrayList<String> tmp = new ArrayList<String>();
	//variabili di servizio per il costruttore della classe
	int p=0, q=0, z=0, v=0;
	char cifra;
	String valore="";
    //Genero la variabile che leggerà l'input da tastiera
	public Scanner riga = new Scanner(System.in);
di seguito riporto il costruttore che ho preparato:
public spreadsheet(int j, int k){
		String datoInserito="", valore="";
		this.setRows(j);
		this.setCols(k);
		//Per ogni riga faccio inserire la stringa con i dati
		for(p=0;p<j;p++){
			datoInserito=riga.nextLine();
			tmp.clear();
			q=0;
			//Scansiono la riga inserita
			for(z=0;z<datoInserito.length();z++){
				cifra=datoInserito.charAt(z);
				if(cifra==' '){
					tmp.add(valore);
					q++;
					valore="";
				}
				else if(z==datoInserito.length()-1){
					valore += cifra;
					tmp.add(valore);
					q++;
					valore="";
				}
				else{
					valore += cifra;
				}
			}	
			//Aggiungo la riga così ottenuta allo spreadsheet
//System.out.println("p ->" + p + "; tmp ->" + tmp + ";");
			celle.add(tmp);
System.out.println("risultato inserito ->"+celle.get(p));
		}
	}
L'ultima System.out.println, quella non commentata, mi fa vedere dei
risultati corretti ogni volta che inserisco una riga.
Il problema nasce quando vado a stampare a video il contenuto della
matrice con il metodo dump:
public void dump(){
		p=this.getRows();
 
		System.out.println("\nDump di spreadsheet:\n");
		for(z=0;z<p;z++){
			System.out.println("z->"+z+", p->"+p+";");
			System.out.print(this.celle.get(z) + "--");
			System.out.println("");
		}
	}
Se subito dopo ogni inserimento i dati sono corretti, qui non lo sono
più. Se ad esempio ho una matrice 2x2, se metto come valori 11 e 22 per
la prima riga, 33 e 44 per la seconda, l'output che ottengo è:
risultato inserito ->[11, 22]
risultato inserito ->[33, 44] {fin qui ok}
Dump di spreadsheet:
z->0, p->2;
[33, 44]--
z->1, p->2;
[33, 44]--
Non riesco a capire da cosa dipenda però. Potete aiutarmi a risolvere
l'inghippo?

il 03.10.2010 20.52, Scrive Alfonso 77217440:

Se guardi il sorgente di javax.swing.table.DefaultTableModel, ti 
accorgerai che utilizza proprio un Vector di righe ed ogni riga e' un 
Vector di colonne, definendolo come:
protected Vector    dataVector;
Per accedere all'elemento (i, j)  la classe utilizza il metodo:
public Object getValueAt(int row, int column) {
   Vector rowVector = (Vector)dataVector.elementAt(row);
   return rowVector.elementAt(column);
}
Utilizzando le defifizioni generics diventa anche piu' facile:
protected Vector<Vector<String>>    dataVector;
public String getValueAt(int row, int column) {
   return dataVector.elementAt(row).elementAt(column);
}
Ti manca solo la gestione dell'esistenza dell'elemento:
if (dataVector != null &&
     dataVector.size() > row &&
     dataVector.elementAt(row) != null &&
     dataVector.elementAt(row).size() > column)
Oppure prepararti a gestire un NullPointerException o un 
IndexOutOfBoundsException cosi' come dovresti fare anche utilizzando gli 
array.
-- 
Dr. Ugo Gagliardelli, Modena, Italy
Spaccamaroni andate a cagare/Spammers not welcome

 protected Vector    dataVector;
Grazie mille del suggerimento, proverò sicuramente a risolvere
l'esercizio così.
Mi sorge però una domanda: "si può" usare la classe Vector o è da
considerare deprecata?
Il dubbio mi viene in base a quanto ho letto in giro in alcuni forum
in rete.
Un'altra domanda a cui non so dare spiegazione è: perchè impostando il
problema con gli
ArrayList (vedi porzioni di sorgente postate nel mio precedente
messaggio) ho dei problemi
in lettura dei dati?
Anche se proverò con i Vector non voglio abbandonare di già
l'approccio con gli ArrayList altrimenti
non imparerò mai niente.

 non imparerò mai niente.
Non c'e' una gran differenza, considera questi due frammenti
List<List<String>> matrice = new Vector<List<String>>();
List<List<String>> matrice = new ArrayList<List<String>>();
operare su matrice con i metodi di List che differenza fa?
