2010-11-09 12 views
6

1) Qualcuno sa se è possibile eseguire il ciclo di un'enumerazione irregolare in Delphi (XE)?Ciclo attraverso enumerazione irregolare in Delphi

Il ciclo su una normale numerazione è ok. Da Delphi Basics:

var 
    suit : (Hearts, Clubs, Diamonds, Spades); 
begin 
// Loop 3 times 
For suit := Hearts to Diamonds do 
    ShowMessage('Suit = '+IntToStr(Ord(suit))); 
end; 

Ma, se 'vestito' invece è dichiarata come

var 
    suit : (Hearts=1, Clubs, Diamonds=10, Spades); 

esso loop 10 volte. Non sorprendente, ma mi piacerebbe loop 3. L'unica soluzione che ho trovato finora è la conversione di un'enumerazione in un set e utilizzare il 'for ... in'-loop come su delphi.about.com.

Quindi, se la risposta alla domanda 1) è no, quindi:
2) Come convertire dall'enumerazione per impostare in Delphi?

Il contesto in cui lo sto utilizzando è un array di componenti di edit-box (TEdit) che ha una numerazione irregolare (edit1, edit5, edit7, edit3, ...). Mentre è possibile riordinare tutte le caselle di modifica, rimuove il motivo dell'utilizzo dell'enumerazione come modo flessibile per consentire l'aggiunta di una casella di modifica nel mezzo dell'enumerazione.

+0

Perché non potete usare qualche discendente 'TList' e iterare su quello? –

+0

L'enumerazione verrà utilizzata come indice nelle matrici di TLabels, TEdit e Stringhe in modo che sia possibile utilizzare StringArray [Job]: = Editbox [Job]. TList potrebbe funzionare, ma l'obiettivo era rendere il codice sorgente più facile da leggere usando enumerazioni (irregolari) come indici, come HashMap in Java. Quello che vedo ora probabilmente non funzionerà ... – Truls

+0

Hai provato a usare XEs RTTI? L'ordinario RTTI dall'unità 'TypInfo' fallisce miseramente. Apparentemente non si può avere 'TypeInfo()' su un'enumerazione irregolare, ho anche provato con un set e mi hanno dato le violazioni di accesso. –

risposta

7

Non ho un compilatore Delphi a portata di mano in questo momento, ma ho tink che l'approccio di Gabr può essere piuttosto significativamente migliorata facendo

type 
    TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades); 

const 
    Suits: array[0..3] of TSuit = (Hearts, Clubs, Diamonds, Spades); 

Chissà, forse non anche compilare.

+0

Dovrebbe assolutamente funzionare. – gabr

+0

Testato questo e funziona! Grazie. Se qualcuno sa se è possibile evitare di ripetere la lista di enumerazione sarei lieto di sapere. – Truls

0

Ciclo con Ord (Cuori) a Ord (Picche)?

+2

Penso che Ord (Hearts) to Ord (Spades) verrà loop 11 volte, e non 3 come voglio. – Truls

3
type 
    TSuit = (Hearts=1, Clubs, Diamonds=10, Spades); 

var 
    suit: TSuit; 
    suitEnum: array [1..4] of TSuit; 

//initialization 
suitEnum[1] := Hearts; 
suitEnum[2] := Clubs; 
suitEnum[3] := Diamonds; 
suitEnum[4] := Spades; 

for suit in suitEnum do 
    DoSomething(suit); 
+0

Grazie per il suggerimento. Dal momento che ho circa 30 elementi nel mio enum speravo di evitare l'inizializzazione manuale. Ma se non ci sono scorciatoie, ci proverò. – Truls

0

Un'opzione sporco, utile per i piccoli enumerazioni:

type 
    TSuit = (Hearts = 1, Clubs, Diamonds = 10, Spades); 
var 
    Suit: TSuit; 
begin 
    for Suit in [Hearts, Clubs, Diamonds] do 
    WriteLn(Ord(Suit)); 

Funziona bello in Delphi 2007. Non so su versioni precedenti. Essere consapevoli, utilizzando for Suit in [Hearts..Diamonds] do ha lo stesso problema del ciclo.
Btw, io uso WriteLn() perché l'ho provato in un'applicazione console. :-)

+0

Grazie per il suggerimento, lo terrò a mente. Tuttavia, poiché questo caso ha circa 30 elementi, userò l'approccio const proposto nella risposta accettata. – Truls

+0

Bene, anche con 30 elementi, dovresti comunque essere in grado di copiare/incollare l'intervallo dalla sua dichiarazione originale e assegnare al set una costante che riutilizzerai per tutti i tuoi loop. Ha un ulteriore vantaggio: puoi saltare elementi tra l'elemento iniziale e quello finale. –

2

Io uso sempre

var 
    s: TSuit; 
begin 
    for s := Low(TSuit) to High(TSuit) do 
    {something}; 
end; 
+1

Funziona bene se l'enumerazione è regolare, cioè numeri consecutivi, tuttavia la chiave qui era ** enumerazione non consecutiva **. – Truls

0

Si dovrebbe comprendere (e spesso non lo è) che il momento in cui mettere le assegnazioni ordinali rigidi in un'enumerazione, cessa a tutti gli di essere un pascaliana enumerato tipo - diventa semplicemente un "sacco di costanti", che non è la stessa cosa. Questo è ciò che i programmatori C chiamano enumerazioni. Tuttavia, un tipo enumerato Pascalian è ORDINALE in tutti i criteri: ha valori consecutivi discreti che rispondono in modo significativo alle operazioni di base ORD, PRED, SUCC. Le enumerazioni in Do non lo fanno, e nemmeno enumano in Pascal una volta forzati gli ordinali.

QUESTO è il motivo per cui RTTI di Delphi si rifiuta fondamentalmente di restituire le informazioni sul tipo una volta che è stato fatto. A tutti gli effetti il ​​tipo è essenzialmente un tkUnknown e deve essere trattato come un "sacchetto" di costanti in fase di compilazione. È solo perché gioca ancora a parole per essere un ordinale e ha un supporto (a volte tremolante) per l'uso in insiemi che le persone sono indotte a credere che dovrebbe comportarsi ancora come un tipo enumerato appropriato. È meglio capirlo per quello che è veramente: un cenno ai valori enumerati in C. Evita di mescolare la metafora del codice!

Se si esegue questa operazione, la soluzione diventa ovvia: si utilizza un tipo enumerato (corretto) per indicizzare una matrice corrispondente di COSTANTI. Quindi puoi rendere gli ordinali come vuoi e le enumerazioni mantengono le loro complete definizioni RTTI come una corretta enumerazione. Quindi: il tuo TIPO ENUMERATO contiene valori ordinali invariati. Ottenete i vostri numeri divertenti indicizzando l'array di costanti usando l'enumerazione -ergo array [MyEnums] di byte = (1,3,8,22,99, qualunque)

Problemi correlati