sscanf and zcmd question about commands with multi parameters
#1

Hello, I just started to work on my new Game Mode, and it has been awhile since I was active on this forum. I decided to use zcmd with sscanf for my commands but I have one question about more complex commands like:



Code:
/safe put/take gun/drugs/money amount

My question is basicly this.

Is this the right usage of sscanf with zcmd (see example command) or is there another better way to use it. Don't get me wrong, the command works fine but this is my first time working with sscanf and zcmd and I just want to know if I'm doing it right.

Example:

pawn Code:
COMMAND:safe(playerid, params[])
{
  new string[64],
    option[4],
    item[5],
    amount[5];
       
  sscanf(params, "sss", option, item, amount);
 
  if (isnull(option))
  {
    SendClientMessage(playerid, COLOR_WHITE, " USAGE: /safe <option>");
    SendClientMessage(playerid, COLOR_WHITE, " OPTIONS: Put, Take");
    return 1;
  }
  if (!strcmp(option, "put"))
  {
    if (isnull(item))
    {
      SendClientMessage(playerid, COLOR_WHITE, " USAGE: /safe put <option>");
      SendClientMessage(playerid, COLOR_WHITE, " OPTIONS: Gun, Drugs, Money");
      return 1;
    }
    if (!strcmp(item, "gun"))
    {
      new ammo = strval(amount),
        weapon = GetPlayerWeapon(playerid);
             
      if (isnull(amount) || !IsNumeric(amount))
      {
        SendClientMessage(playerid, COLOR_WHITE, " USAGE: /safe put gun <ammo>");
        return 1;
      }
      if (weapon == 0)
      {
        SendClientMessage(playerid, COLOR_WHITE, " ERROR: No weapon found in your hands.");
        return 1;
      }
      if (ammo > GetPlayerAmmo(playerid))
      {
        SendClientMessage(playerid, COLOR_WHITE, " ERROR: You don't have that much bullets.");
        return 1;
      }
      GivePlayerWeapon(playerid, weapon, -ammo);
      format(string, sizeof(string), "You have put weapon %s with %d bullets in the safe !", WeaponNames[weapon], ammo);
      SendClientMessage(playerid, COLOR_WHITE, string);
      return 1;
    }
    else if (!strcmp(item, "drugs"))
    {
      // Code for the drugs...
    }
    else if (!strcmp(item, "money"))
    {
      // Code for the money...
    }
  }
  else if (!strcmp(option, "take"))
  {
    if (isnull(item))
    {
      SendClientMessage(playerid, COLOR_WHITE, " USAGE: /safe take <option>");
      SendClientMessage(playerid, COLOR_WHITE, " OPTIONS: Gun, Drugs, Money");
      return 1;
    }
    if (!strcmp(item, "gun"))
    {
      // Code for the gun...
    }
    else if (!strcmp(item, "drugs"))
    {
      // Code for the drugs...
    }
    else if (!strcmp(item, "money"))
    {
      // Code for the money...
    }
  }
  return 1;
}
Thank you...
Reply
#2

Quote:
Originally Posted by Y_Leѕѕ
You need to check params is null, nothing else. sscanf will return a non null value if it fails (i.e. if they enter the wrong parameters).
Last few days I was looking at commands that use sscanf and I always see this condition:

pawn Code:
if (sscanf(params, "s", string)) SendClientMessage(playerid, COLOR_SOMETHING, "Usage: /command <string>");
But I will not need that in my every command because there will be 2-3-4 or more parameters and I don't want it to always return the same message.

So if the player types only for example "/safe" it will return message like "USAGE: /safe <option>" and if the player types "/safe put" it will return message "USAGE: /safe put <item>".

So this command in first post is written just fine?

And one more question... Can I use sscanf more that one time in one command?
Like if on second parameter there is one more parameter but only when I type "gun".

Example

Code:
/safe put gun gunid amount

and

/safe put drugs amount
So first it would be

pawn Code:
sscanf(params, "ss", option, item);
but under the "gun" check can I add this:

pawn Code:
sscanf(params, "is", gunid, amount);
and under the "drugs" check something like this

pawn Code:
sscanf(params, "s", amount);

And if I can do that should this part be changed sscanf(params, ...) or it stays that way?
Reply
#3

Quote:
Originally Posted by Y_Leѕѕ
In that case you would need to do:

sscanf(params, "ssz", option, item, params);
sscanf(params, "is", gunid, amount);

That will store anything remaining in the string back in the string.

Quote:
Originally Posted by Dujma
Quote:
Originally Posted by Y_Leѕѕ
You need to check params is null, nothing else. sscanf will return a non null value if it fails (i.e. if they enter the wrong parameters).
Last few days I was looking at commands that use sscanf and I always see this condition:

pawn Code:
if (sscanf(params, "s", string)) SendClientMessage(playerid, COLOR_SOMETHING, "Usage: /command <string>");
But I will not need that in my every command because there will be 2-3-4 or more parameters and I don't want it to always return the same message.

So if the player types only for example "/safe" it will return message like "USAGE: /safe <option>" and if the player types "/safe put" it will return message "USAGE: /safe put <item>".

So this command in first post is written just fine?
Not quite. As I said sscanf returns 0 if the parameters were correct. If it doesn't return 0 the values of the variables passed are undefined - so your isnull check may fail, but it may not - in which case you will be trying to do code on variables which are empty.
Thank you for your replies.

EDIT: Never mind... Tnx again...
Reply
#4

pawn Code:
new string[64],
    option[4],
    item[5],
    amount[5];
       
  sscanf(params, "sss", option, item, amount);
One of the problems with sscanf is there's no overflow protection. If you type "/safe aaaaaaaaaaaaaaaaa" for example, option (which is only 4 cells) will overflow. You need to make any strings big enough so they wont overflow
pawn Code:
new string[64],
    option[128],
    item[128],
    amount[128];
       
  sscanf(params, "sss", option, item, amount);
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)