随机字符串生成器返回相同的字符串

Pus*_*ode 222 c# random

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

这是代码和输出的示例:

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;
Run Code Online (Sandbox Code Playgroud)

......输出看起来像这样:UNTE-UNTE ......但看起来应该像UNTE-FWNU

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

RCI*_*CIX 305

您正在方法中创建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;
Run Code Online (Sandbox Code Playgroud)

(修改后的代码版本)

  • 请注意,`Random`类的实例成员不会被记录为线程安全的,因此如果同时从多个线程调用此方法(例如,如果您正在制作Web应用程序,很可能)这段代码将是未定义的.您需要使用随机锁定或使用每个线程. (46认同)
  • 另外,你可以使用`ch =(char)random.Next('A','Z')得到一个随机的大写字母;`比不可读的行更简单`ch = Convert.ToChar(Convert.ToInt32(Math) .Floor(26*random.NextDouble()+ 65)));`来自原帖.然后,如果你想把它切换成小写,你可以很容易地切换到`(char)random.Next('a','z');` (19认同)
  • @NickFreeman:记住[上限是独占的](http://msdn.microsoft.com/en-us/library/2dx6wyd4.aspx),所以`ch =(char)random.Next('A','Z ');`永远不会返回''Z'.所以你需要`ch =(char)random.Next('A','Z'+ 1);`包含''Z'. (17认同)

Luk*_*keH 186

您正在实例化Random方法中的对象.

Random物体是从系统时钟种子,这意味着如果你打电话给你的方法多次快速连续它会每次都使用相同的种子,这意味着它会产生随机数的相同的序列,这意味着你我会得到相同的字符串.

要解决这个问题,请将您的Random实例移出方法本身(当您在它的时候,你可以摆脱那些疯狂的调用ConvertFloorNextDouble):

private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private string RandomString(int size)
{
    char[] buffer = new char[size];

    for (int i = 0; i < size; i++)
    {
        buffer[i] = _chars[_rng.Next(_chars.Length)];
    }
    return new string(buffer);
}
Run Code Online (Sandbox Code Playgroud)

  • 另外,我喜欢将这种方法作为Random的扩展方法. (9认同)
  • 请注意,Random类的实例成员不会被记录为线程安全的,因此如果同时从多个线程调用此方法(例如,如果您正在制作Web应用程序,那么很可能)代码将是未定义的.您需要使用随机锁定或使用每个线程. (8认同)
  • 或者使它成为静态和内部的类. (7认同)

Ran*_*vir 135

//一个非常简单的实现

using System.IO;   
public static string RandomStr()

{
    string rStr = Path.GetRandomFileName();
    rStr = rStr.Replace(".", ""); // For Removing the .
    return rStr;
}
Run Code Online (Sandbox Code Playgroud)

//现在只需调用RandomStr()方法

  • @bugnuker"GetRandomFileName方法返回一个加密强大的随机字符串,可以用作文件夹名称或文件名.与GetTempFileName不同,GetRandomFileName不会创建文件.当文件系统的安全性至关重要时,此方法应该用来代替GetTempFileName." 我们谈论的是GetRandomFileName()而不是GetTempFileName(). (25认同)
  • 这会在磁盘上创建文件.来自MSDN:如果GetTempFileName方法用于创建超过65535个文件而不删除以前的临时文件,则会引发IOException.如果没有唯一的临时文件名可用,GetTempFileName方法将引发IOException.要解决此错误,请删除所有不需要的临时文件. (18认同)
  • 太好了!当你发现隐藏在.Net框架中的像GetRandomFileName这样的小宝石时,请喜欢它 (7认同)
  • @AndersFjeldstad同意,我做了一个循环,它在大约130,000次迭代后遇到了碰撞.尽管有1,785,793,904,896种组合. (3认同)
  • 用你的略微编辑.guid = Guid.NewGuid(); mystring = guid.ToString(); mystring = mystring.Replace(" - ",""); mystring = mystring.Substring(0,8); (2认同)

Spo*_*boy 49

只要您使用的是Asp.Net 2.0或更高版本,您也可以使用库调用 System.Web.Security.Membership.GeneratePassword- 但它将包含特殊字符.

获得4个随机字符,最少0个特殊字符 -

Membership.GeneratePassword(4, 0)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在4.0中,第二个整数参数表示要使用的**最小**个nonAlphaNumericCharacters数.所以`Membership.GeneratePassword(10,0);`不会像你想象的那样工作,它仍然会加载大量的非字母数字字符,例如:`z9sge)?pmV` (8认同)

Abd*_*nim 20

只是为了让人们在一行代码中停下来以及如何获得随机字符串

int yourRandomStringLength = 12; //maximum: 32
Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength);
Run Code Online (Sandbox Code Playgroud)

