Reputation: 377
I'm having a problem with making an array containing 8 different characters, each of which is taken from one of 3 different char arrays (one containing strictly lowercase characters, the second only containing uppercase characters and the third containing only numbers).
The problem is, it's supposed to take 1 character at a time from a random char array.
My arrays containing each set of characters is declared here:
Dim lcase() As Char = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
Dim ucase() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Dim num() As Char = "0123456789".ToCharArray()
Dim chars(7) As Char
As for the code to fill up the final array (in my case, chars(7)):
Dim lim As Short = rand.Next(1, 5)
For x = 0 To lim
Dim char_num As Integer = rand.Next(0, lcase.GetUpperBound(0))
chars(x) = lcase(char_num)
Next
Dim lim2 As Short = 6 - lim
For x = 0 To lim2
Dim char_num As Integer = rand.Next(0, num.GetUpperBound(0))
chars(x) = num(char_num)
Next
For x = 0 To 6 - lim2
Dim char_num As Integer = rand.Next(0, ucase.GetUpperBound(0))
chars(x) = ucase(char_num)
Next
This works, although for some reason it tends to (for some reason) leave certain values null, ending up in me getting outputs like these:
QHK M D
LCR86
What I need is for my code to fill up the array properly, so it contains proper values, each taken from the three char arrays.
Note: my chars(7)
is declared as Char
because I swap around the characters contained in it after they were generated, to create a completely random string out of those characters.
I suspect I made a mistake somewhere in the code which fills up the array, but in case my mistake isn't in the code above, here's the code which randomizes the order of the characters in my chars()
array:
Dim j As Integer
Dim swap As Char
Dim r As Random = New Random()
For i As Integer = 0 To chars.GetUpperBound(0)
j = r.Next(0, i)
swap = chars(j)
chars(j) = chars(i)
chars(i) = swap
Next i
Thanks in advance guys.
Update: I realized my mistake, the for
loops keep overwriting what has already been added to the array, thus leaving the last few spots open. All I need now is a way to have them properly add them to the first empty slot.
Upvotes: 0
Views: 670
Reputation: 416059
Why 3 separate arrays? Why not one big one that comprises your "alphabet", like this:
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray()
I can hear you now saying, "But how do I know it picks from each of the character sets?". Part of the answer is that it's not truly random unless the chance exists to pick from an array zero times. The other part is that, if you really need to, you can always just validate an output and re-roll.
That gives you much simpler code:
Dim alphabet() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray()
For x As Integer to chars.Length - 1
chars(x) = rand.Next(0, alphabet.Length)
Next
Return New String(chars)
That's it. That's the whole thing. There's also no need to shuffle these results.
Another nice feature is that this it makes it easy to tweak your alphabet. For example, when communicating these codes to end users, it's often useful to drop certain characters from the alphabet to avoid confusion. To do this, now you only need to change one string:
Dim alphabet() As Char = "ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789".ToCharArray()
If you look at this carefully, you'll notice that three characters are missing: uppercase 'O', lower-case 'L', and numeral '0'. By leaving out these characters and making sure to choose a font that properly distinguishes the others (Courier New will work, but most variable-width fonts will need to drop more characters), you can avoid a good number of calls to your help desk.
Upvotes: 0
Reputation: 377
Ended up finding the solution myself, my initial code kept overwriting the first values instead of continuing the array where the previous loop left off.
Here's the code which actually works:
Dim lcase() As Char = "abcdefghijklmnopqrstuvwxyz".ToCharArray()
Dim ucase() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Dim num() As Char = "0123456789".ToCharArray()
Dim chars(7) As Char
Dim lim As Short = rand.Next(1, 6)
For x = 0 To 7
Dim char_num As Integer = rand.Next(0, lcase.GetUpperBound(0))
chars(x) = lcase(char_num)
Next
For x = 0 To lim
Dim char_num As Integer = rand.Next(0, num.GetUpperBound(0))
chars(x) = num(char_num)
Next
lim = rand.Next(1, 5)
For x = 0 To lim
Dim char_num As Integer = rand.Next(0, ucase.GetUpperBound(0))
chars(x) = ucase(char_num)
Next
Upvotes: 0
Reputation: 6948
I think you may be over thinking things a bit. a simple function that finds the characters directly using ASCII codes would probably be much simpler and easier to debug. Something like this:
Private Function GenPass() As Char()
Dim OutVal(7) As Char
Dim nextchar As Char
Dim rand As New Random(Now.Millisecond)
For I = 0 To 7
Do
nextchar = Chr(rand.Next(48, 122))
Loop Until Not OutVal.Contains(nextchar) AndAlso Not (nextchar > "9"c AndAlso nextchar < "A"c) AndAlso Not (nextchar > "Z"c AndAlso nextchar < "a"c)
OutVal(I) = nextchar
Next
Return OutVal
End Function
The output is an array of Char with random alphanumeric values. Here's one such output:
?GenPass
{Length=8}
(0): "L"c
(1): "l"c
(2): "W"c
(3): "8"c
(4): "P"c
(5): "E"c
(6): "c"c
(7): "2"c
Upvotes: 1