Prev: How To Know
Next: Array Problem
From: Bee on 24 Dec 2009 19:11 Vb6 Replace is fine for what it does and is fast but it has a strange operation. If I specify Start then the string that is returned now begins at the start parameter. Appending it way to slow. So what fast way is there to do a replace at a specified location in a string? The replace may be a vbNullstring, or more or fewer characters than the single or multiple character find string. ReplaceStr(expression, find, replace[, start[, count[, compare]]]) Always returns the beginning and changed part and end part of the expression when start is supplied or not.
From: Ralph on 24 Dec 2009 20:02 "Bee" <Bee(a)discussions.microsoft.com> wrote in message news:33DAF12E-CD12-4848-8198-688E59613373(a)microsoft.com... > Vb6 Replace is fine for what it does and is fast but it has a strange > operation. > > If I specify Start then the string that is returned now begins at the start > parameter. > Appending it way to slow. > So what fast way is there to do a replace at a specified location in a string? > The replace may be a vbNullstring, or more or fewer characters than the > single or multiple character find string. > > ReplaceStr(expression, find, replace[, start[, count[, compare]]]) > > Always returns the beginning and changed part and end part of the expression > when start is supplied or not. > Don't have code immediately at hand, but these hints should help. Create a second temporary buffer - a byte array. Make it the same size as the file (FileLen) plus a little extra. Use Mike's suggestion to step through the original text looking for changes. When found, and a substitute is determined, write the new string of characters to the Temporary buffer using Memcopy. Write out the temporary buffer as the new file. -ralph
From: Donald Lessau on 25 Dec 2009 14:42 "Bee" <Bee(a)discussions.microsoft.com> schrieb im Newsbeitrag news:33DAF12E-CD12-4848-8198-688E59613373(a)microsoft.com... > Vb6 Replace is fine for what it does and is fast but it has a strange > operation. > > If I specify Start then the string that is returned now begins at the > start > parameter. Check at VBspeed. All functions here work the way you like it, and are faster than Vb6 Replace: http://www.xbeat.net/vbspeed/c_Replace.htm Don
From: mayayana on 25 Dec 2009 16:22 The Mid *statement* is very fast. Tokenizing is also surprisingly fast. Here's an "air code" sample that points an integer array at an incoming string and runs a tokenizing routine, building a new string with Mid as it goes. The sample just looks for "***" and replaces it with "**". As you can see from the code, you can run any number of replacement operations based on character codes. The "***" can be editied to replace CrCrLf with CrLf. At the same time you could replace "ball" with "hat", "1" with "2", etc. Also note: The code as written allows for a new string 1.5 times the size of the original. If you're doing a lot of operations you might need to keep an eye on the loop to make sure your new string doesn't need to be reallocated. '--------------------------- module code: Private Type SAFEARRAY1 cDims As Integer fFeatures As Integer cbElements As Long cLocks As Long pvData As Long cElements As Long lLbound As Long End Type Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ptr() As Any) As Long Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long) Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dst As Any, ByVal NBytes As Long) Public Function SReplace(StrToRep As String) As String Dim Lens As Long, LNew As Long, iPos As Long, iPosNew As Long, iPosStart As Long, Len2 As Long Dim SA1 As SAFEARRAY1 Dim iChar As Integer Dim A1() As Integer Lens = Len(StrToRep) LNew = Lens * 1.5 SReplace = String$(LNew, 0) With SA1 '-- set up array for t1.text string. .cbElements = 2 .cElements = Lens + 1 .cDims = 1 .pvData = StrPtr(StrToRep) End With CopyMemory ByVal VarPtrArray(A1), VarPtr(SA1), 4 iPosNew = 1 '-- offset into new string iPos = 0 Do While iPos < Lens iPosStart = iPos + 1 iChar = A1(iPos) Select Case iChar Case 0 Exit Do Case 42 'vbCR If A1(iPos + 1) = 42 Then If A1(iPos + 2) = 42 Then Mid(SReplace, iPosNew) = "**" iPosNew = iPosNew + 2 iPos = iPos + 2 End If End If Case Else Mid(SReplace, iPosNew) = Mid(StrToRep, (iPosStart), 1) iPosNew = iPosNew + 1 End Select iPos = iPos + 1 Loop ZeroMemory ByVal VarPtrArray(A1), 4 Len2 = InStr(1, SReplace, Chr$(0)) If Len2 > 1 Then SReplace = Left$(SReplace, (Len2 - 1)) End Function '-------------------------- form code: '--t1 is a multiline textbox Private Sub Command1_Click() Dim s As String Dim i2 As Long s = String$(10000, "A") For i2 = 3 To 100 Mid(s, (i2 * 50)) = "***" Next T1.Text = s End Sub Private Sub Command2_Click() Dim s As String, s2 As String s = T1.Text s2 = SReplace(s) T1.Text = s2 End Sub
From: Bee on 25 Dec 2009 17:43
Thanks all. I now have several things to try. "mayayana" wrote: > The Mid *statement* is very fast. Tokenizing is also > surprisingly fast. Here's an "air code" sample that points > an integer array at an incoming string and runs a tokenizing > routine, building a new string with Mid as it goes. The sample > just looks for "***" and replaces it with "**". As you can see > from the code, you can run any number of replacement operations > based on character codes. The "***" can be editied to > replace CrCrLf with CrLf. At the same time you could replace > "ball" with "hat", "1" with "2", etc. > > Also note: The code as written allows for a new > string 1.5 times the size of the original. If you're > doing a lot of operations you might need to keep an eye > on the loop to make sure your new string doesn't need > to be reallocated. > > '--------------------------- module code: > > Private Type SAFEARRAY1 > cDims As Integer > fFeatures As Integer > cbElements As Long > cLocks As Long > pvData As Long > cElements As Long > lLbound As Long > End Type > Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" > (ptr() As Any) As Long > Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" > (Destination As Any, Source As Any, ByVal length As Long) > Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (dst As > Any, ByVal NBytes As Long) > > Public Function SReplace(StrToRep As String) As String > Dim Lens As Long, LNew As Long, iPos As Long, iPosNew As Long, iPosStart As > Long, Len2 As Long > Dim SA1 As SAFEARRAY1 > Dim iChar As Integer > Dim A1() As Integer > > Lens = Len(StrToRep) > LNew = Lens * 1.5 > > SReplace = String$(LNew, 0) > With SA1 '-- set up array for t1.text string. > .cbElements = 2 > .cElements = Lens + 1 > .cDims = 1 > .pvData = StrPtr(StrToRep) > End With > CopyMemory ByVal VarPtrArray(A1), VarPtr(SA1), 4 > > iPosNew = 1 '-- offset into new string > iPos = 0 > > Do While iPos < Lens > iPosStart = iPos + 1 > iChar = A1(iPos) > > Select Case iChar > Case 0 > Exit Do > > Case 42 'vbCR > If A1(iPos + 1) = 42 Then > If A1(iPos + 2) = 42 Then > Mid(SReplace, iPosNew) = "**" > iPosNew = iPosNew + 2 > iPos = iPos + 2 > End If > End If > > Case Else > Mid(SReplace, iPosNew) = Mid(StrToRep, (iPosStart), 1) > iPosNew = iPosNew + 1 > End Select > > iPos = iPos + 1 > Loop > > ZeroMemory ByVal VarPtrArray(A1), 4 > Len2 = InStr(1, SReplace, Chr$(0)) > If Len2 > 1 Then SReplace = Left$(SReplace, (Len2 - 1)) > End Function > > '-------------------------- form code: > '--t1 is a multiline textbox > > Private Sub Command1_Click() > Dim s As String > Dim i2 As Long > > s = String$(10000, "A") > For i2 = 3 To 100 > Mid(s, (i2 * 50)) = "***" > Next > > T1.Text = s > End Sub > > Private Sub Command2_Click() > Dim s As String, s2 As String > s = T1.Text > s2 = SReplace(s) > T1.Text = s2 > End Sub > > > > . > |