Shop OBEX P1 Docs P2 Docs Learn Events
reading a concatenated string — Parallax Forums

reading a concatenated string

eiboydeiboyd Posts: 14
edited 2008-01-14 18:35 in Propeller 1
Hello, I am a new propeller user transitioning from Basic Stamp experience.

Question:
I am trying to access a data table (stored in a DAT format) and I have named each entry in the DAT table with a name:

DAT
scrn1 byte {list of comma delimited datas}
scrn2 byte {}
scrn3 byte {}
etc.

Within the body of the program I have a variable (crntscrn) that is an integer corresponding to the number after scrn.
I have the following code to concatenate two strings to make the name tag in the DAT table.

ascii := NUM.ToStr(crntscrn, NUM#DEC) 'string representation of crntscrn
ascii2 := string("scrn") 'zero terminated string
bytemove(@ascii2+strsize(@ascii2),@ascii,strsize(@ascii)) 'hopefully the concatenated string (e.g., scrn2)

I now need a way to read the string into a variable (e.g. dattag) that I can reference to get data from the correct line of the DAT table.

so:

dattag = ??????????
value of interest := dattag 'where dattag is the 6th entry in the DAT table on line corresponding to scrnX

if scrn is zero terminated it might make more sense to replace the bytemove line with:
bytemove(@ascii2+strsize(@ascii2)-1,@ascii,strsize(@ascii)) { -1 added to attach the number(ascii) right after the scrn eliminating the 0? but accessing the
concatenated string as a variable is my primary concern }
I am brand new to spin so if this is giberish I appologize.
Thank you

Comments

  • deSilvadeSilva Posts: 2,967
    edited 2008-01-10 18:07
    It is more difficult with SPIN. There are no string variables, but only pointers to allocated memory where a string starts. So you have to care that all needed memory is allocated so that nothing will be overwritten. E.g. all your BYTEMOVES will overwrite some data. There is no "space" after the end of a string allocated with STRING("ABC"), so you must not copy there.

    It is best to allocate ample space in the DAT section for string maniputalation, e.g.
    DAT
      stringSpace BYTE 0[noparse][[/noparse]200]
    


    or such
  • eiboydeiboyd Posts: 14
    edited 2008-01-10 18:19
    Perhaps my jargon is incorrect. I don't really need a string variable. I want to be able to reference the name tags in the DAT table. The name tags I have used are scrn#. I understand that SPIN uses pointers to memory locations, I think.

    What I am trying to do is simply build up the name tag from a string (scrn) and a number (turned into a string). Being that the scrn is static I can count on the memory size used to be constant. The attached "number" is also going to be a fixed size (in memory).


    I will allocate sufficient memory for a stringspace as deSilva recommends; however, I still need a way to reference the concatenated name tag. I was thinking of building the tag up byte by byte with a loop but I am unsure how to do this.

    much thanks
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-10 18:25
    The Format object can do it in one line:

    DAT
    · byte buf 0[noparse][[/noparse]200] 'reserve space
    OBJ
    · fmt: "Format"
    PUB
    · fmt.sprintf(@buf,string("scrn%1.1d"),crntscrn)

    If crntscrn is 1, 2 or 3 then buf will hold null terminated strings
    "scrn1", "scrn2" or "scrn3"

    The Format object is in the Object Exchange under Tools.

    regards peter
  • eiboydeiboyd Posts: 14
    edited 2008-01-10 18:38
    Format object. Fantastic. Thanks Peter, I will give it a shot. I found the object on the exchange and it appears you wrote it [noparse]:)[/noparse], double thanks.

    My propeller and an LCD screen arrive today, this stuff is code I am developing without the chip so it will be a few days until I can test things.
  • eiboydeiboyd Posts: 14
    edited 2008-01-11 21:26
    I have implemented the Format object and it created the desired concatenated string. Problem is I can't seem to use it to reference my DAT table?

    Code snipet:

    OBJ
    fmt : "Format"

    PUB gui | crntscrn, temp
    crntscrn := 1
    fmt.sprintf(@buf,string("scrn%1.1d"),crntscrn)
    temp := @buf
    updated := temp

    DAT
    buf word 0[noparse][[/noparse]200] 'reserve space
    scrn1 word 2, 2, 2, 10, 100, 2
    scrn2 word 2, 1, 2, 10, 100, 3, 50, 100, 1
    scrn3 word 3, 1, 3, 10, 100, 2, 50, 100, 1, 100, 100, 3

    The above code does not set updated to 10 as expected/desired? @buf does hold scrn1 as desired and putting in a line:
    updated := scrn1 does generate 10

    It would appear I am missing something...

    Do I need to use the sscanf command in format (it so, how do I use that?)

    much thanks
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-11 23:06
    You wanted to contatenate a fixed string "crtnscrn" with a digit
    and Format did that for you.
    You then assign the address of buf to temp.
    And then you assign temp to updated.
    So updated holds the address of buf but you could do that with just updated := @buf.

    Why do you expect updated to hold 10?
    Where does this 10 come from, or is supposed to come from?

    regards peter
  • eiboydeiboyd Posts: 14
    edited 2008-01-11 23:28
    whoops, the line in my post:
    updated := scrn1
    should have been:
    updated := scrn1 thereby referencing the third word in the DAT line starting with scrn1

    perhaps I am completely misunderstanding the uses of the DAT structure?

    I want to have a list of numbers associated with tags (scrn#) and refer to certain values in the table by using:
    scrn#[noparse][[/noparse]#]


    I was trying to assign the actual information at the address of buf (i.e., scrn1 or scrn2 etc.) to temp so I could access a value with scrn1(for example and get 10)

    perhaps this is not possible in spin? I may have to just implement a lookup table approach (not as pleasing as using the labels DAT appears to afford but....)

    thanks again
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-11 23:34
    You don't need format for that, just a simple routine

    PUB getValue(scrn,index):value | buf
    · case scrn
    ··· 1: buf := @scrn1
    ··· 2: buf := @scrn2
    ··· 3: buf := @scrn3
    · return word[noparse][[/noparse]buf+index]

    and to write a value
    PUB putValue(scrn,index,value) | buf
    · case scrn
    ··· 1: buf := @scrn1
    ··· 2: buf := @scrn2
    ··· 3: buf := @scrn3
    ··word[noparse][[/noparse]buf+index] := value


    regards peter
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-01-11 23:37
    eiboyd,

    When you post code fragments with numbers in brackets [noparse]/noparse, leave a space between the left bracket and the number so the forum software doesn't mistake it for a font size tag.

    Thanks,
    Phil
  • eiboydeiboyd Posts: 14
    edited 2008-01-12 00:22
    Thanks for the heads-up on the brackets, I was curious why the font looked odd. Is it all brackets? or just square?

    Peter, thanks for the code snipet, I will give it a try.

    cheers
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-01-12 00:35
    I thought all brackets were square! smile.gif

    () = parentheses
    [noparse]/noparse = brackets
    {} = braces
    <> = ? ... oh, right: "angle" brackets

    Yeah, just the square ones. You can also use [ in place of a left bracket, but if you reedit your post, you have to keep replacing the [noparse][[/noparse] again and again.

    -Phil
  • Ziggy252Ziggy252 Posts: 32
    edited 2008-01-12 01:13
    The reason you can't refer to labels at runtime is that they don't exist anymore - once your Spin and assembly code is prepared for downloading, the text labels are all removed and replaced with memory addresses.

    I sometimes have a similar requirement in my own code - what I generally do is to create a small index array at runtime, which I can refer to when needed. An initialisation routine in Spin places the addresses of various blocks of data into the array. I can then pass the base address of the array to a new cog, which can then locate any block of data it needs.

    Please note that this code is written completely off the top of my head and is almost certainly syntactically incorrect, it's just to look at to get a better idea of what I'm trying to explain.


    [b]CON[/b]
    A_scrn1=0
    A_scrn2=1
    A_out_buffer=3
    A_in_buffer=4
    [b]PUB[/b]
        addresses[noparse][[/noparse]A_scrn1] := @scrn1
        addresses[noparse][[/noparse]A_scrn2] := @scrn2
        addresses[noparse][[/noparse]A_out_buffer] := @scrn1
        addresses[noparse][[/noparse]A_in_buffer] := @scrn2
    
        [b]cognew[/b](@codeblock, @addresses)
    [b]DAT[/b]
    
    addresses [b]long[/b] 0 [noparse][[/noparse]16]
    
    scrn0 ...
    scrn1 ...
    out_buffer ...
    in_buffer ...
    
    [b]org[/b] 0
    codeblock ...
    
    
    
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-12 03:05
    Ziggy252 said...
    The reason you can't refer to labels at runtime is that they don't exist anymore - once your Spin and assembly code is prepared for downloading, the text labels are all removed and replaced with memory addresses.
    Ziggy, the code you posted is valid and makes sense under certain circumstances; however there are more techniques to accomplish what you do...

    What I do not understand is what you want to say with your first sentence I quoted here, and how it relates to your program (or to the OP's problem)?
  • Ziggy252Ziggy252 Posts: 32
    edited 2008-01-12 05:27
    deSilva,

    As far as I could tell from the OP, he (she? - sorry if I'm making an incorrect assumption)·wanted to access a memory location by name, but he wanted to determine the name at runtime. He was attempting to·construct a string and pass it·as a parameter to bytemove. I was explaining why it wasn't giving the result he wanted.

    I am aware that there are many ways to solve the problem. Peter solved it with a case statement, I solved it with an array of pointers. I'm sure there are more, each of which has·advantages and shortcomings. We offer suggestions, and it's up to the OP to determine which is best suited to his application.
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-12 12:22
    Ziggy,
    I have to admit that I did not understand the objective of the OP before your recent posting here smile.gif
    I had not recognized the true root for the confusion!

    Long live TCL and Perl!
  • eiboydeiboyd Posts: 14
    edited 2008-01-14 17:40
    Thank you all for taking the time to answer this ludite's likely inane questions. The case statement approach seems to work although I am intrigued by the array of pointers idea. The pointer idea looks like it has some assembly (org) so I will leave that alone for the time being.

    Regarding Peter's code...

    PUB getValue(scrn,index):value | buf
    case scrn
    1: buf := @scrn1
    2: buf := @scrn2
    3: buf := @scrn3
    return word[noparse][[/noparse] buf+index]

    My understanding is that the getValue method is passed two variables: scrn and index from the main routine and returns a variable named value. In addition it locally declares a variable buf. The case statement evaluates the variable scrn and matches it to 1, 2 or 3. buf is then assigned the pointer to an address.

    The form of the return statement puzzles me? I would have thought it would look like:
    return word buf[noparse][[/noparse] index]

    This does not work and of course Peter's code does...
    I read the whole spin manual (not the assembly section) and this obviously did not stick, what is going on?
    Would return word[noparse][[/noparse] buf] give the word at the start of the address? I.e., is it the same as return word[noparse][[/noparse] buf+0] ????

    As I am writing this the light is starting to turn on regarding the idea of pointers to addresses and the inability to reference them by name....
    the light is dim, bear with me and thanks again
  • eiboydeiboyd Posts: 14
    edited 2008-01-14 17:48
    Woops spoke too soon. The case approach does work (sort of). At least with my implementation it will return the word in the appropriate row of the dat table but the indexing (finding the column) is not working. No matter what I use for index the word returned is the zeroith value in the appropriate row. So the row referencing is working (i.e., the scrn1 or scrn2 or scrn3) but the column indexing is not? I am always returned the zeroith data in whatever row I reference?


    cheers
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-14 18:00
    There is no assembly involved in Ziggy's code; you will benefit from understand his given example.
    Your interpretation of "GetValue" is quite correct.

    When reading through the manual, don't overlook chapter 4! Look for LONG, WORD and BYTE: There are three (or four) different meanings and situations described how to use them.

    Peter's code however can be a little bit confusing to you, as index in not what you might think; his last line should better look like this
    value := WORD[noparse][[/noparse] buf+2*index]
    


    which is functonally equivalent to
    value := WORD[noparse][[/noparse] buf][noparse][[/noparse]index]
    
  • eiboydeiboyd Posts: 14
    edited 2008-01-14 18:22
    Thank you, the code mod:
    value := WORD[noparse][[/noparse] buf+2*index]
    works but I am in the dark as to how?

    I did read chapter 4 but reading and doing are vastly different. I will try and implement Ziggy's suggestion for the purposes of learning the pointer stuff better.
  • Nick MuellerNick Mueller Posts: 815
    edited 2008-01-14 18:33
    > The case approach does work (sort of).

    Then you could use "lookup" too?

    Nick

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Never use force, just go for a bigger hammer!

    The DIY Digital-Readout for mills, lathes etc.:
    YADRO
  • deSilvadeSilva Posts: 2,967
    edited 2008-01-14 18:35
    The things I was referring to are described on pp. 333 to 334..
Sign In or Register to comment.