web-dev-qa-db-fra.com

en boucle à travers les valeurs enum

Est-il possible de parcourir les valeurs énumérées dans Objective-C?

32
Frank

Donné

enum Foo {Bar=0,Baz,...,Last};

vous pouvez itérer les éléments comme:

for(int i=Bar; i<=Last; i++) {
  ...
}

Notez que cela expose la nature vraiment-juste-un-int d'un C enum. En particulier, vous pouvez constater qu'une énumération C ne fournit pas vraiment de sécurité de type, car vous pouvez utiliser une valeur int à la place d'une valeur enum et inversement. De plus, cela dépend de l'ordre de déclaration des valeurs enum: fragile pour le moins. En outre, s'il vous plaît voir le commentaire de Chuck; si les éléments enum sont non contigus (par exemple, parce que vous avez spécifié des valeurs explicites et non séquentielles pour certains éléments), cela ne fonctionnera pas du tout. Beurk.

38
Barry Wark

C'est un peu un kludge (comme le concept entier donc ... hein ...) mais si vous allez le faire plusieurs fois, et que vous voulez être en mesure de faire face à la possibilité d'énums non contigus, vous pouvez créer un tableau (constante globale) et avoir (pour utiliser l'exemple de ennukiller) Directions directions [4] = {Est, Ouest, Nord, Sud}; et ensuite, dans votre boucle, vous pouvez parler des directions [i] plutôt que d'itérer directement sur les instructions elles-mêmes ... 

Comme je l'ai dit, c'est moche, mais c'est un peu moins fragile, je pense ...

8
Brian Postow

Si vous enum est défini comme suit:

enum Direction {  East,  West,  North,  South};

Vous pouvez le parcourir de cette façon:

for ( int direction = East; direction <= South; ++direction)
{
   /* Do something with Direction
}
7
ennuikiller

A la recherche de cela, je viens de concocter la solution suivante qui répondait à mes propres exigences. Je pensais poster ici pour les personnes cherchant quelque chose de similaire.

Dis que j'ai un enum.

typedef NS_ENUM (NSInteger, ISDirection) {
  ISDirectionUp,
  ISDirectionDown,
  ISDirectionLeft,
  ISDirectionRight
};

Pour pouvoir le parcourir en boucle, je définis la macro de préprocesseur suivante.

#define ISDirectionAllAsDir ISDirection dir = ISDirectionUp; dir <= ISDirectionRight; dir++

Ensuite, je l'utilise dans une boucle, en tant que telle:

for(ISDirectionAllAsDir) {
  NSLog(@"Direction %d", dir);
}

Cela place la logique d'itération à un endroit (la macro), ce qui augmente la maintenabilité du code. 

5
CloakedEddy

Pour les énumérations non contiguës, vous pouvez parcourir des valeurs valides en procédant comme suit:

enum {
    value_one   = 0,
    value_two   = 1,
    value_three = 3,
    value_max
}
for ( i = value_one; i < value_max; i++ )
{ 
    switch(i)
    {
        case value_one:
        case value_two:
        case value_three:
        case value_four:
        {
            /* ... Do something with valid enum value ... */
        }
        break;
        default:
            /* Found an invalid enum entry; ignore it */
        break;
    }
}
5
Matt Conway

La longueur (nombre d'éléments) de toute énumération peut être déterminée en obtenant le tableau de noms dans l'énumération et en utilisant la longueur du tableau. Utilisez la méthode GetNames de Enum. Enum.GetNames (enumType) .Length.

{
enum Pig { Snort, Sty, Oink, Curly };
const int Pig_Count = Enum.GetNames(typeof(Pig)).Length;
}
2
GhengisDon

J'aime ce que j'ai obtenu d'ici Itération d'enum dans Objective C?

typedef enum { ENUM1=0,  ENUM2, ENUM3, ENUM4 , TOTAL  } ;


for ( int i=ENUM1 ; i<TOTAL; i++)
{}

de cette façon, vous pourrez continuer à ajouter des énumérations plus tard et ne pas affecter vos boucles?

1
yeahdixon

Je déteste salir mon enum avec une entrée "Last" (et la note d’accompagnement indiquant qu’il ne doit pas être utilisé et qu’il doit toujours être conservé, enfin) et que je n’ai trouvé aucun moyen de le contourner en utilisant la dernière entrée enum comme un "dernier" secret, ce qui, encore une fois, me fait me sentir mal).

Si vous définissez votre enum en utilisant X Macros , vous pouvez très simplement compter le nombre d'éléments dans votre enum. Voir le lien FMI sur l'utilisation de cette approche. Pour résumer, voici à quoi cela ressemble:

#define COLOR_TABLE \
X(red, "red")       \
X(green, "green")   \
X(blue, "blue")

#define X(a, b) a,
enum COLOR {
  COLOR_TABLE
};
#undef X

#define X(a, b) b,
char *color_name[] = {
  COLOR_TABLE
};
#undef X

#define X(a, b) +1
int color_count = 0 COLOR_TABLE;
#undef X
0
beOn

Si ce qui précède ne fonctionne pas pour vous, car vous utilisez C++, devrait: :

enum Foo {
  One,
  Two,
  Three,
  Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
   Foo foo = static_cast<Foo>(fooInt);
   // ...
}
0
serv-inc