C#.net实验一 控制台应用程序——随机数

5 篇文章 0 订阅
4 篇文章 0 订阅

实验一 控制台应用程序——随机数

 信息学院 网络工程3班 黎健成 201130720310

一.    实验要求

这是一个实际的项目衍生出来的核心算法之一。防伪码是我们现在经常在商品上看到的防伪手段之一,现在需要编写一个防伪码生成器,按照输入参数生成防伪码,并且把生成的时间及指定的防伪码输出。

1)防伪码的组成

防伪码由以下字符组成:0123456789ABCDEFGHJKLMNPQRSTUVWXYZ

(数字1和字母I相近、数字0和字母O相近,所以去掉字母I和字母O。全部字母大写)

2)在命令行中输入2个参数,分别是:

防伪码长度,防伪码个数

例如:在命令行中调用程序为:学号.exe 10 10000

指的是防伪码长度为10,生成10000个防伪码。

3)防伪码的生成及注意事项

防伪码的长度由命令行参数决定;

所生成的防伪码不能重复(按照以上例子,生成了10000个防伪码,这10000个防伪码就肯定不能重复)。

二.    设计思路

1.      首先根据格输入“exe 防伪码长度 防伪码个数”读入防伪码的个数,由于C#不支持在一行里面读入两个数字,所以写了函数来实现这一功能。

核心代码:

public static void ReadKeys(ref int icount, ref int ilength)

       {

            try

            {

                string[] str =Console.ReadLine().Split(' ');//根据空格拆分读入字符串

                icount =Convert.ToInt32(str[0]);

 

                if (str.Length > 1)//如果查分到两个字符串,即同时输入了两个参数

                {

                    ilength =Convert.ToInt32(str[1]);

                }

                else//继续读下一个参数

                {

                    ilength =Convert.ToInt32(Console.ReadLine());

                }

            }

            catch (Exception ex)//如果输入有误,抛出异常      

            {

                throw newException(ex.Message);

            }

        }

2.     接着根据防伪码的长度(icount)和个数(ilength)产生防伪码。并将产生的防伪码加入到哈希集(hashSet)中。将防伪码插入哈希集中,如果没有加入成功,即哈希集中没有重复的防伪码则总个数加1。循环地生成规定长度的防伪码直到总个数达到规定的要求。

核心代码:

       public static voidPlayRandom(int icount, int ilength)

        {

            try

            {

                int i = 0;

                HashSet<string> hashSet =new HashSet<string>();

                Random ra = newRandom(DateTime.Now.Millisecond);

                StringBuilder strBuilder = newStringBuilder();

 

                while (i < ilength)//当没有达到规定长度的时候继续生成防伪码

                {

                    strBuilder.Remove(0,strBuilder.Length);

 

                    for (int j = 0; j <icount; j++)

                    {

                       strBuilder.Append(randomList[ra.Next(randomList.Length)]);

                    }//根据长度,产生防伪码

 

                    if(hashSet.Add(strBuilder.ToString())) i++;//如果没有重复,总数加1

 

                }

            }

            catch (Exception ex)

            {

                throw newException(ex.Message);

            }

 

        }程序运行效果图


1.第一组测试数据(10 10000),见图1。

第一张图片

2.第二组测试数据(20 1000000),见图2。

第二张图片
3.第三组测试数据(50 1000000),见图3。

第三张图片

三.    实验总结

作为本学期的第一个作业,乍一看上去,还是挺困难的。但是,看看QQ群上的同学们的讨论,加上在网络上搜索的算法,也给了我不少的提示。

原先以为这是一个非常复杂的过程,但是实际编程的时候确发现还是比较容易实现功能的。但是耗费大量时间才出结果的确令人感到不爽。为此,甚至还动用到了多线程,但是发现结果却还更慢了。于是只好放弃。

最后,在我请教了我班的大神之后,我改用了利用哈希表中的Contains方法直接比较两个防伪码的哈希码,而不是用ContainsValue直接比较两个防伪码是否相同,这样,由原先的O(n)时间复杂度降为O(1),就可以发现防伪码是否重复。

后来,在课上听老师说了哈希集(HashSet)的使用方法,然后就将容器由哈希表改为了哈希集,结果速度又有了很大的提升,更加使我感到无比地兴奋!

总体来说,这次的实验让我对哈希表和哈希集的运用有所加深,也深刻体会到了其便捷。




附完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections;

