Simple String Help
I wrote a little sample code (below) to teach myself how strings work. I expected the output of the string to be "abc" but instead its "..."
This proves that I dont understand how strings work. Can someone point me in the correct direction here?
This proves that I dont understand how strings work. Can someone point me in the correct direction here?
con
_clkmode = xtal1 + pll16x '
_xinfreq = 5_000_000 '
var
long count1
obj
term : "Parallax Serial Terminal"
PUB Main
term.start(9600)
term.str(string("starting...",13))
waitcnt (9000000+cnt)
term.str(string("starting...",13))
count1[0] := "a"
count1[1] := "b"
count1[2] := "c"
waitcnt (90000000+cnt)
term.str(count1)
Comments
Change the variable section to:
VAR byte count1[4]
I think that will fix it.
con _clkmode = xtal1 + pll16x ' _xinfreq = 5_000_000 ' var byte count1 [4] obj term : "Parallax Serial Terminal" PUB Main term.start(9600) term.str(string("starting...",13)) waitcnt (9000000+cnt) term.str(string("starting...",13)) count1[0] := "a" count1[1] := "b" count1[2] := "c" waitcnt (90000000+cnt) term.str(count1)
term.str([COLOR=#ff0000]@[/COLOR]count1)
FYI, this code in the original,
count1[1] := "b"
assigned "b" to the long after count1 or four bytes after "a". ["a"][0][0][0]["b"][0][0][0]If you fix the @ problem in the first code, you'd probably just get "a" displayed since the other three bytes of the long where zero.
The Propeller Manual explains the way longs, word and bytes are stored (I don't remember where). But as I said earlier, it's a good idea to only use bytes when working with charater arrays. (Unless you're using a pointer to the array which should be a word or long.)
You can access individual bytes within a long. There are several ways to to this, the method I generally use is byte[@count1 + 1] to access the second byte.
So if you left count1 as a long and made these changes.
count1 := "a" 'same as before byte[@count1 + 1] := "b" byte[@count1 + 2] := "c"
I think this would get you the output you were looking for but it's a really awkward way to do it.
Why at times does the command
term.str(count1)
work fine without the @ sign and other times we need the @ sign?
term.str(@count1)
addr := string("Hi there") term.str(addr)
will work as advertised (string() returns an address). The other case is when you use an array (VAR or DAT, usually bytes). Simply referring to it by name will give you its first element (which is not normally an address), i.e. array is the same as array[0]. To treat the array as a string we need the @. It returns the address of an array element, i.e. using @array[1] will skip the first character (assuming a byte array).VAR byte array[32] PRI print term.str(@array[0]) ' print string stored in array term.dec( array[0]) ' print array element 0 as number, e.g. first character term.tx( array[0]) ' print array element 0 as character
If you change your variable section to:
VAR byte count1[4] word count2
And make this change. Instead of this:
term.str(@count1)
Use:
count2 := @count1 term.str(count2)
In this case count2 is the address of count1. You could also use the dec method to display the memory location of count1.
term.dec(count2)
Which, after you've made the "count2 := @count1" assignment, should give you the same output as:
term.dec(@count1)
For fun you could add a DAT section at the end like this:
DAT myArray byte "Hello World", 0
And up in the main section of code use:
term.str(string(13, "myArray location = $")) term.hex(@myArray, 4)
Then in the Propeller Tool, use F8, click "Show Hex" and find the location displayed by the terminal window output. You should see "Hello World" in the far right window stored at this location.
This type of activity helped me understand the whole pointer and location concept.
term.start(9600) term.str(string("starting...",13)) waitcnt (9000000+cnt) term.str(string("starting...",13))
As far as I remember the Propeller Tool is not optimizing. So, it does not recognize that both strings are equal and will really create 2 copies in memory.
What you can do is create a version of the string in a DAT section and use this ... or ... I think even more effective is to create a function and call this.
... term.start(9600) term.str( @starting ) waitcnt (9000000+cnt) term.str( @starting ) ... DAT starting byte "starting...",13,0
or
... term.start(9600) strt waitcnt (9000000+cnt) strt ... PUB strt term.str(string("starting...",13))
Another (more awkward) way to do what MagIO2 suggests is to have a word variable to store the string's location.
VAR ' other variables word startingText
And then early in the program use:
startingText := string("starting...")
Then any time you wanted to use the string use.
term.str(startingText)
This is one of those times you don't want to use the "@" operator.
Again, since it's so much fun, you could add (after you've assigned the string to startingText):
term.hex(startingText, 4)
You could then look for this location in your code using F8 and "Show Hex". You should find the text "starting..." in the far right window at the location displayed using the above code.
MagIO2's suggestions on using a string multiple times are much better ways than the way I just described. The method I used was to show what the command "string" is doing and why you don't always need the @ symbol when sending strings to be displayed.