Valhalla Legends Forums Archive | Visual Basic Programming | [VB6] Random string function

AuthorMessageTime
BreW
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:
[code]
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
[/code]
March 18, 2007, 12:34 AM
Barabajagal
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.
March 18, 2007, 12:44 AM
BreW
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
[code]
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
[/code]
Still, any suggestions?
March 18, 2007, 12:57 AM
Barabajagal
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.
March 18, 2007, 1:09 AM
BreW
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.
March 18, 2007, 1:18 AM
Barabajagal
Here's how I'd do it
[code]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[/code]

Note that this isn't fully tested, and I may have made some mistakes some places.
March 18, 2007, 1:39 AM
BreW
[quote author=[RealityRipple] link=topic=16498.msg166864#msg166864 date=1174181940]
Here's how I'd do it
[code]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[/code]

Note that this isn't fully tested, and I may have made some mistakes some places.
[/quote]

Thanks, reality.
March 18, 2007, 1:39 AM
Ante
[quote author=[RealityRipple] link=topic=16498.msg166864#msg166864 date=1174181940]
Here's how I'd do it
[code]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[/code]

Note that this isn't fully tested, and I may have made some mistakes some places.
[/quote]
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)
[Code]
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
[/Code]
You can eliminate the variable I by replacing For I = 1 to iStrLen with Do until Len(strString)=iStrLen and Next I with Loop
March 22, 2007, 10:54 PM
Barabajagal
like i said, i didn't check it at all. and Int(Rnd * 62) wouldn't allow 62.

[code]Dim randval As Integer
    Randomize
    Do Until randval = 62
        randval = Int(Rnd * 62)
        Debug.Print randval
    Loop
    MsgBox "Done"[/code] run that. it will never end.
March 22, 2007, 11:01 PM
Ante
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 author=[RealityRipple] link=topic=16498.msg167058#msg167058 date=1174604469]
like i said, i didn't check it at all. and Int(Rnd * 62) wouldn't allow 62.

[code]Dim randval As Integer
    Randomize
    Do Until randval = 62
        randval = Int(Rnd * 62)
        Debug.Print randval
    Loop
    MsgBox "Done"[/code] run that. it will never end.
[/quote]
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
March 22, 2007, 11:03 PM
Barabajagal
I don't see it saying anything about no repeats. I see it's repeating too much, and he wants it more random...
March 22, 2007, 11:42 PM
BreW
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...
March 23, 2007, 8:15 PM
Barabajagal
uhm... Randomize sets the random seed. Put it at the top of your function.
March 23, 2007, 8:34 PM
BreW
[quote author=[RealityRipple] link=topic=16498.msg167130#msg167130 date=1174682040]
uhm... Randomize sets the random seed. Put it at the top of your function.
[/quote]
I did and it's still very un-random
No worries though... It's not a problem anymore.
March 23, 2007, 11:28 PM

Search