Dobro_replace() question for Fred in last message

Share your advanced PureBasic knowledge/code with the community.
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Dobro_replace() question for Fred in last message

Post 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" )

Last edited by dobro on Tue May 19, 2009 6:29 pm, edited 7 times in total.
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post 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. 8)

But it doesn't take newlines into account.
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Post 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: :)
Last edited by dobro on Sun May 17, 2009 12:49 pm, edited 1 time in total.
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Post 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
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

Post 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)
irc://irc.freenode.org/#purebasic
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Post by dobro »

:lol: :lol:


we have already tried the lib RegularExpression

and that is why "dobro_replace" is born :D
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

Post 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.
irc://irc.freenode.org/#purebasic
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Post by dobro »

Fred can answer only :)
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
AND51
Addict
Addict
Posts: 1040
Joined: Sun Oct 15, 2006 8:56 pm
Location: Germany
Contact:

Re: Dobro_replace()

Post 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?
PB 4.30

Code: Select all

onErrorGoto(?Fred)
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Dobro_replace()

Post 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.
AND51
Addict
Addict
Posts: 1040
Joined: Sun Oct 15, 2006 8:56 pm
Location: Germany
Contact:

Post 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. :P


@ 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.
PB 4.30

Code: Select all

onErrorGoto(?Fred)
User avatar
dobro
Enthusiast
Enthusiast
Posts: 766
Joined: Sun Oct 31, 2004 10:54 am
Location: France
Contact:

Post 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_Procedure205

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 !! :)
Image
Windows 98/7/10 - PB 5.42
■ sites : http://michel.dobro.free.fr/
case
Enthusiast
Enthusiast
Posts: 141
Joined: Thu Aug 07, 2003 11:09 am

Post 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.
AND51
Addict
Addict
Posts: 1040
Joined: Sun Oct 15, 2006 8:56 pm
Location: Germany
Contact:

Post 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.
PB 4.30

Code: Select all

onErrorGoto(?Fred)
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post 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.
Post Reply