Help! This random string function seems to be repeating a lot, I have no idea what to do in order to make it more random. It's supposed to generate a random alphanumeric string with more then 3 characters, but less then 15. Here's what I got:
Public Function Rand() As String
Dim i#, Name$, Char$, Limit#
Randomize
Top:
Name = vbNullString
Limit = Fix(Rnd * 15) + 12
Do Until Len(Name) = Limit
Char = Chr(Fix(Rnd * 126))
If Char Like "*[!A-Za-z0-9]*" Then GoTo Top
Name = Name & Char
Loop
If Len(Name) > 15 Then GoTo Top
Rand = Name
End Function
This should be in the VB Programming section, not the General Programming section. Also, that's some of the most terribly inefficient and poorly written code I've seen in a while.
I know, very improper use of the Goto keyword and I was tired when I wrote that. But it works!
Also why would this have to be in the vb6 programming section? This doesn't really apply to JUST vb, but could to other languages too. Therefore this is why I put it in the general programming section.
EDIT*** Okay, I made it a little better
Public Function Rand() As String
Dim i#, Name$, Char$, Limit#
Randomize
Limit = Fix(Rnd * 15) + 12
Do Until Len(Name) = Limit
Char = Chr(Fix(Rnd * 126))
If Char Like "*[!A-Za-z0-9]*" Then Char = Fix(Rnd * 10)
Name = Name & Char
Loop
If Len(Name) > 15 Then Name = Left(Name, 15)
Rand = Name
End Function
Still, any suggestions?
You're asking for help with vb, so it goes in the vb section.
Here's some 'help':
1) Define a variable to store the length of the string to create and set it to a random int between 4 and 14.
2) Do a For... Next loop to generate each random character.
3) Don't use GoTo, don't use "Like" (I've never even HEARD of that keyword before), and don't use Fix, use CInt or just Int.
Okay, reality.
1). Limit = Fix(Rnd * 15) + 12 I have no idea how I would do "a random number between 4 and 14". That would be GREAT if there was some simple easy way to do that but there isn't.
2). Why a For loop? I want this to keep executing until the length of the string is equal to the limit, obviously. Nothing else.
3). I took the goto out, and what's wrong with Fix? Then... I have to use Like or I have nothing to work with. IF I don't use Like how would I say "if it doesn't have a character between a-z, A-Z, or 0-9"? Just because you've never heard of Like doesn't mean you can't use it. It's always nice to try new things.
Here's how I'd do it
Private Function CreateString()
Dim iStrLen As Integer
Dim iChar As Integer
Dim I As Integer
Dim strString As String
iStrLen = Int(Rnd * 10) + 4
For I = 1 To iStrLen
iChar = Int(Rnd * 62)
If iChar >= 0 And iChar <= 9 Then
strString = strString & Chr$(iChar + 48)
ElseIf iChar >= 10 And iChar <= 35 Then
strString = strString & Chr$(iChar + 55)
ElseIf iChar >= 36 And iChar <= 61 Then
strString = strString & Chr$(iChar + 61)
End If
Next I
CreateString = strString
End Function
Note that this isn't fully tested, and I may have made some mistakes some places.
Quote from: [RealityRipple] on March 17, 2007, 08:39 PM
Here's how I'd do it
Private Function CreateString()
Dim iStrLen As Integer
Dim iChar As Integer
Dim I As Integer
Dim strString As String
iStrLen = Int(Rnd * 10) + 4
For I = 1 To iStrLen
iChar = Int(Rnd * 62)
If iChar >= 0 And iChar <= 9 Then
strString = strString & Chr$(iChar + 48)
ElseIf iChar >= 10 And iChar <= 35 Then
strString = strString & Chr$(iChar + 55)
ElseIf iChar >= 36 And iChar <= 61 Then
strString = strString & Chr$(iChar + 61)
End If
Next I
CreateString = strString
End Function
Note that this isn't fully tested, and I may have made some mistakes some places.
Thanks, reality.
Quote from: [RealityRipple] on March 17, 2007, 08:39 PM
Here's how I'd do it
Private Function CreateString()
Dim iStrLen As Integer
Dim iChar As Integer
Dim I As Integer
Dim strString As String
iStrLen = Int(Rnd * 10) + 4
For I = 1 To iStrLen
iChar = Int(Rnd * 62)
If iChar >= 0 And iChar <= 9 Then
strString = strString & Chr$(iChar + 48)
ElseIf iChar >= 10 And iChar <= 35 Then
strString = strString & Chr$(iChar + 55)
ElseIf iChar >= 36 And iChar <= 61 Then
strString = strString & Chr$(iChar + 61)
End If
Next I
CreateString = strString
End Function
Note that this isn't fully tested, and I may have made some mistakes some places.
that's extremely inefficient.
it would be better if you replaced all Int's with CInt, since they work faster.
Something better is iStrLen = Fix(Rnd * 11) + 4, so that 4 and 14 have equal as many chances as the rest of the numbers. (cint rounds UP for 0.5 and higher, but Fix rounds down) Your way makes 4 and 14 half as likely as the other numbers
you could change
iChar = Int(Rnd * 62)
If iChar >= 0 And iChar <= 9 Then
strString = strString & Chr$(iChar + 48)
ElseIf iChar >= 10 And iChar <= 35 Then
strString = strString & Chr$(iChar + 55)
ElseIf iChar >= 36 And iChar <= 61 Then
strString = strString & Chr$(iChar + 61)
End If
into
iChar = Fix(Rnd * 62) 'Int would allow 62, which wouldnt generate any character
If iChar <= 9 Then
iChar=iChar+48
ElseIf iChar <= 35 Then
iChar=iChar+55
Else
iChar=iChar+61
End If
strString=strString & chr$(iChar+61)
This code isn't much faster, but it does take up less room when compiled and it won't allow the possibility of iChar being 62. It also reduces many times that checking is wasted.
Lastly, after modifying it a bit more, this is a better function:
(This is based on RealityRipple's calculations for which char numbers work)
Private Function CreateString()
Dim iStrLen As Integer
Dim iChar As Integer
Dim I As Integer
Dim strString As String
iStrLen = Fix(Rnd * 10) + 4
For I = 1 To iStrLen
iChar = Fix(Rnd * 62) + 48
If iChar > 9 And iChar < 36 Then
iChar = iChar + 7
Else
iChar = iChar + 13
End If
strString = strString & Chr$(iChar)
Next I
CreateString = strString
End Function
You can eliminate the variable I by replacing For I = 1 to iStrLen with Do until Len(strString)=iStrLen and Next I with Loop
like i said, i didn't check it at all. and Int(Rnd * 62) wouldn't allow 62.
Dim randval As Integer
Randomize
Do Until randval = 62
randval = Int(Rnd * 62)
Debug.Print randval
Loop
MsgBox "Done"
run that. it will never end.
Brew's real problem is that no matter how he tries to make it, its gonna generate some repeats. He wants it to have no repeats.
Quote from: [RealityRipple] on March 22, 2007, 06:01 PM
like i said, i didn't check it at all. and Int(Rnd * 62) wouldn't allow 62.
Dim randval As Integer
Randomize
Do Until randval = 62
randval = Int(Rnd * 62)
Debug.Print randval
Loop
MsgBox "Done"
run that. it will never end.
oh sorry i forgot that the rounding up is only with CInt
also, just make sure that its int (or Fix)(rnd*11)+4 for the strlen
I don't see it saying anything about no repeats. I see it's repeating too much, and he wants it more random...
Yes more random would be nice.. And since Rnd resets every time the program is reset, maybe i should store the last Rnd on form unload in maybe... the registry or a config file. then on the random name function I use the stored rnd value as a base value for my own random function... salted with Rnd... and creating more randomized chars yet again...
uhm... Randomize sets the random seed. Put it at the top of your function.
Quote from: [RealityRipple] on March 23, 2007, 03:34 PM
uhm... Randomize sets the random seed. Put it at the top of your function.
I did and it's still very un-random
No worries though... It's not a problem anymore.