Page 1 of 2
Dobro_replace() question for Fred in last message
Posted: Fri May 15, 2009 1:57 pm
by dobro
original text :
Text$= " coucou toto20 , coucou toto205"
*****************************************************
my procedure
Code: Select all
text2$=dobro_replace(Text$, "toto20" , "Leon" )
result :
coucou Leon , coucou toto205
*****************************************************
Purebasic :
Code: Select all
text3$=ReplaceString(Text$,"toto20","Leon")
result :
coucou Leon , coucou Leon5
*****************************************************
my procedure :
[mode Recursif]
ProcedureDLL.s dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
; by Dobro
Static extrait1$,pos
If pos= Len (chaine$)
text2$=extrait1$
pos=0 :extrait1$= ""
ProcedureReturn text2$
EndIf
pos=pos+1
extrait1$=extrait1$+ Mid (chaine$,pos,1)
car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
If extrait3$=chaine_cherche$
If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
If pos>1
If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
Else
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
EndIf
EndIf
text2$=dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
ProcedureReturn text2$
EndProcedure
[mode iteratif]
ProcedureDLL.s dobro_replace2(chaine$,chaine_cherche$,chaine_remplace$)
; by Dobro
For pos=1 To Len (chaine$)
extrait1$=extrait1$+ Mid (chaine$,pos,1)
car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
If extrait3$=chaine_cherche$
If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
If pos>1
If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
Else
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
EndIf
EndIf
Next pos
text2$=extrait1$
pos=0 :extrait1$= ""
ProcedureReturn text2$
EndProcedure
[Version Library for tailbite]
Global text2$
ProcedureDLL.s dobro_replace(chaine$,chaine_cherche$,chaine_remplace$)
; by Dobro
For pos=1 To Len (chaine$)
extrait1$=extrait1$+ Mid (chaine$,pos,1)
car_avant= Asc ( Mid (chaine$,pos-1,1)) ; le caractere avant
car_apres= Asc ( Mid (chaine$,pos+ Len (chaine_cherche$),1)) ; ) ; le caractere apres
extrait3$= Mid (chaine$,pos, Len (chaine_cherche$)) ; la chaine extraite
If extrait3$=chaine_cherche$
If (car_apres<48 Or (car_apres>57 And car_apres<65) Or (car_apres>90 And car_apres<97) Or car_apres>122 )
If pos>1
If (car_avant<48 Or (car_avant>57 And car_avant<65) Or (car_avant>90 And car_avant<97) Or car_avant>122 )
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
Else
extrait1$= Left (extrait1$, Len (extrait1$)-1)
extrait1$=extrait1$+chaine_remplace$
pos=pos+ Len (chaine_cherche$)-1
EndIf
EndIf
EndIf
Next pos
text2$=extrait1$
pos=0 :extrait1$= ""
ProcedureReturn text2$
EndProcedure
[call sample : for lib ]
Text$ = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"
Debug dobro_replace(Text$, "Procedure20" , "xxx" )
Posted: Fri May 15, 2009 6:03 pm
by Trond
It can be done a bit simpler:
Code: Select all
Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s)
A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ")
ProcedureReturn Right(Left(A, Len(a)-1), Len(a)-2)
EndProcedure
It's also about 15 times faster.
But it doesn't take newlines into account.
Posted: Fri May 15, 2009 8:01 pm
by dobro
your code :
Code: Select all
Haystack.s = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"
Needle.s="Procedure20"
Seam.s="toto"
CallDebugger
Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s)
A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ")
ProcedureReturn Right(Left(A, Len(A)-1), Len(A)-2)
EndProcedure
Debug trond_replace(Haystack.s, Needle.s, Seam.s)
result :
aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20
(coucou)
?? no change !!!
my procedure
result :
aa Test_toto(coucou) bb Test_Procedure205 (coucou) cc Test_toto (coucou) cc Test_toto
(coucou)
you understand ?? :roll:

Posted: Fri May 15, 2009 8:31 pm
by dobro
another procedure

