• Welcome to Valhalla Legends Archive.
 

[VB6] Random string function

Started by brew, March 17, 2007, 07:34 PM

Previous topic - Next topic

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:

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
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

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.

brew

#2
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?
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

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.

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.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Barabajagal

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.

brew

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.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Ante

#7
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
Efficiency is the Key to Productivity, and
Productivity is the Key to Success.

Barabajagal

#8
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.

Ante

#9
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
Efficiency is the Key to Productivity, and
Productivity is the Key to Success.

Barabajagal

I don't see it saying anything about no repeats. I see it's repeating too much, and he wants it more random...

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...
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Barabajagal

uhm... Randomize sets the random seed. Put it at the top of your function.

brew

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.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P