Shop OBEX P1 Docs P2 Docs Learn Events
Help with strcomp — Parallax Forums

Help with strcomp

Don MDon M Posts: 1,652
edited 2013-09-02 16:06 in Propeller 1
There is another thread talking about strcomp that got me to thinking about using it. I have been playing around with some RFID cards and was trying to make use of this but it doesn't work the way I thought it would. What am I doing wrong here?

I have a byte variable called RFIDdata2[10] that the data is read into from a card:
VAR
  byte i, RFIDdata2[10]

I can display it on the terminal fine by using the repeat i routine. It shows 0F03040185 for one card and 0415D87A73 for the other on the terminal:
repeat i from 0 to 9                          
      Term.tx(RFIDdata2[i])

In the DAT section I have only the 1 card listed as:
DAT

Tag1    byte  "0F03040185" 


So I'm trying to use strcomp to compare what is in the RFIDdata2 buffer to the Tag1 in the DAT section but it doesn't work right:
PUB CheckRFID

  if strcomp(RFIDdata2, Tag1)
    term.str(string("Match !"))                                        
  else
    term.str(string("No match !"))                                                                          

I always get a "Match !". It seems as though it is only comparing the first byte which is a "0" for the 2 different tags I have. The second byte is different. One tag is "4" the other is "F". I tried different combinations of adding the "@" before RFIDdata2 and Tag1 but didn't make any difference.

Help!