by Lionel_om (french forum)
Procedure.s SpecialReplaceString(Text$, FindMe$, ReplaceBy$)
Protected index.l = 1, *char.c
Protected lFindMe.l = Len (FindMe$), lReplBy.l = Len (ReplaceBy$)
index = FindString (Text$, FindMe$, index)
While index
*char = PeekC (@Text$ + lFindMe + index - 1)
If *char < '0' Or *char > '9'
Text$ = Left (Text$,index-1) + ReplaceBy$ + Right (Text$, 1+ Len (Text$)-(index+lFindMe))
; Debug Text$
index + lReplBy + 1
Else
index + lFindMe + 1
EndIf
index = FindString (Text$, FindMe$, index)
Wend
ProcedureReturn Text$
EndProcedure
Posted: Fri May 15, 2009 8:40 pm
by Deeem2031
Imho this should work too, but it doesn't
Code: Select all
Haystack.s = "aa Test_Procedure20(coucou) bb Test_Procedure205 (coucou) cc Test_Procedure20 (coucou) cc Test_Procedure20" + Chr (13)+ Chr (10)+ "(coucou)"
Needle.s="Procedure20"
Seam.s="toto"
Procedure.s Deeem2031_Replace(String.s, Find.s, Replace.s)
Protected regex, result.s
regex = CreateRegularExpression(#PB_Any, "(?<![a-zA-Z0-9])"+Find+"(?![a-zA-Z0-9])")
If regex
result = ReplaceRegularExpression(regex, String, Replace)
FreeRegularExpression(regex)
EndIf
ProcedureReturn result
EndProcedure
Debug Deeem2031_Replace(Haystack.s, Needle.s, Seam.s)
Posted: Fri May 15, 2009 8:45 pm
by dobro
we have already tried the lib RegularExpression
and that is why "dobro_replace" is born

Posted: Fri May 15, 2009 8:49 pm
by Deeem2031
But it should work this way, this looks like a bug because all regex-tools i tried did it as expected (try for example:
http://www.fileformat.info/tool/regex.htm). Only PB does not do it right.
Posted: Fri May 15, 2009 8:53 pm
by dobro
Fred can answer only

Re: Dobro_replace()
Posted: Fri May 15, 2009 9:13 pm
by AND51
dobro wrote:original text :
Text$= " coucou toto20 , coucou toto205"
...
result :
coucou Leon , coucou Leon5
Sorry, I don't understand the purpose. Should
only the first match be replaced?
// edit:
Ah, I understand: you only want whole words to be replaced?
Re: Dobro_replace()
Posted: Fri May 15, 2009 9:36 pm
by Trond
AND51 wrote:
// edit:
Ah, I understand: you only want whole words to be replaced?
Which is what I thought as well, but then it turns out my solution is incorrect because it only replaces whole words...
It would be a good idea to post an explanation of what the code actually does when you post a code.
Posted: Fri May 15, 2009 9:46 pm
by AND51
Code: Select all
Procedure.s replaceWholeWords(String.s, Find.s, Replace.s, caseInsensitive=0)
String=" "+String+" "
Find=" "+Find+" "
Replace=" "+Replace+" "
ReplaceString(String, Find, Replace, #PB_String_InPlace)
ProcedureReturn Mid(String, 2, Len(String)-2)
EndProcedure
Procedure.s trond_replace(Haystack.s, Needle.s, Seam.s)
A.s = ReplaceString(" " + Haystack + " ", " " + Needle + " ", " " + Seam + " ")
ProcedureReturn Right(Left(A, Len(a)-1), Len(a)-2)
EndProcedure
s.s="abc abc aBc aBC abc"
f.s="abc"
r.s="xXx"
a=ElapsedMilliseconds()
For n=1 To 1000000
replaceWholeWords(s, f, r)
Next
a=ElapsedMilliseconds()-a
b=ElapsedMilliseconds()
For m=1 To 1000000
trond_replace(s, f, r)
Next
b=ElapsedMilliseconds()-b
MessageRequester("AND51: "+Str(a), "Trond: "+Str(b))
Works like Trond's one, but is about 35% faster.
@ Trond:
Yeah, it would be much better, if there was an additional explanation of what the code does. I tried to understand the example, but first it looks like the first word should only be replaced.
Posted: Fri May 15, 2009 10:13 pm
by dobro
AND51 wrote:
@ Trond:
Yeah, it would be much better, if there was an additional explanation of what the code does. I tried to understand the example, but first it looks like the first word should only be replaced.
no ! i sorry , i dont speak englih !!
the procedure of purebasic for this exemple
Code: Select all
ReplaceString("Test_Procedure20(coucou) bb Test_Procedure205 (coucou) ","Procedure20","xxx")
for this string :
Test_Procedure20(coucou) bb Test_Procedure205 (coucou)
result : (no good !)
Test_xxx(coucou) bb Test_xxx5 (coucou)
no good because Test_Procedure205 is'nt Test_Procedure20 !!
my procedure replace juste Test_Procedure20
and not Test_Procedure20
5
for my procedure is différent ... you understand ??
*************************************************************
si un français passe par la
expliquez leur que ma procedure remplace de façon intelligente
elle ne confond pas
Test_Procedure20(coucou)
et
Test_Procedure205 (coucou)
et que si l'on veux remplacer juste 'Procedure20'
et bien seulement le premier cas sera remplacé
(Test_Procedure20(coucou))
parceque ma procedure reconnait "Procedure20"
et ne touchera pas a
"Test_Procedure205 (coucou)"
parceque 205 c'est pas 20 !!

Posted: Fri May 15, 2009 10:51 pm
by case
what dobro wan't to say is that his procedure only replace the EXACT MATCH , it not replace a part of a sentence if it match the search string...
for exemple you have "print printed printing print printed printing" as a string
with dobro's procedure if you replace 'print' by 'write'
you'll end up with "write printed printing write printed printing"
as you can see it replace only the exact match of the search string if the word is longer than the searched one it will not be replaced
the pb replacestring will leave you with
"write writeed writeing write writeed writeing"
hope it's clearer for you all as dobro seems to not be able to explain it right.
Posted: Fri May 15, 2009 11:05 pm
by AND51
Ah okay. So I did understand you correctly: you only replace entire words.
Then my procedure and Trond's procedure should work right.
Posted: Fri May 15, 2009 11:13 pm
by Demivec
AND51 wrote:Ah okay. So I did understand you correctly: you only replace entire words.
Then my procedure and Trond's procedure should work right.
Both of your code samples don't replace whole words that are followed by punctuation (i.e. one of ";.,(") or a carriage return. so they don't accomplish the same thing as dobro's.
Try your functions with this string:
Code: Select all
s.s = "abc abc aBc aBC abc" + Chr(13) + "abc() abc, abc; abc." ;source string
F.s = "abc" ;find string
r.s = "xXx" ;replace string
Your code and Trond's both produce:
Code: Select all
xXx abc aBc aBC abc
abc() abc, abc; abc.
dobro's code produces:
Code: Select all
xXx xXx aBc aBC xXx
xXx() xXx, xXx; xXx.
That means you may have trouble using either of your functions to replace strings in the text of a program's source code.