我已经开发了一个随机字符串生成器,但它的行为并不像我所希望的那样。我的目标是能够运行两次,并生成两个不同的四字符随机字符串。但是,它只生成一个四个字符的随机字符串两次。

下面是代码和输出示例:

private string RandomString(int size)
{
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;
    for (int i = 0; i < size; i++)
    {
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                 
        builder.Append(ch);
    }

    return builder.ToString();
}

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// create full rand string
string docNum = Rand1 + "-" + Rand2;

...输出如下:UNTE-UNTE ...但它应该看起来像这个UNTE-FWNU

如何确保两个明显随机的字符串?


当前回答

实际上,一个好的解决方案是为随机数生成器提供一个线程安全且不使用锁的静态方法。

这样,同时访问web应用程序的多个用户就不会得到相同的随机字符串。

这里有3个例子: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

我会用最后一个:

public static class RandomGen3
{
    private static RNGCryptoServiceProvider _global = 
        new RNGCryptoServiceProvider();
    [ThreadStatic]
    private static Random _local;

    public static int Next()
    {
        Random inst = _local;
        if (inst == null)
        {
            byte[] buffer = new byte[4];
            _global.GetBytes(buffer);
            _local = inst = new Random(
                BitConverter.ToInt32(buffer, 0));
        }
        return inst.Next();
    }
}

然后就可以适当消去了

Random random = new Random();

只需调用RandomGen3.Next(),而您的方法可以保持静态。

其他回答

以下是我对目前公认答案的修改,我认为它更快更短:

private static Random random = new Random();

private string RandomString(int size) {
    StringBuilder builder = new StringBuilder(size);
    for (int i = 0; i < size; i++)
        builder.Append((char)random.Next(0x41, 0x5A));
    return builder.ToString();
}

注意,我没有使用所有的乘法,math。floor(), Convert等。

编辑:随机的。Next(0x41, 0x5A)可以更改为任何范围的Unicode字符。

您正在该方法中创建Random实例,这将导致它在快速连续调用时返回相同的值。我会这样做:

private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private string RandomString(int size)
    {
        StringBuilder builder = new StringBuilder();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                 
            builder.Append(ch);
        }

        return builder.ToString();
    }

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// creat full rand string
string docNum = Rand1 + "-" + Rand2;

(修改后的代码版本)

在我的情况下,密码必须包含:

至少有一个小写字母。 至少一个大写字母。 至少有一个小数。 至少一个特殊字符。

这是我的代码:

    private string CreatePassword(int len)
    {
        string[] valid = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "1234567890", "!@#$%^&*()_+" };
        RNGCryptoServiceProvider rndGen = new RNGCryptoServiceProvider();

        byte[] random = new byte[len];
        int[] selected = new int[len];

        do
        {
            rndGen.GetNonZeroBytes(random);

            for (int i = 0; i < random.Length; i++)
            {
                selected[i] = random[i] % 4;
            }
        } 
        while(selected.Distinct().Count() != 4);

        rndGen.GetNonZeroBytes(random);

        string res = "";

        for(int i = 0; i<len; i++)
        {
            res += valid[selected[i]][random[i] % valid[selected[i]].Length];
        }
        return res;
    }

另一个样本(在vs2013中测试):

    Random R = new Random();
    public static string GetRandomString(int Length)
    {
        char[] ArrRandomChar = new char[Length];
        for (int i = 0; i < Length; i++)
            ArrRandomChar[i] = (char)('a' + R.Next(0, 26));
        return new string(ArrRandomChar);
    }

    string D = GetRandomString(12);

我自己实现的。

还有另一个版本:我在测试中使用这种方法生成随机的伪股票代码:

Random rand = new Random();
Func<char> randChar = () => (char)rand.Next(65, 91); // upper case ascii codes
Func<int,string> randStr = null;
    randStr = (x) => (x>0) ? randStr(--x)+randChar() : ""; // recursive

用法:

string str4 = randStr(4);// generates a random 4 char string
string strx = randStr(rand.next(1,5)); // random string between 1-4 chars in length

你可以重新定义randChar函数,使用一个“允许的”字符数组,而不是ascii码:

char[] allowedchars = {'A','B','C','1','2','3'};
Func<char> randChar = () => allowedchars[rand.Next(0, allowedchars.Length-1)];