GTA-Center.com » Forum
http://www.gta-center.com/forums/

[GUIDA] Consigli e suggerimenti
http://www.gta-center.com/forums/viewtopic.php?f=40&t=954
Pagina 1 di 1

Autore:  Peppe [ 12/03/2011, 14:16 ]
Oggetto del messaggio:  [GUIDA] Consigli e suggerimenti

Consigli e suggerimenti
In questo topic metterò vari consigli e suggerimenti per migliorare il proprio modo di scriptare e ampliare le proprie conoscenze.


Continuare il codice nella riga successiva
A volte ci serve andare a capo nel codice per vari motivi, ad esempio perché la riga dove stiamo scrivendo una particolare istruzione è troppo lunga.
Possiamo utilizzare \ a fine riga per continuare la riga del codice in quella successiva, Esempio:
Codice:
format(string, sizeof string, "UPDATE users SET aaaaa=1,bbbbbb = 1,cccccc = 2,ddddd = 3,eeeee = 1,qqqqq = 2,rrrrrr = 3, \
lllllll = 65, oioio = 1 WHERE asdhas=123 OR jisa=321");



Definizioni e Macro
Le definizioni permettono in pratica di sostituire, prima della compilazione, una parola del codice in un altra.
Per farle, come molti di voi sapranno, basta usare #define.
Esempio:
Codice:
#define TEST (55)
printf("%d", TEST);

Quindi il compilatore sostituirà automaticamente nel codice TEST in (55).
Questo è utile per creare delle costanti, che però non vengono allocate nella memoria dell'amx.
I #define possono anche ritornare non definiti, usando #undef:
Codice:
#undef MAX_PLAYERS
#define MAX_PLAYERS (100)

In questo caso "undefinisce" MAX_PLAYERS, che è definito negli include di samp, e lo ridefinisce a 100.
Il #define però è uno strumento molto potente, infatti permette di creare delle vere e proprie Macro, ovvero una sorta di funzioni.
Quindi, ad esempio, una funzione come questa:
Codice:
pow(n)
    return n*n;

può essere resa con il #define così:
Codice:
#define pow(%1) %1 * %1

In questo caso, per convenzione, è preferito mettere %1 * %1 tra parentesi
Codice:
#define pow(%1) (%1 * %1)

%1 rappresenta il parametro della macro, ma ci possono essere più parametri, compresi tra %0 e %9.
Esempio:
Codice:
#define InvertValues(%1,%2) \
static const _tmp = %1; \
%1 = %2; \
%2 = _tmp

E' importante sapere che la struttura del #define è questa:
Codice:
#define (parola_o_testo)(spazio)(codice)

Quindi il compilatore riconoscerà ciò che sta prima del primo spazio come codice da sostituire con il codice dopo il primo spazio.


Cicli tra i caratteri di una stringa
Spesso ci serve fare un ciclo per controllare ogni singolo carattere di una stringa, ma la maggior parte delle volte si ricorre ad un for costituito ad esempio così:
Codice:
for(new i; i < strlen(string); i++)
{
    if(string[i] == '_') string[i] = ' ';
}

Però in questo modo ad ogni iterazione del ciclo viene usata la funzione strlen, quando basterebbe eseguirla una sola volta.
Quindi la migliore soluzione per fare un ciclo per ogni carattere di una stringa è questa:
Codice:
for(new i, len = strlen(string); i <  len; i++)
{
    if(string[i] == '_') string[i] = ' ';
}

In questo modo si restituisce la lunghezza della stringa solo nell'inizializzazione del ciclo.
Ecco un esempio di macro che esegue un ciclo di questo tipo:
Codice:
#define LoopString(%1,%2) for(new %2, len = strlen(%1); %2 < len; %2++)

%1 rappresenta la stringa interessata e %2 il nome della variabile che rappresenta l'index del carattere ad ogni iterazione.
Esempio:
Codice:
[code]LoopString(string, i)
{
    if(string[i] == '_') string[i] = ' ';
}[/code]



Cicli tra i player connessi
Quando si deve fare un ciclo per ogni player connesso di solito si usa questa forma di codice:
Codice:
for(new i; i < MAX_PLAYERS; i++)
{
    if(IsPlayerConnected(i))
    {
   
    }
}

Però alcuni, credendo che sia migliore questo metodo, fanno così:
Codice:
for(new i; i < GetMaxPlayers(); i++)
{
    if(IsPlayerConnected(i))
    {
   
    }
}

Be, mi fa piacere dirvi che la prima alternativa tra queste due è molto più veloce ed efficiente della seconda, perché in quest'ultimo caso la funzione GetMaxPlayers() viene seguita ad ogni iterazione del ciclo, quindi numero_slot volte, cosa molto inefficiente e lenta.
Tuttavia il secondo codice si può fare meglio per ottenere risultati migliori:
Codice:
for(new i, MaxPlayers = GetMaxPlayers(); i < MaxPlayers; i++)
{
    if(IsPlayerConnected(i))
    {
   
    }
}

Così GetMaxPlayers() verrà eseguito solo nell'inizializzazione del ciclo e il codice sarà più molto più veloce delle prime due alternative.
Alcuni invece ridefiniscono MAX_PLAYERS settandolo al numero effettivo degli slot del server: si, questo metodo è ancora più veloce, ma per una gamemode che può venire usata in altri server è sconsigliato, visto che bisognerebbe ricompilare lo script in base agli slot del server dove viene usata.
L'alternativa migliore in assoluto è l'include foreach (http://forum.sa-mp.com/showthread.php?t=92679), che io personalmente uso e consiglio a tutti.


Le enumerazioni
Una enumerazione, dichiarabile tramite la keyword enum, è un insieme di costanti in cui ognuna di questa ha come valore uno che ha una relazione con gli altri.
In pratica facendo ad esempio:
Codice:
enum
{
    a,
    b,
    c,
    d
}

vengono dichiarate le costanti a, b, c, d con relativi valori 0, 1, 2, 3.
Quindi di default la relazione tra le costanti è che il valore di ognuna è uguale alla precedente + 1.
Le enumerazioni possono avere anche un nome e spesso vengono usate per rappresentare gli slot di un array come in questo caso:
Codice:
enum E_ARRAY
{
    a,
    b,
    c,
    d
}
new
    Array[E_ARRAY];

Inserendo il nome dell'enumerazione al posto della dimensione dell'array, la dimensione sarà il numero di costanti dell'enumerazione.
Quindi facendo Array[a] si ha accesso al primo slot (0) dell'array, facendo Array[b] al secondo e così via. Questo può essere molto utile per organizzare gli slot di un array e rendere così il codice più comprensibile ad uno che non sa cosa rappresentano quegli slot.
Sia chiaro, non necessariamente dobbiamo utilizzare per forza Array[a] al posto di Array[0], ma di solito su usa farlo e i motivi sono ovvi.
In un'enumerazione le costanti dichiarate possono avere anche un tag, come ad esempio Float:
Codice:
enum E_ARRAY
{
    a,
    b,
    c,
    d,
    Float:x
}
new
    Array[E_ARRAY];

Quindi Array[x] dovrà essere per forza una variabile di tipo Float.
Inoltre possiamo anche specificare una dimensione supplementare dimensione che la costante assume nell'array come in questo caso:
Codice:
enum E_ARRAY
{
    a,
    b,
    c,
    d,
    Float:x,
    string[32]
}
new
    Array[E_ARRAY];

Facendo Array[string] si ha accesso ad un'altro array di 32 celle (caratteri della stringa) e quindi come si può capire è possibile utilizzarlo come se fosse una stringa, o anche un normalissimo array: Array[string][cella].
Queste cose molti di voi le sanno, ma quello che vi vorrei far capire è che le enumerazioni non hanno solo queste funzioni.
Ad esempio mettiamo il caso che dobbiamo definire il numero corrispondente al team di un player in una gm. Di solito si usano i define:
Codice:
#define TEAM_NULL 0
#define TEAM_A 1
#define TEAM_B 2
#define TEAM_C 3
#define TEAM_D 4
#define TEAM_E 5
#define TEAM_F 6

Si può ottenere lo stesso risultato in un modo leggermente più semplice usando un enum:
Codice:
enum E_TEAM
{
    TEAM_NULL,
    TEAM_A,
    TEAM_B,
    TEAM_C,
    TEAM_D,
    TEAM_E,
    TEAM_F
}

Inoltre si può specificare il valore di una costante dell'enumerazione, che però potrebbe influenzare anche quelle successive:
Codice:
enum E_TEAM
{
    TEAM_NULL,
    TEAM_A = 10,
    TEAM_B,
    TEAM_C,
    TEAM_D,
    TEAM_E,
    TEAM_F
}

Quindi TEAM_NULL vale 0, ma da TEAM_A i valori delle costanti vanno da 10 in poi.
Anche se di default l'operazione che lega le costanti dell'enum è un incremento di 1 si può modificare l'operazione così facendo:
Codice:
enum E_BOH (operatore=operando_2)
{
    nomi_costanti,
    //...
}

operatore è appunto il simbolo dell'operazione da effettuare (+, -, *, /, %, ...) e operand_2 è il secondo membro dell'operazione.
Esempio:
Codice:
enum E_COUNTDOWN (-=1)
{
    FIVE = 5,
    FOUR,
    THREE,
    TWO,
    ONE
}

Quindi i valori delle costanti diminuiranno ognuna di uno rispetto alla precedente: FIVE = 5, FOUR = 4, THREE = 3, TWO = 2, ONE = 1.



Guida in continuo aggiornamento.

Autore:  mitosking [ 12/03/2011, 14:33 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Ottima guida Peppe, mi è stata veramente utile ;)... Spero che la possa continuare.

Autore:  Angelo [ 12/03/2011, 14:50 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Fantastica ;)

Autore:  Peppinux AKA Peppe_Stasu [ 12/03/2011, 16:15 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Bella Peppe ;D
Non sapevo che nelle macro non si poteva andare al di fuori di %9, mi è stato utile anche se le altre cose le conoscevo già ;). Ottimo lavoro :D

Autore:  Giovanni94m [ 12/03/2011, 17:10 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Ottima guida peppe.
k+
Cerca però di continuarla dato l'ampio argomento.

Autore:  Peppe [ 12/03/2011, 18:21 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Aggiornata.

Autore:  Peppinux AKA Peppe_Stasu [ 12/03/2011, 18:31 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Visto l'aggiornamento. Molto utile anche perchè non avevo alcune cosa chiare sugli enum. Spero la continuerai veramente complimenti :D.

Autore:  barletheking [ 12/03/2011, 20:53 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Bella e molto utile, ma le sapevo già tutte xD

Autore:  scienziato-pazzo [ 19/05/2011, 13:52 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Bella guida

Autore:  Phanto90 [ 09/06/2011, 22:56 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Peppinux AKA Peppe_Stasu ha scritto:
Non sapevo che nelle macro non si poteva andare al di fuori di %9

Le macro possono avere definiti un massimo di 10 argomenti che vanno indicati usando % e un numero tra 0 e 9 a piacere.
Non seguono una numerazione crescente, il numero è solo indicativo

Autore:  Peppinux AKA Peppe_Stasu [ 10/06/2011, 12:20 ]
Oggetto del messaggio:  Re: [GUIDA] Consigli e suggerimenti

Ehm avevo già letto ._.

Pagina 1 di 1 Tutti gli orari sono UTC + 1 ora [ ora legale ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/