228 votes

Générateur de chaîne aléatoire retournant la même chaîne

J'ai développé un générateur de chaînes aléatoires mais il ne se comporte pas tout à fait comme je l'espérais. Mon objectif est de pouvoir exécuter ceci deux fois et 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();
}

// obtenir la 1ère chaîne aléatoire 
string Rand1 = RandomString(4);

// obtenir la 2ème chaîne aléatoire 
string Rand2 = RandomString(4);

// créer la chaîne aléatoire complète
string docNum = Rand1 + "-" + Rand2;

...et la sortie ressemble à ceci : UNTE-UNTE ...mais elle devrait ressembler à quelque chose comme ceci UNTE-FWNU

Comment puis-je m'assurer que deux chaînes aléatoires distinctes soient générées ?

0 votes

3 votes

Notez que même deux chaînes parfaitement aléatoires ne sont pas garanties d'être uniques. Avec de longues chaînes (120+ bits), il est extrêmement probable qu'elles soient uniques, mais avec des chaînes courtes comme celle-ci, les collisions sont courantes.

0 votes

Ancien fil de discussion mais ... si cela convient, vous pouvez générer un GUID et le convertir en texte.

311voto

RCIX Points 12049

Vous créez l'instance Random dans la méthode, ce qui fait qu'elle renvoie les mêmes valeurs lorsqu'elle est appelée rapidement. Je ferais quelque chose comme ceci :

private static Random random = new Random((int)DateTime.Now.Ticks);//mercipour 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();
    }

// obtenir le 1er string aléatoire 
string Rand1 = RandomString(4);

// obtenir le 2ème string aléatoire 
string Rand2 = RandomString(4);

// créer le numéro de document aléatoire complet
string docNum = Rand1 + "-" + Rand2;

(version modifiée de votre code)

47 votes

Notez que les membres d'instance de la classe Random ne sont PAS documentés comme étant thread-safe, donc si cette méthode est appelée à partir de plusieurs threads en même temps (fortement probable si vous créez une application web, par exemple) alors le comportement de ce code sera indéfini. Vous devez soit utiliser un verrou sur le random, soit le rendre par thread.

0 votes

Oui, le random n'est pas thread-safe et cause de nombreux problèmes sur les sites web asp.net

19 votes

Aussi, vous pouvez obtenir une lettre majuscule aléatoire en utilisant ch = (char)random.Next('A','Z'); beaucoup plus simple que la ligne illisible ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); du post original. Ensuite, si vous voulez le transformer en minuscule, vous pouvez facilement passer à (char)random.Next('a','z');

189voto

LukeH Points 110965

Vous instanciez l'objet Random à l'intérieur de votre méthode.

L'objet Random est initialisé à partir de l'horloge système, ce qui signifie que si vous appelez votre méthode plusieurs fois rapidement, il utilisera toujours la même graine, ce qui signifie qu'il générera la même séquence de nombres aléatoires, ce qui signifie que vous obtiendrez la même chaîne.

Pour résoudre le problème, déplacez votre instance de Random en dehors de la méthode elle-même (et tant que vous y êtes, vous pourriez vous débarrasser de cette séquence folle d'appels à Convert, Floor et 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);
}

7 votes

Ou le rendre statique et interne à la classe.

9 votes

Aussi, j'aime faire de ce genre de méthode une méthode d'extension sur Random.

8 votes

Notez que les membres d'instance de la classe Random NE sont PAS documentés comme étant thread-safe, donc si cette méthode est appelée à partir de plusieurs threads en même temps (très probable si vous créez une application web, par exemple), alors le comportement de ce code sera indéfini. Vous devez soit utiliser un verrou sur le random, soit le rendre par thread.

136voto

Ranvir Points 1301

Une implémentation très simple qui utilise Path.GetRandomFileName():

using System.IO;   
public static string RandomStr()
{
    string rStr = Path.GetRandomFileName();
    rStr = rStr.Replace(".", ""); // Pour supprimer le .
    return rStr;
}

Maintenant il suffit d'appeler RandomStr().

0 votes

J'aime cette méthode mieux que les autres répertoriées. Bonne trouvaille.

7 votes

Super ! J'adore quand vous trouvez une petite pépite comme GetRandomFileName cachée dans le cadre .Net

0 votes

+1 - Utilisé aujourd'hui - j'adore ça!

49voto

Spongeboy Points 1426

Tant que vous utilisez Asp.Net 2.0 ou une version ultérieure, vous pouvez également utiliser l'appel à la bibliothèque - System.Web.Security.Membership.GeneratePassword, cependant cela inclura des caractères spéciaux.

Pour obtenir 4 caractères aléatoires avec un minimum de 0 caractères spéciaux-

Membership.GeneratePassword(4, 0)

9 votes

Notez que dans la version 4.0, le deuxième paramètre entier représente le nombre minimal de caractères non alphabétiques à utiliser. Ainsi, Membership.GeneratePassword(10, 0); ne fonctionnera pas tout à fait comme vous le pensez, cela ajoute toujours beaucoup de caractères non alphanumériques, par exemple : z9sge)?pmV

0 votes

La seule raison à laquelle je peux penser pour ne pas vouloir utiliser cela par rapport à d'autres méthodes est l'ennui que vous devez traverser pour supprimer les caractères spéciaux....... en supposant que vous en avez besoin ce que je ne fais pas

0 votes

Merci keithl8041, réponse mise à jour pour refléter cela.

22voto

Abdul Munim Points 9039

Juste pour les personnes qui passent et qui veulent avoir une chaîne aléatoire en une seule ligne de code

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

PS: Veuillez garder à l'esprit que yourRandomStringLength ne peut pas dépasser 32 car Guid a une longueur maximale de 32.

9 votes

Je ne suis pas sûr que ce sera nécessairement aléatoire. Les GUID sont conçus pour être uniques, pas aléatoires, donc il est possible que les premiers caractères N dans la chaîne soient identiques (selon le générateur de GUID).

1 votes

Je avais juste besoin d'un mot de passe temporaire de 5 caractères à hacher. C'est merveilleux merci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X