PS:请记住,最大长度为32 ,yourRandomStringLength不能超过Guid32.

  • 我不确定这一定是随机的.GUID被设计为唯一的,而不是随机的,因此字符串中的前N个字符可能是相同的(取决于GUID生成器). (9认同)

ole*_*sii 13

此解决方案是Random课程的扩展.

用法

class Program
{
    private static Random random = new Random(); 

    static void Main(string[] args)
    {
        random.NextString(10); // "cH*%I\fUWH0"
        random.NextString(10); // "Cw&N%27+EM"
        random.NextString(10); // "0LZ}nEJ}_-"
        random.NextString();   // "kFmeget80LZ}nEJ}_-"
    }
}
Run Code Online (Sandbox Code Playgroud)

履行

public static class RandomEx
{
    /// <summary>
    /// Generates random string of printable ASCII symbols of a given length
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <param name="length">length of a random string</param>
    /// <returns>Random string of a given length</returns>
    public static string NextString(this Random r, int length)
    {
        var data = new byte[length];
        for (int i = 0; i < data.Length; i++)
        {
            // All ASCII symbols: printable and non-printable
            // data[i] = (byte)r.Next(0, 128);
            // Only printable ASCII
            data[i] = (byte)r.Next(32, 127);
        }
        var encoding = new ASCIIEncoding();
        return encoding.GetString(data);
    }

    /// <summary>
    /// Generates random string of printable ASCII symbols
    /// with random length of 10 to 20 chars
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <returns>Random string of a random length between 10 and 20 chars</returns>
    public static string NextString(this Random r)
    {
        int length  = r.Next(10, 21);
        return NextString(r, length);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mak*_*dov 12

另一个版本的字符串生成器.简单,没有花哨的数学和魔术数字.但是有一些魔术字符串指定允许的字符.

更新: 我使生成器静态,因此多次调用时不会返回相同的字符串.但是,此代码不是 线程安全的,绝对不是 加密安全的.

System.Security.Cryptography.RNGCryptoServiceProvider应使用密码生成.

private Random _random = new Random(Environment.TickCount);

public string RandomString(int length)
{
    string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    StringBuilder builder = new StringBuilder(length);

    for (int i = 0; i < length; ++i)
        builder.Append(chars[_random.Next(chars.Length)]);

    return builder.ToString();
}
Run Code Online (Sandbox Code Playgroud)


Zyg*_*tas 10

还有一个选择:

public System.String GetRandomString(System.Int32 length)
{
    System.Byte[] seedBuffer = new System.Byte[4];
    using (var rngCryptoServiceProvider = new System.Security.Cryptography.RNGCryptoServiceProvider())
    {
        rngCryptoServiceProvider.GetBytes(seedBuffer);
        System.String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        System.Random random = new System.Random(System.BitConverter.ToInt32(seedBuffer, 0));
        return new System.String(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

最好的解决方案是使用随机数生成器进行base64转换

public string GenRandString(int length)
{
  byte[] randBuffer = new byte[length];
  RandomNumberGenerator.Create().GetBytes(randBuffer);
  return System.Convert.ToBase64String(randBuffer).Remove(length);
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*ill 5

一个很好的 LINQ 单线(假设一个private static Random Random)...

public static string RandomString(int length)
{
    return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray());
}
Run Code Online (Sandbox Code Playgroud)