C#.net實驗一 控制檯應用程序——隨機數

實驗一 控制檯應用程序——隨機數

 信息學院 網絡工程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();

        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章