View Full Version : [c++]array bidimensionali
FagioloOne
18-03-2006, 15:06
Sono un programmatore autodidatta perciò se il problema è stupido, o dovuto alla mia ignoranza mi scuso già in precedenza.
Devo creare una funzione che dato un determinato array me lo ridia indietro modificato, come unico valore qualcuno mi sa aiutare. Il mio libro non spiega un bel niente e tutte le mie prove con i puntatori sono stati infruttuose, grazie in anticipo per le vostre eventuali risposte.
Ziosilvio
18-03-2006, 18:14
Non ti sei spiegato molto bene.
Devi manipolare i valori delle componenti di un array bidimensionale?
Oppure devi ottenere un singolo valore, che in qualche modo ti rappresenta l'intero array (ad esempio: una stringa hash)?
Comunque, visto che parli di array bidimensionali... si possono fare, con un trucco.
Quando tu dichiari, ad esempio, "int m[5][6]", m è un array (statico) di 5 array (statici) a 6 componenti intere. Tu vuoi riprodurre questo comportamento con i puntatori, in modo da poter allocare la matrice in modo dinamico.
La prima difficoltà sta nel capire il tipo giusto.
Se m fosse un array di int, e tu lo passassi a una funzione, esso verrebbe convertito in un puntatore di tipo int* (al suo primo elemento): ma dato che m è un array di array, dovrebbe essere convertito in un puntatore ad array di int anziché ad int. Effettuando un'altra conversione, viene fuori che m deve diventare un puntatore a puntatore a int.
Adesso che hai capito che tipo di oggetto devi trattare, devi capire come farlo.
Anzitutto, devi allocare la memoria giusta: se la matrice ha rows righe e cols colonne, allora è chiaro che dovrai allocare prima un vettore di rows vettori di int, e poi rows vettori di cols int.
Ad esempio:
int **matrix_alloc(int rows, int cols)
{
int i, **p;
p = (int**)malloc(rows*sizeof(int*));
if (p==NULL)
return NULL;
for (i=0; i<rows; i++)
{
p[i] = (int*)malloc(cols*sizeof(int));
if (p[i]==NULL) break;
}
if (i<rows) /* l'inizializzazione della riga i-esima e' fallita */
{
for (--i; i>=0; i--)
free(p[i]);
free(p);
return NULL;
}
return p;
}
Nota la sintassi di inizializzazione delle righe: dato che p è un puntatore, p[i] ha lo stesso significato di *(p+i). Questo torna utile quando devi scrivere i valori delle componenti della matrice:
m[i][j] = my_expr();
Per deallocare, liberi prima le singole righe, e poi il vettore:
void matrix_dealloc(int **p, int rows)
{
int i;
for (i=0; i<rows; i++)
free(p[i]);
free(p);
}
wingman87
18-03-2006, 19:49
Ho sentito dire che la memoria va disallocata nell'ordine inverso a quello in cui la si è allocata, un po' come fa il tuo programma quando dice "l'inizializzazione della riga i-esima e' fallita".
Non so spiegarti bene il perchè ma da quel che ho capito quando disallochi la memoria parte dal puntatore che gli dai fino alla fine+1, andando a fare un casino poi nei puntatori successivi.
anche io non ho capito benissimo la domanda.
Parli di C++ (quindi classi, ereditarieta', eccezioni...) e array.
Hai bisogno di una funzione che modifichi un array.
Da quanto dici immagino che l'array esista gia' e tu non lo debba creare (in caso contrario ti e' gia' stato spiegato come fare, anche se, in C++, e' meglio usare new[], delete [] e try/catch(std::bad_alloc)).
Immagino quindi diverse possibilita':
1) hai una CLASSE che implementa il tipo di dato array (e, dal titolo del tuo thread, immagino array bidimensionale)
In questo caso, dovresti creare una funzione del tipo
void Mastrussa(CMatrix& mat)
{
[...]
funzioni varie che elaborano e modificano "mat"
}
Nota che in realta' si passa il reference dell'istanza di una classe: e' questo che ti permette di "cambiare" all'interno della funzione il parametro, pe meglio dire NON viene creata una copia del parametro ma elaborato DIRETTAMENTE il parametro passato.
Al termine della funzione "mat" sara' restituita al chiamante modificata.
2) tu hai gia' una classe che implementa la matrice e vuoi aggiungere un metodo che elabori i dati in essa contenuti e restituisca un qualche risultato su questi, ad esempio per il calcolo del deteminante di una matrice
Allora dovresti avere una cosa del tipo
class CMatrix
{
[...]
public:
double determinante() const
throw(std::runtime_error);
dove:
1 - "const" si ha perche' il calcolo del determinante non porta ad alcuna modificazione dei dati interni della matrice;
2 - la throw e' per comunicare al chiamante eventuali errori (ad esempio nel caso in cui si sia chiesto il determinante di una matrice NON quadrata)
e quindi dovresi implementare la funzione:
double CMatrix::determinante const
{
if (this->rows() != this->columns())
throw std::runtime_error("Matrice non quadrata, determinante impossibile");
// calcolail determinante
}
In questo caso puoi avere il determinate della matrice come:
CMatrix mat;
// popola mat in qualche modo
double det;
try
{
det = mat.determinante();
std::cout << "Determinante = " << det << std::endl;
}
catch (const std::exception& e)
{
std::cerr << "Impossbile calcolare il determinante - " << e.what() << std::endl;
}
Se invece la tua funzione deve cambiare in qualche modo i dati della matrice la funzione non dovra' essere const, ad esempio
/**
* \brief Inverte la matrice
*
* \throw std::runtime_error in caso di errori
*/
void inverti() throw(std::runtime_error);
E il codice per la chiamata:
CMatrix mat;
try
{
mat.inverti();
std::cout << "Matrice inversa: " << std::endl << mat << std::endl;
}
catch (const std exception& e)
{
std::cerr << "Impossibile invertire matrice - " << e.what() << std::endl;
}
3) (caso comune al C)
hai un array bidimensionale e devi creare una funzione che ne cambi i valori.
In questo caso, visto che in realta' per passare un array devi passare un puntatore, tu passi gia' i valori "per reference" (be', in realta' passare un puntatore e' il modo del C per implementare il passaggio di parametri per reference), quindi modifichi gia' la matrice
Un ultima cosa:
per gli array monodimensionali in C e' lecito scrivere
void funzione(int the_array[])
ovvero indichi alla funzione che trattera' un array ma non specifichi le dimensioni
Per i bi-dimensionali invece NON e' possibile scrivere
void funzione(int the_matrix[][])
Devi indicare almeno una delle dimensioni (mi sembra la seconda, ma non ricordo bene). Immagiono che questo limite sia dovuto a come vengono memorizzate in C le matrici in un unico blocco di memoria contiguo...
Ciao,
Mr Hyde
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.