Comments

  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2013-09-02 07:48
    Hi, strcomp compares two zero terminated strings.

    Try making the RFIDdata2 array 11 elements in length and assigning zero to the last element of you RFID string then add a zero to your DAT string.
    DAT
    
    Tag1    byte  "0F03040185",0
    

    Jeff T.
  • Don MDon M Posts: 1,652
    edited 2013-09-02 08:02
    Ok I see now how it works. So if the string already has a "0" whithin but is not the termination "0" how do you get around that? Or can't you?
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2013-09-02 08:10
    The zero in the tag is not zero it is an ASCII character with a byte value of 48 (48=binary %110000 zero=binary %0)

    Jeff T.
  • Mike GMike G Posts: 2,702
    edited 2013-09-02 08:18
    Ok I see now how it works. So if the string already has a "0" whithin but is not the termination "0" how do you get around that? Or can't you?
    A string is defined as a char array ending with a terminating zero. A buffer may contains many strings. Many char arrays ending with a zero in side a buffer. Use code to find the sting bounds (pointer array) by looking for the zeros in the buffer.

    In some cases a char array containing zeros is not a string at all but a protocol. It depends on the application.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-02 08:24
    Change your array to 11 bytes -- make sure the last byte is zero
    Make sure your tags in the DAT section have a terminating zero (zero, not "0")
    Use the address operator (@) with strcomp
    if strcomp(@RFIDdata2, @Tag1)
    
  • Don MDon M Posts: 1,652
    edited 2013-09-02 08:38
    JonnyMac wrote: »
    Change your array to 11 bytes -- make sure the last byte is zero
    Make sure your tags in the DAT section have a terminating zero (zero, not "0")
    Use the address operator (@) with strcomp
    if strcomp(@RFIDdata2, @Tag1)
    

    Thanks JonnyMac! That fixed it.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-02 09:11
    Glad I could help. Remember, the manual is available from the Help menu in the Propeller Tool and it clearly demonstrates how to use strcomp.

    Once you're comfortable with pointers (the address of an element), you could write a method like this that will take your tag and compare it to a known database (in a DAT section). If your tag is found then you'll get 0..n back, if not found, it will return -1.

    Written on-the-fly -- you'll need to test.
    pub check_tag(p_target, p_tags, limit) | idx
    
    '' Compare tag to database
    '' -- return index if found
    '' -- return -1 if not found
    '' -- p_target is pointer to tag to compare
    '' -- p_tags is pointer to tags database
    '' -- limit is # of elements in tags database
    
      idx := 0
    
      repeat
        if (strcomp(p_target, p_tags))                              ' compare target to database
          return idx                                                '  if found, return index
        else
          idx += 1                                                  ' advance index
          p_tags += 11                                              ' advance db pointer
          if (--limit == 0)                                         ' exceeded limit?
            return -1                                               '  return failure
    
  • Don MDon M Posts: 1,652
    edited 2013-09-02 10:30
    JonnyMac wrote: »
    Glad I could help. Remember, the manual is available from the Help menu in the Propeller Tool and it clearly demonstrates how to use strcomp.

    Once you're comfortable with pointers (the address of an element), you could write a method like this that will take your tag and compare it to a known database (in a DAT section). If your tag is found then you'll get 0..n back, if not found, it will return -1.

    Written on-the-fly -- you'll need to test.
    pub check_tag(p_target, p_tags, limit) | idx
    
    '' Compare tag to database
    '' -- return index if found
    '' -- return -1 if not found
    '' -- p_target is pointer to tag to compare
    '' -- p_tags is pointer to tags database
    '' -- limit is # of elements in tags database
    
      idx := 0
    
      repeat
        if (strcomp(p_target, p_tags))                              ' compare target to database
          return idx                                                '  if found, return index
        else
          idx += 1                                                  ' advance index
          p_tags += 11                                              ' advance db pointer
          if (--limit == 0)                                         ' exceeded limit?
            return -1                                               '  return failure
    

    Thanks Jonny. I'm playing with the code now to see how it works.

    So my DAT database looks like this:
    DAT
    
    Tags    byte  "0F03040485",0
            byte  "0F03040185",0    ' I have this tag 
            byte  "0F012045F9",0
            byte  "0415D87A73",0    ' I have this tag
    

    And I invoked you code this way:
    term.dec(check_tag(@RFIDdata2, @Tags, 4)) 
    

    The actual tags I have are the second and fourth tags. The other 2 are just made up numbers.

    It seems to work with the exception of it doesn't matter if I put in a value of 0, 1, 2, 3 or 4 for the limit of elements. It still returns 1 for the second tag and 3 for the fourth tag.

    Edit: Oops.. my bad. I missed copying the last line of code. Sorry. Yes it works. Thanks again!
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-02 14:24
    It still returns 1 for the second tag and 3 for the fourth tag.

    As written, the method returns a 0-based index into the tags database. You can use this index with another database (e.g., names, features, etc.) if desired.

    It's very easy to convert to a 1-based index; by doing this you can evaluate the return as true (non-zero) or false (0) -- this simplifies things if you only care about the existence of a tag in the database and aren't connecting the tag index to anything else.

    Here's the modification:
    pub verify_tag(p_target, p_tags, limit) | idx
    
    '' Compare tag to database
    '' -- return index (1 to limit)/(true) if found
    '' -- return 0 (false) if not found
    '' -- p_target is pointer to tag to verify
    '' -- p_tags is pointer to tags database
    '' -- limit is # of elements in tags database
    
      idx := 1                                                      ' set index to 1st entry
    
      repeat
        if (strcomp(p_target, p_tags))                              ' compare target to database
          return idx                                                '  if found, return index
        else
          idx += 1                                                  ' advance index
          p_tags += 11                                              ' advance db pointer
          if (--limit == 0)                                         ' exceeded limit?
            return false                                            '  return failure
    
  • Don MDon M Posts: 1,652
    edited 2013-09-02 14:51
    JonnyMac wrote: »
    As written, the method returns a 0-based index into the tags database. You can use this index with another database (e.g., names, features, etc.) if desired.

    It's very easy to convert to a 1-based index; by doing this you can evaluate the return as true (non-zero) or false (0) -- this simplifies things if you only care about the existence of a tag in the database and aren't connecting the tag index to anything else.

    Here's the modification:
    pub verify_tag(p_target, p_tags, limit) | idx
    
    '' Compare tag to database
    '' -- return index (1 to limit)/(true) if found
    '' -- return 0 (false) if not found
    '' -- p_target is pointer to tag to verify
    '' -- p_tags is pointer to tags database
    '' -- limit is # of elements in tags database
    
      idx := 1                                                      ' set index to 1st entry
    
      repeat
        if (strcomp(p_target, p_tags))                              ' compare target to database
          return idx                                                '  if found, return index
        else
          idx += 1                                                  ' advance index
          p_tags += 11                                              ' advance db pointer
          if (--limit == 0)                                         ' exceeded limit?
            return false                                            '  return failure
    

    Thanks. I knew it was a zero based index and how the numbering scheme worked. I just worded my response in such a way that it sounded like I didn't understand that the first item would be 0 and so on and that I could have changed the index start to 1 instead of zero. Sorry about that. I had it working fine after I discovered that I had left out the last line of code from copying from the webpage.

    I was also working on just as you mentioned- another database that indexes the tags to the names. I have a few bugs to iron out yet but I'll yell if I get stuck.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-02 15:28
    Here's a bit of code that I use to return the address of a variable-length name in a DAT table. You pass the index of the name you want and the starting address of the table. It's brute force, looping through, counting terminating zeros, until it lands on the start of the desired string.
    pub get_name(idx, p_names) | c
    
      repeat while (idx > 0)
        c := byte[p_names++]
        if (c == 0)
          idx -= 1
    
      return p_names
    
  • Don MDon M Posts: 1,652
    edited 2013-09-02 15:43
    JonnyMac wrote: »
    Here's a bit of code that I use to return the address of a variable-length name in a DAT table.

    You must have read my mind... that is the part I was having trouble with. I padded the names I am using now with spaces to make them all the same length.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-02 16:06
    You must have read my mind...

    I've been around that block a few times. Padding works, but creates problems should you need to increase the maximum length of a name. If you are going to pad to create fixed-width entries, pad with zeros instead of spaces -- this prevents display problems later. For example:
    dat
    
      Names                 byte    "Jon", 0[6], 0
                            byte    "Actor", 0[4], 0
                            byte    "Hollywood", 0
    


    In this case, the longest name is nine characters; the first entry is only three so six additional zeros are added to create the pad.
Sign In or Register to comment.