Newsgroup: it.comp.lang.c++
Titolo: Posso creare dinamicamente una matrice?

Mi spiego:
posso compilare un programma in cui creo (con new quindi nello heap) una matrice di
cui l'utente mi da le dimensioni?
Qualcosa tipo
new int [x][y]
ho provato a farlo con un array e (come previsto tutto ok) ma con la matrice non
compila(uso Borland c++ builder 3)
-----------------------
Un uomo con un orologio e sempre sicuro di che ora e' , un uomo con 2 orologi non lo e' mai!
GYps!

On Tue, 07 Sep 1999 20:25:27 GMT, 
0908...@spv.ing.uniroma1.it
(Cristiano f.) wrote:
int** Matrice = new int*[PrimaDimensione];
for(int i=0; i<PrimaDimensione; ++i)
  Matrice[i] = new int[SecondaDimensione];
pre la deallocazione basta procedere in ordine inverso:
for(int i=0; i<PrimaDimensione; ++i)
  delete[]  Matrice[i];
delete[] Matrice;
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

...


 cui l'utente mi da le dimensioni?
Potresti adottare una soluzione del genere che permette la massima
versatilità (le colonne possono anche essere di dimensioni diverse una
dall'altra):
#include <iostream>
#include <iomanip>
int main()
{
    int **Matrice = new int * [ 10 ];
    for ( int i = 0; i < 10; ++i )
        Matrice[ i ] = new int [ 10 ];
    for ( int i = 0; i < 10; ++i )
        for ( int j = 0; j < 10; ++j )
            Matrice[ i ][ j ] = ( i + 1 ) * ( j + 1 );
    for ( int i = 0; i < 10; ++i )
    {
        for ( int j = 0; j < 10; ++j )
            std::cout << setw( 3 ) << Matrice[ i ][ j ] << " ";
        std::cout << std::endl;
    }
    for ( int i = 0; i < 10; ++i )
        delete [] Matrice[ i ];
    delete [] Matrice;
}
EMG

 necessaria!
Non è esatto. Si può anche creare una matrice allocando tutto insieme lo
spazio necessario:
char *matrice = new [ righe * colonne ];
e poi gestirla facendo le opportune moltiplicazioni sugli indici.
EMG


ICQ #34602650

 writes:
   trovo più pratico e conveniente allocare un unico vettore x*y e
   accedere agli elementi con l'aritmetica dei puntatori.
Qualcuno sa commentare sull'efficienza relativa delle due
implementazioni con i motori/compilatori java attuali?

}
C'é da dire che questo sistema é un pò scomodo.Forse é più
comodo utilizzare un vettore unidimensionale ed accedere agli
elementi del vettore tramite con delle moltiplicazioni sugli indici.Io ho
provato entrambi i sistemi,ed alla fine ho preferito quest'ultimo.
Il Ghenio

Cristiano f. wrote:
Ho visto che altri ti hanno gia` risposto, cmq ...
perche` non ti implementi una classe Matrix come illustra
Stroustrup nella sezione 22.4.6 mediante le classi standard
valarray e slice ?
-- 
Roberto Gerola
Email: 
robert...@penguinpowered.com
WWW: 
http://www.penguinpowered.com/~The_Cpp_Compass

Per la precisione lo spreco relativo sarebbe 1/(m*s)
dove m e` la 2a dimensione della matrice ed s e` la dimensione
in byte di ciascun elemento. Con una matrice 10x10 ed elementi
della dimensione di 4 byte (ad esempio un intero su 32 bit)
lo spreco sarebbe del 10% (assumendo puntatori di 4 byte).
con elementi di 10 byte lo spreco scenderebbe al 4%.


 GYps!
Potresti usare questa "semplice" classe template...
#include <iostream>
#include <stdlib.h>
template <class T>
class Riga
{
   T * riga;
   public:
   Riga( T* r) : riga(r) {}
   ~Riga() {}
   T & operator [] (int i) { return riga[i]; }
};
template <class T>
class Matrice
{
   T * dati;
   int m,n;
   public:
   Matrice(int i,int j) : m(i),n(j) { dati = new T [ m*n ]; }
   ~Matrice() { delete [] dati; }
 
   Riga<T> operator [] (int i) { return Riga<T>(  & dati [n*i] ); }
   const Riga<const T> operator[] (int i) const { return Riga<const T>( & dati [n*i] ); }
};
main(int argc, const char **argv)
{
   if (argc != 3) 
   {
       std :: cerr << "uso : " << argv[0] << " righe colonne " << std::endl;
       exit(10);
   } 
   int righe = atoi ( argv[1] );
   int colonne = atoi ( argv[2] );
   if ( (righe <= 0) || ( colonne <= 0))
   {
       std :: cerr << argv[0] << ": parametri non validi" << std::endl;
       exit(10);
   } 
   Matrice<int> mat(righe,colonne);
   int i,j;
   for (i=0; i<righe; i++)
     for (j=0; j<colonne; j++)
     {
       mat[i][j] = i+j;
       std::cout << "mat[" << i << "][" << j << "] = " << mat[i][j] << std::endl;
     }
}
*Fabio*
-- 
We don't really understand it, so we'll give it to the programmers.

>
Scusa, ma non capisco lo spreco?


Scusa, ma non capisco lo spreco?
Ops... scusami, hai perfettamente ragione, ho sbagliato a
trascrivere la formula che avevo calcolato... (e sinceramente
non capisco come ho fatto...Sara la vecchiaia che avanza!   :(((((
Posto tutto il ragionamento e la formula risultante
Bisogna realizzare una matrice NxM tramite un puntatore a puntatore;
il numero totale di elementi e` dunque dato da N*M. Utilizzando
direttamente una dichiarazione del tipo
TElementi Matrice[N][M];
possiamo supporre che non ci sia occupazione di memoria
superiore a N*M*sizeof(TElementi)
Se utiliziamo invece un TElementi** Matrice
dobbiamo prima allocare un array di N TElementi*
( Matrice = new TElementi*[N] ) che occupa memoria per
N*sizeof(TElementi*),  e poi allocare gli N array di M elementi
(for(int i = 0; i <N; ++i) Matrice[i] = new TElementi[M])
se poniamo S = sizeof(TElementi*)
possiamo calcolare la percentuale di memoria aggiuntiva per
la soluzione dinamica tramite la formula:
((N*M +N*S) - N*M) / N*M == S/M
Il valore che esce fuori moltiplicato per 100 fornisce la
percentuale di memoria "sprecata" rispetto alla matrice
allocata staticamente.
Spero di non aver fatto altri errori stavolta...


>
GRANDE , come sempre....


GRANDE , come sempre....
Magari...
invece un altro errore l'ho fatto, ho trascurato la dimensione degli
elementi... sigh!
Me ne sono accorto proprio ora... nei miei calcoli l'ho sempre
considerata, ma non l'ho riportata nella formula...
quindi:
((N*M*S' + N*S) - N*M*S') / (N*M*S') == S/(M*S')
S' = sizeof(TElementi)
Paolo
P.s.
  E` interessante notare che in caso di allocazione dinamica 
  e` meglio che la prima dimensione sia quella corrispondente a
  min(N, M).
