'Program: ReplaceFunctionExample
' This program shows how the included 'replace' function
' converts all instances of one character in a string to another
'==================================================
' replace function
'==================================================
' copyright 2022 Donald S Montaine
' released under the Creative Commons CC-BY license
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if SearchString = "" or FromChar = "" or ToChar = "" then return ""
dim CurrChar as string
dim OutString as string '
for Ctr as integer = 1 to len(SearchString)
CurrChar=mid(SearchString,Ctr,1)
if CurrChar = FromChar then
OutString += ToChar
else
OutString += CurrChar
end if
next
Return OutString
end function
'==================================================
' Main Program
'==================================================
' Replaces all occurances of "|" with ","
width 80,24
dim InputString as string = "a|b|c|d|e|f|g"
dim OutputString as string = replace(InputString,"|",",")
locate 1,1
print "Replace() function example program"
locate 3,5
print "The original string = " + InputString
locate 4,5
print "The modified string = " + OutputString
locate 6,1
print "Press any key to exit " ;
sleep
Last edited by dmontaine on Jul 20, 2022 4:01, edited 1 time in total.
More concise and faster procedure:
- Since the string is passed by value, we can work directly on it and therefore not recopy the unchanged characters (the original string is not modified).
- Since we are working character by character, we can use the string index operator '[]' (instead of 'mid(...,1)') which is faster.
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if SearchString = "" or FromChar = "" or ToChar = "" then return ""
for Ctr as integer = 0 to len(SearchString) - 1
if SearchString[Ctr] = asc(FromChar) then
SearchString[Ctr] = asc(ToChar)
end if
next
Return SearchString
end function
Last edited by fxm on Jul 19, 2022 14:54, edited 1 time in total.
Reason:Update: Forgot first character of string for test/replacement.
- Keep FromChar and ToChar as byref parameters. It avoids creating tempo string variables.
- Use len()=0 instead comparison with an empty string
- Use tempo variables containing asc() to avoid useless calls in the loop
function replace(byval SearchString as string,FromChar as string,ToChar as string) as string
if len(SearchString) = 0 or len(FromChar) = 0 or len(ToChar) = 0 then return ""
dim as integer fc=asc(FromChar), tc=asc(ToChar)
for Ctr as integer = 1 to len(SearchString) - 1
if SearchString[Ctr] = fc then
SearchString[Ctr] = tc
end if
next
Return SearchString
end function
angros47 wrote: ↑Jul 18, 2022 10:12
The variables fc and tc should be of unsigned byte type, to make it even faster
Not true
- gas32 there is one more instruction when moving asc() to ubyte variable as asc() returns a long. The rest is same number of instructions.
- gas64 more instructions inside the loop when ubytes are used.
All the tests are always done with LONG/INTEGER32 (32bit) and INTEGER64 (64bit)
Here is the modified test program implementing most of the suggestions made. Thank you. The only suggestion I didn't include was passing variables by reference. I avoid global variables and byref parameters because they decrease encapsulation. Just my own personal coding fetish.
'Program: ReplaceFunctionExample
' This program shows how the included 'replace' function
' converts all instances of one character in a string to another
'==================================================
' replace function
'==================================================
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if len(SearchString) = 0 or len(FromChar) = 0 or len(ToChar) = 0 then return ""
dim fc as integer = asc(FromChar)
dim tc as integer = asc(ToChar)
for Ctr as integer = 0 to len(SearchString) - 1
if SearchString[Ctr] = fc then SearchString[Ctr] = tc
next
Return SearchString
end function
'==================================================
' Main Program
'==================================================
' Replaces all occurances of "|" with ","
width 80,24
dim InputString as string = "a|b|c|d|e|f|g"
dim OutputString as string = replace(InputString,"|",",")
locate 1,1
print "Replace() function example program"
locate 3,5
print "The original string = " + InputString
locate 4,5
print "The modified string = " + OutputString
locate 6,1
print "Press any key to exit " ;
sleep
Last edited by dmontaine on Jul 19, 2022 15:11, edited 1 time in total.
dodicat wrote: ↑Jul 18, 2022 23:04
gas64 seems to duplicate at compile time
It should be due to #cmdline "-gen gas64" restarting the compilation.
What version of fbc do you use ? With 1.10 only one time.
asc(F) calls fb_asc() which returns a ULONG.
asc("F") no need to call fb_asc() as value known at compile time and a UINTEGER is used
Obvioulsy no real difference on 32bit but on 64bit ......
Tested on stw build 2022-06-24
FreeBASIC Compiler - Version 1.10.0 (2022-06-24), built for win64 (64bit)
OK, no duplication.
(Should've done that to begin with!)
In the responses, the for statement had a -1 added to the end. Both the original code and the changed code work. What I don't understand is why.
Just looking at it, it seems that the last character in the string should never be accessed as len(SearhString) returns the proper length of the string.
for Ctr as integer = 1 to len(SearchString) - 1
if SearchString[Ctr] = fc then SearchString[Ctr] = tc
next
fxm wrote: ↑Jul 18, 2022 5:14
More concise and faster procedure:
- Since the string is passed by value, we can work directly on it and therefore not recopy the unchanged characters (the original string is not modified).
- Since we are working character by character, we can use the string index operator '[]' (instead of 'mid(...,1)') which is faster.
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if SearchString = "" or FromChar = "" or ToChar = "" then return ""
for Ctr as integer = 0 to len(SearchString) - 1
if SearchString[Ctr] = asc(FromChar) then
SearchString[Ctr] = asc(ToChar)
end if
next
Return SearchString
end function
See my post updated: Forgot first character of string for test/replacement: 'for Ctr as integer = 1= 0 to len(SearchString) - 1'
(the string index operator uses a zero-based offset from the first character)
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if len(SearchString) = 0 or len(FromChar) = 0 or len(ToChar) = 0 then return ""
dim location as integer = 0
do
location = instr(location + 1,SearchString,FromChar)
if location > 0 then mid(SearchString,location,1) = ToChar else exit do
loop
Return SearchString
end function
Berfore going on a blitz to write more string procedures than we can shake a stick at, have a look here. PaulSquires wrote a bunch of them in 2015.
Some of them will benefit from the tips above. However, don't get carried away with performance. Unless we go past a procedure, many times and/or we have a large search string, then the execution time will be in the microsecond domain so trying to boost performance would be a waste of time.
function replace(byval SearchString as string,byval FromChar as string,byval ToChar as string) as string
if len(SearchString) = 0 or len(FromChar) = 0 or len(ToChar) = 0 then return ""
dim location as integer = 1 - len(ToChar)
do
location = instr(location + len(ToChar),SearchString,FromChar)
if location > 0 then
SearchString = left(SearchString,location - 1) & ToChar & mid(SearchString,location + len(FromChar))
else
exit do
end if
loop
Return SearchString
end function