C# good practice to use checkboxes and generate password like this? - c#

Is it good practice to use my code like this?
My code, basically generates a password with the length of 10(currently), and generates a password according to which checkboxes are checked:
Checkboxes:
- Special characters
- Numbers
- Capital letters
bool c_special = false;
bool c_numbers = false;
bool c_capitals = false;
private void btn_generate_Click(object sender, RoutedEventArgs e)
{
checkCheckboxes();
if(c_special && c_numbers && c_capitals)
{
txt_password.Text = generateWithCharactersAndNumbersAndCapitals(10);
}
else if(c_special && c_numbers && !c_capitals)
{
txt_password.Text = generateWithCharactersAndNumbers(10);
}
else if(c_special && !c_numbers && c_capitals)
{
txt_password.Text = generateWithCharactersAndCapitals(10);
}
else if(c_special && !c_numbers && !c_capitals)
{
txt_password.Text = generateWithCharacters(10);
}
else if(!c_special && c_numbers && !c_capitals)
{
txt_password.Text = generateWithNumbers(10);
}
else if(!c_special && c_numbers && c_capitals)
{
txt_password.Text = generateWithNumbersAndCapitals(10);
}
else if(!c_special && !c_numbers && c_capitals)
{
txt_password.Text = generateWithCapitals(10);
}
else if(!c_special && !c_numbers && !c_capitals)
{
txt_password.Text = generateNormalPassword(10);
}
}
/*
* Checks which checkboxes are checked
*/
private void checkCheckboxes()
{
if (cbox_special.IsChecked == true)
{
c_special = true;
}
else
{
c_special = false;
}
if (cbox_numbers.IsChecked == true)
{
c_numbers = true;
}
else
{
c_numbers = false;
}
if (cbox_capitals.IsChecked == true)
{
c_capitals = true;
}
else
{
c_capitals = false;
}
}
//Normal
public string generateNormalPassword(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
//Characters
public string generateWithCharacters(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz!##$%^&*";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
public string generateWithCharactersAndNumbers(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz0123456789!##$%^&*";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
public string generateWithCharactersAndCapitals(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
public string generateWithCharactersAndNumbersAndCapitals(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
//Numbers
public string generateWithNumbers(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
public string generateWithNumbersAndCapitals(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
//Capitals
public string generateWithCapitals(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
private void btn_cancel_Click(object sender, RoutedEventArgs e)
{
MainWindow mw = new MainWindow();
mw.Show();
this.Hide();
}
}
}
I'm trying to learn better practice than this, I'd love to know your opinion how I have done this and where & how to improve.

Your code now has quite a lot of repetition. Mainly, this part is shared across all the generate... methods:
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
Only the string valid is different.
One way to reduce this repetition is to have one generate method that takes flag arguments:
// rnd should be at class level so you don’t create a new one every time
Random rnd = new Random();
public string generateWith(int length, bool capitals, bool numbers, bool symbols) {
string valid = "abcdefghijklmnopqrstuvwxyz";
if (capitals) { // add the capitals to 'valid' }
if (numbers) { // add the numbers to 'valid' }
if (symbols) { // add the symbols to 'valid' }
StringBuilder res = new StringBuilder();
while (0 < length--)
{
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
And then you just have to pass the variables c_special, c_numbers and c_capitals into this method:
generateWith(10, capitals: c_capitals, numbers: c_numbers, symbols: c_special);

Related

Make a password generator

I am currently trying to make a random password generator.
My code works fine if I only pick one type of symbols.
What's the best way to make my code to word for more than one type?
Also what parameters would you add to make the password more secured?
I am thinking of adding an if loop to check if there are more than two same letters, symbols or numbers in a row.
That's how my interface looks like:
and that is my code:
public partial class Form1 : Form
{
// Max number of identical characters in a row
const int Maximum_Identical = 2;
// lower case chars
const string lower_chars = "abcdefghijklmnopqrstuvwxyz";
// capital chars
const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// numbers
const string numbers = "0123456789";
// symbols
const string symbols = #"!#$%&*#\";
// password lenght
int lenght;
private void button1_Click(object sender, EventArgs e)
{
//use stringbuilder so I can add more chars later
StringBuilder password = new StringBuilder();
//take max lenght from numericUpDown
lenght = Convert.ToInt32(numericUpDown1.Value);
// random instance so I can use Next and don't get loops
Random rdm = new Random();
if (small_letters__Box.Checked)
{
//add a random small character to pass untill it reaches the selected lenght
while (lenght-- > 0 )
{
password.Append(lower_chars[rdm.Next(lower_chars.Length)]);
}
}
if (capital_letters__Box.Checked)
{
//add a random capital character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(capital_chars[rdm.Next(capital_chars.Length)]);
}
}
if (numbers_Box.Checked)
{
//add a random character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(numbers[rdm.Next(numbers.Length)]);
}
}
if (symbols_Box.Checked)
{
//add a random character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(symbols[rdm.Next(symbols.Length)]);
}
}
textBox1.Text = password.ToString();
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
}
}
Your password generation has 2 steps.
Determine the character set
Create a password randomly from the character set of length n
Function 1 creates the character set:
// Make sure you have using System.Linq;
private List<char> GetCharacterSet()
{
IEnumerable<char> returnSet = new char[]{};
if (small_letters__Box.Checked)
{
returnSet = returnSet.Append(lower_chars);
}
if (capital_letters__Box.Checked)
{
returnSet = returnSet.Append(capital_chars);
}
if (numbers_Box.Checked)
{
returnSet = returnSet.Append(numbers);
}
if (symbols_Box.Checked)
{
returnSet = returnSet.Append(symbols);
}
return returnSet.ToList();
}
Function 2 creates a password of given length from your character set
private string GetPassword(int length, List<char> characterSet)
{
if(characterSet.Count < 1)
{
throw new ArgumentException("characterSet contains no items!");
}
if(length < 1)
{
return "";
}
Random rdm = new Random();
StringBuilder password = new StringBuilder();
for(int i = 0; i < length; i++){
int charIndex = rdm.Next(0, characterSet.Count)
password.Append(characterSet[charIndex]);
}
return password.ToString();
}
Then simply rig your button click event handler to call these functions and display the resulting password.
below code is my already written code which I wrote more than a couple of years ago and I still use it in my many of my projects where needed, it covers all you are in need of
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;
public static class ArrayExtentions
{
public static object[] Shuffle(this object[] array)
{
var alreadySwaped = new HashSet<Tuple<int, int>>();
var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(array.Length / 4), Convert.ToInt32((array.Length / 2) + 1));
for (var i = 0; i <= rndLoopCount; i++)
{
int rndIndex1 = 0, rndIndex2 = 0;
do
{
rndIndex1 = RandomUtils.GetRandom(0, array.Length);
rndIndex2 = RandomUtils.GetRandom(0, array.Length);
} while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));
alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
var swappingItem = array[rndIndex1];
array[rndIndex1] = array[rndIndex2];
array[rndIndex2] = swappingItem;
}
return array;
}
}
public class RandomUtils
{
private static readonly ThreadLocal<Random> RndLocal = new ThreadLocal<Random>(() => new Random(GetUniqueSeed()));
private static int GetUniqueSeed()
{
long next, current;
var guid = Guid.NewGuid().ToByteArray();
var seed = BitConverter.ToInt64(guid, 0);
do
{
current = Interlocked.Read(ref seed);
next = current * BitConverter.ToInt64(guid, 3);
} while (Interlocked.CompareExchange(ref seed, next, current) != current);
return (int)next ^ Environment.TickCount;
}
public static int GetRandom(int min, int max)
{
Contract.Assert(max >= min);
return RndLocal.Value.Next(min, max);
}
public static int GetRandom(int max)
{
return RndLocal.Value.Next(max);
}
public static double GetRandom()
{
return RndLocal.Value.NextDouble();
}
}
public class StringUtility
{
private const string UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
private const string LowerAlpha = "abcdefghijklmnopqrstuwxyz";
private const string Numbers = "0123456789";
private const string SpecialChars = "~!##$%^&*()_-+=.?";
private static string CreateSourceString(bool includeLowerCase, bool includeUpperCase, bool includenumbers, bool includeSpChars)
{
Contract.Assert(includeLowerCase || includeUpperCase || includenumbers || includeSpChars);
var sb = new StringBuilder();
if (includeLowerCase) sb.Append(LowerAlpha);
if (includeUpperCase) sb.Append(UpperAlpha);
if (includenumbers) sb.Append(Numbers);
if (includeSpChars) sb.Append(SpecialChars);
return sb.ToString();
}
private static string GenerateString(string sourceString, int length = 6)
{
var rndString = Shuffle(sourceString);
var builder = new StringBuilder();
for (var i = 0; i < length; i++)
builder.Append(rndString[RandomUtils.GetRandom(0, rndString.Length)]);
return builder.ToString();
}
public static string GenerateRandomString(int length = 6,
bool includenumbers = false,
bool includeSpChars = false)
{
var sourceStr = CreateSourceString(true, true, includenumbers, includeSpChars);
return GenerateString(sourceStr, length);
}
public static string GenerateRandomString(int minLength,
int maxLength,
bool includenumbers = false,
bool includeSpChars = false)
{
if (maxLength < minLength) maxLength = minLength;
var len = RandomUtils.GetRandom(minLength, maxLength + 1);
return GenerateRandomString(len, includenumbers, includeSpChars);
}
public static string Shuffle(string str)
{
var alreadySwaped = new HashSet<Tuple<int, int>>();
var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(str.Length / 4), Convert.ToInt32((str.Length / 2) + 1));
var strArray = str.ToArray();
for (var i = 0; i <= rndLoopCount; i++)
{
int rndIndex1 = 0, rndIndex2 = 0;
do
{
rndIndex1 = RandomUtils.GetRandom(0, str.Length);
rndIndex2 = RandomUtils.GetRandom(0, str.Length);
} while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));
alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
var swappingChar = strArray[rndIndex1];
strArray[rndIndex1] = strArray[rndIndex2];
strArray[rndIndex2] = swappingChar;
}
return new string(strArray);
}
public static string GeneratePassword(PasswordComplexity complexityLevel)
{
switch (complexityLevel)
{
case PasswordComplexity.Simple: return GenerateSimplePassword();
case PasswordComplexity.Medium: return GenerateMediumPassword();
case PasswordComplexity.Strong: return GenerateStrongPassword();
case PasswordComplexity.Stronger: return GenerateStrongerPassword();
}
return null;
}
private static string GenerateSimplePassword()
{
return GenerateRandomString(6, 9);
}
private static string GenerateMediumPassword()
{
var passLen = RandomUtils.GetRandom(6, 10);
var numCount = RandomUtils.GetRandom(1, 3);
var alphaStr = GenerateRandomString(passLen - numCount);
var numStr = GenerateString(Numbers, numCount);
var pass = alphaStr + numStr;
return Shuffle(pass);
}
private static string GenerateStrongPassword()
{
var lowerCharCount = RandomUtils.GetRandom(2, 5);
var upperCharCount = RandomUtils.GetRandom(2, 5);
var numCount = RandomUtils.GetRandom(2, 4);
var spCharCount = RandomUtils.GetRandom(2, 4);
var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
var spCharStr = GenerateString(SpecialChars, spCharCount);
var numStr = GenerateString(Numbers, numCount);
var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
return Shuffle(pass);
}
private static string GenerateStrongerPassword()
{
var lowerCharCount = RandomUtils.GetRandom(5, 12);
var upperCharCount = RandomUtils.GetRandom(4, 8);
var numCount = RandomUtils.GetRandom(4, 6);
var spCharCount = RandomUtils.GetRandom(4, 6);
var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
var spCharStr = GenerateString(SpecialChars, spCharCount);
var numStr = GenerateString(Numbers, numCount);
var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
return Shuffle(Shuffle(pass));
}
public enum PasswordComplexity
{
Simple, Medium, Strong, Stronger
}
}
I write this code for you. You can just copy and use it. All of my code is just a method that you can pass appropriate arguments and it gives you back a completely randomized password. I test it several times before answering your question, It works well.
private string GeneratePassword(bool useCapitalLetters, bool useSmallLetters, bool useNumbers, bool useSymbols, int passLenght)
{
Random random = new Random();
StringBuilder password = new StringBuilder(string.Empty);
//This for loop is for selecting password chars in order
for (int i = 0;;)
{
if (useCapitalLetters)
{
password.Append((char)random.Next(65, 91)); //Capital letters
++i; if (i >= passLenght) break;
}
if (useSmallLetters)
{
password.Append((char)random.Next(97, 122)); //Small letters
++i; if (i >= passLenght) break;
}
if (useNumbers)
{
password.Append((char)random.Next(48, 57)); //Number letters
++i; if (i >= passLenght) break;
}
if (useSymbols)
{
password.Append((char)random.Next(35, 38)); //Symbol letters
++i; if (i >= passLenght) break;
}
}
//This for loop is for disordering password characters
for (int i = 0; i < password.Length; ++i)
{
int randomIndex1 = random.Next(password.Length);
int randomIndex2 = random.Next(password.Length);
char temp = password[randomIndex1];
password[randomIndex1] = password[randomIndex2];
password[randomIndex2] = temp;
}
return password.ToString();
}
an answer with complete randomize char and using the max repeat of char, i have added a shuffle string function:
const int Maximum_Identical = 2; // Max number of identical characters in a row
const string lower_chars = "abcdefghijklmnopqrstuvwxyz"; // lower case chars
const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //capital chars
const string numbers = "0123456789"; //numbers
const string symbols = #"!#$%&*#\"; //symbols
int lenght = 6; //
bool lowercase = true, capital=true, num=true, sym=true;
List<char[]> PasswordSet = new List<char[]>();
List<char[]> charSet = new List<char[]>();
List<int[]> countSet = new List<int[]>();
if (lowercase) charSet.Add(lower_chars.ToArray());
if (capital) charSet.Add(capital_chars.ToArray());
if (num) charSet.Add(numbers.ToArray());
if (sym) charSet.Add(symbols.ToArray());
foreach(var c in charSet)
countSet.Add(new int[c.Length]);
Random rdm = new Random();
//we create alist with each type with a length char (max repeat char included)
for(int i = 0; i < charSet.Count;i++)
{
var lng = 1;
var p0 = "";
while (true)
{
var ind = rdm.Next(0, charSet[i].Length);
if (countSet[i][ind] < Maximum_Identical )
{
countSet[i][ind] += 1;
lng++;
p0 += charSet[i][ind];
}
if (lng == lenght) break;
}
PasswordSet.Add(p0.ToArray());
}
//generate a password with the desired length with at less one char in desired type,
//and we choose randomly in desired type to complete the length of password
var password = "";
for(int i = 0; i < lenght; i++)
{
char p;
if (i < PasswordSet.Count)
{
int id;
do
{
id = rdm.Next(0, PasswordSet[i].Length);
p = PasswordSet[i][id];
} while (p == '\0');
password += p;
PasswordSet[i][id] = '\0';
}
else
{
int id0;
int id1;
do
{
id0 = rdm.Next(0, PasswordSet.Count);
id1 = rdm.Next(0, PasswordSet[id0].Length);
p = PasswordSet[id0][id1];
} while (p == '\0');
password += p;
PasswordSet[id0][id1] = '\0';
}
}
//you could shuffle the final password
password = Shuffle.StringMixer(password);
shuffle string function:
static class Shuffle
{
static System.Random rnd = new System.Random();
static void Fisher_Yates(int[] array)
{
int arraysize = array.Length;
int random;
int temp;
for (int i = 0; i < arraysize; i++)
{
random = i + (int)(rnd.NextDouble() * (arraysize - i));
temp = array[random];
array[random] = array[i];
array[i] = temp;
}
}
public static string StringMixer(string s)
{
string output = "";
int arraysize = s.Length;
int[] randomArray = new int[arraysize];
for (int i = 0; i < arraysize; i++)
{
randomArray[i] = i;
}
Fisher_Yates(randomArray);
for (int i = 0; i < arraysize; i++)
{
output += s[randomArray[i]];
}
return output;
}
}
There you go :
string[] charList =
{
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
"#\"!#$%&*#\\"
};
int desiredPasswordLength = 12;
var randomNumberGenerator = new Random();
string generatedPassword = "";
for (int i = randomNumberGenerator.Next() % 4; desiredPasswordLength > 0; i = (i+1) % 4)
{
var takeRandomChars = randomNumberGenerator.Next() % 3;
for (int j = 0; j < takeRandomChars; j++)
{
var randomChar = randomNumberGenerator.Next() % charList[i].Length;
char selectedChar = charList[i][randomChar % charList[i].Length];
generatedPassword = string.Join("", generatedPassword, selectedChar);
}
desiredPasswordLength -= takeRandomChars;
}
Console.WriteLine("Generated password: {0}",generatedPassword);
private static string GeneratorPassword(UInt16 length = 8)
{
const string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
Random rnd = new Random();
System.Threading.Thread.Sleep(2);
for (int i = 0; i < length; i++)
{
int index = 0;
if (i % 3 == 0)
{
index = rnd.Next(0, 10);
}
else if (i % 3 == 1)
{
index = rnd.Next(10, 36);
}
else
{
index = rnd.Next(36, 62);
}
sb.Insert(rnd.Next(0, sb.Length), chars[index].ToString());
}
return sb.ToString();
}
static void Main(string[] args)
{
for (int j= 0; j < 100; j++)
{
Console.WriteLine( GeneratorPassword());
}
Console.ReadLine();
}

Index was outside the bounds of the array?

I keep getting this message "System.IndexOutOfRangeException: Index was outside the bounds of the array." when attempting to run a program I built, that utilized an exception catcher.
class StudentS
{
private List theStudentList;
public bool PopulateStudents(string path)
{
theStudentList = new List<Student>();
bool flag = false;
try
{
List<string[]> strArrayList = new List<string[]>();
using (StreamReader streamReader = new StreamReader(path))
{
string str;
while ((str = streamReader.ReadLine()) != null)
{
string[] strArray = str.Split(',');
strArrayList.Add(strArray);
}
}
for (int index1 = 0; index1 < strArrayList.Count; ++index1)
{
string[] strArray = strArrayList[index1];
Student student = new Student(strArray[0], strArray[1], strArray[2]); **where the error is**
int index2 = 3;
while (index2 < strArray.Length)
{
student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
index2 += 2;
}
student.CalGrade();
theStudentList.Add(student);
}
}
catch (Exception e)
{
flag = true;
Console.WriteLine(e);
}
return flag;
}
public int ListLength
{
get
{
return theStudentList.Count;
}
}
public float StudentAverage(int index)
{
return theStudentList.ElementAt(index).Average;
}
public string StudentGrade(int index)
{
return theStudentList.ElementAt(index).LetterGrade;
}
public string StudentID(int index)
{
return theStudentList.ElementAt(index).ID;
}
public string StudentLastName(int index)
{
return theStudentList.ElementAt(index).NameLast;
}
}
class Student
{
private float average;
private ArrayList Earned;
private string letterGrade;
private string nameFirst;
private string nameLast;
private ArrayList Possible;
private string studentID;
public Student(string id)
{
studentID = null;
nameFirst = null;
nameLast = null;
Earned = new ArrayList();
Possible = new ArrayList();
}
public Student(string id, string first)
{
studentID = id;
nameFirst = null;
nameLast = null;
Earned = new ArrayList();
Possible = new ArrayList();
}
public Student(string id, string first, string last)
{
nameFirst = first;
nameLast = last;
studentID = id;
Earned = new ArrayList();
Possible = new ArrayList();
}
public float Average
{
get
{
return average;
}
}
public string ID
{
get
{
return studentID;
}
}
public string LetterGrade
{
get
{
return letterGrade;
}
}
public string NameFirst
{
get
{
return nameFirst;
}
set
{
nameFirst = value;
}
}
public string NameLast
{
get
{
return nameLast;
}
set
{
nameLast = value;
}
}
public void CalGrade()
{
int num1 = 0;
int num2 = 0;
foreach (int num3 in Earned)
num1 += num3;
foreach (int num3 in Possible)
num2 += num3;
average = num1 / (float)num2;
average = (float)Math.Round(average, 2);
if (average >= 0.9)
letterGrade = "A";
if (average >= 0.8 && average < 0.9)
letterGrade = "B";
if (average >= 0.7 && average < 0.8)
letterGrade = "C";
if (average >= 0.6 && average < 0.7)
letterGrade = "D";
if (average >= 0.6)
return;
letterGrade = "U";
}
public void EnterGrade(int earnedValue, int possValue)
{
Earned.Add(earnedValue);
Possible.Add(possValue);
}
}
I am unsure as to what I have done wrong. Thanks for any help!
Edit: I went ahead and added a majority of the code here, in hopes that this answers your questions better. The data set I am dealing with is 4 rows, that are grabbed into the student array.
index2 + 1 may be out of range in the expression strArray[index2 + 1] below:
while (index2 < strArray.Length)
{
student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
index2 += 2;
}
To process two elements at a time, use index2 < strArray.Length - 1
You may have a problem if the file from your path has an empty row as last row.
You access strArray[0], strArray[1], strArray[2] no matter if it is an empty array or not.
Maybe you are missing an Array.resize(). // This worked for me
Array.Resize<string[]>(ref strArrayList , count+ 1); // Count is the current length of strArrayList
Flagged the two spots where you could run into trouble:
public bool PopulateStudents(string path)
{
theStudentList = new List<Student>();
bool flag = false;
try
{
List<string[]> strArrayList = new List<string[]>();
using (StreamReader streamReader = new StreamReader(path))
{
string str;
while ((str = streamReader.ReadLine()) != null)
{
string[] strArray = str.Split(',');
strArrayList.Add(strArray);
}
}
for (int index1 = 0; index1 < strArrayList.Count; ++index1)
{
string[] strArray = strArrayList[index1];
// below that, what makes you believe strArray's length is >= 3 ?
Student student = new Student(strArray[0], strArray[1], strArray[2]);
int index2 = 3;
while (index2 < strArray.Length)
{
// here index2 will be < strArray.Length, but index2+1 might be ==
student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
index2 += 2;
}
student.CalGrade();
theStudentList.Add(student);
}
}
catch (Exception e)
{
flag = true;
Console.WriteLine(e);
}
return flag;
}
Note that your while loop could be replaced with:
for(int index2 = 3; index2 < strArray.Length - 1; index2 += 2)
{
student.EnterGrade(...);
}
This is difficult to diagnose because you provided limited information. If I could see the file you are running through your program, fed in as path, I would be able to compare what the function is attempting to do to the data it is trying to do it on. That said, this looks familiar to me so I will give solving it a try and at least give you a tool to try on it.
I experienced a similar issue with a program that needed to read a CSV file for a graphics program. The problem was that when the CSV file was created, an empty line was left at the end. This left me with an empty array to represent the last line in the file.
Also, have you verified that the arrays that are added to strArrayList are consistently sized?
If you check for this empty line at the end of your file and it does not exist and if you check for commas left at the end of the lines in your file passed in as path then you can try the edits I made above to get an idea of which line(s) in your CSV file is causing the problem. I commented all the edits I made with “EDIT:” so they would be easy to find. Without more information, I cannot fix the problem, but I can maybe help you look in the right direction.
The edited code with the output for line numbers in your file which are associated with errors is below. Good luck!
public bool PopulateStudents(string path)
{
theStudentList = new List<Student>();
bool flag = false;
// EDIT: NEW VARIABLE int lineCounter declared and initialized before try block so it remains in scope when the catch block is called
int counter = 0;
try
{
List<string[]> strArrayList = new List<string[]>();
using (StreamReader streamReader = new StreamReader(path))
{
string str;
while ((str = streamReader.ReadLine()) != null)
{
string[] strArray = str.Split(',');
strArrayList.Add(strArray);
}
}
for (int index1 = 0; index1 < strArrayList.Count; ++index1)
{
// EDIT: UPDATE lineCounter
++lineCounter;
string[] strArray = strArrayList[index1];
Student student = new Student(strArray[0], strArray[1], strArray[2]);
int index2 = 3;
while (index2 < strArray.Length)
{
student.EnterGrade(int.Parse(strArray[index2]), int.Parse(strArray[index2 + 1]));
index2 += 2;
}
student.CalGrade();
theStudentList.Add(student);
}
}
catch (Exception e)
{
flag = true;
Console.WriteLine(e);
// EDIT: PRINT CURRENT LINE
Console.WriteLine(“error at line in file = “ + lineCounter);
}
return flag;
}

Splitting a word with dots between each char

I have a word, for example:
qwerty
I want to add a dot between each char, but also take into consideration all possible cases.
For example, output should be:
qwerty
qwert.y
qwer.ty
qwer.t.y
qwe.rty
qwe.rt.y
qwe.r.ty
qwe.r.t.y
qw.erty
qw.ert.y
qw.er.ty
qw.er.t.y
qw.e.rty
qw.e.rt.y
qw.e.r.ty
qw.e.r.t.y
q.werty
q.wert.y
q.wer.ty
q.wer.t.y
q.we.rty
q.we.rt.y
q.we.r.ty
q.we.r.t.y
q.w.erty
q.w.ert.y
q.w.er.ty
q.w.er.t.y
q.w.e.rty
q.w.e.rt.y
q.w.e.r.ty
q.w.e.r.t.y
I have so far this code:
private void button12_Click(object sender, EventArgs e)
{
int maxPossibilities = Convert.ToInt32(Math.Pow(2.0, txtInput.Text.Length));
List<string> allPossibilities = new List<string>();
for (int i = 0; i < maxPossibilities; i++)
{
string result = "";
string added = Convert.ToString(i, 2).PadLeft(txtInput.Text.Length - 1);
for (int j = 0; j < txtInput.Text.Length; j++)
{
result += txtInput.Text[j] + ((j < txtInput.Text.Length - 1) && (added[j].Equals('1')) ? "." : "");
}
allPossibilities.Add(result);
}
}
I am getting the following output:
qwerty
qwert.y
qwer.ty
qwer.t.y
qwe.rty
qwe.rt.y
qwe.r.ty
qwe.r.t.y
qw.erty
qw.ert.y
qw.er.ty
qw.er.t.y
qw.e.rty
qw.e.rt.y
qw.e.r.ty
qw.e.r.t.y
q.werty
q.wert.y
q.wer.ty
q.wer.t.y
q.we.rty
q.we.rt.y
q.we.r.ty
q.we.r.t.y
q.w.erty
q.w.ert.y
q.w.er.ty
q.w.er.t.y
q.w.e.rty
q.w.e.rt.y
q.w.e.r.ty
q.w.e.r.t.y
q.werty
q.werty
q.wert.y
q.wert.y
q.wer.ty
q.wer.ty
q.wer.t.y
q.wer.t.y
q.we.rty
q.we.rty
q.we.rt.y
q.we.rt.y
q.we.r.ty
q.we.r.ty
q.we.r.t.y
q.we.r.t.y
q.w.erty
q.w.erty
q.w.ert.y
q.w.ert.y
q.w.er.ty
q.w.er.ty
q.w.er.t.y
q.w.er.t.y
q.w.e.rty
q.w.e.rty
q.w.e.rt.y
q.w.e.rt.y
q.w.e.r.ty
q.w.e.r.ty
q.w.e.r.t.y
q.w.e.r.t.y
There are some duplicates in the output, but shouldn't be. Any help is appreciated.
Here is a slight variation on your algorithm that looks at the bits of i to determine which positions should get dots:
string input = "qwerty";
int maxPossibilities = Convert.ToInt32(Math.Pow(2.0, input.Length));
List<string> allPossibilities = new List<string>();
for(int i = 0; i < maxPossibilities; ++i)
{
string result = "";
for(int j = 0; j < input.Length; j++)
{
result += input[j];
if((i & (1 << j)) != 0) { result += "."; }
}
allPossibilities.Add(result);
System.Console.WriteLine(result);
}
If you're just looking to not add the item to the list if it's already there then, try this:
Change
allPossibilities.Add(result);
To
if (!allPossibilities.Contains(result)) { allPossibilities.Add(result); }
try this code, I know it's a little bit too much, but it's structured and I use bitmask for putting dot between characters.
static void Main(string[] args)
{
Do("qwerty");
}
public static void Do(string text)
{
int i = 1;
Text output = new Text();
output.Add(new Dot(i));
i = i * 2;
foreach(char c in text)
{
output.Add(new textChar(c));
output.Add(new Dot(i));
i = i * 2;
}
int possibilites = output.Possibilites;
for (i = 0; i < possibilites; i++)
{
Console.WriteLine(output.ToString(i));
}
}
public class Text
{
public List<character> characters = new List<character>();
public void Add(character c)
{
characters.Add(c);
}
public int Possibilites
{
get
{
return Convert.ToInt32(Math.Pow(2, characters.Count(C => C is Dot)));
}
}
public string ToString(int i)
{
string output = "";
foreach (character c in characters)
{
if (c is textChar)
{
output += c.c;
}
else if (c is Dot)
{
if ((i & ((Dot)c).index) != 0)
output += c.c;
}
}
return output;
}
}
public class character
{
public char c { set; get; }
}
public class textChar : character
{
public textChar(char c)
{
this.c = c;
}
}
public class Dot : character
{
public int index;
public Dot(int i)
{
index = i;
c = '.';
}
}
Another solution which works.
Here the positions of the dots get saved as a matrix in the binarycount List as booleans. They define where the dots will be.
static void Main(string[] args)
{
Console.WriteLine(String.Join(Environment.NewLine, printPossibilities("qwerty")));
}
private static List<string> printPossibilities(string str)
{
List<string> allPossibilities = new List<string>();
List<bool> binarycount = new List<bool>();
for (int i = 0; i < str.Length - 1; i++) {
binarycount.Add(false);
}
bool hasNext = true;
while(hasNext)
{
string temp = str;
for (int i = binarycount.Count - 1; i >= 0; i--)
{
if (binarycount[i])
temp = temp.Insert(i+1, ".");
}
allPossibilities.Add(temp);
hasNext = false;
for (int i = binarycount.Count - 1; i >= 0; i--)
{
if (binarycount[i]) {
binarycount[i] = false;
} else {
binarycount[i] = true;
hasNext = true;
break;
}
}
}
return allPossibilities;
}
output:
qwerty
qwert.y
qwer.ty
qwer.t.y
qwe.rty
qwe.rt.y
qwe.r.ty
qwe.r.t.y
qw.erty
qw.ert.y
qw.er.ty
qw.er.t.y
qw.e.rty
qw.e.rt.y
qw.e.r.ty
qw.e.r.t.y
q.werty
q.wert.y
q.wer.ty
q.wer.t.y
q.we.rty
q.we.rt.y
q.we.r.ty
q.we.r.t.y
q.w.erty
q.w.ert.y
q.w.er.ty
q.w.er.t.y
q.w.e.rty
q.w.e.rt.y
q.w.e.r.ty
q.w.e.r.t.y

C# - Check if string contains characters of another string at the same order

I would like to check if a string contains the characters of another string (returning true or false), but it needs to be in the "right" order but not necessarily contiguous.
Example:
String firstWord = "arm";
String secondWord = "arandomword"; //TRUE - ARandoMword
String thirdWord = "road"; //FALSE - ARanDOmword
The word "arandomword" contains the letters of the word "road" but it's not possible to write it, because they are not at the right order.
Anyone, please?
Use regex. Something simple that passes your tests in linqpad:
void Main()
{
String firstWord = "arm";
String secondWord = "arandomword"; //TRUE - ARandoMword
String thirdWord = "road";
Regex.IsMatch(secondWord,makeRegex(firstWord.ToCharArray())).Dump();
}
// Define other methods and classes here
String makeRegex(char[] chars)
{
StringBuilder sb = new StringBuilder();
foreach (var element in chars.Select(c => Regex.Escape(c.ToString()))
.Select(c => c + ".*"))
{
sb.Append(element);
}
return sb.ToString();
}
you could define an extension method like this:
public static class StringExtensions
{
public static bool ContainsWord(this string word, string otherword)
{
int currentIndex = 0;
foreach(var character in otherword)
{
if ((currentIndex = word.IndexOf(character, currentIndex)) == -1)
return false;
}
return true;
}
}
and call it as expressive as:
String firstWord = "arm";
String secondWord = "arandomword"; //TRUE - ARandoMword
String thirdWord = "road"; //FALSE - ARanDOmword
var ret = secondWord.ContainsWord(firstWord); // true
var ret2 = thirdWord.ContainsWord(firstWord); // false
Something like this?
bool HasLettersInOrder(string firstWord, string secondWord)
{
int lastPos = -1;
foreach (char c in firstWord)
{
lastPos++;
while (lastPos < secondWord.Length && secondWord[lastPos] != c)
lastPos++;
if (lastPos == secondWord.Length)
return false;
}
return true;
}
I can not check right now, but something along the lines:
int i = 0, j = 0;
while(i < first.Length && j < second.Length)
{
while(first[i] != second[j] && j < second.Length) j++;
i++;
j++
}
bool b = i == first.Length;
Thanks for all the replies. I've tried and tried and I did it my way. Definitively it's not the shortest way to do it, but at least it's working:
public static Boolean checkWords(String smallerWord, String biggerWord)
{
int position = 0;
bool gotFirst = false;
bool gotAnother = false;
int positionBigger = 0;
String word = "";
for(int positionSmaller = 0; positionSmaller < smallerWord.Length; positionSmaller++)
{
if(!gotFirst)
{
if(biggerWord.Contains(smallerWord[positionSmaller].ToString()))
{
position = biggerWord.IndexOf(smallerWord[positionSmaller].ToString());
gotFirst = true;
word = smallerWord[positionSmaller].ToString();
}
}
else
{
gotAnother = false;
positionBigger = position + 1;
while(!gotAnother)
{
if(positionBigger < biggerWord.Length)
{
if(biggerWord[positionBigger].ToString().Equals(smallerWord[positionSmaller].ToString()))
{
position = positionBigger;
gotAnother = true;
word += smallerWord[positionSmaller].ToString();
}
else
{
positionBigger++;
}
}
else
{
gotAnother = true;
}
}
}
}
if(smallerWord.Equals(word))
{
return true;
}
else
{
return false;
}
}

random uppercase in a word + multiple string insert

I really need a solution for the next scenario(I've been searching for hours and beating about the bushes to find a smooth solution, but none worked):
I have a winform that:
parse a text file
generate some folders using random words from that file
My code so far:
int value;
string path = null;
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog(this) == DialogResult.OK)
{
path = fbd.SelectedPath;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
value = Convert.ToInt32(textBox1.Text);//store the value from the textbox in variable "value"
}
private void button2_Click(object sender, EventArgs e)
{
if (path != null && Directory.Exists(path))
for (int i = 0; i < value; i++)
{
Random rnd = new Random();
string tick1 = rnd.Next(0, 10).ToString();
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
var r = new Random(DateTime.Now.Millisecond);
var randomLineNumber = r.Next(0, lines.Length - 1);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 3 == 2)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, string.Format("{0}", line.Insert(2, tick1).Insert(4, tick1).Insert(6, tick1))));
}
}
Is there a way to use ToUpper() method as line.Insert() one so that I can get random upper letters? More, is there a better way of randomizing those index positions form line.Insert() (I'm asking this because when it's generating the folders name: the indexes are the same: e.g pe8rs8on8al and just after that the index changes.)?
I want to achieve the following:
if I have the next words in the .txt file:
personal
football
programming
computer
I would like the folder names to look like:
Pe3rs9oN1al
fO8ot5Ba6lL
You can loop through the characters in the string and build a new string depending on random values:
StringBuilder b = new StringBuilder();
for (int i = 0; i < line.Length; i++ ) {
char c = line[i];
if (rnd.Next(2) == 0) {
c = Char.ToUpper(c);
}
b.Append(c);
if (i % 2 == 1) {
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Note: You shouldn't create Random objects in the loop. You should create a single Random object before the loop and use for all random numbers that you need. Creating instances too close in time will make them return the same sequences of random numbers. Also, you don't need to seed the random generator from the clock, the constructor without parameters does that automatically:
Random rnd = new Random();
So, the code in the method would be:
if (path != null && Directory.Exists(path))
Random rnd = new Random();
for (int i = 0; i < value; i++)
{
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
var randomLineNumber = rnd.Next(0, lines.Length);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
}
Note the rnd.Next(0, lines.Length) to pick a random line. The upper limit for the random number is not inclusive, so if you use rnd.Next(0, lines.Length - 1) it will never pick the last line.
That's because you are specifying only tick1 in the same loop. If you want to change this, add additional ticks to your code as below:
string tick1 = rnd.Next(0, 10).ToString();
string tick2 = rnd.Next(0, 10).ToString();
string tick3 = rnd.Next(0, 10).ToString();
Then use those in your formatting of the string:
Directory.CreateDirectory(Path.Combine(path, string.Format("{0}", line.Insert(2, tick1).Insert(4, tick2).Insert(6, tick3))))
Like Guffa said you should not use Random in a loop, in all preference you should only instanciate one of it, but I think you could use it like this
public static class StringRandomize
{
static readonly Random rnd = new Random();
static char[] permmitedCharacters { get; set; }
static StringRandomize()
{
List<char> Chars= new List<char>();
for (int i = 48; i < 48+10; i++)
{
Chars.Add((char)i);
}
for (int i = 65; i < 65+26; i++)
{
Chars.Add((char)i);
}
permmitedCharacters = Chars.ToArray();
}
public static string Randomize(string input, double RandomizePercent = 30)
{
StringBuilder result = new StringBuilder();
int index = 0;
while (index < input.Length)
{
if (rnd.Next(0, 100) <= RandomizePercent)
{
if (rnd.Next(0, 100) <= RandomizePercent)
{
result.Append(GenerateCaracter());
}
else
{
if (rnd.Next(0, 100) > 50)
{
result.Append(input.ToLower()[index]);
}
else
{
result.Append(input.ToUpper()[index]);
}
index++;
}
}
else
{
result.Append(input[index]);
index++;
}
}
return result.ToString();
}
private static char GenerateCaracter()
{
return permmitedCharacters[rnd.Next(0, permmitedCharacters.Length)];
}
}
private static void GenerateRandomDirectories(string path, int value)
{
//I'm supposing value is the number of lines that you want
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
Random rnd = new Random();
if (path != null && Directory.Exists(path))
{
for (int i = 0; i < value; i++)
{
Directory.CreateDirectory(path + "\\" + StringRandomize.Randomize(lines[rnd.Next(0,lines.Length)]));
}
}
}
"pers3o7Nal"
"foOtBaLl"
Got like this
public Form1()
{
InitializeComponent();
string content = "";
using (FileStream fs = new FileStream("D:\\names.txt", FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
content = sr.ReadToEnd();
string[] names = content.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
string path = "D:\\RandDirs";
if (!Directory.Exists(path))Directory.CreateDirectory(path) ;
for (int i = 0; i < 50; i++) Directory.CreateDirectory(path + "\\" + getRandomName(names));
}
Random randName = new Random();
Random insertingNumber = new Random();
Random randUpper = new Random();
Random randInsertNumber = new Random();
string getRandomName(string[] names)
{
string name = names[randName.Next(names.Length)];
name = name.Replace(" ", "");
string result = "";
for (int i = 0; i < name.Length; i++)
result += (randUpper.Next(0, 9) <= 5 ? name[i].ToString().ToLower() : name[i].ToString().ToUpper())
+ (((i + 1) % 2 == 0) ? insertingNumber.Next(0, 9).ToString() : "");
return result;
}
as per your needs, i've changed from randomly inserting numbers to inserting number every 2 characters.

Categories