sscanf richtig einsetzen

  • sscanf richtig einsetzen

    Guten Tag zusammen.

    heute wollte ich euch zeigen wie ihr sscanf richtig einsetzen könnt. Zudem werde ich das Tutorial in 2 Gesamtteile packen. Erstens das sscanf Tutorial, dann ein paar Beispiele im Nächsten Post.Erstmal hier die Gliederung des Tutorials:

    1. Was ist sscanf eigentlich?
    2. Wo wird sscanf gebraucht?
    3. Wie setzt man sscanf richtig ein?


    Zu Anfang sollte ich sagen das bei diesem Tutorial Grundkenntnisse in PAWN erforderlich sind.

    1. Was ist sscanf eigentlich?


    sscanf ist ein Plugin welches von Alex a.k.a. Y_Less erstellt wurde. Mit sscanf kann man Strings splitten.


    2. Wo wird sscanf gebraucht?


    sscanf ist wie oben beschrieben ein Plugin mit dem man Strings splitten kann. Man kann mit sscanf z.b. mehrteilige Befehle machen. Also wenn man z.B. ein Haussystem macht und dort einen Befehl machen will der ingame so aussieht:
    /hsystem [Text]
    Wenn man dann z.b. /hsystem kaufen eingibt kann man das Hauskaufen. So das ist der erste Parameter. Natürlich wird bei sowas auch eine ID und ein Preis benötigt. Also sieht der Befehl dann ingame z.b. so aus: /hsystem kaufen [ID] [Preis] . Viele Fragen sie wie soll das gehen? Das könnt ihr im Nächsten Punkt lesen und lernen.

    3. Wie setzt man sscanf richtig ein?

    Bei sscanf gibt es insgesamt 10 Parameter. Eine Auflistung der Paramenter findet ihr HIER. Da ich euch ja einen einfachen Befehl mit sscanf zeigen möchte mache ich einfach mal einen kleinen Kick Befehl.
    [pwn]ocmd:kick(playerid,params[]) // der Kick Befehl in OCMD
    {
    new pID, reason[128]// News, pID soll hier als Playerid für den der gekickt wird dienen, reason ist der Grund.
    if(sscanf(params,"us",pID,reason))return SendClientMessage(playerid,BLAU,"/kick [id] [grund]");// So hier haben wir sscanf.
    /* also if = wenn (Fragt also ab ) dann (sscanf(params,"u Splittet den Usernamen bzw die ID vom Befehl und speichert den in pID*/ s /*splittet den Grund vom Befehl und speichert den in reason)) dann das "/kick [id] [grund] " kommt nur wenn einer, oder beide der Parameter(also ID und Grund) nicht vorhanden ist.*/
    Kick(pID);// Kickt die pID, wenn dort playerid stehen würde würde der Admin sich ja selber kicken.
    // Viele fragen sich jetzt warum dann reason wenn es hier nicht gebraucht wird? Ganz einfach. Man kann jetzt eine Nachricht an alle User schicken, das mit format und SendClientMessageToAll. Das ist leicht zu machen. Ich wills euch hier nicht vormachen deshalb ist es hier nicht drin.
    return 1;
    })[/pwn]

    So, das ist eigentlich die Erklärung mit einem Beispiel von sscanf. Natürlich kann man mit sscanf noch viel mehr machen als nur den Namen bzw die ID und einen Grund vom Befehl zu splitten.Ich wollte euch hier nur die Grundfunktionen von sscanf erklären. Allerdings sollte euch auffallen das ein kleiner Fehler im Code ist. Der ist drin weil es kein C & P Tutorial ist. Wenn Ihr das lest macht einfach die letzte Klammer also ) weg. Dann geht es ;) .

    Achja ganz wichtig! Um sscanf einzusetzen braucht ihr den sscanf stock! Dieser muss bei benutzung von sscanf am besten unten im Script platziert werden. Dieser sieht wie folgt aus:
    [pwn]/* Sscanf stock */
    stock sscanf(sstring[], format[], {Float,_}:...)
    {
    #if defined isnull
    if (isnull(sstring))
    #else
    if (sstring[0] == 0 || (sstring[0] == 1 && sstring[1] == 0))
    #endif
    {
    return format[0];
    }
    #pragma tabsize 4
    new
    formatPos = 0,
    sstringPos = 0,
    paramPos = 2,
    paramCount = numargs(),
    delim = ' ';
    while (sstring[sstringPos] && sstring[sstringPos] <= ' ')
    {
    sstringPos++;
    }
    while (paramPos < paramCount && sstring[sstringPos])
    {
    switch (format[formatPos++])
    {
    case '\0':
    {
    return 0;
    }
    case 'i', 'd':
    {
    new
    neg = 1,
    num = 0,
    ch = sstring[sstringPos];
    if (ch == '-')
    {
    neg = -1;
    ch = sstring[++sstringPos];
    }
    do
    {
    sstringPos++;
    if ('0' <= ch <= '9')
    {
    num = (num * 10) + (ch - '0');
    }
    else
    {
    return -1;
    }
    }
    while ((ch = sstring[sstringPos]) > ' ' && ch != delim);
    setarg(paramPos, 0, num * neg);
    }
    case 'h', 'x':
    {
    new
    num = 0,
    ch = sstring[sstringPos];
    do
    {
    sstringPos++;
    switch (ch)
    {
    case 'x', 'X':
    {
    num = 0;
    continue;
    }
    case '0' .. '9':
    {
    num = (num << 4) | (ch - '0');
    }
    case 'a' .. 'f':
    {
    num = (num << 4) | (ch - ('a' - 10));
    }
    case 'A' .. 'F':
    {
    num = (num << 4) | (ch - ('A' - 10));
    }
    default:
    {
    return -1;
    }
    }
    }
    while ((ch = sstring[sstringPos]) > ' ' && ch != delim);
    setarg(paramPos, 0, num);
    }
    case 'c':
    {
    setarg(paramPos, 0, sstring[sstringPos++]);
    }
    case 'f':
    {

    new changestr[16], changepos = 0, strpos = sstringPos;
    while(changepos < 16 && sstring[strpos] && sstring[strpos] != delim)
    {
    changestr[changepos++] = sstring[strpos++];
    }
    changestr[changepos] = '\0';
    setarg(paramPos,0,_:floatstr(changestr));
    }
    case 'p':
    {
    delim = format[formatPos++];
    continue;
    }
    case '\'':
    {
    new
    end = formatPos - 1,
    ch;
    while ((ch = format[++end]) && ch != '\'') {}
    if (!ch)
    {
    return -1;
    }
    format[end] = '\0';
    if ((ch = strfind(sstring, format[formatPos], false, sstringPos)) == -1)
    {
    if (format[end + 1])
    {
    return -1;
    }
    return 0;
    }
    format[end] = '\'';
    sstringPos = ch + (end - formatPos);
    formatPos = end + 1;
    }
    case 'u':
    {
    new
    end = sstringPos - 1,
    id = 0,
    bool:num = true,
    ch;
    while ((ch = sstring[++end]) && ch != delim)
    {
    if (num)
    {
    if ('0' <= ch <= '9')
    {
    id = (id * 10) + (ch - '0');
    }
    else
    {
    num = false;
    }
    }
    }
    if (num && IsPlayerConnected(id))
    {
    setarg(paramPos, 0, id);
    }
    else
    {
    #if !defined foreach
    #define foreach(%1,%2) for (new %2 = 0; %2 < MAX_PLAYERS; %2++) if (IsPlayerConnected(%2))
    #define __SSCANF_FOREACH__
    #endif
    sstring[end] = '\0';
    num = false;
    new
    name[MAX_PLAYER_NAME];
    id = end - sstringPos;
    foreach (Player, playerid)
    {
    GetPlayerName(playerid, name, sizeof (name));
    if (!strcmp(name, sstring[sstringPos], true, id))
    {
    setarg(paramPos, 0, playerid);
    num = true;
    break;
    }
    }
    if (!num)
    {
    setarg(paramPos, 0, INVALID_PLAYER_ID);
    }
    sstring[end] = ch;
    #if defined __SSCANF_FOREACH__
    #undef foreach
    #undef __SSCANF_FOREACH__
    #endif
    }
    sstringPos = end;
    }
    case 's', 'z':
    {
    new
    i = 0,
    ch;
    if (format[formatPos])
    {
    while ((ch = sstring[sstringPos++]) && ch != delim)
    {
    setarg(paramPos, i++, ch);
    }
    if (!i)
    {
    return -1;
    }
    }
    else
    {
    while ((ch = sstring[sstringPos++]))
    {
    setarg(paramPos, i++, ch);
    }
    }
    sstringPos--;
    setarg(paramPos, i, '\0');
    }
    default:
    {
    continue;
    }
    }
    while (sstring[sstringPos] && sstring[sstringPos] != delim && sstring[sstringPos] > ' ')
    {
    sstringPos++;
    }
    while (sstring[sstringPos] && (sstring[sstringPos] == delim || sstring[sstringPos] <= ' '))
    {
    sstringPos++;
    }
    paramPos++;
    }
    do
    {
    if ((delim = format[formatPos++]) > ' ')
    {
    if (delim == '\'')
    {
    while ((delim = format[formatPos++]) && delim != '\'') {}
    }
    else if (delim != 'z')
    {
    return delim;
    }
    }
    }
    while (delim > ' ');
    return 0;
    }[/pwn]

    So das war nun der erste Teil des Tutorials. Im nächsten Teil folgen ein paar Beispiele, die auch etwas komplexer sein können.

    MfG G-Mac_x3
  • Du hast sogar noch zwei weitere Copy & Paste Schutzmechanismen, ein ";" fehlt am Ende der "new" Zeile und
    beim Auskommentieren(falls wer die Kommentare mitkopiert) ist ein Fehler, den aber denke ich jeder im Kompiler herauslesen kann.
    Sowie gehört eigentlich hinter dem Parameter "s" ein [128], da sonst folgende Meldung kommt in der Server-Konsole erscheint.
    sscanf warning: Strings without a length are deprecated, please add a destination size.


    Ansonsten muss ich aber sagen, dass ist ein top Tutorial, hat mir den Umgang mit sscanf durchaus erleichert.

    SSL schrieb:

    Schonmal was von sscanf2 gehört?


    Ich denke mal schon, da er ja das Plugin auch als Plugin erwähnt.

    sscanf 2.6