Shop OBEX P1 Docs P2 Docs Learn Events
Simple question: How to manipulate the bytes of a string — Parallax Forums

Simple question: How to manipulate the bytes of a string

ElectricAyeElectricAye Posts: 4,561
edited 2011-08-02 13:44 in Propeller 1
I'm unfamiliar with how strings are manipulated so I'm hoping to get some wisdom regarding the following:

I've loaded a string into a variable like so:
{When using bytemove to move a string, be sure to include a space for the zero terminator... }
Bytemove(@Header, string("650,400,T,500"), 14)

And when I do the following, everything displays on the VGA very nicely:
{Assign the memory address of Header to the HeaderByteAddressPointer...}
HeaderByteAddressPointer := @Header 

{Display the entire header...}
VGA.str(HeaderByteAddressPointer)


So far, so good.

But now I would like to extract and display only the 9th byte of Header, which should be a "T", I think.

For extraction and later use in making comparisons, my guess would be to use something like this to get to the 9th byte:
Byte[(HeaderByteAddressPointer+8)]

And for only displaying the 9th byte of Header, I would guess something like this would work:
VGA.str((HeaderByteAddressPointer+8))

But so far I haven't gotten any of these things to work out. I'm guessing it has something to do with strings needing a zero terminator, but I'm not sure how that is done, or if there is some simpler approach, or somebody has an Object for dealing with this kind of string thing.

Thanks!

Comments

  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2011-08-02 10:58
    I have a couple string manipulating objects (Strings v1.X and Strings v2.X).
    Probably v1 would be easier to work with.

    You have the idea correct, but I think you need to copy the byte you want (Byte[(HeaderByteAddressPointer+8)]) to a new array, and terminate it.
    var
      byte ninthbyte[2]
    
    PUB Main
      ninthbyte[1] := 0
      ninthbyte[0] := Byte[@header + 8] ' maybe header[8] ?
    
      VGA.str(ninthbyte)
    
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-08-02 11:24
    Bobb Fwed wrote: »
    I have a couple string manipulating objects (Strings v1.X and Strings v2.X).
    ...

    Bobb,
    those objects look very handy. I'll try them out and see how they work with this.
    It seems tragic that SPIN doesn't have a simple built-in way of dealing with string operations of this sort, especially considering it has such a dandy video output.

    Thanks for such a fast response!

    Mark
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-08-02 11:32
    string outputing methods go on outputting bytes until they meet the value zero.
    If your 32kB code should happen to have no zero anywere 32kB of characters would be outputted.
    So zero-termination is a must.

    If you want to extract parts of a string you would have to call methods that only send a single byte

    or like Bobb showed copying the bytesequence to an temprorary array one byte bigger than your extracted string
    where this additional byte contains a zero.
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-08-02 13:15
    Okay, so this bit of code worked well and returned the expected character of "6" on the VGA:
    OBJ
    VGA : "VGA_text"
    FwedStrings    : "STRINGS"
    
    
    PUB Main
    bytemove(@Header, string("650,400,T,500"), 14)
    
    VGA.str(string("Header first character = "))
    {Start at the first (0th) character of the Header and take only one character then output it to the VGA...}
    VGA.str(FwedStrings.SubStr(@Header, 0, 1))
    
    

    So far, so good.

    But now I would like to compare that first character (i.e, the "6") extracted from the Header with some other string characters and this does not seem to work:
        {If the first byte in the header is 2 through 9, then set the flag...}
        IF ((FwedStrings.SubStr(@Header, 0, 1)) => "2") AND ((FwedStrings.SubStr(@Header, 0, 1)) =< "9")
            HeaderReadCompletedFlag := 1
    

    I'm guessing my problem here is that "2" and "9" are not the proper way to express this.

    Another guess: FwedStrings.SubStr(@Header, 0, 1) results in an address of the string, not the string itself, so how can that address get converted to a string???

    Any suggestions?
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2011-08-02 13:30
    SubStr returns an address to a string. So you are comparing an address location to 50 ("2") or 57 ("9")...doesn't work too well.

    You would need to use something like this (below) to convert the strings to decimals, then compare those to the desired numbers.
    IF ((byte[FwedStrings.SubStr(@Header, 0, 1)]) => 2) AND ((byte[FwedStrings.SubStr(@Header, 0, 1)]) =< 9)
        HeaderReadCompletedFlag := 1
    
    That might work as you expect it to (only works with single digit numbers).
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-08-02 13:34
    Bobb Fwed wrote: »
    SubStr returns an address to a string. So you are comparing an address location to 50 ("2") or 57 ("9")...doesn't work too well.....

    Okay, I see. Man, this string wrangling business has been tying me in knots!

    Thanks for the help! :-)
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2011-08-02 13:37
    Yeah, it's all confusing because strings are not strings, they are byte arrays with ASCII (decimal) values of letters in it. When you store a string to a variable (as you would in most languages) all you get is the address, the string never moves or get copied unless you use bytemove.
    And lack of typecasting or size checks makes debugging a headache too, if you make a typo.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2011-08-02 13:44
    Oh yeah, also, SubStr and StrParse are almost identical, but StrParse is faster (because it only accepts positive numbers), so you may want to replace the method calls to that.
Sign In or Register to comment.