对于某些协议测试,我需要在很多字符串中随机化每个字符的大小写。 字符串是由我的应用程序创建的命令,它将通过winsock控件发送给客户端。
由于它涉及很多字符串,我希望每个部分尽可能快。
现在我有:
Private Function RandomCaps(strText As String) As String
Dim lngChar As Long
Dim strLower As String, strUpper As String
Dim strRandom As String
strRandom = ""
strLower = LCase$(strText)
strUpper = UCase$(strText)
For lngChar = 1 To Len(strText)
If Int(2 * Rnd) = 0 Then
strRandom = strRandom & Mid$(strLower, lngChar, 1)
Else
strRandom = strRandom & Mid$(strUpper, lngChar, 1)
End If
Next lngChar
RandomCaps = strRandom
End Function
这非常简单,但可能不是最快的方法。
我可以做些什么来提高速度?
答案 0 :(得分:3)
不要将字符串连接在一起,而是使用Mid
来就地更改字符串:
Private Function RandomCaps(s As String) As String
Dim uc As String
Dim i As Long
RandomCaps = LCase$(s)
uc = UCase$(s)
For i = 1 To Len(s)
If Rnd < 0.5 Then
Mid(RandomCaps, i, 1) = Mid(uc, i, 1)
End If
Next i
End Function
您可以尝试使用MidB
,但它几乎没有任何区别 - 因为它适用于单个字节,如果您不知道VB6如何存储字符串,您会遇到一些令人讨厌的意外。
答案 1 :(得分:2)
使用MidB()而不是Mid。 MidB有点快。 另一种解决方案是将stringpointer复制到一个整数数组中。 例如:
Public Type TUDTPtr
pSA As Long
Reserved As Long ' z.B. für vbVarType oder IRecordInfo
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
cElements As Long
lLBound As Long
End Type
Public Type TCharPointer
pudt As TUDTPtr
Chars() As Integer
End Type
Public Enum SAFeature
FADF_AUTO = &H1
FADF_STATIC = &H2
FADF_EMBEDDED = &H4
FADF_FIXEDSIZE = &H10
FADF_RECORD = &H20
FADF_HAVEIID = &H40
FADF_HAVEVARTYPE = &H80
FADF_BSTR = &H100
FADF_UNKNOWN = &H200
FADF_DISPATCH = &H400
FADF_VARIANT = &H800
FADF_RESERVED = &HF008
End Enum
Public Declare Sub RtlMoveMemory Lib "kernel32" ( _
ByRef pDst As Any, _
ByRef pSrc As Any, _
ByVal bLength As Long)
Public Declare Sub RtlZeroMemory Lib "kernel32" ( _
ByRef pDst As Any, _
ByVal bLength As Long)
Public Declare Function ArrPtr Lib "msvbvm60" _
Alias "VarPtr" ( _
ByRef pArr() As Any) As Long
Public Sub New_UDTPtr(ByRef this As TUDTPtr, _
ByVal Feature As SAFeature, _
ByVal bytesPerElement As Long, _
Optional ByVal CountElements As Long = 1, _
Optional ByVal lLBound As Long = 0)
With this
.pSA = VarPtr(.cDims)
.cDims = 1
.cbElements = bytesPerElement
.fFeatures = CInt(Feature)
.cElements = CountElements
.lLBound = lLBound
End With
End Sub
Public Sub New_CharPointer(ByRef this As TCharPointer, ByRef StrVal As String)
With this
Call New_UDTPtr(.pudt, FADF_AUTO Or FADF_FIXEDSIZE, 2, Len(StrVal), 1)
With .pudt
.pvData = StrPtr(StrVal)
End With
Call RtlMoveMemory(ByVal ArrPtr(.Chars), ByVal VarPtr(.pudt), 4)
End With
End Sub
Public Sub DeleteCharPointer(ByRef this As TCharPointer)
With this
Call RtlZeroMemory(ByVal ArrPtr(.Chars), 4)
End With
End Sub
您的功能可能如下所示:
Private Sub RandomCapsX(strText As String) 'As String
Dim i As Long
Dim p As TCharPointer: Call MCharPointer.New_CharPointer(p, strText)
For i = 1 To p.pudt.cElements
Select Case p.Chars(i)
Case 65 To 90
'Uppercase
p.Chars(i) = p.Chars(i) + Int(2 * Rnd) * 32
Case 97 To 122
'lowercase
p.Chars(i) = p.Chars(i) - Int(2 * Rnd) * 32
End Select
Next
Call MCharPointer.DeleteCharPointer(p)
End Sub
答案 2 :(得分:1)
要通过RDHS优化代码,您实际上不需要保留字符串的大写版本。我认为这是最优化的。
代码1:
Private Function RandomCaps(s As String) As String
Dim i As Long
RandomCaps = LCase$(s)
For i = 1 To Len(s)
If Rnd < 0.5 Then
Mid(RandomCaps, i, 1) = UCase(Mid(RandomCaps, i, 1))
End If
Next i
End Function
上面的代码很好,但是,对于非常大的字符串,你可能想尝试这个(没有针对性能与RDHS的代码进行测试):
代码2:
Private Function RandomCaps(s As String) As String
Dim b() As Byte
b = StrConv(Text1.Text, vbFromUnicode)
Dim i As Long
For i = 0 To UBound(b) - 1
If Rnd < 0.5 Then
If UCase(Chr(b(i))) = Chr(b(i)) Then
'original char is uppercase, make it lowercase
b(i) = Asc(LCase(Chr(b(i))))
Else
'original char is lowercase, make it uppercase
b(i) = Asc(UCase(Chr(b(i))))
End If
End If
Next i
RandomCaps = StrConv(b, vbUnicode)
End Function
编辑:
我做了一些性能测试,上面两个代码之间的区别可以忽略不计:第二个代码块比第一个代码块快1%左右。
编辑2:
忽略我之前的编辑。代码2的效率比代码1低大约50%。但是,正如RDHS建议的那样,我调整了代码2来比较值,而不是从CHR到ASC来回传递,并且从大约40个字符的输入字符串开始更有效长。输入字符串越长,代码3的性能越好。使用长度为944640个字符的输入字符串,代码3比代码1快57%。
统计: 第一列是输入字符串的长度(以字符为单位) 与代码2相比,第二列是Code 3效率。 如您所见,字符串长度为5个字符,代码2的效率提高了46%。从字符串长度大约40开始,代码3变得越来越有效。
5 -46.80%
50 6.22%
100 21.50%
500 38.54%
1000 41.11%
10000 44.87%
100000 43.25%
1260000 43.02%
代码3:
Private Function RandomCaps(s As String) As String
Dim b() As Byte
b = StrConv(Text1.Text, vbFromUnicode)
Dim i As Long
For i = 0 To UBound(b) - 1
If Rnd < 0.5 Then
If b(i) >= 64 And b(i) <= 90 Then
'A to Z
b(i) = b(i) + 32
ElseIf b(i) >= 97 And b(i) <= 122 Then
'a to z
b(i) = b(i) - 32
Else
'everything else
End If
End If
Next i
RandomCaps = StrConv(b, vbUnicode)
End Function