The only trick here is that the macro used take a string variable as argument or as well a raw string. Maybe it can be extended to reverse a number also?
#macro _REVERSESTRING( s , t )
t = ""
#if typeOf(s)=typeOf(string)
for i as integer = len(s) - 1 to 0 step -1
t &= chr((s)[i])
next i
#else
for i as integer = len(*(cast(zstring ptr, @(s)))) - 1 to 0 step -1
t &= chr((s)[i])
next i
#endIf
#endMacro
dim as string outstr
_REVERSESTRING( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" , outstr)
? outstr
dim as string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
_REVERSESTRING(s , outstr)
? outstr
'(eof)
'(eof)
Function Revers (ByVal txt As String) As string
Dim lt As Long
Dim As String Text = txt
lt = Len(Text)
If lt > 1 Then
asm
mov eax, [Text] 'Anfang des String im RAM
mov ebx, [lt] 'Laenge des String
mov esi, eax
add eax, ebx
dec eax
mov edi, eax 'letzes Zeichen des String
mov ecx,ebx
shr ecx 'ecx =lt \ 2 ;Laufvariable
lnext:
mov al, [esi] 'al = Anfang
mov ah, [edi] 'ah = Ende
mov [edi], al 'Ende = al
mov [esi], ah 'Anfang = ah
inc esi 'Anfang + 1
dec edi 'Ende - 1
loop lnext 'wie for .. next
End asm
End If
Function = Text
End Function
Dim t As String
t = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Print Revers(" !dlroW olleH ")
Print t
Print Revers (t)
Sleep
Very nice, probably necessary for intensive reversing (asm performance).
From my side I propose this extension to numerical values of the original macro above, with the same level of generality of the input, but something is limitating the use of STR(), so it requires STR2() to be fixed (question of return byref...).
'_macro that can revert a string input, or something numeric
'_output as string
function str2(byref s as const string) byref as const string
return s
end function
#macro _REVERSESTRING( in_ , out_ )
out_ = ""
#if typeOf(in_)=typeOf(string)
for i as integer = len(in_) - 1 to 0 step -1
out_ &= chr((in_)[i])
next i
#elseIf typeOf(in_)=typeOf(integer)
for i as integer = len(str(in_)) - 1 to 0 step -1
out_ &= chr((str2(str(in_)))[i])
next i
#elseIf typeOf(in_)=typeOf(double)
for i as integer = len(str(in_)) - 1 to 0 step -1
out_ &= chr((str2(str(in_)))[i])
next i
#else
for i as integer = len(*(cast(zstring ptr, @(in_)))) - 1 to 0 step -1
out_ &= chr((in_)[i])
next i
#endIf
#endMacro
'------------------------------------------------------------
'--------------------------------------------------------TEST
dim as string outstr
'strings
_REVERSESTRING( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" , outstr)
? outstr
dim as string in_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
_REVERSESTRING(in_str , outstr)
? outstr
'integers
_REVERSESTRING(1234567890 , outstr)
? outstr
dim as integer in_int = 1234567890
_REVERSESTRING(in_int , outstr)
? outstr
'doubles
'terminal zeros are unfortunately lost for decimal numbers
_REVERSESTRING(1234.567890 , outstr)
? outstr
dim as double in_dbl = 1234.567890
_REVERSESTRING(in_dbl , outstr)
? outstr
'(eof)
screen 14
sub gnirtSwarD(s as string,x as long=0,y as long=0)
#define map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c)
var e=8*len(s)
dim as any ptr im(1)={imagecreate(e,16),imagecreate(e,16)}
draw string im(0),(1,0),s
for x as long=0 to e
for y as long=0 to 16
if point(x,y,im(0))=15 then
var x1=map(0,e,x,e,0)
pset im(1),(x1,y)
end if
next
next
put(x,y),im(1)
imagedestroy Im(0)
imagedestroy Im(1)
end sub
gnirtSwarD("ABCDEFGHIJKLMNOPQRSTUVWXYZ",50,50)
sleep
function reverseString(forward as string) as string
dim as string reverse
for i as integer = len(forward) to 0 step -1
reverse = reverse & chr(forward[i])
next i
return reverse
end function
Dim As String s
input "Enter a string:";s
print reverseString(s)
Sleep
Function reverseString2 (Byval s As String) As String
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
Function reverseString2 (Byval s As String) As String 'fxm
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
Function reverseString3 (byref s As String) As String'basiccoder2 -- tweaked
dim as long L=len(s)-1
dim as string t=string(L+1,0)
for n as long=L to 0 step -1
t[L-n]=s[n]
next
return t
end function
dim as string s="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for n as long=1 to 22
s+=s
next
print "Length of string ";len(s)
do
sleep 50
dim as string ans
dim as double t
t=timer
ans= reversestring2(s)
print timer-t,left(ans,72),"fxm"
sleep 50
t=timer
ans= reversestring3(s)
print timer-t,left(ans,72),"other"
print
loop until inkey=chr(27)
sleep
I notice that in the method by fxm, instead of passing a string byval, it is much faster to pass the string byref and make a copy inside the function.
VIZ:
Function reverseString2 (Byref s1 As String) As String 'fxm
dim as string s=s1
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
Function reverseString3 (byref s As String) As String'basiccoder2 -- tweaked
dim as long L=len(s)-1
dim as string t=string(L+1,0)
for n as long=L to 0 step -1
t[L-n]=s[n]
next
return t
end function
dim as string s="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for n as long=1 to 22
s+=s
next
print "Length of string ";len(s)
do
sleep 50
dim as string ans
dim as double t
t=timer
ans= reversestring2(s)
print timer-t,left(ans,72),"fxm"
sleep 50
t=timer
ans= reversestring3(s)
print timer-t,left(ans,72),"other"
print
loop until inkey=chr(27)
No, that must be equivalent because a string is a pseudo "complex" object.
When one passes to a procedure a complex object (ie: of a Type with destructor or copy-constructor) for a parameter declared byval, in fact the caller does a copy of this object and this copy is passed byref to the procedure (complex objects are always passed by reference).
In fact complex objects are always passed by reference, either directly or through a copy.
dodicat wrote:I notice that in the method by fxm, instead of passing a string byval, it is much faster to pass the string byref and make a copy inside the function.
Only for the long strings, when you build little strings we see nothing really clear.
Same here, even for long string, that's unclear, somehow random? Should theorically byref as const string be fastest, slowest? Maybe it's a totally dumb question, but it had to be asked at least once in a life :-)
Function reverseString2 (Byref s1 As const String) As const String 'fxm
dim as string s=s1
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
Function reverseString3 (Byref s1 As String) As String 'fxm
dim as string s=s1
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
dim as string s="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for n as long=1 to 22
s+=s
next
print "Length of string ";len(s)
do
sleep 50
dim as string ans
dim as double t
t=timer
ans= reversestring3(s)
print timer-t,left(ans,72),"fxm "
sleep 50
t=timer
ans= reversestring2(s)
print timer-t,left(ans,72),"fxm byref const"
print
loop until inkey=chr(27)
Function reverseString2 (Byref s1 As String) As const String 'fxm
dim as string s=s1
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
Function reverseString3 (Byval s As String) As String 'fxm
Dim As Integer l = Len(s)
For i As Integer = 0 To l\2-1
Swap s[i], s[l-1-i]
Next i
Return s
End Function
dim as string s="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
for n as long=1 to 22
s+=s
next
print "Length of string ";len(s)
do
sleep 50
dim as string ans
dim as double t
t=timer
ans= reversestring2(s)
print timer-t,left(ans,72),"byref "
sleep 50
t=timer
ans= reversestring3(s)
print timer-t,left(ans,72),"byval"
print
loop until inkey=chr(27)
I am not just nitpicking with this, I have abandoned using byval strings in my bigint functions, they are noticeably slower.