PDA

Visualizza la versione completa : Accesso monodimensionale a matrice dinamica


^EvAmPiReS^
01-05-2008, 03:14
La domanda probabilmente è molto banale ma proprio non riesco a risolvere sta cosa:
Ho allocato dinamicamente una matrice di double in questo modo:


double** coeffMatAlloc (int nrow, int ncol){

int i = 0;
int j = 0;
double** mat;

if((mat = (double**)malloc(nrow*(sizeof(double*)))) == NULL){
printf("\nErrore nell'allocazione delle righe della matrice o spazio insufficiente\n");
exit(0);
}

else
{
for (i=0; i<nrow; i++)
if((mat[i] = (double*)malloc(ncol*(sizeof(double)))) == NULL){
printf("\nErrore nell'allocazione delle colonne della matrice o spazio insufficiente\n");
exit(0);
}
}

i = 0;



Ora vorrei inzializzarla, ma evitare due cicli for, ma uno unico che acceda in maniera
monodimensionale alla matrice, trattandola di fatto come un array.


for(i=0; i<nrow*ncol; i++)
mat[i] = 0;

return mat;
}


Il programma arrivato all'ultima cella (ho fatto dei printf di debug), crasha.
Perchè? Grazie anticipatamente.

MacApp
01-05-2008, 07:31
Se allochi per righe e colonne, allora devi inizializzare/accedere per righe e colonne.
Se vuoi inizializzare/accedere in modo linearizzato, allora devi allocare in modo linearizzato.

Il tuo programma crasha perché allochi per righe e colonne e poi pretendi d'inizializzare/accedere in modo linearizzato:

L'ultimo elemento valido è "mat [nrow -1]" e contiene un puntatore a double.. se vai oltre (e tu vai a mat [nrow*ncol -1]) il comportamento è giustamente indefinito. Che poi ti crashi solo all'ultimo elemento, e non prima, non importa: sempre comportamento indefinito è.

^EvAmPiReS^
01-05-2008, 20:11
Grazie la risposta è quello che temevo...
Quindi creando una matrice con double** non è possibile inizializzarla
utilizzando l'accesso linearizzato?

Scusate l'ignoranza :incupito:

oregon
01-05-2008, 20:13
Se ci pensi un po', con quel metodo crei un array di puntatori per le colonne.

Tutti quei puntatori che crei puntano a zone di memoria non necessariamente contigue ...

mondobimbi
01-05-2008, 20:19
tu hai inizializzato un vettore di puntatori a double di dimensione n_righe.
Il primo elemento del tuo vettore contiene un puntatore a un vettore di double di dimensione n_colonne. I dati relativi a questi vettore non è detto che siano contigui.

In alternativa potevi dichiarare un double matrice[][]; , che ha la struttura che tu ti aspetti.

ciao
sergio

^EvAmPiReS^
01-05-2008, 23:06
Si pensando alla struttura dati che ho allocato ho capito che l'accesso
che volevo è insensato.
In ogni caso matrice[][] mi precluderebbe di modificare la suddetta (e non una copia),
visto che la devo poi far tornare alla funzione per usarla altrove ed inoltre posso
mantenere la sua dinamicità a livello di allocazione di memoria?

Spero di essere stato chiaro, son di fretta scusate. :nonlodire

:ciauz:

MacApp
01-05-2008, 23:28
Io con le matrici numeriche ho sempre trovato più semplice linearizzare.
Ti allochi un bel vettore di dimensioni righe per colonne, quindi ti fai le funzioni per accedervi.

Chiaramente troverai conveninente sviluppare una funzioncina che permetta di trasformare le coordinate matriciali nell'indice del vettore e viceversa.

Alla lunga converrai di mettere il vettore e le sue dimensioni in una struttura, e le varie funzioncine d'accesso opereranno su quella struttura.

Insomma astrarrai il problema, e volendo potrai scegliere al volo se internamente utilizzare una vera matrice od un vettore.

Così avrai pure, senza rendertene conto, iniziato a programmare ad oggetti.

L'ho fatta breve, ma il percorso ideale è quello.

;-)

EDIT:
Ad esempio per allocare un vettore lineare di dimensioni n = righe * colonne:


double * NewMatrixOfDouble (const int theMatrixNumRow, const int theMatrixNumCol){
return (double *) malloc (theMatrixNumRow * theMatrixNumCol * sizeof (double));
}

mondobimbi
01-05-2008, 23:45
la matrice la puoi allocare staticamente se conosci a priori le sue dimensioni con la notazione

double mat[row][col];

o dinamicamente con

double *mat = (double *) malloc(row*col);

In questo caso per accedere ai valori della tua matrice non puoi più utilizzare la notazione mat[][] ma eseguire un semplice calcolo mat[i*row+j].
Questa soluzione chiede al sistema operativo un blocco contiguo di memoria di dimensioni row*col, il metodo che utilizza invece il puntatore di puntatori ha il vantaggio di non richiedere un blocco continuo (che potrebbe causare problemi nel caso di matrici molto estese) ma permette anche di avere eventualmente vettori tutti di dimensioni differenti.
ciao
sergio

oregon
01-05-2008, 23:48
Originariamente inviato da mondobimbi
o dinamicamente con

double *mat = (double *) malloc(row*col);


Sergio ... non basta il row*col ... hai dimenticato il sizeof(double) ...

mondobimbi
02-05-2008, 07:39
ovviamente :dhò:

Loading