Случайный строковый генератор, возвращающий одну строку

Я разработал генератор случайных строк, но он не ведет себя так, как я надеюсь. Моя цель состоит в том, чтобы иметь возможность запускать это дважды и генерировать две различные случайные строки из четырех символов. Однако он просто генерирует одну случайную строку из четырех символов дважды.

Здесь код и пример его вывода:

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

Как я могу обеспечить две явно случайные строки?

Ответы

Ответ 1

Вы производите экземпляр 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;

(измененная версия вашего кода)

Ответ 2

Вы создаете объект Random внутри своего метода.

Объект Random посеян из системных часов, что означает, что если вы вызовете свой метод несколько раз подряд, это будет используйте одно и то же семя каждый раз, что означает, что он будет генерировать ту же последовательность случайных чисел, что означает, что вы получите ту же строку.

Чтобы решить проблему, переместите свой экземпляр Random вне самого метода (и пока вы на нем можете избавиться от этой сумасшедшей последовательности вызовов Convert и Floor и NextDouble)

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);
}

Ответ 3

//Очень простая реализация

using System.IO;   
public static string RandomStr()

{
    string rStr = Path.GetRandomFileName();
    rStr = rStr.Replace(".", ""); // For Removing the .
    return rStr;
}

//Теперь просто вызовите метод RandomStr()

Ответ 4

Пока вы используете Asp.Net 2.0 или выше, вы также можете использовать библиотеку call- System.Web.Security.Membership.GeneratePassword, однако он будет содержать специальные символы.

Чтобы получить 4 случайных символа с минимум 0 специальными символами -

Membership.GeneratePassword(4, 0)

Ответ 5

Просто для людей, останавливающихся и имеющих случайную строку только в одной строке кода

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

PS: Имейте в виду, что yourRandomStringLength не может превышать 32, поскольку Guid имеет максимальную длину 32.

Ответ 6

Это решение является расширением для класса 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}_-"
    }
}

Реализация

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);
    }
}

Ответ 7

Еще одна версия генератора строк. Простой, без причудливых математических и магических цифр. Но с некоторой магической строкой, которая указывает допустимые символы.

Update: Я сделал генератор статическим, поэтому он не будет возвращать одну и ту же строку при вызове несколько раз. Однако этот код не потокобезопасен и определенно не криптографически защищен.

Для генерации паролей 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();
}

Ответ 8

Вот еще один вариант:

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());
    }
}

Ответ 9

Лучшее решение - использовать генератор случайных чисел для преобразования base64

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

Ответ 10

Это связано с тем, что каждый новый экземпляр Random генерирует одинаковые числа из так называемых быстрых. Не продолжать создавать новый экземпляр, просто вызвать next() и объявить ваш случайный класс вне вашего метода.

Ответ 11

Однострочный 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());
}

Ответ 12

У вас должен быть один случайный объект класса класса, инициированный один раз в конструкторе и повторно используемый для каждого вызова (это продолжает ту же последовательность псевдослучайных чисел). Конструктор без параметров уже сгенерирует генератор с помощью Environment.TickCount внутри.

Ответ 13

Я добавил вариант выбора длины с помощью решения Ranvir

public static string GenerateRandomString(int length)
    {
        {
            string randomString= string.Empty;

            while (randomString.Length <= length)
            {
                randomString+= Path.GetRandomFileName();
                randomString= randomString.Replace(".", string.Empty);
            }

            return randomString.Substring(0, length);
        }
    }

Ответ 14

Вот моя модификация принятого в настоящее время ответа, который я считаю немного быстрее и короче:

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 и т.д.

EDIT: random.Next(0x41, 0x5A) можно изменить на любой диапазон символов Юникода.

Ответ 15

Мой RandomString() метод для создания случайной строки.

private static readonly Random _rand = new Random();

/// <summary>
/// Generate a random string.
/// </summary>
/// <param name="length">The length of random string. The minimum length is 3.</param>
/// <returns>The random string.</returns>
public string RandomString(int length)
{
    length = Math.Max(length, 3);

    byte[] bytes = new byte[length];
    _rand.NextBytes(bytes);
    return Convert.ToBase64String(bytes).Substring(0, length);
}

Ответ 16

Я думаю, может быть, это тоже приемлемо и просто.

Guid.NewGuid().ToString() 

Ответ 17

Вот сообщение в блоге, которое предоставляет немного более надежный класс для генерации случайных слов, предложений и абзацев.

Ответ 18

Если вы хотите сгенерировать строку чисел и символов для надежного пароля.

private static Random random = new Random();

