PDA

Visualizza la versione completa : [c++] Passaggio di un array di oggetti bidimensionale ad una funzione


Kreator
23-12-2004, 18:50
Ciao raga.

Volevo sapere come si puo' fare per passare ad una funzione generica, un array bidimensionale di oggetti (ad es. TBoat[Rows][Columns]).

Mi bastano le signature delle funzioni ...
tipo:

Chiamante:
Function1(...);

Chiamato:
void __fastcall Function1 (...);

:dhò: :dhò: :dhò: :dhò:

anx721
23-12-2004, 20:58
Se allochi l'array staticamente, quindi sai a compile time le dimensioni:



#define ROWS 10
#define COLUMNS 10


void fun(tipo array[ROWS][COLUMNS]);


quindi nel main dichiari un array:



tipo array[ROW][COLUMNS];


e invochi la funzione:



fun(array);



Se allochi dinamicamente l'array:




void fun(tipo **array, int rows, int cols){
...
...
...
}


quindi crei il vettore e chiami la funzione:



tipo ** array = (tipo**)malloc(rows * sizeof(tipo *));
for(int i = 0; i < cols; i++)
array[i] = (tipo *)malloc(cols * sizeof(tipo));
//eventuale codice per inizializzare gli elementi dell'array
//...
fun(array, roes, cols)



In C++ puoi anche usare new per allocare l'array e avere un puntatore al primo elemento.

Kreator
24-12-2004, 10:55
ti spiego meglio ...
Il fatto e' che ho un array bidimensionale di questo tipo:



#define DRows 2000
#define DColumns 2000

TBoat *FSectionBoat[DRows][DColumns]


con le define definisco il numero massimo di celle, poi la dimensione massima fino a dove arrivare ad allocare l'array e' definita da due variabili:

int FRows;
int FColumns;

Questo array lo devo passare alla funzione generica ... ed e' dinamico ... come posso fare ?

Sostanzialmente non basterebbe passare solamente l'indirizzo dell'array ?

Io lo passo in questa maniera ma mi da errore dicendomi che non risce a trovare un match tra la funzione chiamante e la funzione chiamata ... ecco come ho fatto io:

nel main:

ThreadNewProfile = new TThreadLoadNewProfile (false, PrincipalForm, FSectionBoat, FRows, FColumns);

la signature del costruttore del thread e' questa:

__fastcall TThreadLoadNewProfile(bool CreateSuspended, TComponent *_PrincipalForm, TBoat **_Boat, int ARows, int AColumns);

pprllo
24-12-2004, 11:21
Guarda mi sa che fai prima a fare:


void func(TBoat *Sections[DRows][DColumns], int rows, int columns);


Non è molto elegante ma funziona.

Oppure potresti fare nella funzione un ciclo che va avanti finchè l'elemento a cui arriva non è null. Tipo:


void func(TBoat *Sections[DRows][DColumns])
{
int i, j;
for(i = 0, j = 0;Secttions[i][j]!=0;i++, j = 0)
for(;Sections[i][j]!=0;j++)
{
// Fai qualcosa
}
return;
}

Naturalmente, nel codice del main, dovrai premurarti che per ogni riga e per ogni colonna l'ultimo elemento sia un puntatore null:


//scrivi gli elementi della colonna
Sections[CurrentRow][LastColumn] = 0;
//Ripeti per tot volte
//Alla fine
Sections[LastRow][FirstColumn] = 0;
func(Sections);

pprllo
24-12-2004, 11:26
Il tuo codice non funziona perchè tu passi un array bidimensionale di puntatori. Cioè:
Array bidimensionale di puntatori =
Array di array di puntatori =
Array di puntatori a puntatori =
Puntatore a puntatore a puntatore.
Sarebbe tipo TBoat ***Sections, ma la conversione da TBoat
*Sections[][] a TBoat ***Sections non riesce, quindi meglio che fai come ho scritto io.

pprllo
24-12-2004, 11:29
Come esempio pratico di quanto detto prima, eccolo fatto con gli int:


#include <iostream>
using namespace std;

void func(int *array[3][4]);

int main()
{
int *array[3][4];

array[0][0] = new int(3);
array[0][1] = new int(4);
array[0][2] = 0;
array[1][0] = new int(5);
array[1][1] = new int(6);
array[1][2] = 0;
array[2][0] = 0;

func(array);
}

void func(int *array[3][4])
{
int i, j;
for(i = 0, j = 0;array[i][j]!=0;i++, j = 0)
for(;array[i][j]!=0;j++)
{
cout << *array[i][j];
}
return;
}

Kreator
24-12-2004, 11:53
Perfetto ora ho risolto grazie mille.

Ti volevo chiedere una cosa.
Dentro il costrutture del mio thread mi devo ad andare ad allocare quel parametro TBoat *_Boat[MAX][MAX] ad un array sempre delle stesse dimensioni e dello stesso tipo:

TBoat *GlobalBoat[MAX][MAX]

appartenente esclusivamente al thread.

Ho provato a fare un assegnazione normalissima:

GlobalBoat = _Boat;

ma mi da errore e mi dice: L value required

Perche' ?

pprllo
24-12-2004, 12:02
Perchè con gli array l'istruzione di assegnazione "=" non funziona. L'unico modo che hai è fare una copia elemento per elemento con una funzione tipo quella che ho scritto nel post precedente :)

Kreator
24-12-2004, 12:08
ma allora mi sorge spontanea una domanda ...
se non posso utilizzare l'operatore = significa che a quel punto non ho + un riferimento ma bensi' una copia, giusto ???
Quindi la domanda e' questa ... come faccio a modificare direttamente l'array che io passo al costruttore del thread, quando le vere operazioni di modifica devono essere effettuate nella parte Execute () del thread ?

pprllo
24-12-2004, 12:18
Se tu hai un array di puntatori e copi gli elementi dell'array, le copie saranno puntatori che punteranno alla stessa zona di memoria, quindi effettivamente modificando i valori puntati dall'array copia, modificherai anche quelli puntati dall'array originale. Per avere 2 array completamente indipendenti, devi invece fare una cosa tipo (sempre riferendomi all'esempio di prima):


void func(int *array[3][4])
{
int *secondarray[3][4]
int i, j;
for(i = 0, j = 0;array[i][j]!=0;i++, j = 0)
{
for(;array[i][j]!=0;j++)
{
secondarray[i][j] = new int();
*secondarray[i][j] = *array[i][j];
}
secondarray[i][j] = array[i][j];
}
secondarray[i][j] = array[i][j];
//Quello che vuoi.
}

Per avere invece un array che punti ai valori originali basta:


void func(int *array[3][4])
{
int *secondarray[3][4]
int i, j;
for(i = 0, j = 0;i<3;i++, j = 0)
for(;j<4;j++)
{
secondarray[i][j] = array[i][j];
}
return;
}

Loading