实验要求:
1)防伪码的组成
防伪码由以下字符组成:0123456789ABCDEFGHJKLMNPQRSTUVWXYZ
(数字1和字母I相近、数字0和字母O相近,所以去掉字母I和字母O。全部字母大写) \
2)在命令行中输入2个参数,分别是:
防伪码长度
防伪码个数
例如:在命令行中调用程序为:学号.exe 10 10000
指的是防伪码长度为10,生成10000个防伪码。
3)防伪码的生成及注意事项
防伪码的长度由命令行参数决定;
所生成的防伪码不能重复(按照以上例子,生成了10000个防伪码,这10000个防伪码就肯定不能重复)。
设计思路:
1)随机数生成: Random,种子的选择问题,可用默认的、GUID、RNGCryptoServiceProvider等等作为随机数种子
2)怎么样保证,新生成的防伪码和以生成的防伪码有没有重复: 使用Hashtable,或使用Hashset。后来发现使用Hashset的效率会比Hashtable要高。
3)stringBuilder的用法,试试用string和stringBuilder有什么不同(后面揭晓)
核心代码:
public static void calculTime(int codeLength, int codeCount)
{
Stopwatch timer = new Stopwatch(); //计算时间.
string strTableChar = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
System.Text.StringBuilder newRandom = new System.Text.StringBuilder(codeLength);
Hashtable hashtable = new Hashtable(); //哈希表
Random r = new Random();
byte[] buffer = Guid.NewGuid().ToByteArray();
int iSeed = BitConverter.ToInt32(buffer, 0);
r = new Random(iSeed); //利用GUID作为种子产生的随机数能更加随机
timer.Start();
for (int i = 0; i < codeCount; i++)
{
newRandom.Clear();
for (int j = 0; j < codeLength; j++)
{
newRandom.Append(strTableChar[r.Next(0, strTableChar.Length-1)]);//随机生成防伪码字符串
}
//使用hashtable判断重复
if (hashtable.Contains(newRandom.ToString()))
{
i--; //若有重复则重新产生
}
else
{
hashtable.Add(newRandom.ToString(), " ");
}
}
timer.Stop();
double dMilliseconds = timer.Elapsed.TotalMilliseconds;
Console.WriteLine("生成个数为:{0},运行时间为:{1}", codeCount, dMilliseconds);
Console.ReadKey();
后来将Hashtable改为Hashset后,发现效率高了不少,具体的区别我一时还未能说清: Hashtable继承Map接口,实现一个key-value映射的哈希表。HashSet实现了Set接口,Set是一种不包含重复的元素的Collection(请参见http://www.blogjava.net/fisher/archive/2006/12/13/87398.html)。
string和stringBuilder有什么不同?
string类由于具有不可变性(即对一个string对象进行任何更改时,其实都是创建另外一个string类的对象),所以当需要频繁的对一个string类对象进行更改的时候,建议使用StringBuilder类,StringBuilder类的原理是首先在内存中开辟一定大小的内存空间,当对此StringBuilder类对象进行更改时,如果内存空间大小不够,会对此内存空间进行扩充,而不是重新创建一个对象,这样如果对一个字符串对象进行频繁操作的时候,不会造成过多的内存浪费,其实本质上并没有很大区别,都是用来存储和操作字符串的,唯一的区别就在于性能上。