Passer un tableau int de longueur variable en tant que paramètre de fonction dans Objective C
-
05-07-2019 - |
Question
J'ai le code suivant qui fonctionne très bien ...
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: testarr];
Qui appelle cette fonction:
- (void)testCall: (int[3][3]) arr {
NSLog(@"cell value is %u",arr[1][1]);
}
J'ai besoin que le tableau soit de longueur variable - Quel est le meilleur moyen de déclarer la fonction?
L'utilisation de blancs ne fonctionne pas:
- (void)testCall: (int[][]) arr {
Merci de votre aide.
La solution
J'écrirais ceci comme suit:
- (void) testCall: (int *) aMatrice;
Cela vous permet d'éviter plusieurs mallocs et que le calcul permettant de calculer un seul décalage dans un tableau linéaire en fonction des coordonnées x, y d'un tableau 2D est trivial. Cela évite également les multiples mallocs impliqués par int ** et les limitations de la syntaxe de tableau 2D perpétuée par le langage.
Donc, si vous vouliez un tableau 4x5, vous pourriez faire:
#define WIDTH 4
#define HEIGHT 5
#define INDEXOF(x,y) ((y*WIDTH) + x)
int *myArray = malloc(sizeof(int) * 5 * ELEMS_PER_ROW);
Vous pouvez ensuite initialiser le tableau de manière linéaire ou avec une boucle imbriquée:
for(int x=0; x<width; x++)
for(int y=0; y<height; y++)
myArray[INDEXOF(x,y)] = ... some value ...;
Et vous le transmettriez à la méthode suivante:
[foo testCall: myArray];
Bien que vous souhaitiez également conserver la largeur et la hauteur ou, mieux encore, créer une sous-classe IntMatrix de NSObject qui englobe toute l'arithmétique du pointeur et le stockage au-delà d'une belle API propre.
(tout le code est entré dans SO)
Autres conseils
Les tableaux C ne peuvent pas être variables dans plusieurs dimensions.
Vous ne pouvez pas avoir ceci:
int testarr[][] = {
{1,1,1},
{1,0,1,2},
{1,1}
};
Mais vous pouvez avoir ceci:
int testarr[][3] = {
{1,1,1},
{1,0,1},
{1,1,1},
{4,5,6},
{7,8,9}
}
foo(testarr);
void foo(int param[][3])
{
printf("%d", param[3][1]); // prints 5
}
Vous ne pouvez pas utiliser int [] []
car la taille de la deuxième dimension affecte la disposition du tableau en mémoire. Si vous connaissez la deuxième dimension, vous pouvez utiliser int [] [x]
, sinon vous devrez utiliser int **
auquel vous pourrez accéder comme un tableau.
Pourquoi n'utilisez-vous pas simplement NSArray
ou NSMutableArray
avec NSInteger
s? Ces classes de tableaux sont de longueur variable et beaucoup plus faciles à utiliser.
Cela se traduirait par
- (void)testCall: (NSArray *) arr {
NSLog(@"cell value is %u", [[arr objectAtIndex:1] objectAtIndex:1]);
}
(Bien entendu, vous devrez également définir testarr à l'aide de NSArray.)
Si vous voulez vraiment utiliser des tableaux en C, faites de l'argument de méthode un pointeur sur un entier avec
- (void) testCall: (int *) arr {
fonctionnera probablement (le reste du code restant identique).
appeler
int testarr[3][3] = {
{1,1,1},
{1,0,1},
{1,1,1}
};
[self testCall: (int *)testarr];
fonction
- (void)testCall: (int *) arr
{
int (*V_arr)[3] = (int(*)[3])arr;
NSLog(@"cell value is %u",V_arr[1][1]);
}