Shop OBEX P1 Docs P2 Docs Learn Events
Split string after first character — Parallax Forums

Split string after first character

ryfitzger227ryfitzger227 Posts: 99
edited 2013-11-21 13:18 in Propeller 1
Hello!

I've did some searching on this and found one other thread on here, but it doesn't explain how to do what I'm wanting to do.

I'm sending a string via serial port to the Propeller of "1ABCDEFG". I'm wanting to be able to split the string into two variables. The first character will be the "type variable" and anything after that will be the "content variable."

So this is what I want:

MainVar = 1ABCDEFG (sent from serial port)
TypeVar = 1 (first character in string MainVar)
ContentVar = ABCDEFG (everything after the first character in MainVar)

Any idea on how to do this?

Comments

  • Beau SchwabeBeau Schwabe Posts: 6,566
    edited 2013-11-19 17:31
    This should do what you want ...

    CON
            _clkmode = xtal1 + pll16x
            _xinfreq = 5_000_000
    
    OBJ
    
    PST     :       "Parallax Serial Terminal"
           
    PUB TESTing  | StringAddress
    
        PST.Start(19200)
    
    
        StringAddress := String("1ABCDEFG")                                         'Initialize a string to some value and get the Address
    
        bytemove(StringAddress+2,StringAddress+1,strsize(StringAddress)-1)          'Split String starting at the second character and 'bump' the remaining
                                                                                    'characters one place to the right
    
        byte[StringAddress+1]:=0                                                    'Insert a Zero where we split the string ; the Zero is a string terminator 
        
        pst.str(StringAddress)                                                      'Display the first string      
        pst.Char(9)
        pst.str(StringAddress+2)                                                    'Display the second string
    
  • AribaAriba Posts: 2,690
    edited 2013-11-19 17:34
    A simple way to do it:
    DAT
    TypeChar  byte  "1ABCDEFG",0
    
    PUB Main | MainStr, ContentStr
     MainStr := @TypeChar
     ContentStr := @TypeChar+1
     ser.str(MainStr)           'send whole string
     if TypeChar == "1"         'test first char
       ser.str(ContentStr)      'send string from second char
    

    Andy
  • Beau SchwabeBeau Schwabe Posts: 6,566
    edited 2013-11-19 17:39
    Ariba, beat me to it ... I was going to post a similar alternative
  • kuronekokuroneko Posts: 3,623
    edited 2013-11-19 17:51
    bytemove(StringAddress+2,StringAddress+1,strsize(StringAddress)-1) 'Split String starting at the second character and 'bump' the remaining
    FWIW, this is a really bad move especially when applied to built-in strings.
  • ryfitzger227ryfitzger227 Posts: 99
    edited 2013-11-20 13:39
    Okay. Here's where I'm at. I tried to use Ariba's code, but I couldn't get it to work. Maybe I'm doing something stupid. The only thing that came close was a spin off of Beau's code.

    One thing I'm doing is sending a string from the serial port. It's not always going to be 1ABCDEFG but it could also be 2GFEDCBA, 112345678, and so on. I also don't want to just display it in the serial port, but rather do something with it - if TypeVar == 1....

    Here's what I used.
    CON
             
            _clkmode = xtal1 + pll16x                                               
            _xinfreq = 5_000_000
    
    
    VAR
    
    
      long stack[50]
      long readBuffer, MyVar
        
    OBJ
    
    
      serial      : "Extended_FDSerial"
    
    PUB main
    
    
      serial.start(31,30,0,9600)
    
    
      cognew(readSerial, @stack)
      
    PUB readSerial | StringAddress
    
    
    repeat
    
    
      dira[23] := 1
      outa[23] := 1
    
    
      readBuffer := "0"
      serial.rxflush
      
      repeat until readBuffer <> "0"
        serial.RxStr(@readBuffer)
        
      if readBuffer == "A" 'tell the computer to RESET me
        serial.str(string("RESET"))
      else 'decode the string (get TypeVar and ContentVar)
        StringAddress := String("1ABCDEFG")                                         'Initialize a string to some value and get the Address
    
    
        bytemove(StringAddress+2,StringAddress+1,strsize(StringAddress)-1)          'Split String starting at the second character and 'bump' the remaining
                                                                                    'characters one place to the right
    
    
        byte[StringAddress+1]:=0                                                    'Insert a Zero where we split the string ; the Zero is a string terminator 
        
        serial.str(StringAddress)
    
    
    [COLOR=#ff0000]    if StringAddress == "1"[/COLOR]
    [COLOR=#ff0000]      dira[16] := 1[/COLOR]
    [COLOR=#ff0000]      outa[16] := 1[/COLOR]
    
        waitcnt(clkfreq * 2000 + cnt) 'slight pause before sending the content variable
        
        serial.str(StringAddress+2)
    
    
    

    The only problem with this is that when I receive the second line (serial.str(StringAddress+2)) on the computer it comes up as
    Capture-Forums.PNG
    .

    Also, when I change StringAddress to readBuffer it doesn't work, and that's really what I need (since the Serial Port is setting the string and it's not already set). Another thing that didn't work was the code in red. I want to see if the first character equals one. If so, light an led.

    Anyone got anything that could fix these problems? If you have any questions, please ask.
    79 x 17 - 581B
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-11-20 14:20
    It seems like all you want to do is access the first byte of the received string to get the type and use the rest of the string as your content. You need to define readBuffer as an array so that it can hold the received string. If you define it as a byte array you can access each character by just using an index. The first byte doesn't require an index. So you would do something like this:
    VAR
      byte readBuffer[80] ' This will hold up to 79 character plus the terminating null
    ...
    PUB readSerial | TypeVar, ContentVar
    ...
      serial.RxStr(@readBuffer)
      TypeVar := readBuffer ' Get first byte
      ContentVar := @readBuffer[1] ' Get string address starting at the second byte
    
  • ryfitzger227ryfitzger227 Posts: 99
    edited 2013-11-20 18:01
    Aha! Never knew it was that simple... Seems how everything works out.

    Last thing and this should finalize this part of the project. I'm trying to use the ContentVar as an integer value to set a pause in the code. The way it is supposed to work is the string sent from the computer will be somewhere along the lines of "11000". The first character being the TypeVar ("1") and the rest ("1000") being the time, in ms, to pause for. How do I transfer ContentVar to an integer that waintcnt can use? - I think I'm saying that right. Haha.
       TypeVar:= readBuffer
        ContentVar := @readBuffer[1]
    
    
        if TypeVar == "1"
          dira[16] := 1
          outa[16] := 1
                                                    
         waitcnt(clkfreq * ContentVar + cnt)'*****
        
          dira[17] := 1
          outa[17] := 1
    

    Thanks.
    - Ryan

    EDIT: Sometimes the Type can also be a letter, so think of the string sent from the computer as "A1000" A being the TypeVar and 1000 being the ContentVar, or time in ms to pause for.
  • T ChapT Chap Posts: 4,223
    edited 2013-11-20 19:26
    PUB str2dec(str) | index
      result := 0
      repeat index from 0 to strsize(str)
        result *= 10
        result += byte[str][index] - "0"
    

    I just did a search on the forum search tool for str2dec and this was one of many things that came up that may get you started. Get the string converted to a decimal, then convert the decimal to the wait period you need.


    More ideas:
    pub str2dec(pntr) | value, b
    
    '' Converts string to decimal value
    
      value := 0                                                    ' reset value
    
      repeat
        b := byte[pntr++]                                           ' get digit from string
        if ((b => "0") and (b =< "9"))                              ' if digit
          value := value * 10 + (b - "0")                           '  update value
        else
          quit
    
      return value
    
  • ryfitzger227ryfitzger227 Posts: 99
    edited 2013-11-21 13:18
    T Chap,

    Thanks so much for that code. I din't really know what to search for in this, so this helped a lot. The second code block worked perfect.

    Thanks again,
    - Ryan
Sign In or Register to comment.