2009-11-02 18 views
29

È possibile eseguire il ciclo dei valori enum in Objective-C?looping dei valori enum

+0

rimarcato: questo è (AFAIK) una domanda pura C. Avrai più risposta con il tagging più generale. –

+14

Risponde anche alla domanda per le persone che lo cercano in Obj-C. Aggiunto quel tag indietro. – pbh101

risposta

7

Se enum è definito come segue:

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

È possibile scorrere in questo modo:

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

Non l'ho mai fatto, quindi ho alcune domande. Non dovrebbe essere Direction.East and Direction.South? Inoltre, la condizione non dovrebbe essere direction <= Direction.South? Ancora non l'ho mai fatto, non sto cercando di correggerti, vorrei solo imparare. –

+3

C'è un modo migliore per farlo? Semplicemente curioso, ma sembra che dipendere dall'ordine di dichiarazione dei valori enumerati sia al massimo fragile. –

+0

@blaenk: penso che tu stia confondendo le strutture con le enumerazioni. – pxl

36

Dato

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

è possibile scorrere gli elementi come:

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

Si noti che questo espone la natura davvero-proprio-int di un C enum. In particolare, si può vedere che un C enum non fornisce realmente sicurezza di tipo, poiché è possibile utilizzare un int al posto di un valore enum e viceversa. Inoltre, questo dipende dall'ordine di dichiarazione dei valori enum: fragile a dir poco. Inoltre, per favore vedi il commento di Chuck; se gli elementi enumerati non sono contigui (ad esempio perché hai specificato valori espliciti e non sequenziali per alcuni articoli), questo non funzionerà affatto. Yikes.

+8

Richiede inoltre che tutti gli elementi nell'enumerazione siano contigui. Ma è il meglio che otterrai. – Chuck

+0

non riconosce Foo in per looo per me. – Frank

+6

È un nitpick puro, ma è scritto 'vice versa'. – new123456

8

È un po 'un kludge (come è l'intero concetto quindi ... eh ...) ma se lo farai più volte, e vuoi essere in grado di gestire la possibilità di non -le enigmi contigui, è possibile creare una matrice (costante globale) e avere (per usare l'esempio di ennukiller) Direzioni stradali [4] = {Est, Ovest, Nord, Sud}; e poi nel vostro ciclo si può parlare di direzioni [i], piuttosto che l'iterazione direttamente sopra le direzioni stessi ...

Come ho detto, è brutto, ma è un po 'meno fragile penso ...

+0

Mi sembra buono. C'è un modo per aggiungere un qualche tipo di macro che genererà automaticamente array C per ogni tipo di enum che dichiariamo? – ArtOfWarfare

+1

@ArtOfWarfare Lo uso sempre: '#define ENUM (tipo, ...) enum _ ## tipo {__VA_ARGS__}; enum _ ## tipo type ## s [] = {__VA_ARGS__} ', sebbene funzioni solo per quelli contigui. Non uso enumerazioni non contigue, perché questo per me segnala un cattivo design. Inoltre ho 'typedef struct _list List;', 'typedef enum _direction Direction' ovunque nel mio codice C che usa questa macro, motivo per cui sto anteponendo _ al tipo. 'ENUM (direzione, NORD, EST, SUD, OVEST);' fornisce 'enum _direction {NORD, EST, SUD, OVEST}; enum _direction directions = {NORD, EST, SUD, OVEST}; 'Mi piace. –

1

mi piace quello che ho ottenuto da qui Iteration over enum in Objective C?

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


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

questo modo è possibile continuare ad aggiungere enumerazioni più tardi e non influenzare i cicli?

5

Alla ricerca di questo, ho appena inventato la seguente soluzione che soddisfaceva le mie esigenze. Ho pensato di pubblicarlo qui per le persone che cercano qualcosa di simile.

Dire che ho un enum.

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

Per essere in grado di eseguire il loop su di esso, definisco la seguente macro di preprocessore.

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

Poi lo uso all'interno di un ciclo, come ad esempio:

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

Questo mette la logica per l'iterazione in un unico luogo (la macro) che aumenta la manutenibilità del codice.

3

Per enumerazioni non contigui è possibile iterare su valori validi facendo:

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; 
    } 
} 
+0

In questo caso, non utilizzerei affatto un ciclo. Lasciare uno dopo l'altro i blocchi dell'interruttore, sarà più pulito e talvolta più efficiente. –

+0

Certo, sono completamente d'accordo con te e non lo scriverei nel codice di produzione; l'unico motivo per cui ho racchiuso l'interruttore all'interno di un ciclo è perché è quello che veniva chiesto dal poster originale;) –

2

La lunghezza (numero di elementi) di qualsiasi enumerazione può essere accertata da ottenere l'array di nomi nella enumerazione e utilizzando il lunghezza dell'array. Utilizza il metodo GetNames di Enum. Enum.GetNames (enumType) .Length.

{ 
enum Pig { Snort, Sty, Oink, Curly }; 
const int Pig_Count = Enum.GetNames(typeof(Pig)).Length; 
} 
-3
enum direction = {South, North, East, West}; 

//this is used to loop through enum in the while loop, and will contain the enum length when the while loop finishes. 
int index = 0; 
while(direction[index] != null){ 
    index++; 
} 

//loop through all the values in the enum 
for (int i = 0; i < index; i++){ 
    //your code here, 'direction[index]' will return the enum name 
} 
+2

Il post originale (OP) riguardava l'iterazione tramite enumerazione. Non c'è niente nella tua risposta che indirizzi la domanda originale. Si prega di modificare la risposta per rispondere alla domanda. – rothloup

+0

il codice sopra registrerà ogni nome enum nella "direzione" enum. come fa ora a rispondere alla domanda? – allanjwalter

+0

Forse dovresti aggiungere qualche spiegazione o codice per indicare che "direzione" è l'enum che stai registrando. Forse per un programmatore esperto è ovvio dal tuo codice, ma un tale programmatore non avrebbe pubblicato la domanda in primo luogo. Aggiungere una piccola spiegazione aiuterà a chiarire la tua risposta e renderla più utile a chiunque la trovi. – rothloup