StringekNos, ahogy Y_Less is leírta az ő SAMPos topicjába, az embereknek elég eltérő nézetük van a stringekkel kapcsolatba. Valaki azt gondolja, nem lehet nagyobb mint 256 cella (ami hülyeség, ugyanis a string limit 1024), valaki azt gondolja, alapból 256 cellát foglal el, és a többi. Nos, megmutatjuk, hogy pazarlás, és meglátjuk, mennyi helyet takaríthatunk meg.
Alapvető tudnivalókA STRING a pawno-ban karakterek tömbje. Viszont van egy lényeges eltérés. A stringek alapból 1 cella hosszúak. Ugyanis, ha valaki már programozott más nyelveken, tudja, hogy az ASCII minden karakterláncot a \"NULL\" vagy \"\\0\" karakterrel zár le. Lássunk egy jó példát a stringek használatára:
new string[3] = \"hi\"
Ez három cella hosszú, egy a \"h\" karakternek, egy az \"i\" karakternek, egy pedig a \"NULL\"-nak.
new string[3] = { \'h\', \'i\', \'\\0\' }
Ez tulajdonképp ugyanaz, csak itt cellánként vannak felosztva a karakterek. A Pawno a stringben minden karaktert a terminátor NULL-ra álílt be, ha meghívjuk, ezért ha ezt írjuk be:
new string[256]
Tulajdonképp ezt tesszük:
for(new i = 0, i < *stringhosszúság*, i++) return str = 0;
Rendben, de miért ne használjam?Mert lassú. Ahogy láthattuk, minnél több stringet adunk meg, annál több lesz a stringhosszúság, így annál több ideig tart a ciklus, echte annál többször kell a karaktereket 0-znia a PAWNO-nak.
Mert nincs rá szükséged. Pl.
new modlevel[256]; if(PeepThatShit == 0) new string[256]; format(string,sizeof(string),\"Csak a %d szint feletti adminok tekinthetik meg ezt a valamit.\",ModLevel);
Ez egy abszolút rossz példa. Vegyük úgy, egy 5 szintes admin scripttel van dolgunk. Akkor az maximum 1 cellát foglal le, + a NULL. Szóval:
new modlevel[2];
A stringnek se muszály ekkora értéket adni. Nézzük meg mennyi karakterből áll ez a string:
Ez összesen 61 cellából áll, ugyanis a \"%d\" nem számít bele, szóval -2 karaktert levontunk, ám ezt rögtön a 2 cella hosszú modlevel miatt vissza is kell adni. + a NULL.
new modlevel[2]; if(PeepThatShit == 0) new string[61]; format(string,sizeof(string),\"Csak a %d szint feletti adminok tekinthetik meg ezt a valamit.\",ModLevel);
Mivel tudjuk, hogy 1 cella 4 bájtból áll, ezért kiszámolhatjuk, hogy össz. 192 cellát mentettünk meg. Ha ezt megszorozzuk néggyel, 768 byte, több mint fél megabájt memóriát vesztettünk.
Chat: Ha a chattel kapcsolatos funkciókat nézzük, akkor a chat imput 128 karakter. Tehát ennyit tudunk összesen a chatbe írni. A 256 cellának a 3/4-ét takarítottuk meg így.
A chat output 256 karakter, tehát ennyit tud maximum a chat kijelezi. Ugyanazt tudom elmondani, mint az előbb, minek 512 cella, ha a fele kárbavész?
Ezenkívül további limiteket is szem előtt tarthatunk ha takarékosságról van szó. Például ha egy adott változóba a játékos nevét tároljuk el, és ha nem vagyunk biztosak a mértékében, jobb, ha az a_samp.inc függvénykönyvtárból hívjuk be a cellahosszot.
new IsAnRPName[MAX_PLAYER_NAME]
Ugyanez vonatkozik a többi hasonló limitált mennyiségű script property-re.
Másik érdekes példa:
public OnPlayerCommandText(playerid, cmdtext[])
{
new
string[256],
cmd[256];
cmd = strtok(cmdtext, idx);
}
Ez teljesen hibás.
new string[256], cmd[256];
cmd = strtok(cmdtext, idx);
Miért kéne a cmd string ide? Mért csinálunk 2 hatalmas változót a parancsnak, és az adatnak is? Az adatot csak akkor használod, ha beírtad a parancsot. Szóval egyszerűsítsük le.
new string[256];
string = strtok(cmdtext, idx);
Miért 256 cella hosszú? Ahogy előbb már letárgyaltuk, a chatbe max 128 karaktert tudunk beírni. Ezért írjuk is át.
new string[128];
string = strtok(cmdtext, idx);
Memória (stack): Ha meghívunk egy funkciót, akkor az eltárolódik egy bizonyos stack-ban.
new gVar = 2;
stock StackUse()
{
new str[9];
format(str, sizeof (str), \"gVar = %d\", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}
Nézzük meg mi történik. adunk gVar-nak egy értéket, ami 2, majd csinálunk egy 9 cella értékű stringet (nem pazarlunk) ugyanis a következő érték: \"gVar = \" 7 cellából áll, + a gVar értéke, ami 2. Elküldi a változó értékét, majd lekérdezi, hogy a gVar meghívódott-e. Ha igen, akkor a gVar-t egyesével csökkentjük. Mivel 9 cellával van dolgunk, és a gVar 2, ezt csökkentjük 3 alkalommal (2 > 1 > NULL) mindegyik között a funkció meghívódik mégegyszer.
És mi történik ha 256-tal használunk?
new gVar = 2;
stock StackUse()
{
new str[256];
format(str, sizeof (str), \"gVar = %d\", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}
A gVar-t továbbra is ürítjük, ám a pawno-nak időbe tellik, mire a 256 stringből mindet átírja NULL-ra, ezért a memóriahasználat 2800%-a az eredtinek.
Mikor használjak 256-ot?MySQL adatbázis lekéréseknél, mivel azoknál nem biztos az adat mennyisége, különösen nem a TEXT típusú adatmezőkben.
Fájlkiolvasás: Szintén nem tudhatjuk, mekkora lesz az output.
Írta Y_Less, kibővítette krisk.