Enumeradores
Há algo sobre enums que muitos scripters não conhecem.
Muitos de vocês usam enums em seu script para armazenar dados de jogador/veículo/casa etc. (especialmente informações do usuário)
Um exemplo típico (ou muito comum):
Código do peão:Muitos de vocês usam enums em seu script para armazenar dados de jogador/veículo/casa etc. (especialmente informações do usuário)
Um exemplo típico (ou muito comum):
- Código:
enum
e_PlayerInfo
{
PONTUAÇÃO,
DINHEIRO,
MATAS,
MORTES
} ;
- Código:
novo pInfo [ MAX_PLAYERS ] [ e_PlayerInfo ] ;
Agora, é assim que é usado:
Código do peão:- Código:
public OnPlayerDeath ( playerid, killerid, razão )
{
pInfo [ playerid ] [ MORTES ] ++ ;
if ( IsPlayerConnected ( killerid ) && killerid != playerid )
pInfo [ killerid ] [ KILLS ] ++ ;
retornar 1 ;
}
Tudo bem, agora isso é facilmente compreendido.
Agora:
Código do peão:Agora:
- Código:
enum
e_PlayerInfo
{
PONTUAÇÃO,
DINHEIRO = 9 ,
MATA = 5 ,
MORTES = 56
} ;
- Código:
novo pInfo [ MAX_PLAYERS ] [ e_PlayerInfo ] ;
- Código:
printf ( "%i | %i | %i | %i" , pInfo [ 0 ] [ SCORE ] , pInfo [ 0 ] [ MONEY ] , pInfo [ 0 ] [ KILLS ] , pInfo[ 0 ] [ MORTES ] ) ;
Então, a saída será "0 | 9 | 5 | 56", certo?
Se você pensou "yeah"..
Errado, porque vai dar: "0 | 0 | 0 | 0", você pode pensar que os enums são os que armazenam dados.
Quando fiz "MONEY = 9" no enum, depois usei "pInfo[0][MONEY]" no printf, ele considerou pInfo[0][9] e não ePlayerInfo:MONEY. O que significa que usei "MONEY" como um índice para minha variável pInfo.
Portanto, enums NÃO são variáveis! Eles são realmente "constantes", eles apenas ajudam você a atribuir um nome específico ao seu índice de variável.
Ok, vamos nos aprofundar um pouco mais e esperamos que você entenda mais..
Exemplo:
Código do peão:Se você pensou "yeah"..
Errado, porque vai dar: "0 | 0 | 0 | 0", você pode pensar que os enums são os que armazenam dados.
Quando fiz "MONEY = 9" no enum, depois usei "pInfo[0][MONEY]" no printf, ele considerou pInfo[0][9] e não ePlayerInfo:MONEY. O que significa que usei "MONEY" como um índice para minha variável pInfo.
Portanto, enums NÃO são variáveis! Eles são realmente "constantes", eles apenas ajudam você a atribuir um nome específico ao seu índice de variável.
Ok, vamos nos aprofundar um pouco mais e esperamos que você entenda mais..
Exemplo:
- Código:
const e_CAR1 = 0 ;
const e_CAR2 = 1 ;
const e_CAR3 = 2 ;
novos MyCars [ 3 ] ;
- Código:
main ( )
{
MeusCarros [ e_CAR1 ] = 520 ;
MeusCarros [ e_CAR2 ] = 458 ;
MeusCarros [ e_CAR3 ] = 411 ;
}
Faremos a mesma coisa com enums agora:
Código do peão:- Código:
enum
e_TEST
{
e_CAR1,
e_CAR2,
e_CAR3
} ;
novos MyCars [ e_TEST ] ;
- Código:
main ( )
{
MeusCarros [ e_CAR1 ] = 520 ;
MeusCarros [ e_CAR2 ] = 458 ;
MeusCarros [ e_CAR3 ] = 411 ;
}
Ambos (usando const e enums aqui) irão compilar bem e fazer a mesma coisa, você vê a diferença?
Sim, apenas em como você cria o código.
Este pedaço de código que mostrei a você diz que enums fazem as mesmas coisas que constantes.
Mas existem algumas diferenças que nos fazem usar enums em vez de constantes ou definições (const e_CAR1 = 0; ou #define e_CAR1 0) Falaremos sobre as diferenças mais tarde.
Primeiro você deve entender como os enums são estruturados:
Código do peão:Sim, apenas em como você cria o código.
Este pedaço de código que mostrei a você diz que enums fazem as mesmas coisas que constantes.
Mas existem algumas diferenças que nos fazem usar enums em vez de constantes ou definições (const e_CAR1 = 0; ou #define e_CAR1 0) Falaremos sobre as diferenças mais tarde.
Primeiro você deve entender como os enums são estruturados:
- Código:
enum TESTE
{
Abc,
Def,
Ghi,
} ;
Abc é uma constante com o valor de 0 (quase o mesmo que fazer const Abc = 0; ou #define Abc 0),
Def é uma const de valor 1 (const Def = 1; ou #define Def 1)
E Ghi é uma const de valor 2 (const Ghi = 2; ou #define Ghi 2)
O pré-compilador define automaticamente os valores dessas constantes começando de 0 a .. n
Considerando que, ao criar constantes, você é quem deve atribuí-las. Mas em enum, é estruturado automaticamente.
Exemplo:
Código do peão:Def é uma const de valor 1 (const Def = 1; ou #define Def 1)
E Ghi é uma const de valor 2 (const Ghi = 2; ou #define Ghi 2)
O pré-compilador define automaticamente os valores dessas constantes começando de 0 a .. n
Considerando que, ao criar constantes, você é quem deve atribuí-las. Mas em enum, é estruturado automaticamente.
Exemplo:
- Código:
enum TEST
{
e_ONE, //Isso obterá automaticamente "0"
e_TWO, //this: "1"
e_THREE, // "2"
e_FOUR = 12 , // Agora, aqui está uma diferença, já que você atribuiu "12" a ele , ao invés de ser "3", ele se tornará 12..
e_FIVE, //Este será 13 porque seu enumerador superior tinha "12"
e_SIX //Este será 14. É superior: "13"
}
Como você pode ver, se você mesmo atribuir um (como eu fiz "e_FOUR = 12") O próximo enumerador terá e_FOUR+1 e assim por diante. Mais algumas
explicações:
Código do peão:explicações:
- Código:
enum
DATA
{
INT, //Isto obterá "0" (Lembre-se, valor inicial)
STRING [ 10 ] , //(Isto obterá 1, mas como é uma string, apenas um bloco não é suficiente!)
//^ Então , os números corretos serão: 1,2,3,4,5,6,7,8,9,10! Porque o comprimento da string é 10!
INT2, //Isso vai pegar o número 11, ele vem depois do STRING[10] que tinha o último número 10..
STRING2 [ 10 ] //E isso vai começar com 12 e terminar em 22 porque requer 10 espaços.
} ;
Usando
Código do peão:- Código:
printf ( "%i" , _ : DADOS ) ;
Eu obtive: "22"
Porque o tamanho de toda a enumeração é 22.
INT, STRING, INT2, STRING2
1+ 10+ 1+ 10 = 22
Agora, você pode pensar porque usei "1" para mostrar INT e não "0 "?
O problema é que estou mostrando a você "QUANTOS" blocos estão sendo usados pelo INT, não "QUAL UM".
Se fosse "qual", então seria "0", o bloco 0 é ocupado por INT.
Para um bloco de tamanho 22, estes são os índices "0..1..2 até 19..20..21" < Você tem 22 números aqui.
Usando
Código do peão:Porque o tamanho de toda a enumeração é 22.
INT, STRING, INT2, STRING2
1+ 10+ 1+ 10 = 22
Agora, você pode pensar porque usei "1" para mostrar INT e não "0 "?
O problema é que estou mostrando a você "QUANTOS" blocos estão sendo usados pelo INT, não "QUAL UM".
Se fosse "qual", então seria "0", o bloco 0 é ocupado por INT.
Para um bloco de tamanho 22, estes são os índices "0..1..2 até 19..20..21" < Você tem 22 números aqui.
Usando
- Código:
printf ( "%i" , _ : STRING ) ;
Eu obtive: "1"
porque o primeiro bloco foi ocupado por INT que é "0"
E, portanto, STRING começou a partir do bloco "1"
Se eu mostrar o uso de blocos por cada enumerador, ficará assim:
INT : bloco 0
STRING : blocos 1,2,3,4,5,6,7,8,9,10
INT2 : bloco 11
STRING2 : blocos 12,13,14,15,16,17,18,19,20,21
Usando
Código do peão:porque o primeiro bloco foi ocupado por INT que é "0"
E, portanto, STRING começou a partir do bloco "1"
Se eu mostrar o uso de blocos por cada enumerador, ficará assim:
INT : bloco 0
STRING : blocos 1,2,3,4,5,6,7,8,9,10
INT2 : bloco 11
STRING2 : blocos 12,13,14,15,16,17,18,19,20,21
Usando
- Código:
nova Matriz [ DADOS ] ;
printf ( "%i" , tamanho do Array ) ;
Também me deu 22, porque, sim, "DATA" tinha o tamanho de 22.
Finalmente, vemos que Array é na verdade:
Array[INT + STRING + INT2 + STRING2];
(não irá compilar, apenas visualizá-lo)
Portanto, sempre que você usar enums, use a variável real e os enumeradores como índices.
Um exemplo esquemático:
Outro exemplo:
Código do peão:Finalmente, vemos que Array é na verdade:
Array[INT + STRING + INT2 + STRING2];
(não irá compilar, apenas visualizá-lo)
Portanto, sempre que você usar enums, use a variável real e os enumeradores como índices.
Um exemplo esquemático:
Outro exemplo:
- Código:
enum
TEST
{
SomeInteger = 124 ,
SomeString [ 12 ] ,
Float : SomeFloat
} ;
- Código:
[size=14][size=13]public OnFilterScriptInit ( )
{
new var_TEST [ TEST ] ;
var_TEST [ SomeInteger ] = 1337 ;
printf ( "1) Armazenado em var: %i, Constante: %i" , var_TEST [ SomeInteger ] , _ : SomeInteger ) ;//1
formato ( var_TEST [ AlgumaString ] , 12 , "Ei!" ) ;
printf ( "2) Armazenado em var: %s, Constante: %i" , var_TEST [ SomeString ] , _ : SomeString ) ; //2
var_TEST [ SomeFloat ] = 2054.124 ;
printf ( "3) Armazenado em var: %f, Constante: %i" , var_TEST [ SomeFloat ] , _ : SomeFloat ) ;//3
retorna verdadeiro;
}[/size][/size]
Saídas:
1) "Stored in var: 1337, Constant: 124"
Como você viu, atribuí var_TEST[SomeInteger] com 1337.
E nas enumerações, SomeInteger tem um valor constante de 124.
2) "Stored in var: Hey!, Constant: 125"
Aqui, atribuí var_TEST[SomeString] com "Hey!".
E nas enumerações, SomeString tem um tamanho de 12, mas imprimiu 125
porque, 125 é o bloco inicial da string, termina em 125 + 12.
3) "Stored in var: 2054.124023, Constant: 137"
Ponto flutuante impresso normalmente, mas SomeFloat imprimiu "137"!
Deve ser 126 certo? Porque foi criado depois de SomeString que tinha o valor de 125..
Mas, como SomeString[12] é um Array (String), ele ocupou mais 12 espaços. O que fez SomeFloat obter o valor de 137
(Observe que 125 + 12 = 137)
Mais algumas informações importantes:
Enums também podem ser usados como tags:
Código do peão:1) "Stored in var: 1337, Constant: 124"
Como você viu, atribuí var_TEST[SomeInteger] com 1337.
E nas enumerações, SomeInteger tem um valor constante de 124.
2) "Stored in var: Hey!, Constant: 125"
Aqui, atribuí var_TEST[SomeString] com "Hey!".
E nas enumerações, SomeString tem um tamanho de 12, mas imprimiu 125
porque, 125 é o bloco inicial da string, termina em 125 + 12.
3) "Stored in var: 2054.124023, Constant: 137"
Ponto flutuante impresso normalmente, mas SomeFloat imprimiu "137"!
Deve ser 126 certo? Porque foi criado depois de SomeString que tinha o valor de 125..
Mas, como SomeString[12] é um Array (String), ele ocupou mais 12 espaços. O que fez SomeFloat obter o valor de 137
(Observe que 125 + 12 = 137)
Mais algumas informações importantes:
Enums também podem ser usados como tags:
- Código:
enum E_EG
{
E_FIRST = 4 ,
E_SECOND = 2
}
Agora eu posso fazer:
novo E_EG : SomeVar;
E:
Código do peão:- Código:
novo E_EG : MinhaVariável = E_FIRST; // Sem avisos apesar de usar "E_FIRST".
//Porque E_FIRST já faz parte do enumerador E_EG
//Desde que marcamos MyVariable com E_EG, está tudo bem com E_FIRST.
Código do peão:
- Código:
novos dados [ E_EG ] ;
dados [ E_FIRST ] = 7 ; // Erro do compilador - índice fora dos limites
//Porque o valor de E_EG é 3 e E_FIRST é 4 (o índice não existe)
Enums anônimos:
Código do peão:enum //<< Não demos um nome.
- Código:
{
E_TEST [ 10 ] = 32 ,
E_VAR
} ;
- Código:
main ( )
{
novos dados [ E_TEST ] ; //E_TEST = 32 não 10.
//Observe que também não usamos nenhuma tag _:E_TEST
}
Tags fortes e fracos:
Código do peão:- Código:
enum
E_STRONG //< Como o nome começa com letra maiúscula, a tag é considerada "Forte"
{
E
_VAR = 64
} ;
- Código:
principal ( )
{
novo Teste = E_STRONG : E_VAR;
//Será um aviso: "tag mismatch" porque "Test" não tem a tag E_STRONG
#pragma não utilizado Teste
}
Código do peão:
- Código:
enum
e_WEAK //< E aqui começa com letra minúscula, então o enum cria uma tag fraca.
{
E_VAR = 64
} ;
- Código:
principal ( )
{
novo Teste = e_WEAK : E_VAR;
//Sem aviso...
#pragma teste não utilizado
}
Isso é quase tudo sobre enums, e essas são as razões pelas quais preferimos usar enums.
* Obrigado a Y_Less por suas explicações.
* Obrigado a Y_Less por suas explicações.