Shop OBEX P1 Docs P2 Docs Learn Events
Looking for help with string formatting objects — Parallax Forums

Looking for help with string formatting objects

turbosupraturbosupra Posts: 1,088
edited 2011-10-01 09:46 in Propeller 1
Being used to C sharp, string formatting is killing me in spin :)

I found 2 string objects, but none of them include the type of formatting functions I'd like to do.

I'm used to foreach loops and string.Contains()/array.Contains(), so I have been trying to figure out a way to do something like this
public removeChars(array unwantedArray)
{

  foreach(byte in byteArray)
  {
     if unwantedArray.Contains(byte)
        {
          byteArray.Remove(byte)
        }
  }

}

Is there any interest in putting together an expanded string object?

Unfortunately I'm not very good at spin code, or I'd have written the ones I wanted and offered them to the forum.

Comments

  • Mike GMike G Posts: 2,702
    edited 2011-09-30 12:49
    There are a few ways to do this...

    One is using two pointers one pointer (A) keeps track of of the array index while the other pointer (B) reads bytes. Both pointer start at the same location. When a wanted character is found both pointer increment. When an unwanted character is found the index pointer (A) stays in position and pointer B increments. If the next byte is wanted then that byte is copied to the location of the index pointer (A) and both pointer increment else B increments again. The process repeats until you reach the end, probably a zero terminator. Finnaly copy the zero term to A. This is destructive to the original array.

    Another way is to read a byte and if it is wanted copy the byte to a known buffer and increment the buffer pointer. If the byte is unwanted, go to the next byte and validate. This is not destructive to the original array but takes more memory.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-09-30 12:52
    New language = new paradigms. Here's the Spinnish way to do it.
    ptr := @byteArray
    repeat while (char := byte[ptr])
      if (lookdown(char : "u", "w", "a", "n", "t", "e", "d")
        bytemove(ptr, ptr + 1, strsize(ptr))
      ptr++
    

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2011-09-30 13:00
    Thank you both for the quick replies. I spent hours trying to figure this out and had mild success, so I have to ask ...

    Is there a way to accumulate some of the other string functions found in c sharp, to a spin method such as

    EndsWith
    IndexOf
    IndexOfAny
    LastIndexOf
    LastIndexOfAny
    Remove
    Replace
    StartsWith
    ToCharArray
    TrimEnd
    TrimStart
  • Mike GMike G Posts: 2,702
    edited 2011-09-30 13:03
    I believe most, if not all, of your list already exists in string object found in the OBEX. Off the top of my head I'm thinking the StrEngine object
  • turbosupraturbosupra Posts: 1,088
    edited 2011-09-30 13:11
    Thanks Mike. I have seen strings and strings 2, but not strengine. I will search for that now and reply back if needed.



    Mike G wrote: »
    I believe most, if not all, of your list already exists in string object found in the OBEX. Off the top of my head I'm thinking the StrEngine object
  • turbosupraturbosupra Posts: 1,088
    edited 2011-09-30 13:15
    No object called strengine, searched under just engine, with nothing and str had a lot of hits, but nothing relevant outside of stringsv1 and stringsv2. Could it have been called something different?
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-09-30 15:08
    I couldn't find StrEngine at the link you posted. How do you access it?

    turbosupra, the list of functions you posted should be pretty easy to code in Spin. Each function should take just a few lines to implement.

    BTW, I believe the lookdown technique that Phil posted would only work with a fixed list of characters. If yiou want to handle a string of characters in unwantedArray you would need to write a Contains method, as follows.
    pub removeChars(byteArray, unwantedArray) | val
      repeat while (val := byte[byteArray])
        if Contains(unwantedArray, val)
          Remove(byteArray)
        byteArray++
    
    pub Contains(ptr, val) | val1
      repeat while (val1 := byte[ptr++])
        if val1 == val
          return 1
    
    pub Remove(ptr)
      bytemove(ptr, ptr+1, strsize(ptr))
    
  • turbosupraturbosupra Posts: 1,088
    edited 2011-09-30 20:14
    Thanks Dave.

    Maybe we can all work together and get a cumulative string object, as they aren't so easy for me, but maybe one day. I will be trying your code shortly.

    As for Mike G's code link, it's a little tricky to find, but this link should work


    STREngine Download Link

    Dave Hein wrote: »
    I couldn't find StrEngine at the link you posted. How do you access it?

    turbosupra, the list of functions you posted should be pretty easy to code in Spin. Each function should take just a few lines to implement.

    BTW, I believe the lookdown technique that Phil posted would only work with a fixed list of characters. If yiou want to handle a string of characters in unwantedArray you would need to write a Contains method, as follows.
    pub removeChars(byteArray, unwantedArray) | val
      repeat while (val := byte[byteArray])
        if Contains(unwantedArray, val)
          Remove(byteArray)
        byteArray++
    
    pub Contains(ptr, val) | val1
      repeat while (val1 := byte[ptr++])
        if val1 == val
          return 1
    
    pub Remove(ptr)
      bytemove(ptr, ptr+1, strsize(ptr))
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-10-01 09:46
    If the "unwanted array" is used more than once, it will be more efficient to compile it into a bitmapped set, where each of the 256 bit positions in the eight longs corresponds to an eight-bit character. Then, for each character comparison, you have only to check whether its bit is set, as I've done below in the character substitution example:
    CON
    
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    
    OBJ
    
      pst   :       "Parallax Serial Terminal"
    
    VAR
    
      long char_mask[8]
    
    PUB  start 
    
      pst.start(9600)
      make_mask(@char_mask, string("Characters to replace"))
      pst.str(@my_string)
      pst.char(13)
      substitute(@my_string, @char_mask, "*")
      pst.str(@my_string)
      pst.char(13)
    
    PUB make_mask(mask_ptr, str) | char
    
      longfill(mask_ptr, 0, 8)
      repeat while (char := byte[str++])
        long[mask_ptr][char >> 5] |= 1 << (char & 31)
    
    PUB substitute(str, mask_ptr, subst) | char
    
      repeat while (char := byte[str])
        if long[mask_ptr][char >> 5] & (1 << (char & 31))
          byte[str] := subst
        str++
    
    DAT
    
    my_string     byte      "This is a test of replacing characters", 0    
    

    The make_mask method could easily be made fancier, to include options like case-independence, for example.

    -Phil
Sign In or Register to comment.