【问题标题】:Generate random string [duplicate]生成随机字符串[重复]
【发布时间】:2010-12-07 01:29:06
【问题描述】:

可能重复:
c# random string generator

我需要生成一个给定长度的随机字符串。到目前为止,这是我的代码。问题是随机字符串每次都像“RRRRRR”或“SSSSS”一样的字母。就在我重新启动应用程序时,字母发生了变化。我需要类似“asrDvgDgREGd”的东西

    public string GenerateChar()
    {
        Random random = new Random();

        return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
    }

    public string GenerateChar(int count)
    {        
        string randomString = "";

        for (int i = 0; i < count; i++)
        {
            nahodneZnaky += GenerateChar();
        }

        return randomString;
    }

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    尝试对整个字符串使用相同的随机对象,而不是为每个字符初始化一个。

    随机对象将根据从“种子”数字开始的数学级数生成“伪随机”数字。如果每次都将 Random 对象初始化为相同的种子,您实际上可以获得相同的“随机”数字序列。

    现在,当您在不指定种子的情况下初始化 Random 时,它会将计算机的时钟作为种子。在这种情况下,您可能做得足够快,以至于时钟没有从一个初始化更改为另一个,并且您总是得到相同的种子。

    您最好在生成随机字符串的函数中初始化 Random 对象,并将其作为参数传递给 GenerateChar 函数,这样您就可以在同一个 Random 实例上多次调用 NextDouble()对象,而不是只在它的不同实例上一次。

    【讨论】:

    • +1 用于解释为什么他的代码会给出该输出。
    • 谢谢。我仍然认为他应该接受 James 对这个特殊案例的建议,但我相信理解为什么会发生这种情况会很有用,因为 Random 在其他场景中是很常见的。
    • 一个小的改进可能是还有一个名为 IsUpperCase 的方法,它可以生成 0-1 之间的随机数
    【解决方案2】:

    不要在每次迭代时创建 Random 的新实例 - 这将使用当前时间(以毫秒为单位)为每个实例播种,这显然不太可能在迭代之间发生变化。

    创建Random 的单个实例,并将其传递给方法。我还建议您不要在循环中连接这样的字符串,甚至不要创建那么多字符串。此外,如果您使用Random.Next(int, int) 让您的生活更轻松。

    试试这个:

    public char GenerateChar(Random rng)
    {
        // 'Z' + 1 because the range is exclusive
        return (char) (rng.Next('A', 'Z' + 1));
    }
    
    public string GenerateString(Random rng, int length)
    { 
        char[] letters = new char[length];
        for (int i = 0; i < length; i++)
        {
            letters[i] = GenerateChar(rng);
        }
        return new string(letters);
    }
    
    private static readonly Random SingleRandom = new Random();
    
    public string GenerateStringNotThreadSafe(int length)
    { 
        return GenerateString(SingleRandom, length);
    }
    

    现在值得注意的是,Random 不是线程安全的,所以如果您有多个线程,您不应该在没有锁定的静态变量中只拥有一个 Random 实例。有多种方法可以解决这个问题 - 要么创建Random 的子类,线程安全的,要么是一组做同样事情的静态方法,或者使用线程局部变量来拥有一个实例每个线程。

    我有一个StaticRandom class 作为MiscUtil 的一部分,但这些天我倾向于线程本地版本并在适当的情况下将其传递到链中。有一天我会把它作为另一个选项添加到 MiscUtil...

    【讨论】:

      【解决方案3】:

      从调用方法传递 random 并初始化一次 - 您每次都使用相同的种子重新播种 Random 生成器......

      【讨论】:

        【解决方案4】:

        你应该在方法之外初始化你的随机变量:

        public Random random = new Random();
        
        public string GenerateChar()
            {
               return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
            }
        
        ...
        

        【讨论】:

        • 小心!这不是线程安全的。如果您在网络应用程序中执行此操作,您可能会遇到奇怪的线程问题(我很难学会)
        • 好吧,他没有提到他是为一个网络应用程序做的,但是好的,谢谢你的建议。 ;-)
        【解决方案5】:

        您可以省去麻烦并使用Membership.GeneratePassword 方法。它本质上是在做你需要的。

        用法:

        int passwordLength = 5;
        int alphaNumericalCharsAllowed = 2;
        string random = Membership.GeneratePassword(passwordLength, alphaNumericalCharsAllowed);
        

        为了可读性,您可以将其包装在辅助方法中:

        private string GenerateRandomString(int length, int alphaNumericalChars)
        {
              return Membership.GeneratePassword(length, alphaNumericalChars);
        }
        

        【讨论】:

        • 这个解决方案的问题是虽然我将第二个参数设置为0,但生成的字符串中仍然存在标点符号。
        • 我对此进行了调查,结果发现该方法的文档并不完全正确,它确实包含标点符号(即使文档告诉您否则!)。在那种情况下,我可能会编写自己的自定义随机字符串生成器。
        • 或者,您可以在 for 循环中使用 GeneratePassword 并检查每个生成的密码是否有标点符号,直到找到没有标点符号的密码。虽然不理想,但会工作。
        • 使用 .NET API 显示。我已经使用会员资格 1 年以上,但不知道这种方法! +1
        【解决方案6】:

        也许您会发现 Path.GetRandomFileName 方法很有用,具体取决于您在字符串中需要的确切字符。

        【讨论】:

          【解决方案7】:

          尝试静态

          public string GenerateChar()
          {
              static Random random = new Random();
          
              return Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString();
          }
          

          【讨论】:

          • 小心!这可能不是线程安全的。如果您在网络应用程序中执行此操作,您可能会遇到奇怪的线程问题(我很难学会)
          • 丹尼尔马格里奥拉,真的。为此,您可以锁定生成: public string GenerateChar() { static Random random = new Random();字符串 rndString;锁定(随机){ rndString = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))).ToString(); } 返回 rndString; }
          【解决方案8】:

          我知道这可能不是最好的解决方案,但我有点喜欢能够指定“允许”字符的想法:

              private const int _defaultNumberOfCharacters = 8;
              private const int _defaultExpireDays = 10;
              private static readonly string _allowedCharacters = "bcdfghjklmnpqrstvxz0123456789";
          
              public static string GenerateKey(int numberOfCharacters)
              {
                  const int from = 0;
                  int to = _allowedCharacters.Length;
                  Random r = new Random();
          
                  StringBuilder qs = new StringBuilder();
                  for (int i = 0; i < numberOfCharacters; i++)
                  {
                      qs.Append(_allowedCharacters.Substring(r.Next(from, to), 1));
                  }
                  return qs.ToString();
              }
          

          【讨论】:

          • 我对此表示赞同,因为我发现排除“1”和“l”以及“0”和“O”是很重要的,因为用户会混淆它们。
          【解决方案9】:

          没什么特别的,但很简短。 32 和 127 是您要生成的字符的最小和最大范围。

          public static string GetRandomString(int length)
          {
              var r = new Random();
              return new String(Enumerable.Range(0, length).Select(n => (Char)(r.Next(32, 127))).ToArray());
          }
          

          【讨论】:

            【解决方案10】:

            http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx

            string randomName = Path.GetRandomFileName();
            randomName = randomName.Replace(".", string.Empty);
            
            // take substring...
            

            【讨论】:

              【解决方案11】:

              试试这个。

              public string GetRandomString()
              {
                  int randomNumber = new Random().Next();
                  string RandomString = string.Empty;
                  for(int i = 0;i < randomNumber.ToString().Length;i++)
                  {
                      RandomString += ((char)Convert.ToUInt32(randomNumber.ToString()[i])).ToString();
                  }
                  return RandomString;
              }
              

              【讨论】:

                猜你喜欢
                • 2015-08-16
                • 2014-02-05
                • 2017-01-06
                • 2017-04-05
                • 1970-01-01
                • 1970-01-01
                • 2017-04-11
                • 2019-07-11
                相关资源
                最近更新 更多