Newsgroup: it.comp.lang.c++
Titolo: Come dimensionare una ARRAY?

Cerco di dichiarare un array di interi con
int i=20;
int x[i];
e il compilatore mi segnala che devo utilizzare un valore costante.
C'è una soluzione per dichiarare un array in funzione di una variabile?Vi
prego di rispondermi anche in caso contrario.

 wrote:

Non puoi definire uno spazio variabile che viene allocato nello
stack, ma puoi farlo se lo allochi nel free store ovvero devi far
ricorso all'operatore new.
// esempio di allocazione dinamica di un array di interi
int *x, i;
// 'i' viene modificato dal programma, poi allochiamo lo spazio
x = new int[i];
// ora possiamo usare gli elementi da x[0] a x[i-1]....
...
// a fine uso di x, dobbiamo liberare lo spazio occupato
delete [] x;
Tutto qui.
Vinicio Coletti - 
v.co...@iol.it
 - 
http://www.webcom.com/vcoletti
President of the International Individualist Association
- If you want to join, sorry, we accept just one member -

...


Un metodo è :
int  dimindex;
int* x  // pointer vettore
// assegno, in qualche modo, il valore al dimensionamento
dimindex = 20;
x = (int*)malloc(sizeof(int c[dimindex]));
// Ora puoi usarlo


>C'č una soluzione per dichiarare un array in funzione di una variabile?Vi


 prego di rispondermi anche in caso contrario.
No, devi usare l'operatore new per allocare lo spazio che ti serve in 
modo dinamico.
int* p = new (i*sizeof(int));
poi puoi usare p++, p+10, ecc.. ecc.., per recuperare l'elemento 3 fai
*(p+3) credo che valga anche p[3], prova.
occhio a non sforare con p, ma questo valeva anche con gli array.
<< The show must go home ! >>
** Email replies to 
md7...@mclink.it
 **
visit my homepage at: 
http://www.volftp.tin.it/IT/IT/ITALIANI/rullo/index.htm
 

...


OK, Marco, questo "malloc" funziona. Ma ho ancora bisogno di aiuto: non so
infatti come fare lo stesso con un array a 2 dimensioni...





OK, Vinicio, funziona (ringrazio tutta la International Individualist
Association), ma ho ancora bisogno di aiuto: non so infatti come fare lo




OK, anche questo funziona, ma ho ancora bisogno di aiuto: non so infatti


OK, Damiano, "malloc" funziona, ma ho ancora bisogno di aiuto: non so


infatti come fare lo stesso con un array a 2 dimensioni...
Il C e il C++ non hanno in realta` un concetto di "array a 2
dimensioni" (cosi` come non lo ha il computer di per se);
questo concetto matematico si puo` mappare in due modi
diversi:
1. un array di array (piu` flessibile, meno efficiente);
2. un array monodimensionale (concetto che, lui si`, E`
    presente nelle macchine e nei linguaggi) e una regola
    per calcolare un singolo offset nell'array a partire da
    due (o piu`, naturalmente) indici (piu` efficiente, meno
    flessibile).
