我正在努力训练如何在弦乐的所有可能性之间循环,但我似乎没有进展得很好。
到目前为止,我已将一组角色放入一个阵列,但我不能让我的生活让我了解如何让它发挥作用。我已经走到了这一步,但我的大脑似乎无法绕过它。
任何人都可以说明正确的方法,也可能伪代码,这样我就可以创建自己的代码。
Function passwordGenerator(length As Integer)
Dim characters() As String
Dim x As Integer
Dim y As Integer
Dim p As Integer
Dim t As Integer
Dim oldpassword As String
Dim newcharacter As String
ReDim Preserve characters(1)
For x = 48 To 90
ReDim Preserve characters(UBound(characters) + 1)
characters(UBound(characters) - 1) = VBA.Chr(x)
Next x
y = 1
Do
For x = 1 To length
oldpassword = generateBlank(x)
p = 1
For t = 1 To p
newpassword = WorksheetFunction.Replace(oldpassword, t, 1, characters(y))
For y = 1 To UBound(characters)
newpassword = WorksheetFunction.Replace(oldpassword, p, 1, characters(y))
Debug.Print newpassword
p = p + 1
Next y
Next t
Next x
Loop
End Function
Function generateBlank(length As Integer)
Dim x As Integer
For x = 1 To length
generateBlank = generateBlank & "A"
Next x
End Function
EDIT :::
我已编辑了我的代码,但这样我必须知道长度并且不能创建有效的算法?有什么帮助吗?
Function passwordGenerator()
Dim characters() As String
Dim x As Integer
Dim y As Integer
Dim p As Integer
Dim t As Integer
Dim w As Integer
Dim e As Integer
Dim r As Integer
Dim u As Integer
Dim oldpassword As String
Dim newcharacter As String
ReDim Preserve characters(1)
For x = 48 To 90
ReDim Preserve characters(UBound(characters) + 1)
characters(UBound(characters) - 1) = VBA.Chr(x)
Next x
y = 1
oldpassword = generateBlank(3)
For x = 1 To UBound(characters)
oldpassword = WorksheetFunction.Replace(oldpassword, 1, 1, characters(x))
For t = 1 To UBound(characters)
oldpassword = WorksheetFunction.Replace(oldpassword, 2, 1, characters(t))
For y = 1 To UBound(characters)
oldpassword = WorksheetFunction.Replace(oldpassword, 3, 1, characters(y))
For q = 1 To UBound(characters)
oldpassword = WorksheetFunction.Replace(oldpassword, 4, 1, characters(q))
For w = 1 To UBound(characters)
oldpassword = WorksheetFunction.Replace(oldpassword, 5, 1, characters(w))
Debug.Print oldpassword
DoEvents
Next w
Next q
Next y
Next t
Next x
End Function
答案 0 :(得分:2)
我认为这就是你想要的:
Public Function GeneratePassword(ByVal index As Long, ByVal pw_len As Byte, ByRef characters As String) As String
' Convert string 'characters' into array of characters in 'dict'
Dim s As Integer, n As Integer
n = Len(characters)
Dim pw As String
pw = vbNullString
Dim j As Long, base As Long
base = n
For s = 1 To pw_len
j = ((index - 1) Mod n) + 1
pw = Mid(characters, j, 1) & pw
index = (index - j) \ n + 1
Next s
GeneratePassword = pw
End Function
Public Sub TestPwGen()
Dim i As Long, pw() As String, abc As String
abc = "ABC"
Dim n As Integer, l As Integer, m As Long
' password length 4, generate 18 passwords
l = 4: m = Len(abc) ^ l
n = 18
ReDim pw(1 To n)
For i = 1 To n 'Total is m
pw(i) = GeneratePassword(i, l, abc)
Debug.Print pw(i)
Next i
End Sub
结果:
AAAA
AAAB
AAAC
AABA
AABB
AABC
AACA
AACB
AACC
ABAA
ABAB
ABAC
ABBA
ABBB
ABBC
ABCA
ABCB
ABCC
答案 1 :(得分:1)
我已经在JA72的答案中编辑了代码,以便提供更全面的技术来强制限制编辑"密码。我删除了array
和ReDim
部分,并将它们全部合并为一个子部分。 JA方法的问题是,虽然它适用于ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
的字符集,但对于4个字符的密码([26 + 26 + 10] ^ 4 = 14,776,336种可能性),它不能用于5个字符的密码([26 + 26 + 10] ^ 5 = 916,132,832种可能性)。原始代码中的数组函数会导致32位Office应用程序在尝试使用5个字符或更多密码时立即耗尽内存。我还注意到内存使用率攀升,因为它使用原始代码迭代了1400万种可能性,而内存使用情况与下面的代码保持一致。
此示例专门针对Word ActiveDocument.Unprotect
方法。它很简单,可以将尝试使用密码的部分更改为适合您需要的任何Office对象模型。
此代码在几个小时后为我工作,大约有4亿次密码尝试。我觉得它可能是哈希冲突与实际密码,但我会采取有效的方法。
如果您希望在提交几个小时的CPU之前看到输出工作,为方便起见,包含了一些内容。这在代码注释中也有解释。
n
变量来设置迭代次数。 For i = 1 to m
更改为For i = 1 to n
,以便循环这么多次而不是所有可能的次。 If i Mod showEvery = 0 Then Debug.Print i, pw
行,打开输出。 showEvery
设置为1,否则请选择其他号码以查看每个第n个密码。ActiveDocument.Unprotect
的部分并检查错误。它在代码中标记了注释。 Sub GetPassword()
Dim s As Integer, totalChars As Integer, j As Long 'GeneratePassword loop vars
Dim gpi As Long 'GeneratePassword index
Dim characters As String 'characters that can be part of the password.
Dim pw As String 'password attempt string
characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
totalChars = Len(characters)
Dim i As Double 'count integer
Dim n As Double 'number of interations to complete (if active)
Dim pwLen As Integer 'length of password
Dim m As Double 'number of permutations
Dim showEvery As Integer 'show multiples of this in debug log
pwLen = 5 'password length
m = totalChars ^ pwLen 'number of potential combinations of characters for the length
n = 1000 'number of loop iterations if you don't want all of them.
showEvery = 1 'use 1 here to show every password. 10000 shows every 10,000th password, etc...
On Error Resume Next 'no need to invoke an error handler, just check the Err.Number
For i = 1 To m 'use "1 to n" if you want to test a certain number or "1 to m" if you want try all combinations.
pw = vbNullString
gpi = i 'assign GeneratePassword loop integer our loop integer
'GeneratePassword loop
For s = 1 To pwLen
j = ((gpi - 1) Mod totalChars) + 1
pw = Mid(characters, j, 1) & pw
gpi = (gpi - j) \ totalChars + 1
Next s
'writes out if uncommented and it's the right i. comment out once you're sure of the output.
'If i Mod showEvery = 0 Then Debug.Print i, pw
'try the password to unprotect the document, comment if just testing passwords in Immediate window
ActiveDocument.Unprotect password:=pw
If Err.Number <> 5485 Then
MsgBox "Unexpected Error Code: " & Err.Number & vbCrLf & Err.Description & vbCrLf & pw
End If
If ActiveDocument.ProtectionType = wdNoProtection Then
MsgBox "Unprotected with password: " & vbCrLf & pw
Debug.Print "Unprotect Password: " & pw
Exit Sub
End If
'end trying the password.
Next i
End Sub
答案 2 :(得分:0)
不幸的是,在我不得不写下我的解决方案之前,这个问题一直困扰着我。我认为@ ja72的解决方案更优雅,但我会列出我的另一种方式。
Option Explicit
Function passwordGenerator()
Dim characters() As String
Dim loASCII As Integer
Dim hiASCII As Integer
Dim numASCII As Integer
Dim i As Integer
loASCII = 48
hiASCII = 90
numASCII = hiASCII - loASCII
ReDim characters(numASCII)
For i = loASCII To hiASCII
characters(i - loASCII) = VBA.Chr(i)
Next i
PermutationsOn characters, 2
End Function
Sub PermutationsOn(ByRef charSet() As String, numPlaces As Integer)
'--- Generates every possible combination of characters from the given
' character set for an n-place string
' Inputs: charSet - string array of all possible values
' numPlaces - integer noting how many characters in the output string
Dim chars() As String
Dim thisString As String
Dim i As Integer
Dim t As Long
Dim numInCharSet As Integer
Dim start As Integer
Dim placevalues() As Integer
'--- this array is used as a set of indexes into the character set, the
' indexes will range from charSet(0) to charSet(last), "counting" as
' in a base-n number, where n = len(charSet)+1
ReDim placevalues(1 To numPlaces) As Integer
ReDim chars(1 To numPlaces)
start = LBound(charSet)
numInCharSet = UBound(charSet)
'--- initialize the arrays
For i = 1 To numPlaces
placevalues(i) = 0
Next i
For i = 1 To numPlaces
chars(i) = charSet(start)
Next i
Debug.Print "Permutations on a " & numPlaces & "-place value from a character set"
Debug.Print "Character set (len=" & numInCharSet + 1 & "): '" & ConcatToString(charSet) & "'"
'--- build the first string...
t = 1
thisString = BuildStringFromSet(placevalues, charSet)
Debug.Print t & ": " & thisString
Do Until IncrementValues(placevalues, charSet)
'--- build the current string...
thisString = BuildStringFromSet(placevalues, charSet)
t = t + 1
Debug.Print t & ": " & thisString
Loop
Debug.Print "Total strings generated: " & t
End Sub
Function IncrementValues(ByRef placevalues() As Integer, ByRef placeRange() As String) As Boolean
'--- views the placeValues array as a "single" number with a numeric base of "numInRange+1"
Dim highestValueReached As Boolean
Dim numPlaces As Integer
Dim numInRange As Integer
Dim i As Integer
numPlaces = UBound(placevalues)
numInRange = UBound(placeRange)
highestValueReached = False
For i = 1 To numPlaces
If placevalues(i) <> numInRange Then
placevalues(i) = placevalues(i) + 1
Exit For
Else
If i = numPlaces Then
highestValueReached = True
Exit For
Else
placevalues(i) = 0
End If
End If
Next i
IncrementValues = highestValueReached
End Function
Function BuildStringFromSet(ByRef placevalues() As Integer, ByRef charSet() As String) As String
Dim i As Integer
Dim finalString As String
finalString = ""
For i = UBound(placevalues) To 1 Step -1
finalString = finalString & charSet(placevalues(i))
Next i
BuildStringFromSet = finalString
End Function
Function ConcatToString(chars() As String) As String
Dim finalString As String
Dim j As Integer
finalString = ""
For j = LBound(chars) To UBound(chars)
finalString = finalString & chars(j)
Next j
ConcatToString = finalString
End Function
输出结果:
Permutations on a 5-place value from a character set
Character set (len=43): '0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1: 00000
2: 00001
3: 00002
4: 00003
...
147008441: ZZZZX
147008442: ZZZZY
147008443: ZZZZZ
Total strings generated: 147008443
答案 3 :(得分:0)
我实际上想出了一个答案我自己的答案。今天在工作中找到了我。
Public characters() As String
Public oldpassword As String
Function passwordGenerator1(maxLength)
Dim x As Integer, newcharacter As String
ReDim Preserve characters(1)
'set characters in array
For x = 48 To 90
ReDim Preserve characters(UBound(characters) + 1)
characters(UBound(characters) - 1) = VBA.Chr(x)
Next x
'loop through all lengths
For x = 1 To maxLength
oldpassword = generateBlank(x)
changeCharacter 1, x
Next x
End Function
-
Function changeCharacter(characterPos, length As Integer)
For x = 1 To UBound(characters)
If characterPos <> length Then changeCharacter characterPos + 1, length
oldpassword = WorksheetFunction.Replace(oldpassword, characterPos, 1, characters(x))
Debug.Print oldpassword
DoEvents
Next x
End Function
-
Function generateBlank(length As Integer)
Dim x As Integer
For x = 1 To length
generateBlank = generateBlank & "A"
Next x
End Function
答案 4 :(得分:0)
这可能会有所改进,但一个简单的想法是分别处理角色并像里程表那样滚动。顺便说一下,我为数组使用了基于一的索引,但是对于各个数字使用了从零开始的索引。
Public Sub PasswordGen()
Const MaxDigit = 42
Const MaxLoops = MaxDigit * MaxDigit * MaxDigit * MaxDigit * MaxDigit
Dim places(10) As Integer
Dim counter As Integer
Dim digit As Integer
Dim password As String
counter = 0
Do While counter < MaxLoops
password = Chr(places(5) + 48) & Chr(places(4) + 48) & Chr(places(3) + 48) & Chr(places(2) + 48) & Chr(places(5) + 48)
'Debug.Print password
counter = counter + 1
digit = 1
Do While digit < 10
places(digit) = places(digit) + 1
If places(digit) = MaxDigit Then
places(digit) = 0
digit = digit + 1
Else
Exit Do
End If
Loop
Loop
End Sub
你也可以取消计数器,当数字等于11时退出循环,因为第十位的执行(溢出)。无论如何,我怀疑你实际上会让它运行那么久。