5

我正在尝试生成一个没有重复字符的 16 个字符的随机字符串。我认为这不应该太难,但我被困住了。

我正在使用 2 种方法,一种用于生成密钥,另一种用于删除重复字符。在 main 中,我创建了一个 while 循环以确保生成的字符串长度为 16 个字符。

我的逻辑有问题,因为它只会生成带有重复项的 16 字符字符串。就是做不好。

编码:

public string RemoveDuplicates(string s)
{
    string newString = string.Empty;
    List<char> found = new List<char>();
    foreach (char c in s)
    {
        if (found.Contains(c))
            continue;

        newString += c.ToString();
        found.Add(c);
    }
    return newString;
}

public static string GetUniqueKey(int maxSize)
{
    char[] chars = new char[62];
    chars =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
    byte[] data = new byte[1];
    RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
    crypto.GetNonZeroBytes(data);
    data = new byte[maxSize];
    crypto.GetNonZeroBytes(data);
    StringBuilder result = new StringBuilder(maxSize);
    foreach (byte b in data)
    {
        result.Append(chars[b % (chars.Length)]);

    }
    return result.ToString();
}

string builder = "";

do
{                       

    builder = GetUniqueKey(16);
    RemoveDuplicates(builder);

    lblDir.Text = builder;
    Application.DoEvents();


} while (builder.Length != 16);
4

5 回答 5

9

考虑实施洗牌算法,您将使用独特的字符对字符串进行洗牌,然后只拾取前 16 个字符。

您可以就地执行此操作,方法是分配StringBuffer将包含您的初始数据(“abc ....”)的单个,并使用 Durstenfeld 的算法版本来改变您的缓冲区,而不是返回前 16 个字符。

于 2013-03-03T11:59:31.773 回答
8

有很多算法可以解决这个问题。

一个简单的方法是:

  1. 用可用的字符填充一个字符数组。
  2. 随机排列数组。
  3. 取前 N 个项目(其中 N 是您需要的字符数)。

示例代码:

using System;

namespace ConsoleApplication2
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            Random rng = new Random();

            for (int i = 0; i < 10; ++i)
            {
                string randomString = RandomString(16, chars, rng);
                Console.WriteLine(randomString);
            }
        }

        public static string RandomString(int n, char[] chars, Random rng)
        {
            Shuffle(chars, rng);
            return new string(chars, 0, n);
        }

        public static void Shuffle(char[] array, Random rng)
        {
            for (int n = array.Length; n > 1; )
            {
                int k = rng.Next(n);
                --n;
                char temp = array[n];
                array[n] = array[k];
                array[k] = temp;
            }
        }
    }
}
于 2013-03-03T12:00:43.177 回答
6
const string chars = 
               "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var r = new Random();
var s = new string(chars.OrderBy(x => r.Next()).Take(16).ToArray());
于 2013-03-03T12:12:37.323 回答
0

我正在使用 GUID 生成方法,它本身会生成随机字符串,如果开头出现数字,您可以对其进行修改,使用下面给出的代码:

string guid = System.Guid.NewGuid().ToString("N");
            while (char.IsDigit(guid[0]))
                guid = System.Guid.NewGuid().ToString("N");

希望有帮助。

于 2015-07-17T06:36:53.900 回答
0

看看这是否有帮助:

    RandomString()
    {
        string randomStr = Guid.NewGuid().ToString();
        randomStr = randomStr.Replace("-", "").Substring(0, 16);   
        Console.WriteLine(randomStr);
    }

这将返回字母数字字符串。

于 2015-10-06T02:45:23.777 回答