Bug with strcmp?
#1

I'm using zcmd and sscanf, but within a /anim command to save making every single one it's own command..... I use strcmp to check if the params match.

For example:
Код:
CMD:anim(playerid, params[])
{
  new aStr[32]

  // All animations in one command.
  sscanf(params, "s[32] ", aStr);
 
  if      (strcmp("rsmg", aStr, true) == 0 || strcmp("rm4", aStr, true) == 0 || strcmp("rak", aStr, true) == 0)          { OnePlayAnim(playerid, "UZI", "UZI_reload", 4.0, 0, 0, 0, 0, 0); }
  else if (strcmp("rdeagle", aStr, true) == 0)      { OnePlayAnim(playerid, "COLT45", "colt45_reload", 4.0, 0, 0, 0, 0, 1); }
  else if (strcmp("carjacked1", aStr, true) == 0)   { LoopingAnim(playerid, "PED", "CAR_jackedLHS", 4.0, 0, 1, 1, 1, 0); }
  else if (strcmp("carjacked2", aStr, true) == 0)   { LoopingAnim(playerid, "PED", "CAR_jackedRHS", 4.0, 0, 1, 1, 1, 0); }
  else { SendClientMessage(playerid, COLOR_WHITE, "USAGE: /anim [animation]"); }
  
  return 1;
}
Now if I use /anim rsmg or any other defined param, it works. If I use /anim followed by any character at all, it tells me how to use it properly (the else statement fires up). BUT if I just use /anim or /anim (with space(s)) it actually in my case used the gun reloading animation.....

I even did a format/SendClientMessage to see exactly what was being compared and it all adds up. How can it possibly say that "" or " " is equal to "rdeagle" or some such.....?
Reply
#2

pawn Код:
if(sscanf(params, "s[32] ", aStr)) return SendClientMessage(playerid, COLOR_WHITE, "USAGE: /anim [animation]");
Remove the else statement and put this one at the top
Reply
#3

It works but the else statement is still necessary (if I type /anim f, or some random text it does or shows nothing without the else).

I guess that fixes it, but logically if I check for "hello" then do..., else if "goodbye" then do...., else do.....

It should be impossible for "" or " " to do anything other than execute the else statement. It also means I repeat the same message twice in the function when there shouldn't be a need. Maybe I can fix up strcmp myself.

It's fixed for now though, thanks mate!
Reply
#4

pawn Код:
CMD:anim(playerid, params[])
{
  new aStr[32];

  // All animations in one command.
  sscanf(params, "s[32] ", aStr); return SendClientMessage(playerid, -1, "Usage: /anim [animation]");
  {
       if(strcmp("rsmg", aStr, true) == 0 || strcmp("rm4", aStr, true) == 0 || strcmp("rak", aStr, true) == 0)          
       {
            OnePlayAnim(playerid, "UZI", "UZI_reload", 4.0, 0, 0, 0, 0, 0);
       }
       else if(strcmp("rdeagle", aStr, true) == 0)      
       {
            OnePlayAnim(playerid, "COLT45", "colt45_reload", 4.0, 0, 0, 0, 0, 1);
       }
       else if (strcmp("carjacked1", aStr, true) == 0)  
       {
            LoopingAnim(playerid, "PED", "CAR_jackedLHS", 4.0, 0, 1, 1, 1, 0);
       }
       else if (strcmp("carjacked2", aStr, true) == 0)  
       {
            LoopingAnim(playerid, "PED", "CAR_jackedRHS", 4.0, 0, 1, 1, 1, 0);
       }  
       }
       return 1;
}
Try this, And if you think i have helped you then hand me one Rep+
Reply
#5

Quote:
Originally Posted by $India$
Посмотреть сообщение
pawn Код:
CMD:anim(playerid, params[])
{
  new aStr[32];

  // All animations in one command.
  sscanf(params, "s[32] ", aStr); return SendClientMessage(playerid, -1, "Usage: /anim [animation]");
  {
       if(strcmp("rsmg", aStr, true) == 0 || strcmp("rm4", aStr, true) == 0 || strcmp("rak", aStr, true) == 0)          
       {
            OnePlayAnim(playerid, "UZI", "UZI_reload", 4.0, 0, 0, 0, 0, 0);
       }
       else if(strcmp("rdeagle", aStr, true) == 0)      
       {
            OnePlayAnim(playerid, "COLT45", "colt45_reload", 4.0, 0, 0, 0, 0, 1);
       }
       else if (strcmp("carjacked1", aStr, true) == 0)  
       {
            LoopingAnim(playerid, "PED", "CAR_jackedLHS", 4.0, 0, 1, 1, 1, 0);
       }
       else if (strcmp("carjacked2", aStr, true) == 0)  
       {
            LoopingAnim(playerid, "PED", "CAR_jackedRHS", 4.0, 0, 1, 1, 1, 0);
       }  
       }
       return 1;
}
Try this, And if you think i have helped you then hand me one Rep+
Is there rep- for a person that posted something that wouldn't work?
Reply
#6

