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: 11810 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: 11810 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: 11810 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: 11810 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: 11810 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 |
|
 |
|