0

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?

1
  • 1
    Where does your Append() function come from? Is it an extension method you defined? Otherwise, this code should not compile. Use a StringBuilder instead of a char array. It has all the functions you are looking for. Commented Sep 22, 2019 at 1:36

3 Answers 3

2

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();
Sign up to request clarification or add additional context in comments.

1 Comment

There is more problems then this
1

To add to the other answers, you also have an issue with your ifs, 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

Or another way

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

Or another way

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

1 Comment

True, All this info and examples are very help full.
0

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/

5 Comments

So your solution is to tell the OP to throw away his code and use some other code that has different functionality?
I disagree. The above code does the exact same thing as what he is doing but reduces the complexity. Did you read his code and then compare it to what this function does?
Yes, of course I read the code. And I found that the code produces different results - the probability distribution of the individual characters is very different. In OP's code, approximately 33% of the final password are letters. In yours, it is about 71%.
Well Wile this was not quite what I was looking for, it did help. As I said I am new to C# and the way I did it in python was more simple than what I did here, as I am still learning everything. I did not know I could just print a char array.
You are right @NicoSchertler. I didn't see statistics in the tag but saw something similar to a random password generator in c#.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.