Click to See Complete Forum and Search --> : Random String Generator


aktome2001
06-23-2005, 08:18 PM
I've written a small script to generate any number of random strings of any length.

I'd really like some feedback on my method of creating the random string. I've tested this with a high number of strings and there were no duplicates.

You can see a working example at http://www.erictompkins.com/rand_password.php

The code can be seen at http://www.erictompkins.com/rand_password.php?view=code and it's below as well. The code on the page also includes a basic sample of setting up the form and calling the class.


<?php
/**
* RandString class
* Generates a number of random strings based on the number of charactors needed
* and the number of strings needed
*
* @author Eric Tompkins, North Wind Media, www.NorthWindMedia.com
* @version 1.1 06/15/2005
*/

class RandString {

/**
* Creates the random string(s)
* @access public
* @param int $length The length of the string(s)
* @param int $num_output The number of strings to return
* @return array
*/
function create_string($length=8,$num_output=1) {
$rand = array();

//Build the seed
list($msec,$sec) = explode(' ',microtime());
$seed = ((float)$msec * 1000000) + (float) $sec;
mt_srand($seed);

//Generate the number of random strings needed
for ($a = 0; $a < $num_output; $a ++) {

//Generate a random 100 length string
for ($i = 0; $i < 100; $i ++) {
//Get a random number between 1 and 100
$rn = mt_rand(1,100);
//Get a random number between 100 and 100,000
$rn2 = mt_rand(100,100000);
//Get the first digit of the modulus between the two numbers
//This number is used to retrieve a certain ASCII charactor
$number = substr(($rn2 % $rn),0,1);
//Build a string based on ASCII charactors
//0 and 1 are not retrieved to avoid confusion between the letter O and number 0,
//and letter I or letter l and number 1
switch ($number) {
case 0: $str .= chr(mt_rand(50,57)); break; //2-9
case 1: $str .= chr(mt_rand(65,90)); break; //A-Z
case 2: $str .= chr(mt_rand(97,122)); break; //a-z
case 3: $str .= chr(mt_rand(50,57)); break; //2-9
case 4: $str .= chr(mt_rand(65,90)); break; //A-Z
case 5: $str .= chr(mt_rand(97,122)); break; //a-z
case 6: $str .= chr(mt_rand(50,57)); break; //2-9
case 7: $str .= chr(mt_rand(65,90)); break; //A-Z
case 8: $str .= chr(mt_rand(97,122)); break; //a-z
case 9: $str .= chr(mt_rand(50,57)); break; //2-9
}
}

//Generate the output string
for ($b = 0; $b < $length; $b++) {
$substr = mt_rand(0,99);
$string .= substr($str,$substr,1);
}

//Assign the string to the $rand array
$rand[] = $string;
//'Empty' the varible $string
unset($string);
}
return $rand;
}
}
?>



Thank you.

planetsim
06-23-2005, 09:22 PM
First thoughts.

Since there is only one method is making it a class really the best idea? Maybe just use it as a function.

Other than that not bad.

Weedpacket
06-25-2005, 02:11 AM
The switch could be shortened

switch ($number%3) {
case 0: $str .= chr(mt_rand(50,57)); break; //2-9
case 1: $str .= chr(mt_rand(65,90)); break; //A-Z
case 2: $str .= chr(mt_rand(97,122)); break; //a-z
}

or replaced by

$lo_ranges = array(50, 65, 97);
$hi_ranges = array(57, 90, 122);
$lo_range = $lo_ranges[$number%3];
$hi_range = $hi_ranges[$number%3];
$str .= chr(mt_rand($lo_range, $hi_range));

or

$digits='23456789'; $max_digit=7;
$uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $max_uppercase=25;
$lowercase='abcdefghijklmnopqrstuvwxyz'; $max_lowercase=25;
switch ($number%3) {
case 0: $str .= $digits{mt_rand(0,$max_digit)}; break; //2-9
case 1: $str .= $uppercase{mt_rand(0,$max_uppercase)}; break; //A-Z
case 2: $str .= $lowercase{mt_rand(0,$max_lowercase)}; break; //a-z
}

I don't see what the point of $rn and $rn2 are in generating $number is; what's wrong with $number=mt_rand(0,9)? Or even mt_rand(0,2) (except that (0,2) doesn't have a bias in favour of selecting digits over upper- or lowercase letters).

I also don't see the point of randomly generating a lot more characters than necessary and then making a random selection from those - a uniformly distributed selection from a uniform distribution is still just a uniform distribution.

//0 and 1 are not retrieved to avoid confusion between the letter O and number 0,
//and letter I or letter l and number 1
$character_sets = array(
'23456789',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'
);
$character_set_max_offsets = array(7,25,25);

for($count_passwd=0; $count_passwd<$num_output; ++$count_passwd)
{
$str = '';
for($char=0; $char<$length; ++$char)
{
$n = mt_rand(0,9)%3;
$character_set = $character_sets[$n];
$character_set_max_offset = $character_set_max_offsets[$n];
$str .= $character_set{mt_rand(0,$character_set_max_offset)};
}
$rand[] = $str;
}