A sscanf függvény Mi is ez?A sscanf függvény segítségével karakterláncokat bonthatunk szét megadott egységek szerint. Hasonlít a strtok függvényre, de
sokkal gyorsabb, egyszerûbb, és sokoldalúbb is.
Telepítés / üzembehozásElõször is töltsük le a plugint
innen, majd a
szervermappád/plugins mappába másold be a
sscanf.dll-t. Ezután nyisd meg a
server.cfg-t, és a plugins sorhoz add hozzá a sscanf-ot így:
plugins sscanf
plugins sscanf.so
Most helyezzük el a
sscanf2.inc-t a
szervermappánk/pawno/include mappában. Ezek után nyissuk meg a Pawno-t, és ágyazzuk be a fejállományt:
[pawn]#include < sscanf2 >[/pawn]
És már használhatjuk is a függvényt!
Megjegyzés: Ha a forrásodban a sscanf valamelyik régebbi verzióját használtad, akkor töröld ki, mivel a fordító nem fogja átfordítani a kódodat!
MûködéseMint már fentebb említettem, megadhatjuk, hogy az általunk kiválasztott sztringet milyen formátum( ok )ba darabolja szét. Ez sokkal egyszerûbb, mint amilyennek hangzik.
Lássunk egy példát!
[pawn]
public OnFilterScriptInit( ) {
//Tárolók létrehozása
new szStr[ 12 ];
new iNum;
//A karakterlánc szétválasztása, és a darabok elhelyezése a megfelelõ tárolókban
sscanf( \"Sscanf 2\", \"s[12]i\", szStr, iNum );
print( szStr );
printf( \"%i\", iNum );
return;
}
[/pawn]
Az alábbi eljárást lefuttatva ezt az eredményt kapjuk:
Sscanf
2
Fontos észrevennünk, hogy így a részek a megadott formátumba kerülnek át a sztring formátum helyett( kivétel ha sztring formátumba választjuk szét, akkor ugyanaz marad természetesen ).
Lehetséges elválasztók:Jelölés | Név | Példaérték |
i, d | Integer | 1, 42, -10 |
c | Karakter | a, o, * |
s | Karakterlánc | sztring, példa |
l | Logikai | true, false |
b | Bináris | 01001, 0b1100 |
h, x | Hexadecimális | 1A, 0x23 |
o | Oktális | 045 12 |
n | Szám | 42, 0b010, 0xAC, 045 |
f | Lebegõpontos | 0.7, -99.5 |
g | IEE lebegõpontos | 0.7, -99.5, INFINITY, -INFINITY, NAN, NAN_E |
u | Felhasználó név/id | ZeRo, 1 |
q | NPC név/id | ShopBot, 13 |
r | Játékos név/id | ZeRo, 33 |
Az \'átmentés\' módszere:Íme egy rossz példa:
[pawn]sscanf( \"ez sscanf 2\", s[12]i, string, integer );[/pawn]
Ugyanis a fenti példában a \'
sscanf\' karakterlánc( sztring ) típusú, de az elválasztásban mi az
i betût használtuk, ami egész számot( integert ) kellene jelöljön. Ezt kiküszöbölhetjük az
átmentés módszerével, aminek a jele a
\\\\( mivel a sima
\\ a fordítóprogram által már használatban van ). Tehát, az elõzõ példánk helyesen így nézne ki:
[pawn]sscanf( \"ez\\\\ sscanf 2\", s[12]i, string, integer );[/pawn]
Ha a
string, és az
integer nevû változók létre lennének hozva, és lefuttatnánk a fenti kódot, akkor az eredményünk a következõ lenne:
ez sscanf //Ez a \'string\' karakterlánc értéke
2 //Ez az \'integer\' változó értéke
Enumerációs elválasztás:A sscanf egyik elõnye( például a strtok-al szemben ), hogy lehetõségünk van az adatokat egybõl egy felsorolt adattípusba( Enum ) rendezni. Ennek az elválasztásnak a jelölése egy
\'e\' betûvel kezdõdik, ami az
enumerációs elválasztást jelöli, egy \'
<\' jellel folytatódik, ami az
enumerációs elválasztás kezdetét jelöli, majd az elválasztók után egy \'
>\' jellel végzõdik, ami pedig
a folyamat végét jelöli. Egy példa:
[pawn]
//Globális névtérben létrehozunk egy felsorolt adattípust
enum eTest {
szString[ 32 ],
Float: fFloat,
iInteger
}
new eData[ eTest ];
//És valahol hivatkozunk rá, mégpedig egy sztringbõl bemásoljuk az adatokat a megfelelõ helyekre
sscanf( \"Unformat 3.141593 2010\", \"e<s[32]fi>\", eData );
[/pawn]
Ezzel feltöltöttük értékekkel az
eData vektort. De például, ha rossz sorrendben hivatkozunk rá, akkor hibaüzenetet fogunk kapni.
[pawn]sscanf( \"2010 Unformat 3.141593\", \"e<s[32]fi>\", eData);[/pawn]
Mivel a
2010 nem karakterlánc, az \'
Unformat\' nem lebegõpontos érték, és a
3.141593 pedig nem egész típusú szám.
Ez a kis funkciója a függvénynek hasznos lehet például nagyobb játékmódoknál, vagy játékos-adatokat kezelõ rendszereknél, vagy bárhol máshol, ahol felsorolt adattípussal dolgozunk.
A \'kihagyás\' módszere:A
kihagyás lényege az, hogy a megadott részt beolvassuk a sztringbõl( bármilyen formátumú is az ), és ellenõrizzük( tehát feltétellel ki lehet szûrni, ha rossz a bevitt érték ), de a különbség az a sima elválasztással szemben, hogy itt a kihagyott rész
nem kerül mentésre, tehát nem kell megadnunk változót a visszatérési értéknek.
A jele a \'
{\', illetve a \'
}\' karakterek, ami egyértelmûen a kihagyás
kezdetét, és
végét jelölik. Az alábbi példában az elsõ értéket kezeljük a kihagyással:
[pawn]sscanf( \"6 47\", {i}i, integer );[/pawn]
Amint fent is említettem, két értéket, és két elválasztó karaktert láthatunk, de
csak egy visszatérési változót, aminek oka - amint már leírtam - az, hogy a kihagyással kezelt érték nem kerül mentésre, tehát a kód folytatása során
nem tudunk rá hivatkozni.Így a fenti példában az \'integer\' nevû változónk értéke 47 lesz, a 6 pedig törlõdik( elvetõdik ). És amint azt az elején leírtam, a bevitt adatok ugyanúgy ellenõrzésre kerülnek, tehát a következõ kód hibát eredményezne:
[pawn]
new integer;
if( sscanf( \"kettõ 2\", {i}i, integer ) )
[/pawn]
Mivel a \'kettõ\' sztring típusú, de mi integer típusú elválasztót rendeltünk hozzá( ugyan kihagyás van, de ezt nem zárja ki ).
Ezt a módszert akárhányszor alkalmazhatjuk az elválasztásaink során, amikor csak szükségünk van rá. Ezenkívül az enumerációs elválasztásokba is beágyazhatjuk õket, nem lesz rá hatással.
[pawn]sscanf( \"7 3.14 kutya 42 INFINITY x\", \"e<ifs[12]{ig}c>\", enumData );[/pawn]
Karakteres elválasztásokA függvénnyel lehetõségünk van továbbá karakterek által elválasztott adatok szétválasztására is. Nézzünk egy egyszerû példát!
[pawn]sscanf( \"1,2,3\", \"p<,>iii\", num1, num2, num3 );[/pawn]
A fenti kódrészletben a sztringet a megadott karakter mentén( itt a
, mentén ) elválasztottuk, és integer típusú változókba helyeztük. Alakja egyszerû: a
p jelenti a karakteres elválasztást, a
< az elválasztás kezdetét, a
benne lévõ karakter( itt a VESSZÕ ) az elválasztási karaktert, a
> pedig az elválasztás végét( szerkezete majdnem megegyezik az enumerációs elválasztáséval ).
Ez a módszer természetesen mûködik az enumerációs elválasztásban is, és ez az egyetlen eset, ahol két
<> van egymásba ágyazva. Egy példa:
[pawn]
//Létrehozunk egy enumerációs egységet
enum e_Data {
int,
Float: ffloat,
string[ 24 ]
}
//Valahol hivatkozunk rá, mondjuk egy parancsban
new e_Var[ e_Data ];
sscanf( \"12432 3.14,ZeRo\", \"e<ip<,>fs[24]>\", e_Var );
[/pawn]
Ha csak karakterláncokkal használjuk ezt a módszert, akkor a mûvelet viselkedése kicsit módosul, ugyanis a legtöbb elválasztó érzékeny a szóközre. Ez azt jelenti, hogy például ez mûködni fog, annak ellenére, hogy nincs benne \';\' karakter:
[pawn]sscanf( \"1 2 3\", \"p<;>iii\", var0, var1, var2 );[/pawn]
De ez nem minden esetben mûködik. Példa egy kivételre:
[pawn]sscanf( \"hello 1\", \"p<->s[32]i\", str, var );[/pawn]
Itt ugyanis a
str változó értéke
hello 1 lesz. És végül zárjunk egy helyes példával:
[pawn]sscanf( \"hello there>27\", \"p<>>s[32]i\", str, var );[/pawn]
Ez mûködni fog, és a következõ eredményt adja vissza:
hello there
27
Példa egy parancsban való használatraAz alábbi parancsban megmutatom, hogy mennyivel egyszerûbb kezelni ezt az egészet a sscanf-al, mint mondjuk a strtok-al. Nézzünk egy /pm parancsot!
[pawn]
CMD:pm( playerid, params[ ] ) {
//Tároló létrehozása az azonosítónak, és az üzenetnek
new iPid;
new szMsg[ 100 ];
if( sscanf( params, \"is[100]\", iPid, szMsg ) ) {
SendClientMessage( playerid, COLOR_RED, \"Használat: /pm < JátékosID > < Üzenet >\" );
} else if( !IsPlayerConnected( iPid ) || IsPlayerNPC( iPid ) ) {
SendClientMessage( playerid, COLOR_RED, \"Érvénytelen azonosító!\" );
} else {
new szStr[ 128 ];
format( szStr, sizeof szStr, \"[ PM ]: %s( %i ): %s\", GetPlayerNameEx( playerid ), playerid, szMsg );
SendClientMessage( iPid, COLOR_YELLOW, szStr );
}
return 1;
}
GetPlayerNameEx( playerid ) {
new z[ MAX_PLAYER_NAME ];
GetPlayerName( playerid, z, sizeof z );
return z;
}
[/pawn]
Megjegyzés:A függvényt lehetõségünk van
unformat néven is használni. Ezt az alternatív megoldást azért hozta létre Y_Less, hogy elkerülje a félreértéseket ezzel, és a C nyelv beli sscanf függvénnyel kapcsolatban.
Utolsó frissítés: 2011/05/09