c# - visual - vb net random




Générateur de chaîne aléatoire renvoyant la même chaîne (20)

Cette question a déjà une réponse ici:

J'ai développé un générateur de chaînes aléatoires mais ça ne se comporte pas comme j'espère. Mon but est d'être capable de courir deux fois et de générer deux chaînes aléatoires distinctes de quatre caractères. Cependant, il génère juste une chaîne aléatoire de quatre caractères deux fois.

Voici le code et un exemple de sa sortie:

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;

... et la sortie ressemble à ceci: UNTE-UNTE ... mais il devrait ressembler à ceci UNTE-FWNU

Comment puis-je m'assurer deux chaînes distinctement aléatoires?


// Une implémentation très simple

using System.IO;   
public static string RandomStr()

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

// Maintenant appelez simplement RandomStr () Méthode


Bonjour
Vous pouvez utiliser WordGenerator ou LoremIpsumGenerator à partir du package nuget MMLib.RapidPrototyping.

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

   Console.WriteLine(randomWord);
} 

Site de Nuget
Site du projet Codeplex


C'est parce que chaque nouvelle instance de Random génère les mêmes numéros d'être appelé si vite. Ne continuez pas à créer une nouvelle instance, appelez next () et déclarez votre classe aléatoire en dehors de votre méthode.


Cette solution est une extension pour une classe Random .

Usage

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}_-"
    }
}

la mise en oeuvre

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

Dans ma situation, le mot de passe doit contenir:

  • Au moins un minuscule.
  • Au moins un majuscule.
  • Au moins une décimale
  • Au moins un caractère spécial.

Voici mon code:

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

En fait, une bonne solution est d'avoir une méthode statique pour le générateur de nombres aléatoires qui est thread-safe et n'utilise pas de verrous.

Ainsi, plusieurs utilisateurs accédant à votre application Web en même temps n'obtiennent pas les mêmes chaînes aléatoires.

Il y a 3 exemples ici: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

J'utiliserais le dernier:

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

Ensuite, vous pouvez éliminer correctement

Random random = new Random();

Et appelez simplement RandomGen3.Next (), alors que votre méthode peut rester statique.


Et voici une autre idée basée sur les GUID. Je l'ai utilisé pour le test de performance Visual Studio pour générer une chaîne aléatoire contenant uniquement des caractères alphanumériques.

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

J'ai ajouté l'option de choisir la longueur en utilisant la solution 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);
        }
    }

J'ai trouvé cela plus utile, car c'est une extension, et cela vous permet de sélectionner la source de votre code.

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

J'espère que cela t'aides.


Je pense que c'est peut-être aussi acceptable et simple.

Guid.NewGuid().ToString() 

La meilleure solution consiste à utiliser le générateur de nombres aléatoires avec la conversion en base64

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

Ma méthode RandomString() pour générer une chaîne aléatoire.

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

Si vous avez accès à un processeur compatible Intel Secure Key, vous pouvez générer des nombres aléatoires et des chaînes à l'aide de ces bibliothèques: https://github.com/JebteK/RdRand et https://www.rdrand.com/

Il suffit de télécharger la dernière version à partir d' here , d'inclure Jebtek.RdRand et d'ajouter une instruction using pour cela. Ensuite, tout ce que vous devez faire est ceci:

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

De plus, vous bénéficiez également de ces fonctionnalités supplémentaires:

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

Si vous n'avez pas de CPU compatible pour exécuter le code, utilisez simplement les services RESTful sur rdrand.com. Avec la bibliothèque de wrappers RdRandom incluse dans votre projet, il vous suffit de le faire (vous recevez 1000 appels gratuits lors de votre inscription):

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

Vous pouvez également générer des tableaux d'octets aléatoires et des entiers non signés comme suit:

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

Si vous vouliez générer une chaîne de nombres et de caractères pour un mot de passe fort.

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

Un LINQ one-liner pour une bonne mesure (en supposant un private static Random Random ) ...

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

Voici ma modification de la réponse actuellement acceptée, que je crois que c'est un peu plus rapide et plus court:

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

Notez que je n'ai pas utilisé toute la multiplication, Math.floor() , Convert etc

EDIT: random.Next(0x41, 0x5A) peut être modifié pour n'importe quelle plage de caractères Unicode.


Vous créez l'instance aléatoire dans la méthode, ce qui la fait retourner les mêmes valeurs lorsqu'elle est appelée en succession rapide. Je ferais quelque chose comme ça:

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;

(version modifiée de votre code)


Vous devriez avoir un objet Random de niveau classe initié une fois dans le constructeur et réutilisé à chaque appel (cela continue la même séquence de nombres pseudo-aléatoires). Le constructeur sans paramètre lance déjà le générateur avec Environment.TickCount en interne.


Voici un article de blog qui fournit une classe un peu plus robuste pour générer des mots, des phrases et des paragraphes aléatoires.


Un autre échantillon (testé dans 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);

Mis en œuvre par moi-même.





random