Newsgroup: it.comp.lang.c++
Titolo: Matrici e prototipi di funzione

Salve ragazzi,
devo fare una funzione che prenda una matrice, di dimensioni ignote
(ma indicate tramite argomenti della chiamata), per leggere i valori
contenuti e farne delle operazioni..
Io avevo fatto così:
void funzione(double **M, int numeroRighe, int numeroColonne)
{
...
}
ma quando la chiamo passandogli una matrice che ho definito come
double matrice[3][3];
tramite funzione(matrice, 3, 3);
Visual Studio mi dice
error C2664: 'funzione' : cannot convert parameter 1 from 'double [3]
[3]' to 'double **'
Ma com'è possibile? Io ricordavo che si potesse non specificare la
dimensione della matrice nel prototipo!
Io voglio fare una funzione "universale", che funzioni sia quando
passo una matrice dichiarata staticamente con dimensioni qualsiasi,
sia quando passo una matrice allocata al momento.. come posso fare?

 tramite funzione(matrice, 3, 3);
E dov'è il puntatore a puntatore?
Dovresti fare così:
void funzione(double *p, int nRighe, int nColonne)
{
}

Lascia stare il messaggio di poco fa, ho fatto un popò con i tasti e
l'ho inviato incompleto.
La funzione deve essere così dichiarata:
void funzione(double *p, int nRighe, int nColonne)
{
  /* qui il codice */
}
e richiamarla così:
funzione(&matrice, 3, 3);
Tu avevi dichiarato un puntatore a puntatore e poi passavi
direttamente la matrice.

 double matrice[3][3];
er come hai dichiarato il parametro (che non è una matrice 
ma un puntatore a puntatore), il compilatore non può essere 
consapevole di quanto sia la dimensione degli indici 
"leftmost". Per implementare in modo automatico (compile 
time) il calcolo degli indici come vorresti tu, ossia con la 
scrittura matriciale, il compilatore deve invece conoscere 
"staticamente" le dimensioni di TUTTI gli indici tranne il 
rightmost. Nel tuo caso uno è incognito, e non sa come 
calcolare l'indirizzo fisico, che a prescindere dalla 
semantica di scrittura è invece sempre lineare.
Quindi puoi girarci intorno dichiarando la matrice come 
puntatore plain, ed eseguendo tu stesso i calcoli che 
normalmente in modo statico farebbe lui
M [Riga * numerorighe + Colonna]
con Riga e Colonna usate come indici. Da questo vedi che 
numerocolonna (il rightmost) è l'unico indice che ti serve 
solo FUORI dal calcolo dell'indirizzo, ad es. come limite 
massimo del loop
diversamente, ma non l'ho provato, potresti tentare la via 
templatica ...
tipo :
template <int numcolonne>
void funzione((double *) [numcolonne] M, int numeroRighe)
a quel punto una scrittura matriciale può assumere il senso 
voluto,
perché M[Riga] è un puntatore ad un'array lineare di double, 
e come tale può essere usato con un ulteriore indice.
P.S. scusa, ma siccome non ho compilato e visto messaggi di 
errore, non vorrei essermi confuso con l'associatività, per 
scrupolo se ti va tenta anche la sintassi, diversissima,
template <int numcolonne>
void funzione(double [numerorighe] * M, int numcolonne)
concettualmente mi sembra errata, perché qui M è un 
puntatore ad un vettore di numrighe double.
il problema, in entrambi i casi, è che non mi ricordo 
affatto se il compilatore accetti tra i parametri delle 
matrici dichiarate staticamente o parzialmente, come 
garantito dal parametro templatico.
Di sicuro ricordo che NON accetta valori variabili, ma se li 
accetti costanti non sono comunque sicuro
Te la potresti cavare con qualche sporco casting, 
dichiarando come double * * M il parametro critico  e 
creando uan variabile automatica ausiliaria del tipo voluto
(double *) [numcolonne] Aux = cast(M) etc
ovviamente sprechi della memoria, e magari il cast ti manda 
a quel paese
Diciamo che il calcolo manuale degli indici magari è noioso 
ma funziona sempre (se hai capito la faccenda della 
dimensionalità), questi altri accrocchi non ho idea se 
fungano o meno
ciao
Soviet


funzione(&matrice, 3, 3);
Cosi non compila. La sintassi �:
double Matrice [3][3];
void funzione(double p[][3], int nRighe, int nColonne) { }
int main() {
    funzione(Matrice, 3, 3);
    return 0;
}
Comunque la gestione di array n-dimensionali come parametro di funzione � un 
po seccante in C++. Ad esempio come mai questo codice non compila?
L'ho anche postato in un altro thread:
typedef char Matrice [10][10];
Matrice rotation(Matrice m) {
    return m;
}
int main() {
}
`rotation' declared as function returning an array
In function `int rotation(char (*)[10])':
invalid conversion from `char (*)[10]' to `int' 

 `rotation' declared as function returning an array
Si vede che il valore di ritorno di una funzione non puï¿œ essere un array.
E.

 Si vede che il valore di ritorno di una funzione non pu� essere un array.
Brutta cosa, direi.
Ma esiste una classe che simuli gli array (non std::vector)?
Nel C++0X introdurrando qualcosa di meglio di quei primitivi Array stile C? 

 invalid conversion from `char (*)[10]' to `int'
in c++ non puoi restituire array, puoi provare a restituire un
riferimento:
...
Matrice &rotation(Matrice &m) {
    return m;
}
...
ciao
Giacomo

 Ma esiste una classe che simuli gli array (non std::vector)?
Perchï¿œ non std:vector? E' fatto apposta.
E,

 Perch� non std:vector? E' fatto apposta.
Perch� il suo uso per array multidimensionali mi sembra poco intuitivo 
rispetto all'uso degli array classici. Ad esempio de ho bisogno di un array 
tridimensionale la scrittura:
int A[X][Y][Z];
mi sembra molto pi� chiara di:
vector<vector<vector<int> > > v; 

 Nel C++0X introdurrando qualcosa di meglio di quei primitivi Array stile C?
Cos'ha std::vector che non va per la maggior parte dei casi non-
numerici e banali in circolazione (il 90%)?
Se vuoi un'implementazione particolare di matrice, devi scriverla tu o
usare qualche liberia che implementi le BLAS.
Consiglio le boost come implementazione già fatta:
http://www.boost.org/doc/libs/1_39_0/libs/numeric/ublas/doc/matrix.htm
Le boost in generale sono ottime librerie ausiliarie alle STL, tanto
che molte delle innovazioni del C++0x per quanto riguarda la libreria
standard arrivano proprio da lì.
Ciao,
Matteo

 vector<vector<vector<int> > > v; 
Il C++ ha voluto garantire una certa retrocompatibilitï¿œ con il C. Per 
questo alcuni costrutti risultano meno chiari del dovuto.
E.