namespace test1
{
    class Program
    {
        public static string randomList = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
        public static void Pause()
        {
            Console.Write("请键入任意字符以结束……");
            Console.ReadKey(true);
        }
        public static void ReadKeys(ref int icount, ref int ilength)
        {
            try
            {
                Console.WriteLine("输入格式:长度 个数");

                string[] str = Console.ReadLine().Split(' ');
                icount = Convert.ToInt32(str[0]);

                if (str.Length > 1)
                {
                    ilength = Convert.ToInt32(str[1]);
                }
                else
                {
                    ilength = Convert.ToInt32(Console.ReadLine());
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public static void PlayRandom(int icount, int ilength)
        {
            try
            {
                int i = 0;
                HashSet<string> hashSet = new HashSet<string>();
                Random ra = new Random(DateTime.Now.Millisecond);
                StringBuilder strBuilder = new StringBuilder();

                while (i < ilength)
                {
                    strBuilder.Remove(0, strBuilder.Length);

                    for (int j = 0; j < icount; j++)
                    {
                        strBuilder.Append(randomList[ra.Next(randomList.Length)]);
                    }

                    if (hashSet.Add(strBuilder.ToString())) i++;

                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

        static void Main(string[] args)
        {
            Stopwatch timer1 = new Stopwatch();
            int icount = 0, ilength = 0;

            try
            {
                ReadKeys(ref icount, ref ilength);//读入防伪码长度,个数

                timer1.Start();

                PlayRandom(icount, ilength);//产生随机防伪码
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                timer1.Stop();
                double dMilliseconds = timer1.Elapsed.TotalMilliseconds;
                Console.WriteLine("生成个数为:{0},运行时间为:{1}ms", ilength, dMilliseconds);
            }
            Pause();

        }
    }
}


这是老师做过的一个项目,抽取了当中核心之一的内容给大家试试,有些难度。 1、实验目的 1)掌握C#命令行参数的接收; 2)掌握C#中的泛型用法; 3)掌握C#的基本流程语句; 4)掌握C#随机数生成; 5)了解C#的异常处理流程; 6)掌握C#的计时器及对代码的性能优化。 7)本实验注重算法实现,在实现功能的前提下,尽量优化计算速度。 2、实验要求 这是一个实际的项目衍生出来的核心算法之一。防伪码是我们现在经常在商品上看到的防伪手段之一,现在需要编写一个防伪码生成器,按照输入参数生成防伪码,并且把生成的时间及指定的防伪码输出。 1)防伪码的组成 防伪码由以下字符组成:0123456789ABCDEFGHJKLMNPQRSTUVWXYZ (数字1和字母I相近、数字0和字母O相近,所以去掉字母I和字母O。全部字母大写) \ 2)在命令行中输入2个参数,分别是: 防伪码长度 防伪码个数 例如:在命令行中调用程序为:学号.exe 10 10000 指的是防伪码长度为10,生成10000个防伪码。 3)防伪码的生成及注意事项 防伪码的长度由命令行参数决定; 所生成的防伪码不能重复(按照以上例子,生成了10000个防伪码,这10000个防伪码就肯定不能重复)。 3、提交内容 1)请把整个项目源代码压缩为RAR文件进行提交 2)运行: a) exe 10 10000 b) exe 20 1000000 c) exe 50 1000000 (即防伪码长度为10,10000个;长度为20,一百万个;长度为50,一百万个)共三个测试用例,记下时间,贴在“自评备注”中,格式如下: a) 时间;b) 时间;c) 时间 下面可以写写自己的感想等 4、实验评分 程序能运行,按照全部要求实现:A及以上 程序能运行,但有Bug的(指生成重复的防伪码等):B 程序不能运行,但有思路的:C及以下 0:发现抄袭行为,本次实验0分,累计两次,平时成绩0分。 额外要求:代码命名必须有一定规范、代码格式必须靓仔,歪歪扭扭的扣分。 5、采用的函数及思路 1)开发时,在解决方案中,鼠标右键选择项目,然后点选“属性”,在“调试”项目中的“命令行参数”里面,可以预先输入需在命令行接收的参数,这样开发的时候就可以直接读入了。注意,不用对这些参数进行校验,默认输入的都是正确的参数,注意程序运行时的异常处理。 2)程序运行计时 在最上面加入using System.Diagnostics; 在程序头加入: Stopwatch timer1 = new Stopwatch();//计时器类 timer1.Start();//开始计时 在程序最尾加入: timer1.Stop();//停止计时 double dMilliseconds = timer1.Elapsed.TotalMilliseconds; Console.WriteLine("生成个数为:{0},运行时间为:{1}", icount, dMillisecondes); Console.ReadKey(); Stopwatch是C#一个类似秒表的东西,用来计算程序的运行时间,注意,必须按照要求,计时器在程序运行时就要开启,在结束时停止并输出结果,不能放置在其他地方。 3)防伪码生成思路 例如,有以下定义: string strTableChar = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; 生成一个从0到strTableChar.Length的数字a,然后使用strTableChar[a]就可以随机返回一个字母,重复n次(n等于防伪码的长度),这样就可以组合到一串随机字符串,也就是防伪码了。 6、思路及技巧 1)随机数生成:种子的选择问题,可用默认的、GUID、RNGCryptoServiceProvider等等作为随机数种子…… 2)怎么样保证,新生成的防伪码和以生成的防伪码有没有重复? 3)stringBuilder的用法,试试用string和stringBuilder有什么不同?听听老师的课…… 4)多次运行程序后,会不会发现程序运行速度会加快?看看这里:《告诉一个不一样的.NET Framework字符串驻留》,另外也可以找找对应.NET Framework底层实现的文章。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值