Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Ho iniziato a studiare le matrici dinamiche, non ho capito come devo fare per passare ad una stessa routine una matrice dinamica o una matrice statica.
Il seguente codice ha una void che visualizza il contenuto di una matrice con due dimensioni uguali, funziona correttamente con le matrici statiche, ma non se la matrice è stata inizializzata in runtime, pensavo di aver sbagliato l'uso di malloc, ma se stampo la matrice dinamica senza passare per la routine, la matrice sembra allocata e riempita correttamente:
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdlib.h>
#define DIM 5
int**dinamica;
int statica[DIM][DIM];
void visualizza(int m[DIM][DIM]){
for(int r=0; r<DIM; r++){
printf("\n");
for(int c=0; c<DIM; c++){
printf("%02d ",m[r][c]);
}
}
printf("\n\n");
}
int main()
{// riempio la matrice statica a due dimensioni come fosse un vettore seriale
printf("Matrice statica a due dimensioni riempita serialmente");
int*s=*statica;// s punta l'inizio della matrice
for(int i=0; i<DIM*DIM; i++){
s[i]=i;// posso riempire serialmente
}
visualizza(statica);// funziona
// alloco una matrice dinamica a due dimensioni
dinamica =(int**)malloc(DIM*sizeof(int*));
for(int r=0; r<DIM; r++)
dinamica[r]=(int*)malloc(DIM*sizeof(int));
// riempio la matrice dinamica per riga e colonna
for(int r=0; r<DIM; r++){
for(int c=0; c<DIM; c++){
dinamica[r][c]=c+r*DIM ;
}
}
printf("Matrice dinamica visualizzata errata con routine");
visualizza(dinamica);// ho un warning puntatore incompatibile! come si deve passare?
printf("Matrice dinamica visualizzata direttamente e correttamente");
for(int r=0; r<DIM; r++){
printf("\n");
for(int c=0; c<DIM; c++){
printf("%02d ",dinamica[r][c]);
}
}
printf("\n\n");
// dealloco
for(int r=0; r<DIM; r++)
free(dinamica[r]);
free(dinamica);
return0;
}
se modifico la dichiarazione della void in:
Codice sorgente - presumibilmente C/C++
void visualizza(int **m)
la routine visualizza(), funziona con la matrice dinamica ma non funziona con la matrice statica...
Ultima modifica effettuata da Carlo il 11/02/2021 alle 13:01
Ho cercato e ricercato una soluzione al tuo quesito, trovando diverse pagine che mi davano soluzioni sicuramente corrette (alcune facevano capo a siti universitari) ma che non son riuscito a sentire vicine al mio modo di intendere le cose. Così ho provato a cercare una via d'uscita tutta mia -- come al solito ti metto in guardia, ricordandoti che non sono un esperto e che potrei prendere cantonate di tutto rispetto. Detto questo, ecco cosa ho pensato...
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdlib.h>
void visualizza(void*m, size_t qr, size_t qc){
int r, c, *mi = m;
for( r=0; r<qr; r++)
for( c=0; c<qc; c++)
printf("%02d%c", mi[r*qr+c], c!=qc-1?' ':'\n');
}
int**crea_matrice(size_t qr, size_t qc ){
int**m =NULL;
if(0!=qr &&0!=qc ){// deve poter contenere qualcosa!
m =calloc( qr*sizeof(*m)+ qr*qc*sizeof(**m), 1 );// un unico blocco
if(NULL!= m ){
size_t r;
for( r=0; r<qr;++r )
m[r]=(int*)((m+qr)+r*qc);// colloca i puntatori alle righe
// in testa al blocco allocato in m
}
}
return m;
}
int main(){
constint qr =5;// qr: quantita' righe
constint qc =5;// qc; quantita' colonne
int statica[qr][qc];
int**dinamica =NULL;
int i, r, c, *s;
// riempio la matrice statica a due dimensioni come fosse un vettore seriale
free( dinamica );// dealloco; avendo allocato un unico blocco, la
// deallocazione si risolve in un'unica chiamata
return0;
}
Noterai che ho usato un metodo di allocazione della matrice dinamica diverso da quello che hai usato tu. Col mio metodo ( lo trovi "isolato" in crea_matrice() ) finisci per avere un unico blocco allocato, con tutti i puntatori "in testa", seguiti dai dati in posizioni contigue.
A quel punto, per far "digerire" al compilatore C (non C++!) il passaggio di puntatori diversi, ho usato un generico void*, che viene convertito in int** all'interno di visualizza(). L'idea è passare alla funzione l'indirizzo al primo elemento del blocco di memoria dove si trovano, in posizioni contigue, tutti i dati. Per far questo, quando tratto la matrice dichiarata come int statica[qr][qc] passo statica e basta, mentre quando tratto la matrice allocata con crea_matrice() passo statica+qr per "passare oltre" allo spazio riservato ai puntatori in testa al blocco.
Lo so che è una forzatura, prendila per quel che vale.
Ultima modifica effettuata da AldoBaldo il 10/02/2021 alle 23:03
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
Bingo!!
Con il tuo esempio e altre ricerche, ho capito che la mia dichiarazione di matrice dinamica, è una collezione di doppi puntatori che non necessariamente puntano a zone contigue di memoria.
Infatti tu hai allocato un unico blocco, ho variato un po', ora la matrice dinamica si comporta come la matrice statica:
printf("dinamica 2dim riempita serialmente e visualizzata con routine a indici\n");
pd=*dinamica;// pd punta l'inizio della matrice
for(i=0; i<DIMr*DIMc; i++) pd[i]=(i+1)*2;// posso riempire serialmente, tabellina del 2
visualizza(pd);// funziona
free(dinamica[0]);
free(dinamica);
return0;
}
Ho cercato di trovare una forma più logica per me, perché così sono in grado di ricordarla.
Il tuo codice mi ha dato delle dritte e delle conferme, ma ha aperto ulteriori dubbi, l'ho archiviato tra gli esempi da studiare.
Sai dove applicherò tali nuove conoscenze!
Ultima modifica effettuata da Carlo il 27/02/2021 alle 0:09
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.