Tudom létezik több száz leírás de írok egyet én is.
Az strtok nem más mint egy karakterlánc feldarabolására használatos eljárás.
A kód:
stock strtok(const string[], &index)
{
new length = strlen(string);
while ((index < length) && (string[index] <= \' \'))
{
index++;
}
new offset = index;
new result[20];
while ((index < length) && (string[index] > \' \') && ((index - offset) < (sizeof(result) - 1)))
{
result[index - offset] = string[index];
index++;
}
result[index - offset] = EOS;
return result;
}
Használata eléggé egyszerû: (fontos megjegyezni hogy ezen verzió maximálisan 20 karakternyi karakterláncokra darabolja a bevitt adatainkat. (new result[20];)
Példaként egy parancsot használnék, legyen a parancsunk a:
/nem fogod használni 1 percet sem ezt a parancsot
Ha mi ezt beírnánk játék közben akkor ez visszahívásként megjelenne nekünk az OnPlayerCommandText cmdtext[] változójában.
public
OnPlayerCommandText(playerid, cmdtext[])
{
new
PlayerName[MAX_PLAYER_NAME];
GetPlayerName(playerid, PlayerName, sizeof PlayerName);
printf(\"(%d %s) - %s\", playerid, PlayerName, cmdtext);
return 1;
}
Miután játék közben beírtuk a parancsot, a fenti kód sorozat az azonosító számunkat(playerid) a játékosnevünket(PlayerName) és a beírt parancsunkat(cmdtext[]) kiírja konzolba és menti a server_log.txt fájlba, a következõképp:
(0 Zsolesszka) - /nem fogod használni 1 percet sem ezt a parancsot
Innen láthatjuk hogy a használt parancsot a cmdtext[] változó tárolja számunkra.
Nekünk ezt fel kell darabolni hogy feltudjuk használni minden egyes paraméterét külön, konzolban egymás alá kifogjuk íratni a parancsunk elemeit, erre használhatjuk az strtok függvényt de erre a célra több eljárás is létezik, a legismertebb és a legtöbbet használt Y_Less sscanf pluginja által biztosított sscanf( ) eljárás.
Azt tudjuk már hogy a cmdtext[] változó tárolja a parancsot.
Ezt kell nekünk strcmp-vel le ellenõriztetnünk. Amirõl még nem ejtettem szót az az hogy az strtok az a space karakter mentén darabolja parancsukat.
Ezt persze meg is lehet változtatni, de alap esetben és legtöbbet a space-t használjuk még ebben a leírásban is a szavak elválasztására használom. :laugh:
Az strcmp-hez szokás legelsõnek feldaraboltatni strtok-kal minden bejövõ adatot amit a (cmdtext[]) tárol, mert ha nem tennénk, akkor a következõ ellenõrzést hajtaná végre, ami hamis eredményhez vezethet.
strcmp(cmdtext, \"/nem\", true)
strcmp(\"/nem fogod használni 1 percet sem ezt a parancsot\", \"/nem\", true)
A cmdtext tartalmát behelyettesítettem az strcmp-be és így láthatjuk hogy az összehasonlítás nem megfelelõ számunkra. Mert csak a legelsõ résszel kellene össze hasonlítást végeztetnünk.
public
OnPlayerCommandText(playerid, cmdtext[])
{
new
idx = 0,
str[20];
str = strtok(cmdtext, idx);
if(strcmp(str, \"/nem\", true) == 0)
// if(strcmp(\"/nem\", \"/nem\", true) == 0)
{
return 1;
}
return 0;
}
Az strtok vissza tért nekünk a \"/nem\" karakterekkel és elmentette az (str[20];) változóba, miközben a (cmdtext[]) még mindíg tárolja számunkra a komplett parancsunkat. Így már az strcmp egyezést fog találni és megfelelõ eredményt ad vissza ami a program futását megfelelõ írányba engedi tovább.
Az idx változó pedig tárolja a space karakterek pozicióját számunkra. (az str változónak 20-as értéket adtam meg, mert felesleges nagyobb a példában, mert az strtok is 20 karakternyi értékkel tér vissza (new result[20];).
A parancsunk többi paraméterét az strtok többszöri használatával tudjuk feldaraboltatni, amit egy komplett példával szemléltetnék.
public
OnPlayerCommandText(playerid, cmdtext[])
{
// cmdtext = \"/nem fogod használni 1 percet sem ezt a parancsot\"; // Ezt tartalmazza a cmdtext változó
new
idx = 0, // space karakter poziciójának tárolása
str[20]; // Az strtok által visszatért adat tárolása 20 karakternyi az strtok maximálisan annyival tér vissza ami elég szokott lenni (new result[20]
str = strtok(cmdtext, idx); // strtok által visszatért adat str = \"/nem\" idx = 4; (a \"/nem\" karakterlánc utáni space vagy null karakter \'\\0\' pozíciója)
if(strcmp(str, \"/nem\", true) == 0) // strcmp(\"/nem\", /nem\", true);
{
printf(\"%s idx: %d\", str, idx); // nem
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 4);
printf(\"%s idx: %d\", str, idx); // fogod
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 10);
printf(\"%s idx: %d\", str, idx); // használni
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 20);
printf(\"%s idx: %d\", str, idx); // 1
printf(\"strval: %d\", strval(str)); // 1
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 22);
printf(\"%s idx: %d\", str, idx); // percet
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 29);
printf(\"%s idx: %d\", str, idx); // sem
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 33);
printf(\"%s idx: %d\", str, idx); // ezt
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 37);
printf(\"%s idx: %d\", str, idx); // a
str = strtok(cmdtext, idx); // strtok-nak küldött adat: strtok(\"/nem fogod használni 1 percet sem ezt a parancsot\", 39);
printf(\"%s idx: %d\", str, idx); // parancsot
return 1;
}
return 0;
}
Ebbõl láthatjuk hogy az idx változónk a space karakterek pozicióját tárolja.
A pawn nyelv 0-tól számol sok mindent, ezért a per jelünk (/) a nulladik karakter.
/nem(4)fogod(10)használni(20)1(22)percet(29)sem(33)ezt(37)a(39)parancsot(49)
Remélem így már kicsit érthetõbb lesz pár személynek, az strtok használata.