Sorry if this wont work, My Windows is crashed and i am on my Phone so there is mistake, But i tried to help him out.
Reply
#7

I know what you were getting at but what I am looking to do now while I have a temporary solution provided by Lorenc_ (I +rep by the way) is to see if I can modify strcmp to resolve this so I don't need to essentially provide the message twice.

Just looking through the includes now to see if the source for it is actually there.

EDIT: Looks like I have to override it, it's not actually in an include, bummer :P.
Reply
#8

Lorenc_'s solution will be the best, but sscanf is not needed:
pawn Код:
CMD:anim(playerid, params[])
{
  new aStr[32]

  // All animations in one command.
  if(isnull(params)) return SendClientMessage(playerid, COLOR_WHITE, "USAGE: /anim [animation]");
 
  if      (strcmp("rsmg", aStr, true) == 0 || strcmp("rm4", aStr, true) == 0 || strcmp("rak", aStr, true) == 0) OnePlayAnim(playerid, "UZI", "UZI_reload", 4.0, 0, 0, 0, 0, 0);
  else if (strcmp("rdeagle", aStr, true) == 0) OnePlayAnim(playerid, "COLT45", "colt45_reload", 4.0, 0, 0, 0, 0, 1);
  else if (strcmp("carjacked1", aStr, true) == 0) LoopingAnim(playerid, "PED", "CAR_jackedLHS", 4.0, 0, 1, 1, 1, 0);
  else if (strcmp("carjacked2", aStr, true) == 0) LoopingAnim(playerid, "PED", "CAR_jackedRHS", 4.0, 0, 1, 1, 1, 0);
  else SendClientMessage(playerid, COLOR_WHITE, "USAGE: /anim [animation]");
  return 1;
}
strcmp is not designed to comp are if two string completely matches (since it also returns 1 or -1 depends on the string length).
Also, if you do this:
pawn Код:
strcmp("", "asdasd", true)
it will always return 0.

You may try my strcmpex function, which don't have such problems, and it is slightly faster in case insensitive checks:
pawn Код:
stock strcmpex(const string1[],const string2[],bool:ignorecase = false,length = cellmax)
{
    if(!isnull(string1) && !isnull(string2))
    {
        new len1 = strlen(string1),len2 = strlen(string2);
        if(len1 == len2 || length != cellmax)
        {
            if(length > len1) length = len1;
            if(!ignorecase)
            {
                for(new i = 0;i < length;i++)
                    if(string1[i] != string2[i]) return 1;
            }
            else
            {
                for(new i = 0;i < length;i++)
                    if(string1[i] != string2[i])
                    {
                        switch(string1[i])
                        {
                            case 'A'..'Z','a'..'z':
                            {
                                switch(string2[i])
                                {
                                    case 'A'..'Z','a'..'z': if((string1[i] | 0x20) != (string2[i] | 0x20)) return 1;
                                    default: return 1;
                                }
                            }
                            default: return 1;
                        }
                    }
            }
            return 0;
        }
    }
    else if(isnull(string1) && isnull(string2)) return 0;
    return 1;
}

#if defined strcmp
    #undef strcmp
#endif
#define strcmp strcmpex
Reply
#9

It's a very strange behaving function lol, most languages that have string or if you like character array manipulation simply return true or false 1 or 0, there was either a match, or not one.

But my primary language is Object Pascal and you don't use a function to compare a string, it's simply:

Код:
If (myStr1 = myStr2)
Begin
  MessageBox(0, "Success",  "They match", MB_OK);
End;
@leong124: I'm using something very similar, except overriding strcmp (checking if null first), and it's working great.

IS that generally faster than strcmp?
Reply
#10

Quote:
Originally Posted by GrimR
Посмотреть сообщение
It's a very strange behaving function lol, most languages that have string or if you like character array manipulation simply return true or false 1 or 0, there was either a match, or not one.
If sscanf fails, it returns the error ID. Though there aren't any errors yet, it just returns '0 = good' or '1 = error'.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)