2009-06-10 6 views
4

J'ai trouvé ce snippet de code qui génère une chaîne de caractères aléatoires.Est-ce un bon moyen de générer une chaîne de caractères aléatoires?

Mais y a-t-il une manière plus élégante/plus rapide/plus fiable de faire ceci? Cela semble reposer sur le fait que les chiffres 26 à 91 sont des caractères valides étant donné l'encodage actuel.

/// <summary> 
/// Generates a random string with the given length 
/// </summary> 
/// <param name="size">Size of the string</param> 
/// <param name="lowerCase">If true, generate lowercase string</param> 
/// <returns>Random string</returns> 
private string RandomString(int size, bool lowerCase) 
{ 
    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); 
    } 

    if(lowerCase) 
     return builder.ToString().ToLower(); 

    return builder.ToString(); 
} 
+1

Il ne repose pas sur l'encodage en cours - Convert.ToChar * toujours * utilise Unicode, quelle que soit la encodage par défaut du système. C'est moche de bien d'autres façons cependant :) –

Répondre

21

Je préfère passer l'instance Random dans la méthode - alors vous pouvez réutiliser la même instance à plusieurs reprises, ce qui est important si vous devez générer beaucoup de chaînes aléatoires en succession rapide. Cependant, je voudrais aussi un peu quand même le modifie:

public const string LowerCaseAlphabet = "abcdefghijklmnopqrstuvwyxz"; 
public const string UpperCaseAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

public static string GenerateUpperCaseString(int size, Random rng) 
{ 
    return GenerateString(size, rng, UpperCaseAlphabet); 
} 

public static string GenerateLowerCaseString(int size, Random rng) 
{ 
    return GenerateString(size, rng, LowerCaseAlphabet); 
} 

public static string GenerateString(int size, Random rng, string alphabet) 
{ 
    char[] chars = new char[size]; 
    for (int i=0; i < size; i++) 
    { 
     chars[i] = alphabet[rng.Next(alphabet.Length)]; 
    } 
    return new string(chars); 
} 
  • Il n'y a pas besoin d'utiliser un StringBuilder lorsque vous connaissez la longueur finale
  • L'utilisation Random.NextDouble() indique un manque de connaissance de la classe aléatoire. (En particulier Random.Next(int, int)
  • Création d'un nouveau aléatoire sur chaque appel est susceptible d'entraîner des chaînes en double
  • Appel Convert.ToInt32 et Convert.ToChar semble laid contre seulement coulée
  • Basse-boîtier après semble inutile par rapport avec la cueillette des lettres minuscules pour commencer
  • Fournir un alphabet à choisir est beaucoup plus flexible (avec des méthodes d'assistance pour les cas communs)
+0

Ouais, je pense que c'est beaucoup mieux. Créez simplement une chaîne complète de caractères acceptables, puis choisissez au hasard des caractères de cette chaîne, en créant les vôtres. Je pense que l'exemple ci-dessus pourrait être simplifié, en n'exigeant pas que les paramètres rng et alphabet soient transmis à la méthode, mais cela vous donne l'idée. – Jeremy

+0

@Jeremy: Passer dans le RNG est * très * important sauf si vous voulez une méthode susceptible de créer des chaînes dupliquées. Vous * pouvez * conserver une instance aléatoire statique, mais vous devrez également vous soucier du verrouillage. –

+2

Excellente réponse comme toujours Jon. Couple d'autres choses à considérer. (1) Comment aléatoire est assez aléatoire? Étant donné une chaîne de longueur suffisante à partir de votre version, il y a assez de données pour en déduire ce que sera chaque sortie future, à condition que l'attaquant connaisse la taille, l'alphabet et si le même Random est réutilisé. Ce niveau de hasard ne convient pas aux utilisations de crypto, à la génération de mots de passe, etc. (2) Ces chaînes aléatoires vont-elles être affichées à l'utilisateur? Je peux penser à un certain nombre de sorties aléatoires que les utilisateurs pourraient trouver offensantes ou rebutantes. Peut-être vouloir filtrer pour les mots grossiers. –

1

Si je devais le faire (et j'ai, b ut dans Java, squirreled quelque part), je fournirais un tableau de caractères permis, et utiliser un RNG simplement pour choisir l'index du caractère. Cela vous permet également de ne pas autoriser les caractères que vous ne voulez pas générer (si vous créez une clé de licence à saisie humaine, vous ne voulez pas générer de caractères qui peuvent être confondus entre eux; 0 et O, par exemple, ou 1 et l).

EDIT: ouais, comme ce que Jon a fait ...

+0

+1 pour l'effort :) –

1

Path.GetRandomFileName()

string randomName = Path.GetRandomFileName(); 
randomName = randomName.Replace(".", string.Empty); 

// take substring... 
Questions connexes