Nessun problema. Nota che io ti ho offerto 2 coppie di funzioni in ogni caso: una usa malloc e free, l'altra new e delete.
Se c'è qualcosa che non capisci chiedi pure (:
![]()
Nessun problema. Nota che io ti ho offerto 2 coppie di funzioni in ogni caso: una usa malloc e free, l'altra new e delete.
Se c'è qualcosa che non capisci chiedi pure (:
![]()
"Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares
Ciao scara! Il tuo programma funziona correttamente, ho preferito utilizzare le funzioni con new int e delete che, a mio parere, sono più semplici da ricordare e da scrivere. Ho continuato il programma, ora è a buon punto, ho aggiunto una funzione che mi calcola l'indice minimo nelle colonne, te lo faccio vedere
Però ti vorrei chiedere alcune cose. Nel programma mi è quasi tutto chiaro, devo solo capire, qual'è precisamente la funzione di new int? La funzione di delete è quella di liberare la memoria altrimenti si appesantisce il sistema, ma new int, prima di size nella prima funzione, a che serve precisamente?codice:#include <iostream> #include <fstream> #include <cstdlib> using namespace std; int **readMat(int**&m, size_t& size) { ifstream in("mat.txt"); in >> size; m = new int *[size]; for(int i = 0; i < size; ++i) m[i] = new int[size]; for(int i = 0; i < size; ++i) for(int j = 0; j < size; ++j) in >> m[i][j]; return m; } void freeMat(int **&m, size_t size) { for(int i = 0; i < size; ++i) delete[] m[i]; delete[] m; } int calc_ind_min(int **&m,int size,int r) { int min=m[r][0]; int i,indmin=0; for (i=0;i<size;i++) { if (m[r][i]<min) { min=m[r][i]; indmin=i; } } cout<<indmin; return indmin; } int main(void) { size_t size; int **m; readMat(m, size); for(int i = 0; i < size; ++i) { for(int j = 0; j < size; ++j) cout << m[i][j] << '\t'; cout << endl; } int r; for(r=0;r<size;r++) { calc_ind_min(m,size,r); } freeMat(m, size); return 0; }
E poi, size_t che tipo è? Ha la stessa funzione di unsigned int? Grazie per il tuo tempo!!
Un consiglio, mai eseguire istruzioni di input output all'interno di una funzione che non dovrebbe prevedere IO, come quella che hai scritto tu.
Quindi parto con qualche correzionePassiamo ora a rispondere alle tue domande.codice:void freeMat(int **&m, size_t size) { for(int i = 0; i < size; ++i) delete[] m[i]; delete[] m; //correzione sul mio stesso codice :D anche se non strettamente necessaria m = NULL; //in caso di doppia deallocazione non lancia errore } int calc_ind_min(int ** m,int size,int r) //non è necessaria &, ti lascio approfondire { int min=m[r][0]; int i,indmin=0; for (i=0;i<size;i++) { if (m[r][i]<min) { min=m[r][i]; indmin=i; } } //meglio evitare IO all'interno di funzione non create SPECIFICATAMENTE per IO return indmin; } //... for(r=0;r<size;r++) { cout << calc_ind_min(m,size,r); } //...
size_t non è altro che un intero positivo che rappresenta le grandezze in bytes, è definito proprio come typedef unsigned int size_t;.
Analizziamo la funzione per l'allocazione della matrice. In particolare, assumendo size l'ordine della matrice quadrata e m una variabile int **,Per l'allocazione della matrice non la si considera come tale, ma come array di array: ad esempio la matricecodice:m = new int *[size]; for(int i = 0; i < size; ++i) m[i] = new int[size];è rappresentata dome un arraycodice:m 1 2 3 4 5 6 7 8 9dove A B C sonocodice:m = A B CPerciò l'allocazione di divide in due parti: una prima parte che alloca un array di puntatori ad intericodice:A = 1 2 3 B = 4 5 6 C = 7 8 9e una parte dove ad ogni puntatore è assegnato un array di intericodice:m = new int *[size];La deallocazione avviene all'inverso, prima si deallocano i blocchi interni, poi quelli esterni. Qui per la precisione si parla di jagged arrays. Puoi cercare su internet.codice:for(int i = 0; i < size; ++i) m[i] = new int[size];
"Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares
Aggiungo solo una coppia di brevi esempi (ormai una FAQ) sull'allocazione dinamica "da manuale" di array multidimensionali.
Esempio di base, volutamente incompleto:
Esempio di allocazione indiretta, entro una funzione accessoria.codice:#include <stdio.h> #include <stdlib.h> int main(void) { size_t righe, colonne, i, j; int **matrice; printf(" Righe........: "); scanf("%d", &righe); printf(" Colonne......: "); scanf("%d", &colonne); puts(""); matrice = (int **)malloc(righe * sizeof(int *)); if (NULL == matrice) { fputs("Errore di allocazione base array !\n", stderr); return 1; } for (i = 0; i < righe; ++i) { int *p; p = (int *)malloc(colonne * sizeof(int)); if (NULL != p) { matrice[i] = p; } else { fprintf(stderr, "Errore di allocazione alla riga %d!\n", i); while (i--) { free(matrice[i]); } free(matrice); return 2; } } for(i = 0; i < righe; ++i) { for(j = 0; j < colonne; ++j) { printf("Inserisci elemento riga %d e colonna %d: ", i, j); scanf("%d", &matrice[i][j]); puts(""); } } for(i = 0; i < righe; ++i) { printf("matrice[%d] = {%d", i, matrice[i][0]); for(j = 1; j < colonne; ++j) { printf(", %d", matrice[i][j]); } puts("}"); free(matrice[i]); } free(matrice); return 0; }
Infine, un esempio ancora più avanzato che mostra una panoramica di metodi di allocazione dinamica a vari livelli di indirezione.codice:/************************************************************************/ /** Scopo del programma:...............................................**/ /************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <assert.h> #define ASIZE (8) typedef enum {FALSE, TRUE} Bool_t; Bool_t matrix_alloc(int ***m, const size_t row, const size_t col) { size_t i; assert(row > 0); assert(col > 0); /* ** PRIMO STEP: allocazione array di base */ *m = (int **)malloc(row * sizeof(int *)); if (NULL == *m) { fputs("Errore di allocazione base array !\n", stderr); return (FALSE); } for (i = 0; i < row; ++i) { int *p; /* ** SECONDO STEP: allocazione di ogni singolo array-riga */ p = (int *)malloc(col *sizeof(int)); if (NULL != p) { /* ** TERZO e ULTIMO STEP: collegamento riga ad array base */ (*m)[i] = p; } else { fprintf(stderr, "Errore di allocazione alla riga %d!\n", i); while (i--) { free((*m)[i]); fprintf(stderr, "%d ", i); } free(*m); return (FALSE); } } return (TRUE); } int main(void) { int **array; size_t righe, colonne; size_t i, j; Bool_t status; righe = ASIZE; colonne = ASIZE; printf("Allocazione dinamica di un array " "bidimensionale %d x %d\n", righe, colonne); status = matrix_alloc(&array, righe, colonne); if(status) { printf("** Allocazione effettuata. " "Inizializzazione di %d celle in corso...\n", righe * colonne); for (i = 0; i < righe; ++i) { for (j = 0; j < colonne; ++j) { array[ i ][ j ] = i * 10 + j; } } puts("** Contenuto dell'array:"); for (i = 0; i < righe; ++i) { for (j = 0; j < colonne; ++j) { printf( "array[%d][%d] = %02d\n", i, j, array[ i ][ j ]); } free(array[i]); } free(array); } return (EXIT_SUCCESS); }/* EOF: alloc_array.c */
Aggiungo solo un paio di note che forse potranno tornare utili all'OP solo in una fase più avanzata dello studio.
1) L'uso di jagged arrays va imparato (per scopi scolastici) e poi dimenticato. Nel real world l'allocazione in un blocco unico impera nel 99% del codice, per motivi che spaziano dalle prestazioni, alla robustezza, alla manutenibilità del codice: i rari casi nei quali si ricorre ad un array di arrays come nella manualistica e nella didattica sono legati, ad esempio, alla rappresentazione di matrici sparse e/o di array di liste, alberi ed altri ADT che possano beneficiare della potenzialità di una simile struttura, ossia la capacità di referenziare con un solo array di base altri array di lunghezze potenzialmente molto diverse tra loro.
2) In linguaggio C++ è comunque del tutto sconsigliato l'uso degli array C-alike. Esistono apposite classi come vector, valarray, list, string e altre. Si veda questo famoso thread per una spiegazione in merito.
Ultima modifica di M.A.W. 1968; 11-06-2014 a 13:42
• Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.
Ringrazio entrambi! Quindi Scara se ho capito bene non sempre devo dichiarare parametri di I/O per le funzioni? Ma se non lo faccio non rischio che il compilatore mi dia errori?
Mi è molto più chiaro lo scopo di size_t, e ho compreso concettualmente come funziona l'allocazione di array di array! Inoltre poco fa ho aggiunto una nuova funzione al mio programma, completandolo. Ecco qui:
codice:#include <iostream>#include <fstream> #include <cstdlib> using namespace std; // lettura matrice da file + allocazione int **readMat(int**&m, size_t& size) { ifstream in("mat.txt"); in >> size; m = new int *[size]; for(int i = 0; i < size; ++i) m[i] = new int[size]; for(int i = 0; i < size; ++i) for(int j = 0; j < size; ++j) in >> m[i][j]; return m; } // Liberazione memoria void freeMat(int **&m, size_t size) { for(int i = 0; i < size; ++i) delete[] m[i]; delete[] m; } // Calcolo del minimo delle righe int calc_ind_min(int **m,int size,int r) { int min=m[r][0]; int i,indmin=0; for (i=0;i<size;i++) { if (m[r][i]<min) { min=m[r][i]; indmin=i; } } return indmin; } // Calcolo del massimo delle colonne + calcolo e stampa del punto di sella int trova_punto_sella(int**m,int size, int t) { int sella; int posc; posc = calc_ind_min(m,size,t); int maxcol=m[t][posc]; for(int i=0;i<size;i++) { if(maxcol<m[i][posc]) maxcol=m[i][posc]; } if(maxcol==m[t][posc]) { sella=maxcol; cout<<sella<<" Punto di sella in posizione "<<t<<" "<<posc<<endl; return sella; } else return -1; } int main(void) { size_t size; int **m; readMat(m, size); // stampa a video della matrice allocata for(int i = 0; i < size; ++i) { for(int j = 0; j < size; ++j) cout << m[i][j] << '\t'; cout << endl; } int r; for(r=0;r<size;r++) { calc_ind_min(m,size,r); } cout << endl; cout << endl; int t; for(t=0;t<size;t++) { trova_punto_sella(m,size,t); } freeMat(m, size); return 0; }
Ultima modifica di DaemonDestroyer; 11-06-2014 a 16:00
Ti ringrazio MAW per i materiali da te fornitomi, poiché sono diciamo nella fase iniziale dello studio del C++, mi saranno molto utili. Mi permetto di dire, che spesso confronti come questo sui forum (almeno nel mio caso) risultano molto più utili alla comprensione e allo studio dei linguaggi informatici che non leggere dai libri universitari, spesso non molto chiari...
No hai mal interpretato: devi evitare operazioni di IO all'interno delle funzioni se non create appositamente per quello scopo, cioè devi evitare cin>> cout<< ...
Il principio è: se non è necessario alla funzione non includerlo nella funzione, ma nel main.
Concordo con M.A.W. che è molto migliore l'allocazione di un blocco unico.
"Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares