INDENTIFIKÁCIÓ
Üdv! Ezt a mai leírásomat abból a szándékból kezdtem el írni, hogy rávezessem a kezdõket az indentifikáció használatának szükségességére.
Elõször tisztázzuk le ennek fogalmát: egy teljesen megegyezõ futtatandó fájlhoz
(.amx) különbözõ stílusú, de azonos mûveleteket tartalmazó forráskód
(.pwn) tartozhat, mivel a Pawn fordítója a fordítás során a formázásokat figyelmen kívül hagyja. Formázásnak tekintjük a kommenteket, az üres sorokat ill. a behúzást vagy idegen szóval indentifikációt.
A behúzás azt jelenti, hogy egy bizonyos blokkba (függvény, elágazás, ciklus, stb.) írt kódot mindig egy meghatározott mennyiséggel beljebb húzzuk a kijjebb álló kódnál, ezzel megkapva ez \"csontvázas\" kinézetet, így ránézésre láthatjuk, hogy \"mi min belül van\".
MIÉRT?
Talán a kezdõknek nem tûnhet ez olyan fontosnak, de képzeljük el, hogy egy több ezer parancsot tartalmazó programról van szó, és abban szeretnénk mondjuk egy függvényen belül a 8. egymásba ágazott
if utasításban valamit változtatni. Kín és szenvedés lenne egy azonos behúzási szinten lévõ kódban ezt megtalálni, nem beszélve arról, ha magukban az elágazásokban is eleve hosszú kód van, míg indentifikálva egybõl láthatjuk a szinteket.
A következõ részben egy rövid kódot fogok nektek beilleszteni egy szkriptbõl indentifikáció nélkül, majd vele. Próbáljátok megfejteni mit csinál mindkét esetben. Hogyan volt könnyebb?
public OnPlayerUpdate(playerid){
if(!newround && living[playerid]){
new Float:X, Float:Y, Float:Z;
GetPlayerPos(playerid, X, Y, Z);
if(Z < 150.0){
printf(\"DEBUG: ID %d knocked out, put in Spec\", playerid);
new outstr[128];
GetPlayerName(playerid, outstr, 128);
format(outstr, 128, \"{FFCC33}%s {CC33FF}kiesett...\", outstr);
SendClientMessageToAll(0xCC33FFFF, outstr);
living[playerid] = false;
if(IsPlayerInAnyVehicle(playerid)){
new id = GetPlayerVehicleID(playerid);
DestroyVehicle(id);
}
for(new i; i < GetMaxPlayers(); i++){
if(specing == playerid){
specing++;
while(!living[specing]){
specing++;
if(specing > GetMaxPlayers()-1) specing = 0;
}
PlayerSpectatePlayer(i, specing);
}
}
new count = 0;
for(new i; i < GetMaxPlayers(); i++) if(living) count++;
printf(\"DEBUG: Player alive count is %d\", count);
SetPlayerPos(playerid, 100.0, 100.0, 200.0);
TogglePlayerSpectating(playerid, true);
specing[playerid] = 0;
while(!living[specing[playerid]] && specing[playerid] < GetMaxPlayers()) specing[playerid]++;
PlayerSpectatePlayer(playerid, specing[playerid]);
if(count < 2){
newround = true;
SetTimer(\"NextRound\", 3000, false);
for(new i; i < GetMaxPlayers(); i++){
if(living){
new pName[MAX_PLAYER_NAME];
GetPlayerName(i, pName, 128);
format(outstr, 128, \"{CC33FF}A KÖRT {FFCC33}%s {CC33FF}NYERTE!\", pName);
SendClientMessageToAll(0xCC33FFFF, outstr);
points++;
}
}
}
}
}
return true;
}
public OnPlayerUpdate(playerid){
if(!newround && living[playerid]){
new Float:X, Float:Y, Float:Z;
GetPlayerPos(playerid, X, Y, Z);
if(Z < 150.0){
printf(\"DEBUG: ID %d knocked out, put in Spec\", playerid);
new outstr[128];
GetPlayerName(playerid, outstr, 128);
format(outstr, 128, \"{FFCC33}%s {CC33FF}kiesett...\", outstr);
SendClientMessageToAll(0xCC33FFFF, outstr);
living[playerid] = false;
if(IsPlayerInAnyVehicle(playerid)){
new id = GetPlayerVehicleID(playerid);
DestroyVehicle(id);
}
for(new i; i < GetMaxPlayers(); i++){
if(specing == playerid){
specing++;
while(!living[specing]){
specing++;
if(specing > GetMaxPlayers()-1) specing = 0;
}
PlayerSpectatePlayer(i, specing);
}
}
new count = 0;
for(new i; i < GetMaxPlayers(); i++) if(living) count++;
printf(\"DEBUG: Player alive count is %d\", count);
SetPlayerPos(playerid, 100.0, 100.0, 200.0);
TogglePlayerSpectating(playerid, true);
specing[playerid] = 0;
while(!living[specing[playerid]] && specing[playerid] < GetMaxPlayers()) specing[playerid]++;
PlayerSpectatePlayer(playerid, specing[playerid]);
if(count < 2){
newround = true;
SetTimer(\"NextRound\", 3000, false);
for(new i; i < GetMaxPlayers(); i++){
if(living){
new pName[MAX_PLAYER_NAME];
GetPlayerName(i, pName, 128);
format(outstr, 128, \"{CC33FF}A KÖRT {FFCC33}%s {CC33FF}NYERTE!\", pName);
SendClientMessageToAll(0xCC33FFFF, outstr);
points++;
}
}
}
}
}
return true;
}
Azt hiszem, mostanra mindenki megértette az indentifikáció fontosságát!A fenti kódtól pedig ne tessék megijedni, csak illusztráció...HOGYAN?
Az indentifikációt mindenki saját belátása szerint végzi, fõ az átláthatóság, ám az alábbiakban néhány elterjedtebb módszert mutatok be.
1.) Allman-stílusAz Allman-stílus az ANSI C illetve vele együtt több C-alapú nyelv (pl. PAWN) hivatalosan támogatott behúzási módja.
Egy TAB-ot használ a behúzásra, a nyitó- és zárójeleket új sorba helyezi el az eredeti szinten.
Az indentifikáció akkor helyes, ha az adott kódrészlet befejezésével a kiindulási szintre érünk vissza.
PÉLDA:
while(x == y)
{
valami();
valami2();
}
ciklusonkivulivalami();
2.) Whitesmiths-stílusAz Allman-stílustól eltérõen a nyitó- és zárójeleket behúzva írja.
Az intentifikáció akkor helyes ha a kód végén a kiindulástól egy szinttel beljebb vagyunk.
PÉLDA:
while(x == y)
{
valami();
valami2();
}
ciklusonkivulivalami();
3.) 1TBS-stílusJómagam is ezt használom.
A nyitójeleket az elõzõ sor végére rakja, a zárójeleket külön sorba eredeti szinten, de ha pl. else állítás van, akkor azonos sorban folytatja.
Az indentifikáció akkor helyes, ha az adott kódrészlet befejezésével a kiindulási szintre érünk vissza.
PÉLDA:
while(x == y){
valami();
valami2();
}
ciklusonkivulivalami();
További stílusok és példák:
>> ITT <<Még egyszer mondom: teljesen mindegy, ki hogyan használja a behúzásokat, de használnunk kell, hogy más számára is követhetõvé váljon a gondolatmenetünk.