String 随机化字符串大小写的最快方法

String 随机化字符串大小写的最快方法,string,optimization,random,vb6,String,Optimization,Random,Vb6,对于一些协议测试,我需要将许多字符串中每个字符的大小写随机化。 字符串是由我的应用程序创建的命令,将通过winsock控件发送到客户端 因为它涉及很多弦,我希望每个部分都尽可能快 现在我有: Private Function RandomCaps(strText As String) As String Dim lngChar As Long Dim strLower As String, strUpper As String Dim strRandom As String st

对于一些协议测试,我需要将许多字符串中每个字符的大小写随机化。 字符串是由我的应用程序创建的命令,将通过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
这很简单,但可能不是最快的方法

如何提高其速度?

使用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

使用
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
私有函数RandomCaps(作为字符串)作为字符串
将uc设置为字符串
我想我会坚持多久
RandomCaps=LCase$(s)
uc=UCase$(s)
对于i=1到Len(s)
如果Rnd<0.5,则
Mid(随机上限,i,1)=Mid(uc,i,1)
如果结束
接下来我
端函数

您可以尝试使用
MidB
,但这几乎没有什么区别——而且由于它可以处理单个字节,如果您不知道VB6如何存储字符串,您将遇到一些令人不快的惊喜。

要通过RDH优化代码,您实际上不需要保留字符串的大写版本。我认为这是你能得到的最优化的

代码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
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
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
私有函数RandomCaps(作为字符串)作为字符串
我想我会坚持多久
RandomCaps=LCase$(s)
对于i=1到Len(s)
如果Rnd<0.5,则
Mid(RandomCaps,i,1)=UCase(Mid(RandomCaps,i,1))
如果结束
接下来我
端函数
上面的代码很好,但是,对于非常大的字符串,您可能希望尝试以下方法(与RDHS的代码相比,没有进行性能测试):

代码2:

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
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
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
私有函数RandomCaps(作为字符串)作为字符串
Dim b()作为字节
b=StrConv(Text1.Text,vbFromUnicode)
我想我会坚持多久
对于i=0到UBound(b)-1
如果Rnd<0.5,则
如果UCase(Chr(b(i))=Chr(b(i)),那么
'原始字符为大写,请将其设置为小写
b(i)=Asc(LCase(Chr(b(i)))
其他的
'原始字符是小写的,请使用大写
b(i)=Asc(UCase(Chr(b(i)))
如果结束
如果结束
接下来我
RandomCaps=StrConv(b,vbUnicode)
端函数
编辑:

我做了一些性能测试,上面两个代码之间的差异可以忽略不计:第二个代码块仅比第一个代码块快1%左右

编辑2:

忽略我以前的编辑。代码2的效率大约比代码1低50%。然而,正如RDHS所建议的,我调整了代码2以比较值,而不是从CHR到ASC来回,从大约40个字符长的输入字符串开始更有效。输入字符串越长,代码3的性能越好。对于长度为944640个字符的输入字符串,代码3比代码1快57%

统计数字: 第一列是输入字符串的长度(以字符为单位) 第二列是代码3的效率,与代码2相比。 如您所见,字符串长度为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 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
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
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
私有函数RandomCaps(作为字符串)作为字符串
Dim b()作为字节
b=StrConv(Text1.Text,vbFromUnicode)
我想我会坚持多久
对于i=0到UBound(b)-1
如果Rnd<0.5,则

若b(i)>=64和b(i),若您使用ASCII大小写范围(65-90,97-122)并通过加/减32转换大小写,您的第二个代码示例将变得更快,并且对于大于约100个字符的字符串,性能优于我的答案。我将使用ASCII范围进行简短测试谢谢!也感谢您的全面测试!字符串的长度将从4到255个字符,大多数字符串的长度约为10个字符,因此我也将在程序中进行一些测试,并选择最快的代码:)谢谢!我总是忘记我也可以在左手边使用mid$(),这已经让它快了很多:)谢谢!目前,我将使用乔治答案中的代码。但是,请保存您的代码,以便稍后我进行一些微调,并尝试最大限度地提高其速度。也许您不需要它,因为在我的机器上它只比以前快10-20%。但一定要了解它是如何工作的。如果你想尝试,你必须在RandomCaps之外定义TCharpointer。谢谢你会使用它,也是因为我对它的工作原理很好奇:)不要忘记在最后调用DeleteCharPointer,可能是以表单卸载,否则它可能会崩溃。这种技术的好处是您可以直接访问VB(BSTR)的unicode字符。(如果需要)