Vediamo entrambe le soluzioni in C++, ad esempio,
che permette una maggiore espressivita`.
template <class T>
class array1d {
    T* data;
public:
    array1d(int lunghezza=0): data(new T[lunghezza]) {}
    ~array1d() { delete[] data; }
    T& operator[](int indice) { return data[indice]; }
};
template <class T>
class array2d {
    array1d<T> *data;
public:
    array2d(int lunghezza, int larghezza) {
        data = new array1d<T>[larghezza];
        for(int i=0; i<larghezza; ++i)
            data[i] = new array1d<T>(lunghezza);
     }
    ~array2d() { delete[] data; }
    array1d<T>& operator[](int indice) { return data[indice]; }
};
Qui puoi dichiarare una variabile che sia un array di int,
ad esempio, dimensionata al volo da dimensioni i e j,
come:
array2d<int> aMatrix(i,j);
e accedere ai suoi elementi con doppio indice:
    aMatrix[3][2]
per avere il terzo elemento della quarta riga (gli
indici essendo naturalmente a base zero).
L'equivalente in C richiede di dichiarare aMatrix
come puntatore a puntatore a int, ed eseguire
la malloc primaria e il loop di malloc secondarie
quando conosci le dimensioni; dopo di che puoi
sempre usare le doppie quadre come sopra.
La doppia indirettezza ad ogni accesso, e le
N+1 allocazioni separate, sono inefficienti.
Ecco dunque un'alternativa basata sull'altro
modo di mappare la bidimensionalita`:
template <class T>
class matrice {
    T *data;
    int lung;
public:
    matrice(int lunghezza, int larghezza) {
        lung = lunghezza;
        data = new T[lunghezza*larghezza];
     }
    ~matrice() { delete[] data; }
    T& operator()(int i, int j) { return data[i+j*lung]; }
};
Nota che qui dobbiamo usare per l'accesso
l'operatore parentesi-tonda (poiche` esso puo`
accettare due argomenti, mentre l'operatore
parentesi-quadra e` limitato a 1 argomento solo!).
Qui l'uso sarebbe dunque:
    matrice<int>    aMatrix(i,j);
    aMatrix(3,4)
Questa soluzione, benche` possibilissima, e`
decisamente piu` scomoda in C perche` ad
ogni accesso la moltiplicazione di uno degli
indici per la "leading-dimension" va, o resa
esplicita, o nascosta da qualche parte, e non
e` inoltre possibile usare le reference che in
C++ permettono il comodissimo accesso a
due indici agli elementi della matrice.
Se fossi costretto a usare il C per una soluzione
di questo tipo, penso che metterei insieme un
qualche tipo di accrocco di preprocessore per
nascondere la goffaggine.  Ma la soluzione C++
e` liscia come l'olio e decisamente superiore.
Alex

stesso con un array a 2 dimensioni...
#include <iostream.h> // per cout
int main() {
    int dimA = 2, dimB = 2; // dimensioni dell'array
    int** x= new int*[dimA]; // inizializza dimA puntatori
    for (int i = 0; i < dimA; i++) x[i] = new int[dimB]; // inizializza dimB
interi dimA volte
    /**/
    x[0][0] = 0; // assegna
    x[0][1] = 1; // valori ai
    x[1][0] = 2; // membri
    x[1][1] = 3; // dell'array
    cout << endl << x[0][0] << x[0][1] << x[1][0] << x[1][1] << endl; //
mostra i valori dell'array
    /**/
    for (int j = 0; j < dimA; j++) delete[] x[j]; // cancella tutti gli
array di interi
    delete[] x; // cancella tutti gli array di puntatori
    return 0;
}
Se hai capito come funziona il "giochino" puoi ripeterlo fino ad esaurimento
della memoria per creare array di quante dimensioni vuoi!!!
Rodolfo Tedeschi - 
thet...@tin.it


Se almeno una dimensione e conosciuta puoi utilizzare :
#define DIM   2
int dim = 2 ;
int (*Vettore)[DIM] ;
Vettore = new int [dim][DIM] ;
Vettore[0][0] = 0 ; // primo elemento
delete [] Vettore ;

 template <class T>
Be, vacci piano, se non ho capito male sta iniziando adesso col C, per
i template c'e' tempo.
Ciao.


 infatti come fare lo stesso con un array a 2 dimensioni...
risposto in altro mex.
A forse mi ero dimenticato, quando hai finito ricordati di liberare la
memoria allocata con free, senno' consumi rapudamente quella zona di 
memoria riservata per queste operazioni (heap).


 template <class T>
Be, vacci piano, se non ho capito male sta iniziando adesso col C, per
i template c'e' tempo.
Ciao.


i template c'e' tempo.
Beh, puo` sempre "istanziare a mano" il template, dopo tutto...
e` estremamente facile, basta togliere la riga sopra quotata e
sostituire testualmente T con, ad esempio, int, dovunque
appaia nel corpo della classe!
Alex

 template <class T>
Be, vacci piano, se non ho capito male sta iniziando adesso col C, per
i template c'e' tempo.
Ciao.



Sono rimasto semplicemente esterrefatto della risposta di Alex
Martelli. Cavolo! Tanto di cappello per la competenza! Sono le
occasioni in cui mi rendo conto che ho taaaaanto da imparare ancora!
Questo per dirti, prendi ilmio tentativo di risposta come il consiglio
di un principiante ad un principiante. Io ho risolto il problema in
questo modo (gli esperti non ridano della poca eleganza della mia
soluzione :-)
Un array 1*n (un vettore, quindi) dinamico, lo allochi dichiarandolo
come puntatore a interi (se il vettore e' un vettore di interi,
ovviamente) e poi allocando con l'operatore new lo spazio di memoria
necessario. Quindi:
int DimesioneDelVettore=10;
int* Vettore; // Questo puntatore puntera' al primo
                   // elemento del tuo vettore.
Vettore=new int[DimensioneDelVettore]
Con questa istruzione hai allocato DimensioneDelVettore interi in un
blocco di memoria. Vettore sarà il puntatore che punta all'inizio di
questo blocco. Per questo, puoi usare il puntatore Vettore come se
fosse un vero e proprio vettore. Per esempio, puoi scrivere
Vettore[3]=12;
Per un array multidimensionale, per quello che ho capito io, non
esiste un operatore apposito, ma puoi risolvere il problema guardando
all'array come vettore di vettori. Diciamo che vuoi allocare un array
DimensioneX*DimensioneY, e chiamare questo array Array. Intanto
dichiara Array come puntatore di puntatore a intero:
int** Array;
Poi devi allocare la memoria, come hai fatto prima. Ma non creerai un
vettore di interi, ma un vettore di puntatori ad interi. Quindi
	Array = new int*[DimensioneX];
Adesso in Array[0], Array[1]....Array[DimensioneX-1] puoi mettere i
putatori a altrettanti vettori di dimensione DimensioneY.
	Array[0] = new int[DimensioneY];
	Array[1] = new int[DimensioneY];
	..
	Array[DimensioneX] = new int[DimensioneY];
(Come vedi, le righe precedenti, conviene infilarle in un bel ciclo
for..)
Adesso puoi accedere all'elemento 5,6 di Array con la riga
Array[5][6]=180;
Spero di non aver tirato eresie....
Topoldo!
__
NoSpamMePle...@writeme.com

soluzione :-)
La tua soluzione dovrebbe funzionare benissimo, solo con appena
un po' meno di generalita`.
Approfitto poi per offrire una soluzione anche piu` semplice...:
#include <vector>
using std::vector;
template <class T>
class matrice: public vector< vector<T> > {
public:
    matrice(size_t dx, size_t dy): vector<  vector<T> >(dx) {
        for(iterator i=begin(); i!=end(); ++i)
            (*i).resize(dy);
    }
};
Questa soluzione (non di massima efficienza) e` pero` della
massima semplicita`, concisione, generalita`.  Includi questo
header-file (chiamalo matrice.h, ad esempio) e puoi fare cose
come: 
template <class T>
void trasponi(matrice<T>& m)
{
    size_t dx, dy;
    matrice<T> t((dx=m[0].size()), (dy=m.size()));
    for(int i=0; i<dx; ++i)
        for(int j=0; j<dy; ++j)
            t[i][j] = m[j][i];
    m.swap(t);
}
e ovviamente arricchire con grande semplicita` la classe
per fornire funzioncine di utilita` come accedere a dx e dy,
cambiarle, e cosi` via... tutto quel che ti serve, insomma!
Alex

 };
Grazie a chiunque voglia darmi dei chiarimenti.
(togli "togli" dal mio e-mail per rispondermi!!!)
?manu*











Grazie a chiunque voglia darmi dei chiarimenti.
Spero di avere aiutato un poco, ma tieni presente che
la "programmazione generica", quella che i template
permettono, e` uno strumento *potentissimo* e che merita
bene l'investimento in un buon libro aggiornato (e in un
compilatore idem, specialmente se gratis come il GCC
2.8.0:-) per imparare a farne buon uso...
Alex