private static string CreateTempPass(int size)
        {
            var pass = new StringBuilder();
            for (var i=0; i < size; i++)
            {
                var binary = random.Next(0,2);
                switch (binary)
                {
                    case 0:
                    var ch = (Convert.ToChar(Convert.ToInt32(Math.Floor(26*random.NextDouble() + 65))));
                        pass.Append(ch);
                        break;
                    case 1:
                        var num = random.Next(1, 10);
                        pass.Append(num);
                        break;
                }
            }
            return pass.ToString();
        }

Ответ 19

Объединение ответа с помощью "Pushcode", а также с использованием семени для случайного генератора. Мне нужно было создать серию псевдо-читаемых "слов".

private int RandomNumber(int min, int max, int seed=0)
{
    Random random = new Random((int)DateTime.Now.Ticks + seed);
    return random.Next(min, max);
}

Ответ 20

Я создал этот метод.

Он отлично работает.

public static string GeneratePassword(int Lenght, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "[email protected]#$%^&*()_-+=[{]};:<>|./?";
        Random rd = new Random();

        if (NonAlphaNumericChars > Lenght || Lenght <= 0 || NonAlphaNumericChars < 0)
            throw new ArgumentOutOfRangeException();

            char[] pass = new char[Lenght];
            int[] pos = new int[Lenght];
            int i = 0, j = 0, temp = 0;
            bool flag = false;

            //Random the position values of the pos array for the string Pass
            while (i < Lenght - 1)
            {
                j = 0;
                flag = false;
                temp = rd.Next(0, Lenght);
                for (j = 0; j < Lenght; j++)
                    if (temp == pos[j])
                    {
                        flag = true;
                        j = Lenght;
                    }

                if (!flag)
                {
                    pos[i] = temp;
                    i++;
                }
            }

            //Random the AlphaNumericChars
            for (i = 0; i < Lenght - NonAlphaNumericChars; i++)
                pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];

            //Random the NonAlphaNumericChars
            for (i = Lenght - NonAlphaNumericChars; i < Lenght; i++)
                pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];

            //Set the sorted array values by the pos array for the rigth posistion
            char[] sorted = new char[Lenght];
            for (i = 0; i < Lenght; i++)
                sorted[i] = pass[pos[i]];

            string Pass = new String(sorted);

            return Pass;
    }

Ответ 21

И вот еще одна идея, основанная на GUID. Я использовал его для теста производительности Visual Studio для генерации случайной строки, содержащей только буквенно-цифровые символы.

public string GenerateRandomString(int stringLength)
{
    Random rnd = new Random();
    Guid guid;
    String randomString = string.Empty;

    int numberOfGuidsRequired = (int)Math.Ceiling((double)stringLength / 32d);
    for (int i = 0; i < numberOfGuidsRequired; i++)
    {
        guid = Guid.NewGuid();
        randomString += guid.ToString().Replace("-", "");
    }

    return randomString.Substring(0, stringLength);
}

Ответ 22

public static class StringHelpers
{
    public static readonly Random rnd = new Random();

    public static readonly string EnglishAlphabet = "abcdefghijklmnopqrstuvwxyz";
    public static readonly string RussianAlphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";

    public static unsafe string GenerateRandomUTF8String(int length, string alphabet)
    {
        if (length <= 0)
            return String.Empty;
        if (string.IsNullOrWhiteSpace(alphabet))
            throw new ArgumentNullException("alphabet");

        byte[] randomBytes = rnd.NextBytes(length);

        string s = new string(alphabet[0], length);

        fixed (char* p = s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                *(p + i) = alphabet[randomBytes[i] % alphabet.Length];
            }
        }
        return s;
    }

    public static unsafe string GenerateRandomUTF8String(int length, params UnicodeCategory[] unicodeCategories)
    {
        if (length <= 0)
            return String.Empty;
        if (unicodeCategories == null)
            throw new ArgumentNullException("unicodeCategories");
        if (unicodeCategories.Length == 0)
            return rnd.NextString(length);

        byte[] randomBytes = rnd.NextBytes(length);

        string s = randomBytes.ConvertToString();
        fixed (char* p = s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                while (!unicodeCategories.Contains(char.GetUnicodeCategory(*(p + i))))
                    *(p + i) += (char)*(p + i);
            }
        }
        return s;
    }
}

Вам также понадобится следующее:

public static class RandomExtensions
{
    public static string NextString(this Random rnd, int length)
    {
        if (length <= 0)
            return String.Empty;

        return rnd.NextBytes(length).ConvertToString();
    }

    public static byte[] NextBytes(this Random rnd, int length)
    {
        if (length <= 0)
            return new byte[0];

        byte[] randomBytes = new byte[length];
        rnd.NextBytes(randomBytes);
        return randomBytes;
    }
}

И это:

