Reverse Dereferencing?

BlitzMax Forums/BlitzMax Programming/Reverse Dereferencing?

Russell(Posted 2007) [#1]
I like the fact that I can get the ASCII value of a character within a string by going:
str:String = "Hello"
LastChar = str[4]

but I was a little bummed out that I'm not allowed to do this:
str:String = "Hello"
str[4] = Asc("X")

to change the last character to something else.

This would be a handy feature that is much shorter than using other string handling commands to change the last character (or some other character within the string).

Russell


N(Posted 2007) [#2]
Yeah, bummed me out too. Could always add a SetChar method to the string type that modifies the buffer, or just add a GetBuffer method to the string.


Russell(Posted 2007) [#3]
True.

Mark, is this something that you could add? Could be useful!

Russell


Dreamora(Posted 2007) [#4]
Sounds like there are at least 2 well known member that have not checked the worklogs for 1.26 then ;-)

str:String = "Hello World"
str = str[0..3] + "X" + str[4..]
Print str

Delay 3000



Floyd(Posted 2007) [#5]
That's exactly what they want to avoid. It's like building a new array just to change one element.


N(Posted 2007) [#6]
Floyd: Correct.
Dreamora: Think before you talk. On another note, in the case of strings, concatenation of strings (strings are returned when you slice them, not arrays) has been in since release. Have you been oblivious to this?


marksibly(Posted 2007) [#7]
Hi,

Max strings are 'immutable', meaning they cannot be modified once created. This is really what makes them strings, and not just funky short arrays.

This does in fact prevent a lot of unnecessary copying. Consider this code:

Local t$="Hello"
DoSomething( t )
Assert t="Hello"

...currently, this code is guaranteed not to cause an exception since nothing can modify the string.

However, if string modification were allowed, you'd have to do something like...

Local t$="Hello"
DoSomething( t.Copy() )
Assert t="Hello"

...unless of course you knew before hand that DoSomething() didn't modify its argument. However, this is not generally the case.

In fact, you'd have to do a lot of copying - when calling functions, when storing string in fields, globals etc - 'just in case' the original string was later modified.

All in all, I believe the current system makes dealing with strings much easier and ultimately faster.


Dreamora(Posted 2007) [#8]
Noel and Floyd: There is a serious difference between using slicing and and manual string concatenation.

But if you insist on instring manipulation:
temp:byte ptr = Somefunction(str.toCstring())
str = String.FromCString( temp )
free( temp )


where you do all your "in string" modification in that single function which accepts a byte ptr


And just to make that clear: I actually thought about a solution.
But the target and "things we want to avoid" was not clearly specified -> any answer is correct that achieves the result in an efficient and intelligent way.

Or do what has been suggested like 8-12 months ago: Do what java does and implement a stringbuffer class that holds a Bytestream you can alter at any place.
That wouldn't even be hard (byte ptr to a byte array or using a real TStream to allow encrypted streams and the like)


Vlad(Posted 2007) [#9]

Local t$="Hello"
DoSomething( t )
Assert t="Hello"

...currently, this code is guaranteed not to cause an exception since nothing can modify the string.


Yes this right. But two things:
1) Is this really really need?
2) If I really want i can change string in function DoSomething. Not so easy, but this is possible. So no guaranties.
And indexed access to string's elements is useful.

If Mark don't want do this, this don't meant that we can't do this.
Enjoy:
Local str$ = "Hello"
Print str

'getting pointer to chars:
Local p:Int Ptr = Int Ptr(Varptr(str))
Local pchar:Short Ptr = Short Ptr(p[0])
pchar :+ 6 'this offset depends on string's structure

pchar[0]=Asc("H")
pchar[1]=Asc("e")
pchar[2]=Asc(" ")
pchar[3]=Asc("h")
pchar[4]=Asc("e")

Print str