I'm trying to generate a string of a random length which consists out of random chars.
To do so I have this code:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
MyString test = new MyString();
test.Random();
Console.WriteLine(test.Value);
}
Console.ReadLine();
}
}
public class MyString
{
private string value = string.Empty;
private Random r = new Random();
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public void Random()
{
int length = (r.Next() % (100)) + 1;
for(int i = 0; i < length; i++)
{
value = value + RandomChar();
}
}
public char RandomChar()
{
// 32 to 126
int c = (r.Next() % 95) + 32;
char ch = (char)c;
return ch;
}
}
Now, lets look at a part of the output:
As you can see, the output is far from random, it contains a lot of repeating strings. How is this possible, and how do I solve it?
It looks like you are creating a new instance of the Random class every time your MyString constructor is called. The Random class probably seeds itself based on the current time (to some resolution). Random number generators seeded with the same value will generate the same pseudo-random sequence.
The solution is to construct one instance of Random and use that everywhere.
http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx
string randomName = Path.GetRandomFileName();
randomName = randomName.Replace(".", string.Empty);
// take substring...
Related
I'm trying to create random character combination. Then I'd like to output it on the console. The following code does work as long as I'm using string instead of char datatypes.
The problem with using just sting datatype is, that the output will only be in upper case and I can't simply lowercase everything and only uppercase the first string.
So I tried to do it with a char array appending every character to a stringBuilder. But somehow I can't Console.WriteLine what I coded. and I don't know why... Do you guys maybe have a hint for solving the issue?
cheers
using System;
namespace WinGen
{
public class NamenGenerator
{
private int NamenLaenge { get; set; }
private char[] BuchstabenKombination { get; set; }
private int CharShifter { get; set; }
private int CharPicker { get; set; }
private int RangeMin { get; set; }
private int RangeMax { get; set; }
public NamenGenerator()
{
Random _namenLaenge = new Random();
this.NamenLaenge = _namenLaenge.Next(4, 10);
CharShifter = 0;
RangeMin = 0;
RangeMax = 25;
BuchstabenKombination = new char[this.NamenLaenge];
}
public void StringGenerator()
{
try
{
while (this.NamenLaenge != 0)
{
Random charakter = new Random();
CharPicker = charakter.Next(RangeMin, RangeMax);
BuchstabenKombination[CharShifter] = Convert.ToChar((Buchstaben)CharPicker);
this.NamenLaenge--;
this.CharShifter++;
}
StringBuilder sb = new StringBuilder();
string t = string.Empty;
foreach (char c in BuchstabenKombination)
{
t = Convert.ToString(c);
sb.Append(t);
Console.WriteLine(t);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}
}
So you can rewrite your loop like this:
foreach (char c in BuchstabenKombination)
{
sb.Append(c);
}
Console.WriteLine(sb.ToString());
This will print the entire completed string to the console.
The other issue is that you're generating characters between 0 and 25, which are mostly control codes according to the ASCII chart. I understand that you tried to mitigate this by using an enum, but enums are essentially named integer values, so you're basically still generating characters from 0 and 25 on the ASCII chart.
To verify this, you can change your code to
BuchstabenKombination[CharShifter] = Convert.ToChar(CharPicker + 65); // aka CharPicker + 'A'
This will now generate characters A-Y.
I imagine you created an enum so that you can choose from a set of characters. Overall, I'd rewrite your code like this:
Random charakter = new Random();
StringBuilder sb = new StringBuilder();
int desiredLength = 5;
const string characters = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < desiredLength; ++i)
{
int charIdx = charakter.Next(0, characters.Length);
sb.Append(characters[charIdx]);
}
Console.WriteLine(sb.ToString()); // outputs a 5 character long string with characters randomly chosen from the characters string
Try it online
I have the below scenario. I need to call a method which is implemented in the same class. But it is throwing errors. How can we rewrite this?
public class A
{
Random random = new Random(2);
string Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string randomString = GenerateString(5);
public string GenerateString(int size)
{
char[] chars = new char[size];
for (int i = 0; i < size; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars);
}
}
Will this scenario works?
You need to learn about constructors.
Specifically, in your code you need a constructor initializing randomString. Also, Alphabet is never going to change during execution, so it is a great candidate to become const.
public class A {
const string Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public A()
{
random = new Random(2);
randomString = GenerateStrig(5);
}
public string GenerateString(int size)
{
char[] chars = new char[size];
for (int i = 0; i < size; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars);
}
string randomString;
Random random;
}
Hope this helps.
You cannot access non-static method GenerateString in static context.
You can write your code just like this:
public class A
{
static Random _random = new Random(2);
const string Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string _randomString = GenerateString(5);
public static string GenerateString(int size)
{
char[] chars = new char[size];
for (int i = 0; i < size; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars);
}
}
Another possibility is to turn randomString field into read-only property:
string randomString => GenerateString(5);
all you have to do is to add > after =; further refactoring:
public class A
{
//TODO: Random(2) for debug only; Random() for real life
readonly Random random = new Random(2);
// Alphabet is a constant isn't it?
const string Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// read-only property; initial value is GenerateString(5)
//TODO: You may want to capitalize the property - RandomString
string randomString => GenerateString(5);
public string GenerateString(int size)
{
// Validation
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size), "size must be non-negative");
// Linq is often compact and readable
return string.Concat(Enumerable
.Range(0, size)
.Select(i => Alphabet[random.Next(Alphabet.Length)]));
}
}
Edit: As Progman noticed in comments property (and thus GenerateString(5)) will be executed each time when accessed, e.g.
A a = new A();
// call randomString 3 times
string test = string.Join(Environment.NewLine, Enumerable
.Range(0, 3).Select(i => a.randomString));
Console.Write(test);
will print out three different values
RE5Z3
BSG80
R10ID
Change what you have to include a default constructor that you call that from.
public class A
{
Random random;
string Alphabet;
string randomString;
public A()
{
Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
random = new Random(2);
randomString = GenerateString(5);
}
public string GenerateString(int size)
{
char[] chars = new char[size];
for (int i = 0; i < size; i++)
{
chars[i] = Alphabet[random.Next(Alphabet.Length)];
}
return new string(chars);
}
}
It's generally considered best practice to initialize all of your member variables inside the constructor rather than when you declare them, it helps with readability and maintainability.
I have to make a string which consists a string like - AAA0009, and once it reaches AAA0009, it will generate AA0010 to AAA0019 and so on.... till AAA9999 and when it will reach to AAA9999, it will give AAB0000 to AAB9999 and so on till ZZZ9999.
I want to use static class and static variables so that it can auto increment by itself on every hit.
I have tried some but not even close, so help me out thanks.
Thanks for being instructive I was trying as I Said already but anyways you already want to put negatives over there without even knowing the thing:
Code:
public class GenerateTicketNumber
{
private static int num1 = 0;
public static string ToBase36()
{
const string base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sb = new StringBuilder(9);
do
{
sb.Insert(0, base36[(byte)(num1 % 36)]);
num1 /= 36;
} while (num1 != 0);
var paddedString = "#T" + sb.ToString().PadLeft(8, '0');
num1 = num1 + 1;
return paddedString;
}
}
above is the code. this will generate a sequence but not the way I want anyways will use it and thanks for help.
Though there's already an accepted answer, I would like to share this one.
P.S. I do not claim that this is the best approach, but in my previous work we made something similar using Azure Table Storage which is a no sql database (FYI) and it works.
1.) Create a table to store your running ticket number.
public class TicketNumber
{
public string Type { get; set; } // Maybe you want to have different types of ticket?
public string AlphaPrefix { get; set; }
public string NumericPrefix { get; set; }
public TicketNumber()
{
this.AlphaPrefix = "AAA";
this.NumericPrefix = "0001";
}
public void Increment()
{
int num = int.Parse(this.NumericPrefix);
if (num + 1 >= 9999)
{
num = 1;
int i = 2; // We are assuming that there are only 3 characters
bool isMax = this.AlphaPrefix == "ZZZ";
if (isMax)
{
this.AlphaPrefix = "AAA"; // reset
}
else
{
while (this.AlphaPrefix[i] == 'Z')
{
i--;
}
char iChar = this.AlphaPrefix[i];
StringBuilder sb = new StringBuilder(this.AlphaPrefix);
sb[i] = (char)(iChar + 1);
this.AlphaPrefix = sb.ToString();
}
}
else
{
num++;
}
this.NumericPrefix = num.ToString().PadLeft(4, '0');
}
public override string ToString()
{
return this.AlphaPrefix + this.NumericPrefix;
}
}
2.) Make sure you perform row-level locking and issue an error when it fails.
Here's an oracle syntax:
SELECT * FROM TICKETNUMBER WHERE TYPE = 'TYPE' FOR UPDATE NOWAIT;
This query locks the row and returns an error if the row is currently locked by another session.
We need this to make sure that even if you have millions of users generating a ticket number, it will not mess up the sequence.
Just make sure to save the new ticket number before you perform a COMMIT.
I forgot the MSSQL version of this but I recall using WITH (ROWLOCK) or something. Just google it.
3.) Working example:
static void Main()
{
TicketNumber ticketNumber = new TicketNumber();
ticketNumber.AlphaPrefix = "ZZZ";
ticketNumber.NumericPrefix = "9999";
for (int i = 0; i < 10; i++)
{
Console.WriteLine(ticketNumber);
ticketNumber.Increment();
}
Console.Read();
}
Output:
Looking at your code that you've provided, it seems that you're backing this with a number and just want to convert that to a more user-friendly text representation.
You could try something like this:
private static string ValueToId(int value)
{
var parts = new List<string>();
int numberPart = value % 10000;
parts.Add(numberPart.ToString("0000"));
value /= 10000;
for (int i = 0; i < 3 || value > 0; ++i)
{
parts.Add(((char)(65 + (value % 26))).ToString());
value /= 26;
}
return string.Join(string.Empty, parts.AsEnumerable().Reverse().ToArray());
}
It will take the first 4 characters and use them as is, and then for the remainder of the value if will convert it into characters A-Z.
So 9999 becomes AAA9999, 10000 becomes AAB0000, and 270000 becomes ABB0000.
If the number is big enough that it exceeds 3 characters, it will add more letters at the start.
Here's an example of how you could go about implementing it
void Main()
{
string template = #"AAAA00";
var templateChars = template.ToCharArray();
for (int i = 0; i < 100000; i++)
{
templateChars = IncrementCharArray(templateChars);
Console.WriteLine(string.Join("",templateChars ));
}
}
public static char Increment(char val)
{
if(val == '9') return 'A';
if(val == 'Z') return '0';
return ++val;
}
public static char[] IncrementCharArray(char[] val)
{
if (val.All(chr => chr == 'Z'))
{
var newArray = new char[val.Length + 1];
for (int i = 0; i < newArray.Length; i++)
{
newArray[i] = '0';
}
return newArray;
}
int length = val.Length;
while (length > -1)
{
char lastVal = val[--length];
val[length] = Increment(lastVal);
if ( val[length] != '0') break;
}
return val;
}
Currently my program generates random 8 character strings made from numbers.
See below
public static string GenerateNewCode()
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
// keep going until we find a unique code
do
{
newCode = random.Next(0, 9999).ToString("0000")
+ random.Next(0, 9999).ToString("0000");
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
However, I want to be able to create random codes of 8, 9, 10, 11 and 12 numbers.
Not sure the most efficient way of doing this.
My idea was to create a random number between 0 - 9 and then do this X amount of times based on the length of code required.
There must be an easy/more efficient way to doing this .....
Unless this is time critical I would just generate a 12-digit random number every time and just use the 8-12 digits I need. You're testing and retrying for uniqueness, so that should still work.
internal class Program {
private static void Main(string[] args) {
Console.WriteLine(GetNumber(7));
Console.WriteLine(GetNumber(8));
Console.WriteLine(GetNumber(12));
Console.WriteLine(GetNumber(500));
}
public static string GetNumber(int length) {
return string.Concat(RandomDigits().Take(length));
}
public static IEnumerable<int> RandomDigits() {
var rng = new Random(System.Environment.TickCount);
while (true) yield return rng.Next(10);
}
}
or
internal class Program {
private static void Main(string[] args) {
Console.WriteLine(GetNumber(12));
}
public static string GetNumber(int length) {
var rng = new Random(Environment.TickCount);
return string.Concat(Enumerable.Range(0, length).Select((index) => rng.Next(10).ToString()));
}
}
Easy? yes. Most efficient? maybe not.
var r = new Random();
z = 12
Enumerable.Range(1,z).Select(x => r.Next(10).ToString()).Aggregate((x,y) => x + y)
maybe not that efficient but looks cool :D
If you want to length of the code be predefind use:
public static string GenerateNewCode(int length)
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
// keep going until we find a unique code
do
{
newCode = random.Next(Math.Pow(10,length-1), Math.Pow(10,length)-1).ToString("0000")
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
if you want the length to be random use this:
public static string GenerateNewCode()
{
string newCode = String.Empty;
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random random = new Random(seed);
int length = random.Next(9,12);
// keep going until we find a unique code
do
{
newCode = random.Next(Math.Pow(10,length-1), Math.Pow(10,length)-1).ToString("0000")
}
while (!ConsumerCode.isUnique(newCode));
// return
return newCode;
}
I would do it like this:
List<int> li = new List<int>();
for(int i = 0; i<=9999; i++)
{
li.Add(i);
}
List<int> liRandom = new List<int>();
for(int i = 0; i<= 9999; i++) //replace 9999 with a number you need to gen
{
int randomIndex = rand.Next(0,li.Length);
liRandom.Add(li[randomIndex]);
li.Remove(li[randomIndex]);
}// liRandom now contains needed numbers
Hope you got the idea :)
and this one might actually be efficient
public static string GetNumber(int length) {
var rng = new Random(Environment.TickCount);
var number = rng.NextDouble().ToString("0.000000000000").Substring(2, length);
return number;
}
works up to 12 characters, may work up to 16.
There is a library to generate Random numbers, so why isn't there a library for generation of random strings?
In other words how to generate a random string, and specify desired length, or better, generate unique string on specification you want i.e. specify the length, a unique string within my application is enough for me.
I know I can create a Guid (Globally Unique IDentifier) but those are quite long, longer they need to be.
int length = 8;
string s = RandomString.NextRandomString(length)
uniquestringCollection = new UniquestringsCollection(length)
string s2 = uniquestringCollection.GetNext();
I can't recall where I got this, so if you know who originally authored this, please help me give attribution.
private static void Main()
{
const string AllowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz##$^*()";
Random rng = new Random();
foreach (string randomString in rng.NextStrings(AllowedChars, (15, 64), 25))
{
Console.WriteLine(randomString);
}
Console.ReadLine();
}
private static IEnumerable<string> NextStrings(
this Random rnd,
string allowedChars,
(int Min, int Max)length,
int count)
{
ISet<string> usedRandomStrings = new HashSet<string>();
(int min, int max) = length;
char[] chars = new char[max];
int setLength = allowedChars.Length;
while (count-- > 0)
{
int stringLength = rnd.Next(min, max + 1);
for (int i = 0; i < stringLength; ++i)
{
chars[i] = allowedChars[rnd.Next(setLength)];
}
string randomString = new string(chars, 0, stringLength);
if (usedRandomStrings.Add(randomString))
{
yield return randomString;
}
else
{
count++;
}
}
}
How about-
static Random rd = new Random();
internal static string CreateString(int stringLength)
{
const string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!#$?_-";
char[] chars = new char[stringLength];
for (int i = 0; i < stringLength; i++)
{
chars[i] = allowedChars[rd.Next(0, allowedChars.Length)];
}
return new string(chars);
}
How about
string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)new Random().Next(127)));
or
var rand = new Random();
string.Join("", Enumerable.Repeat(0, 100).Select(n => (char)rand.Next(127)));
Random string using Concatenated GUIDs
This approach uses the minimum number of concatenated GUIDs to return a random string of the desired number of characters.
/// <summary>
/// Uses concatenated then SubStringed GUIDs to get a random string of the
/// desired length. Relies on the randomness of the GUID generation algorithm.
/// </summary>
/// <param name="stringLength">Length of string to return</param>
/// <returns>Random string of <paramref name="stringLength"/> characters</returns>
internal static string GetRandomString(int stringLength)
{
StringBuilder sb = new StringBuilder();
int numGuidsToConcat = (((stringLength - 1) / 32) + 1);
for(int i = 1; i <= numGuidsToConcat; i++)
{
sb.Append(Guid.NewGuid().ToString("N"));
}
return sb.ToString(0, stringLength);
}
Example output with a length of 8:
39877037
2f1461d8
152ece65
79778fc6
76f426d8
73a27a0d
8efd1210
4bc5b0d2
7b1aa10e
3a7a5b3a
77676839
abffa3c9
37fdbeb1
45736489
Example output with a length of 40 (note the repeated '4' - in a v4 GUID, thee is one hex digit that will always be a 4 (effectively removing 4 bits) -- the algorithm could be improved by removing the '4' to improve randomness, given that the returned length of the string can be less than the length of a GUID (32 chars)...):
e5af105b73924c3590e99d2820e3ae7a3086d0e3
e03542e1b0a44138a49965b1ee434e3efe8d063d
c182cecb5f5b4b85a255a397de1c8615a6d6eef5
676548dc532a4c96acbe01292f260a52abdc4703
43d6735ef36841cd9085e56f496ece7c87c8beb9
f537d7702b22418d8ee6476dcd5f4ff3b3547f11
93749400bd494bfab187ac0a662baaa2771ce39d
335ce3c0f742434a904bd4bcad53fc3c8783a9f9
f2dd06d176634c5b9d7083962e68d3277cb2a060
4c89143715d34742b5f1b7047e8107fd28781b39
2f060d86f7244ae8b3b419a6e659a84135ec2bf8
54d5477a78194600af55c376c2b0c8f55ded2ab6
746acb308acf46ca88303dfbf38c831da39dc66e
bdc98417074047a79636e567e4de60aa19e89710
a114d8883d58451da03dfff75796f73711821b02
C# Fiddler Demo: https://dotnetfiddle.net/Y1j6Dw
I commonly use code like the following to generate a random string:
internal static class Utilities {
static Random randomGenerator = new Random();
internal static string GenerateRandomString(int length) {
byte[] randomBytes = new byte[randomGenerator.Next(length)];
randomGenerator.NextBytes(randomBytes);
return Convert.ToBase64String(randomBytes);
}
}
This will create a Base64 encoded string of the random bytes generated by the random object. It isn't thread safe so multiple threads will have to lock around it. Additionally I use a static Random object so two calls to the method at the same time won't get the same initial seed.
A library for generating random strings wouldn't be very useful. It would either be too simple, so that you often need to replace it anyway, or too complex in order to be able to cover any possible situation, that you replace it because it's to complicated to use.
Creating random strings is quite easy by using the random geneator for numbers, given the exact details of your needs. It's just more efficient to write the code specifically for each situation.
If you want a unique string, there is two possibilities. You can either keep every random string that is created, so that you can check for uniqueness, or you can make it really long so that it's incredibly unlikely that there would be duplicates. A GUID does the latter (which explains why it's so long), so there is already an implementation for that.
Sometimes a random string can be useful in something like a unit test, if it was me I would add the AutoFixture nuget package and then do something like this.
In my example I need a 121 character string...
var fixture = new Fixture();
var chars = fixture.CreateMany<char>(121).ToArray();
var myString = new string(chars);
If this wasn't in a unit test then I'd create myself a nuget package and use Autofixture in that, or something else if I needed only certain character types.
You've sort of answered your own question; there is no RandomString() function because you can use a random number generator to generate a string easily.
1) Make the range of numbers between the ASCII characters that you wish to include
2) Append each character to a string until the desired length is reached.
3) Rise and repeat for each string needed (add them to an array, etc.)
Surely that'd do it?
How about something like this...
static string GetRandomString(int lenOfTheNewStr)
{
string output = string.Empty;
while (true)
{
output = output + Path.GetRandomFileName().Replace(".", string.Empty);
if (output.Length > lenOfTheNewStr)
{
output = output.Substring(0, lenOfTheNewStr);
break;
}
}
return output;
}
Output
static void Main(string[] args)
{
for (int x = 0; x < 10; x++)
{
string output = GetRandomString(20);
Console.WriteLine(output);
}
Console.ReadKey();
}
r323afsluywgozfpvne4
qpfumdh3pmskleiavi3x
nq40h0uki2o0ptljxtpr
n4o0rzwcz5pdvfhmiwey
sihfvt1pvofgxfs3etxg
z3iagj5nqm4j1f5iwemg
m2kbffbyqrjs1ad15kcn
cckd1wvebdzcce0fpnru
n3tvq0qphfkunek0220d
ufh2noeccbwyfrtkwi02
Online Demo: https://dotnetfiddle.net/PVgf0k
References
• https://www.dotnetperls.com/random-string
public static String getAlphaNumericString(int n) {
String AlphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "abcdefghijklmnopqrstuvxyz";
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
// generate a random number between
// 0 to AlphaNumericString variable length
int index = (int) (AlphaNumericString.length() * Math.random());
// add Character one by one in end of sb
sb.append(AlphaNumericString.charAt(index));
}
return sb.toString();
}
Here is some modification from above answers.
private static string GetFixedLengthStrinng(int len)
{
const string possibleAllChars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789!##$%^&*()_+{}:',.?/";
StringBuilder sb = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i < len; i++)
{
sb.Append(possibleAllChars[randomNumber.Next(0, possibleAllChars.Length)]);
}
return sb.ToString();
}