public static class ByteArrayExtensions
{
    public static string ConvertToString(this byte[] bytes)
    {
        if (bytes.Length <= 0)
            return string.Empty;

        char[] chars = new char[bytes.Length / sizeof(char)];
        Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}

Ответ 23

На самом деле хорошим решением является статический метод генератора случайных чисел, который является потокобезопасным и не использует блокировки.

Таким образом, несколько пользователей, обращающихся к вашему веб-приложению в одно и то же время, не получают одинаковые случайные строки.

Здесь есть 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(), в то время как ваш метод может оставаться статичным.

Ответ 24

Для генератора случайных строк:

#region CREATE RANDOM STRING WORD
        char[] wrandom = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','W','Y','Z'};
        Random random = new Random();
        string random_string = "";
        int count = 12; //YOU WILL SPECIFY HOW MANY CHARACTER WILL BE GENERATE
        for (int i = 0; i < count; i++ )
        {
            random_string = random_string + wrandom[random.Next(0, 24)].ToString(); 
        }
        MessageBox.Show(random_string);
        #endregion

Ответ 25

Я нашел, что это более полезно, поскольку это расширение, и оно позволяет вам выбрать источник вашего кода.

static string
    numbers = "0123456789",
    letters = "abcdefghijklmnopqrstvwxyz",
    lettersUp = letters.ToUpper(),
    codeAll = numbers + letters + lettersUp;

static Random m_rand = new Random();

public static string GenerateCode(this int size)
{
    return size.GenerateCode(CodeGeneratorType.All);
}

public static string GenerateCode(this int size, CodeGeneratorType type)
{
    string source;

    if (type == CodeGeneratorType.All)
    {
        source = codeAll;
    }
    else
    {
        StringBuilder sourceBuilder = new StringBuilder();
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Numbers)
            sourceBuilder.Append(numbers);
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Letters)
            sourceBuilder.Append(letters);
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.LettersUpperCase)
            sourceBuilder.Append(lettersUp);

        source = sourceBuilder.ToString();
    }

    return size.GenerateCode(source);
}

public static string GenerateCode(this int size, string source)
{
    StringBuilder code = new StringBuilder();
    int maxIndex = source.Length-1;
    for (int i = 0; i < size; i++)
    {

        code.Append(source[Convert.ToInt32(Math.Round(m_rand.NextDouble() * maxIndex))]);
    }

    return code.ToString();
}

public enum CodeGeneratorType { Numbers = 1, Letters = 2, LettersUpperCase = 4, All = 16 };

Надеюсь, что это поможет.

Ответ 26

В моей ситуации пароль должен содержать:

  • Как минимум один нижний регистр.
  • Как минимум один верхний регистр.
  • Как минимум одно десятичное число.
  • Как минимум один специальный символ.

Вот мой код:

    private string CreatePassword(int len)
    {
        string[] valid = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "1234567890", "[email protected]#$%^&*()_+" };
        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;
    }

Ответ 27

Здравствуйте,
вы можете использовать WordGenerator или LoremIpsumGenerator из пакета MMLib.RapidPrototyping nuget.

using MMLib.RapidPrototyping.Generators;
public void WordGeneratorExample()
{
   WordGenerator generator = new WordGenerator();
   var randomWord = generator.Next();

   Console.WriteLine(randomWord);
} 

Сайт Nuget
Проект проекта Codeplex

Ответ 28

Если у вас есть доступ к совместимому с Intel Secure Key процессору, вы можете генерировать реальные случайные числа и строки, используя эти библиотеки: https://github.com/JebteK/RdRand и https://www.rdrand.com/

Просто скачайте последнюю версию здесь, включите Jebtek.RdRand и добавьте для нее инструкцию using. Затем все, что вам нужно сделать, это следующее:

bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters

Кроме того, вы также получаете следующие дополнительные возможности:

string apiKey = RdRandom.GenerateAPIKey(); //Generate 64 random characters, useful for API keys
byte[] b = RdRandom.GenerateBytes(10); //Generate an array of 10 random bytes
uint i = RdRandom.GenerateUnsignedInt() //Generate a random unsigned int

Если у вас нет совместимого процессора для выполнения кода, просто используйте службы RESTful на странице rdrand.com. С библиотекой обертки RdRandom, включенной в ваш проект, вам просто нужно это сделать (вы получаете 1000 бесплатных звонков при регистрации):

string ret = Randomizer.GenerateKey(<length>, "<key>");

Вы также можете генерировать массивы случайных байтов и целые числа без знака следующим образом:

uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");

Ответ 29

И еще одна версия: я использую этот метод для генерации случайных символов псевдо-акций при тестировании:

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)];

Ответ 30

Другой образец (протестирован в 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);

Реализовано мной.