it-swarm.com.ru

Генератор случайных строк, возвращающий ту же строку

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

Вот код и пример его вывода:

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

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

222
PushCode

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

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

304
RCIX

Вы создаете экземпляр объекта 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);
}
186
LukeH

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

using System.IO;   
public static string RandomStr()

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

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

134
Ranvir

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

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

Membership.GeneratePassword(4, 0)
49
Spongeboy

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

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

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

20
Abdul Munim

Это решение является расширением для 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);
    }
}
12
oleksii

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

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

Для генерации пароля следует использовать 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();
}
12
Maksym Davydov

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

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

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

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

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

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

4
John T

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

3
Kenan E. K.

Я добавил опцию, чтобы выбрать длину, используя решение 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);
        }
    }
2
João Miguel

Мой метод 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);
}
2
AechoLiu

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

Guid.NewGuid().ToString() 
2
wener

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

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

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

2
quantum
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);
    }
}
1
Konard

А вот еще одна идея, основанная на 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);
}
1
Maciej Zaleski

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

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

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

1
Stefan Steiger

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

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

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

Это прекрасно работает.

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;
    }
1
Hugo

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

#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
1
Toprak

Объединение ответа с помощью "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);
}
1
Ideogram

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

1
Nick Olsen

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

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

Вот мой код:

    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;
    }
0
Jules

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

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

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>");
0
JebaDaHut

Привет
вы можете использовать WordGenerator или LoremIpsumGenerator из пакета nuget MMLib.RapidPrototyping.

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

   Console.WriteLine(randomWord);
} 

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

0
Mino

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

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

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

0
WhyMe

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

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

0
Amin Ghaderi

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

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

Это мое решение:

private string RandomString(int length)
{
    char[] symbols = { 
                            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'                             
                        };

    Stack<byte> bytes = new Stack<byte>();
    string output = string.Empty;

    for (int i = 0; i < length; i++)
    {
        if (bytes.Count == 0)
        {
            bytes = new Stack<byte>(Guid.NewGuid().ToByteArray());
        }
        byte pop = bytes.Pop();
        output += symbols[(int)pop % symbols.Length];
    }
    return output;
}

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

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

// create full Rand string
string docNum = Rand1 + "-" + Rand2;
0
ADM-IT