Reputation: 241
I am trying to learn C#. I already know Python. I wanted to replicate a simple password generator program I wrote in Python with C#. My problem is I don't know how to join the characters together into one string so I can display it. When I try to display it I just get blank spaces where the characters from the password should be.
In Python I can do this
password = []#will have random items appended by generator code
s = ''.join(password)#makes one string
print(s)#prints
namespace learning
{
public static class PasswordGenerator
{
private static string Letters = "abcdefghijklmnopqrstuvwxyz";
private static string Numbers = "1234567890";
private static string Symbols = "!@#$%^&*()";
public static string Generate()
{
string[] letters = new string[10];
string[] choice = { "letter", "number", "symbol" };
string[] UL = { "uper", "lower" };
string get;
char c;
for (int i = 0; i <= 9; i++)
{
get = Rand.RandString(choice);
if (get == "letter")
{
c = Rand.RandChar(Letters);
get = Rand.RandString(UL);
if (get == "uper")
{
c = char.ToUpper(c);
letters.Append(c.ToString());
}
else
{
letters.Append(c.ToString());
}
}
if (get == "number")
{
c = Rand.RandChar(Numbers);
letters.Append(c.ToString());
}
if (get == "symbol")
{
c = Rand.RandChar(Symbols);
letters.Append(c.ToString());
}
}
return String.Join(",", letters);
}
}
public class Rand
{
private static Random Generator = new Random();
public static Char RandChar(string items) //Choose a random char from string
{
int myIndex = Generator.Next(items.Length);
char l = items[myIndex];
return l;
}
public static string RandString(string[] items)//Choose a random string from a list
{
int myIndex = Generator.Next(items.Length);
string s = items[myIndex];
return s;
}
}
}
When I run the code I call Console.WriteLine(PasswordGenerator.Generate())
but It will not print my password. It will only print some commas and have blank spaces where the characters from the password should be. I need it to display my password. What am I doing wrong? How can I get it to display my password?
Upvotes: 0
Views: 84
Reputation: 81513
To add to the other answers, you also have an issue with your if
s, they should be if then else
or a switch
if you want to keep your length correct
Small refactor
Uses an iterator method and a switch
public static IEnumerable<char> Generate(int size, string[] choice, string[] ul)
{
for (var i = 0; i < size; i++)
{
switch (Rand.RandString(choice))
{
case "letter":
if (Rand.RandString(ul) == "uper")
yield return char.ToUpper(Rand.RandChar(Letters));
else
yield return Rand.RandChar(Letters);
break;
case "number":
yield return Rand.RandChar(Numbers);
break;
case "symbol":
yield return Rand.RandChar(Symbols);
break;
}
}
}
Usage
string[] choice = { "letter", "number", "symbol" };
string[] UL = { "uper", "lower" };
Console.WriteLine(string.Concat(Generate(10, choice, UL)));
Demo here
https://dotnetfiddle.net/qSHimm
public class Rand
{
private static Random Generator = new Random();
public static T Get<T>(T[] items) //Choose a random char from string
=> items[Generator.Next(items.Length)];
}
private static string Letters = "abcdefghijklmnopqrstuvwxyz";
private static string Numbers = "1234567890";
private static string Symbols = "!@#$%^&*()";
public enum Options
{
Upper,Lower, Numbers, Symbols
}
public static IEnumerable<char> Generate(int size, params Options[] options)
{
for (var i = 0; i < size; i++)
{
switch (Rand.Get(options))
{
case Options.Upper: yield return char.ToUpper(Rand.Get(Letters.ToCharArray())); break;
case Options.Lower: yield return Rand.Get(Letters.ToCharArray()); break;
case Options.Numbers: yield return Rand.Get(Numbers.ToCharArray()); break;
case Options.Symbols: yield return Rand.Get(Symbols.ToCharArray());break;
}
}
}
Usage
Console.WriteLine(string.Concat(Generate(10, Options.Upper,Options.Numbers)));
Output
R0P76UYO1D
public static string Generate(int size, params Options[] options)
=> string.Concat(Enumerable.Repeat(0,size).Select(x => GetChar(options)));
private static char GetChar(params Options[] options)
{
switch (Rand.Get(options))
{
case Options.Upper: return char.ToUpper(Rand.Get(Letters.ToCharArray())); ;
case Options.Lower: return Rand.Get(Letters.ToCharArray());
case Options.Numbers: return Rand.Get(Numbers.ToCharArray());
case Options.Symbols: return Rand.Get(Symbols.ToCharArray());
default: throw new ArgumentOutOfRangeException();
}
}
Usage
Console.WriteLine(Generate(10, Options.Upper,Options.Numbers));
Upvotes: 1
Reputation: 18155
When you are attempting letters.Append
, you are attempting to append an array, which is not possible since it is fixed length.You could use List<String>
, but in this particular case, you could instead make use of a specialized .Net class, called StringBuilder.
Since string is immutable, in situations where you need to perform repeated modifications to a string, such as appending values to it, the overhead associated with creating a new String object can be costly. This is where StringBuilder comes into rescue.
var letters = new StringBuilder();
Now, you can append the characters without the ToString() conversion.
letters.Append(c)
Finally, to return the string from StringBuilder, you can use the ToString method.
return letters.ToString();
Upvotes: 2
Reputation: 142
This looks overly complicated for generating a random password. You could use the code below using an optional parameter (if they pass nothing to the function it generates it with a length of 15).
private static string CreateRandomPassword(int length = 15)
{
string validChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*?_-";
Random random = new Random();
// Select one random character at a time from the string
// and create an array of chars
char[] chars = new char[length];
for (int i = 0; i < length; i++)
{
chars[i] = validChars[random.Next(0, validChars.Length)];
}
return new string(chars);
}
Found this quick solution just googling this url: https://www.c-sharpcorner.com/article/how-to-generate-a-random-password-in-c-sharp-and-net-core/
Upvotes: 0