| Precedente :: Successivo | 
	
	
		| Autore | Messaggio | 
	
		| ZTP Eroe
 
  
  
 Registrato: 17/02/09 23:40
 Messaggi: 60
 Residenza: Terra, terzo pianeta dal Sole
 
 | 
			
				|  Inviato: 08 Apr 2009 19:13    Oggetto: * [C++] matrici "generali" come argomento di funzi |   |  
				| 
 |  
				| Vorrei creare una funzione che abbia come argomenti una matrice bidimensionale e il suo numero di righe e colonne, per poi stamparla. Il problema è che quando dichiaro la funzione devo necessariamente indicare il numero di colonne, e se provo a passare una matrice diversa -anche più piccola!- il compilatore mi segnala un errore -.- In pratica, se questa è la funzione
 
  	  | Citazione: |  	  | void StampaMatrice(int mat[][10], int rig, int col) {
 for(int i = 0; i < rig; i++)
 {
 for(int j = 0; j < col; j++)
 cout << mat[i][j] << endl;
 }
 }
 | 
 Posso usarla solo e unicamente per stampare matrici di 10 colonne. C'è un modo per rendere la funzione 'generale'? Probabilmente non è niente di astronomico ma sono ancora agli inizi T_T Grazie in anticpo!
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 08 Apr 2009 20:52    Oggetto: |   |  
				| 
 |  
				| Devi usare i puntatori. Come primo parametro della funzione avrai un int**, la matrice dovrà essere allocata dinamicamente fuori dall afunzione e poi passata alla stessa. Gli ultimi due parametri ti servono ancora. 
 L'ultima modifica di freemind il 01 Lug 2009 23:38, modificato 1 volta
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 08 Apr 2009 21:00    Oggetto: |   |  
				| 
 |  
				| Mi son reso conto che il post di prima è praticamente inutile. Un po' di codice:
 
  	  | Codice: |  	  | #include <iostream.h>
 void StampaMatrice(int **mat,int righe,int colonne)
 {
 for (int i=0;i<righe;++i)
 {
 for (int j=0;j<colonne;++j)
 {
 cout<<mat[i][j]<<" ";
 }
 cout<<endl;
 }
 }
 void main()
 {
 int **m;// puntatore doppio
 m=new int*[3];  // un array di array di 3 elementi
 for (int i=0;i<3;++i)  // allochi i 3 array dandogli dimensione 3
 m[i]=new int[3];
 // qui inizializzi la matrici e poi...
 
 // chiami la tua funzione
 StampaMatrice(m,3,3);
 }
 
 
 
 | 
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| ZTP Eroe
 
  
  
 Registrato: 17/02/09 23:40
 Messaggi: 60
 Residenza: Terra, terzo pianeta dal Sole
 
 | 
			
				|  Inviato: 09 Apr 2009 10:29    Oggetto: |   |  
				| 
 |  
				| Wow, grazie *Q* Esattamente quello che mi serviva. Avevo provato a usare i puntatori ma più che litigarci non ho fatto  Invece adesso la cosa è più chiara. Grazie! |  | 
	
		| Top |  | 
	
		|  | 
	
		| SverX Supervisor Macchinisti
 
  
  
 Registrato: 25/03/02 12:16
 Messaggi: 11860
 Residenza: Tokelau
 
 | 
			
				|  Inviato: 09 Apr 2009 12:26    Oggetto: |   |  
				| 
 |  
				| freemind: perchè usi puntatore a puntatore a int e non direttamente un puntatore a int? Qualcosa mi sfugge, sono certo che possa funzionare anche solo con un puntatore a int... 
 edit: anzi, siamo sicuri che funzioni? Quando usi
 
 tu parti dal principio che il compilatore sappia quanti elementi ci sono in ogni riga della matrice, e questo è vero se la matrice è definita in compile time (come nel tuo esempio), ma non lo è se la matrice fosse definita in runtime...
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 09 Apr 2009 13:13    Oggetto: |   |  
				| 
 |  
				| New alloca a run-time non in compile-time. Lascia perdere le dimesioni che io ho usato come costanti, era perchè ero di volata. In teoria avrei dovuto usare due parametri inizializzati in qualche modo per contenere i numeri di righe e di colonne.
 
 Uso il doppio puntatore (quindi un puntatore ad un array di puntatori) per poter concettualmente rappresentare l'array bi-dimensionale come matrice in due dimensioni.
 In questo modo potremmo arrivare a creare una "matrice anomala" in cui le righe hanno un numero diverso di colonne, ma questa è un'altra storia.
 Il compilatore non sa quanti elementi ci sono nelle righe e nelle colonne ma utilizzando nella funzione StampaMatrice i due parametri sono sicuro che se non faccio viaggiare i puntatori oltre allora non esco dalla matrice.
 
 Hai ragione quando dici che si potrebbe usare un puntatore int*, anzi, sarebbe il modo più corretto anche perchè tanto in ram la memoria viene allocata consecutivamente: facendo così però avrei dovuto comunque ragionare con un vettore e non con una matrice, allontanandomi dal concetto "matematico" di matrice bi-dimensionale.
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| SverX Supervisor Macchinisti
 
  
  
 Registrato: 25/03/02 12:16
 Messaggi: 11860
 Residenza: Tokelau
 
 | 
			
				|  Inviato: 09 Apr 2009 14:25    Oggetto: |   |  
				| 
 |  
				|  	  | freemind ha scritto: |  	  | New alloca a run-time non in compile-time | 
 
 Chiaro, io intendevo che la dimensione della riga è dichiarata nel sorgente e quindi 'risolta' in compile time
 
 
 Per il resto ho capito il tuo discorso sul concetto matematico, rimane però che per poter avere una funzione che lavori su una matrice n*m dove sia n che m saranno dichiarate solo durante l'esecuzione del programma, dovrai obbligatoriamente usare un int* e puntare all'elemento i-j-esimo dell'array (la matrice in memoria) usando qualcosa del tipo
 
 
 In questo modo la funzione lavorerà su matrici di qualunque dimensione scelta in run-time
   
 
  |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 09 Apr 2009 15:55    Oggetto: |   |  
				| 
 |  
				|  	  | SverX ha scritto: |  	  | ...
 Chiaro, io intendevo che la dimensione della riga è dichiarata nel sorgente e quindi 'risolta' in compile time
 
 ...
 
 | 
 Ok, tieni conto che al posto del 3 visto che stiamo parlando di memoria dinamica poteva essere chiamata una variabile e quindi anche dimensione diventerebbe dinamica.
 
 Il tuo discorso sull'uso del puntatore int* è corretto, io però pensavo che ZTP si limitasse alle matrici bi-dimensionali.
 Bisogna però anche tener presente che l'utilizzo di una matrice "generica" come la intendi tu ha la sfiga di aver a quel punto anche il numero di indici dinamico e diventerebbe non semplice/veloce da gestire.
 
 Oltre le 3 dimensioni secondo me vale la pensa cambiare struttura.
 
 Miao
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| SverX Supervisor Macchinisti
 
  
  
 Registrato: 25/03/02 12:16
 Messaggi: 11860
 Residenza: Tokelau
 
 | 
			
				|  Inviato: 09 Apr 2009 17:00    Oggetto: |   |  
				| 
 |  
				| aspe... io intendevo generica ma comunque bidimensionale... generica solo nel valore delle (2) dimensioni... 
 
  	  | freemind ha scritto: |  	  | tieni conto che al posto del 3 visto che stiamo parlando di memoria dinamica poteva essere chiamata una variabile e quindi anche dimensione diventerebbe dinamica. | 
 
 non l'ho capita... mi fai un esempio? Tu dici che se quel 3 fosse una variabile, poi a run-time il codice generato dal compilatore è in grado di accedere all'elemento ?
 
 O i compilatori hanno cambiato funzionamento (sarò rimasto indietro?) oppure mi sa che non funzionerebbe proprio...
 
 Se hai un attimo prova a compilare con
 
 con n letto da input utente, poi vediamo che dice...
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 09 Apr 2009 17:15    Oggetto: |   |  
				| 
 |  
				| Il codice che ti posto è stato compilato tramite g++ 4.1 su Ubuntu 7.10 e funziona. Anche se il mio c++ è un po' arrugginito io mi ricordo che ho sempre fatto così (oppure usavo un indice solo seguendo il tuo discorso) ed è sempre andato. 
  	  | Codice: |  	  | #include <iostream>
 
 using namespace std;
 
 void StampaMatrice(int **mat,int righe,int colonne)
 {
 for (int i=0;i<righe;++i)
 {
 for (int j=0;j<colonne;++j)
 {
 cout<<mat[i][j]<<" ";
 }
 cout<<endl;
 }
 }
 int main()
 {
 int **m;// puntatore doppio
 
 int righe=0,colonne=0;
 int i=0,j=0;
 
 cout<<"Numero di righe: ";
 cin>>righe;
 
 cout<<"Numero di colonne: ";
 cin>>colonne;
 
 m=new int*[righe];  // un array di array di 3 elementi
 
 for (i=0;i<righe;++i)  // allochi i 3 array dandogli dimensione 3
 m[i]=new int[colonne];
 
 for (i=0;i<righe;++i)
 for (j=0;j<colonne;++j)
 {
 cout<<"Elemento["<<i<<","<<j<<"]: ";
 cin>>m[i][j];
 }
 
 StampaMatrice(m,righe,colonne);
 }
 
 | 
 Forse ti stai confondendo con il caso:
 
  	  | Codice: |  	  | ...
 int m[righe][colonne];// questo è scorretto!
 ...
 
 | 
 Lì la matrice è risolta dal compilatore quindi o righe e colonne sono due costanti oppure non si compila.
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| SverX Supervisor Macchinisti
 
  
  
 Registrato: 25/03/02 12:16
 Messaggi: 11860
 Residenza: Tokelau
 
 | 
			
				|  Inviato: 09 Apr 2009 18:52    Oggetto: |   |  
				| 
 |  
				| Wow.   
 Ok, ci ho messo un po' ma adesso ho capito.
 
 E adesso mi è chiaro anche perchè usi il puntatore a puntatore a interi... in pratica perchè la matrice non la allochi in memoria come 'un sol blocco' di righe*colonne elementi interi di seguito, ma la allochi come un array di colonne elementi, nel quale ogni elemento è un puntatore ad un array lungo righe interi. C'ho preso?
   
 E' curioso. Non l'avrei mai pensato così. Si vede che sono troppo abituato con il C (e anche sono troppo abituato a pensare che qualunque matrice n-dimensionale è comunque possibile trattarla come un array...)
 
 Grazie per il tempo speso a chiarire il mio dubbio
 
 
  |  | 
	
		| Top |  | 
	
		|  | 
	
		| freemind Supervisor sezione Programmazione
 
  
  
 Registrato: 04/04/07 21:28
 Messaggi: 4643
 Residenza: Internet
 
 | 
			
				|  Inviato: 09 Apr 2009 19:40    Oggetto: |   |  
				| 
 |  
				|  	  | SverX ha scritto: |  	  | in pratica perchè la matrice non la allochi in memoria come 'un sol blocco' di righe*colonne elementi interi di seguito, ma la allochi come un array di colonne elementi, nel quale ogni elemento è un puntatore ad un array lungo righe interi. C'ho preso?   
 | 
 In realtà alloco un array di righe elementi e oguno è un puntatore ad un array di colonne elementi, c++ è row-based e comunque se noti, nel codice la prima allocazione è con righe.
 Uno schemino potrebbe essere:
 R0->C0 C1 C2...Ccolonne
 R1->C0 C1 C2...Ccolonne
 ...
 Rrighe->C1 C2...Ccolonne
 
 Per il resto c'hai preso!
 Io amo molto sia il C che il C++, sono i miei linguaggi preferiti anche se purtroppo ora non li uso praticamente mai!
 
 bau!
 |  | 
	
		| Top |  | 
	
		|  | 
	
		| SverX Supervisor Macchinisti
 
  
  
 Registrato: 25/03/02 12:16
 Messaggi: 11860
 Residenza: Tokelau
 
 | 
			
				|  Inviato: 10 Apr 2009 10:11    Oggetto: |   |  
				| 
 |  
				|  	  | freemind ha scritto: |  	  | In realtà alloco un array di righe elementi e oguno è un puntatore ad un array di colonne elementi, c++ è row-based e comunque se noti, nel codice la prima allocazione è con righe. | 
 
 Sì, ho confuso i due termini, mi capita spesso
  |  | 
	
		| Top |  | 
	
		|  | 
	
		|  |