当前位置: 爱符号 - 所有分类 - 资源共享 - 文档 - C# - [身份证号码生成]细说哈希表和字典
[身份证号码生成]细说哈希表和字典  [ShenFenZhengHaoMaShengCheng]XiShuoHaXiBiaoHeZiDian
flyher 发表于:2013-07-31 10:09:22 阅读(9654)
关键词:C# C# 哈希表 哈希表 数组 数组 字典 字典 多级联动 多级联动 HashTable HashTable
摘要:本篇博文,仅仅是自己学习了一些字典和哈希表的小知识,顺便,想体验一下,没想到搞了这么多。 知识总结如下,通过本文,你需要加深如下了解: ①哈希表,字典,二维数组 的使用(超大数据的提取和写入中作为缓存,后面例子将用到); ②文件写入和读取(后面将做个超简单的文件浏览器雏形); ③下拉表绑定和多级联动; ④窗体之间的传值,正传和反传; ⑤其它

    一个小小的问题引发的联想,仅仅是为了学习一下哈希表和字典,没想到一下子写了这么多,姑且做个总结吧。实在想不出该用什么标题,随便聊聊。

1.添加编号、省份和编号、地区 对照信息:

这个需要用到键值对,想想List,只能用到List<string>,倒是没见过使用List<string ,string>刚开始想到了哈希表,然后又想到二维数组和字典,斟酌再三,于是选中字典。理由如下

二维数组在长度和添加更多的省市对照信息时候需要考虑不少,搞不定多了就晕的要超出长度了;

HashTable在遍历时会大乱顺序;

DictionayHashTable比较字典速度更快。(在某个博客看到的)

首先,我们来添加省份对照信息,这方面,百度文库可以出来:

初始化:

1         // 使用字典初始化

2         Dictionary<string, string> dtpro = new Dictionary<string, string>();//省份

3         Dictionary<string, string> dtplace = new Dictionary<string, string>();//城市

 

添加编号、省份对照表:

 1         /// <summary>

 2         /// 添加编号、省份对照信息

 3       /// xxx.add("xx");让我想起了List<string>中的add

 4         /// </summary>

 5         public void adddtpro()

 6         {

 7             #region 添加省份信息

 8           dtpro.Add("11", "北京市");

 9             dtpro.Add("12", "天津市");

10             dtpro.Add("13", "河北省");

11             dtpro.Add("14", "山西省");

12             dtpro.Add("15", "内蒙古自治区");

13             dtpro.Add("21", "辽宁省");

14             dtpro.Add("22", "吉林省");

15             dtpro.Add("23", "黑龙江省");

16             dtpro.Add("31", "上海市");

17             dtpro.Add("32", "江苏省");

18             dtpro.Add("33", "浙江省");

19             dtpro.Add("34", "安徽省");

20             dtpro.Add("35", "福建省");

21             dtpro.Add("36", "江西省");

22             dtpro.Add("37", "山东省");

23             dtpro.Add("41", "河南省");

24             dtpro.Add("42", "湖北省");

25             dtpro.Add("43", "湖南省");

26             dtpro.Add("44", "广东省");

27             dtpro.Add("45", "广西壮族自治区");

28             dtpro.Add("46", "海南省");

29             dtpro.Add("50", "重庆市");

30             dtpro.Add("51", "四川省");

31             dtpro.Add("52", "贵州省");

32             dtpro.Add("53", "云南省");

33             dtpro.Add("54", "西藏自治区");

34             dtpro.Add("61", "陕西省");

35             dtpro.Add("62", "甘肃省");

36             dtpro.Add("63", "青海省");

37             dtpro.Add("64", "宁夏回族自治区");

38             dtpro.Add("65", "新疆维吾尔自治区");

39             dtpro.Add("71", "台湾省");

40             dtpro.Add("81", "香港特别行政区");

41             dtpro.Add("82", "澳门特别行政区");

42             #endregion

43         }

View Code

添加编号、城市对照表:(改的手麻,卡,还好有正则替换的记事本)

1         /// <summary>

2         /// 添加编号、城市对照信息

3         /// </summary>

4         public void adddtplace()

5         {

6             //大约3400多条,

7         }

 

这样,就把省份和城市的信息初始化了,需要时调用就行,先别急,这是我们的准备工作。

2.检查身份证号码前两位(省份)

    既然把省份和城市信息搞定,那么我们是不是得准备一个附加功能,提供对身份信息的查询呢,这样,就意味着要检查前两位号码;因为信息不多,姑且用数组尝尝味道把,

 1         /// <summary>

 2         /// 检查前2

 3         /// </summary>

 4         /// <param name="str">2个数字</param>

 5         /// <returns>返回省份</returns>

 6         public string checkpro(string str)

 7         {

 8             string[,] proarray = new string[,] { { "北京市", "11" }, { "天津市", "12" }, { "河北省", "13" }, { "山西省", "14" }, { "内蒙古自治区", "15" }, { "辽宁省", "21" }, { "吉林省", "22" }, { "黑龙江省", "23" }, { "上海市", "31" }, { "江苏省", "32" }, { "浙江省", "33" }, { "安徽省", "34" }, { "福建省", "35" }, { "江西省", "36" }, { "山东省", "37" }, { "河南省", "41" }, { "湖北省", "42" }, { "湖南省", "43" }, { "广东省", "44" }, { "广西壮族自治区", "45" }, { "海南省", "46" }, { "重庆市", "50" }, { "四川省", "51" }, { "贵州省", "52" }, { "云南省", "53" }, { "西藏自治区", "54" }, { "陕西省", "61" }, { "甘肃省", "62" }, { "青海省", "63" }, { "宁夏回族自治区", "64" }, { "新疆维吾尔自治区", "65" }, { "台湾省", "71" }, { "香港特别行政区", "81" }, { "澳门特别行政区", "82" } };

 9        

10             string prostr = "";

11

12             for (int i = 0; i < proarray.Length / 2; i++)

13             {

14                 if (proarray[i, 1] == str)

15                 {

16                     prostr = proarray[i, 0];

17

18                     break;

19                 }

20             }

21             return prostr;

22         }

View Code

3.判断城市信息

    这里,我们提供一个对身份证编号前6位的查询方法,这样就可以查询到具体城市。

 1         /// <summary>

 2         /// 判断城市信息

 3         /// </summary>

 4         /// <param name="str">6</param>

 5         /// <returns>返回所在位置,没有则返回空</returns>

 6         public string checkplace(string str)

 7         {

 8             adddtplace();//得先初始化信息将其添加到字典

 9             //ContainsKey:这是字典中的一个方法,有点类似HashTable,我们在 1 中增加了dtplace并在上一行初始化了,现在信息已经存入字典。

10             //这里的ContainsKey是查看key里面,键值对,即键中 是否包含str

11             if (dtplace.ContainsKey(str))

12                 return dtplace[str].ToString();//返回城市名称

13             else

14                 return "";//没有则返回空

15         }

4.检查校验码

     理解校验码可以查看某百科,这是复制下来的话:

、将前面的身份证号码17位数分别乘以不同的系数。第i位对应的数为[2^(18-i)]mod11(这个是什么意思?没理解)。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
、将这17位数字和系数相乘的结果相加;
、用加出来和除以11,看余数是多少?;
、余数只可能有0 1 2 3 4 5 6 7 8 9 1011个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2
、通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的。如果余数是10,身份证的最后一位号码就是2
例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。
首先:我们得出,前17位的乘积和是189
然后:用189除以11得出的结果是17 + 2/11,也就是说余数是2
最后:通过对应规则就可以知道余数2对应的数字是x。所以,这是一个合格的身份证号码。

 好了,我们用程序生成,代码如下:

 1         /// <summary>

 2         /// 检查校验码

 3         /// </summary>

 4         /// <param name="str">输入前17</param>

 5         /// <returns>返回校验码</returns>

 6         public string checkcode(string str)

 7         {

 8             int sumno = 0;

 9             sumno += strToint(str[0].ToString()) * 7;

10             sumno += strToint(str[1].ToString()) * 9;

11             sumno += strToint(str[2].ToString()) * 10;

12             sumno += strToint(str[3].ToString()) * 5;

13             sumno += strToint(str[4].ToString()) * 8;

14             sumno += strToint(str[5].ToString()) * 4;

15             sumno += strToint(str[6].ToString()) * 2;

16             sumno += strToint(str[7].ToString()) * 1;

17             sumno += strToint(str[8].ToString()) * 6;

18             sumno += strToint(str[9].ToString()) * 3;

19

20             sumno += strToint(str[10].ToString()) * 7;

21             sumno += strToint(str[11].ToString()) * 9;

22             sumno += strToint(str[12].ToString()) * 10;

23             sumno += strToint(str[13].ToString()) * 5;

24             sumno += strToint(str[14].ToString()) * 8;

25             sumno += strToint(str[15].ToString()) * 4;

26             sumno += strToint(str[16].ToString()) * 2;

27

28             int result = sumno % 11;

29             string checkcode = "-1";

30             switch (result)

31             {

32                 case 0:

33                     checkcode = "1";

34                     break;

35                 case 1:

36                     checkcode = "0";

37                     break;

38                 case 2:

39                     checkcode = "X";

40                     break;

41                 case 3:

42                     checkcode = "9";

43                     break;

44                 case 4:

45                     checkcode = "8";

46                     break;

47                 case 5:

48                     checkcode = "7";

49                     break;

50                 case 6:

51                     checkcode = "6";

52                     break;

53                 case 7:

54                     checkcode = "5";

55                     break;

56                 case 8:

57                     checkcode = "4";

58                     break;

59                 case 9:

60                     checkcode = "3";

61                     break;

62                 case 10:

63                     checkcode = "2";

64                     break;

65                 default:

66                     checkcode = "-1";

67                     break;

68             }

69             return checkcode;

70         }

View Code

5.判断闰年

    在让用户选择日期的时候,是不是得考虑到下来列表的情况呢?

    有点类似级联表,即上述的省份和城市对照表,就是例子。当然年月日也是这样,考虑闰年中的229天和28天情况。当年份整除以4并且不能整除以100或者整除以400的情况下才是闰年。

    用代码判断吧:

 1         /// <summary>

 2         /// 判断是否闰年

 3         /// </summary>

 4         /// <param name="year">年份</param>

 5         /// <returns>返回bool</returns>

 6         public bool cheakYear(int year)

 7         {

 8             if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)

 9             {

10                 return true;

11             }

12             else

13             {

14                 return false;

15             }

16         }

6.检查年月日是否正确

    涉及到闰年中的2月。闰年229天,非闰年228天。

 1         /// <summary>

 2         /// 检查年月日是否正确

 3         /// </summary>

 4         /// <param name="str">输入前17</param>

 5         /// <returns>返回错误提示,没有错误则返回空字符串</returns>

 6         public string checkdate(string str)

 7         {

 8             int checkyear = strToint(str[6].ToString() + str[7].ToString() + str[8].ToString() + str[9].ToString());

 9             int checkmonth = strToint(str[10].ToString() + str[11].ToString());

10             int checkday = strToint(str[12].ToString() + str[13].ToString());

11

12             int year = strToint(DateTime.Now.Year.ToString());//当前年份

13             int month = strToint(DateTime.Now.Month.ToString());//当前月份

14             int day = strToint(DateTime.Now.Day.ToString());//当前几号

15

16             if (checkyear > year || checkyear + 100 < year)

17                 return "输入年份尚未生效或已经过期!";

18             else

19             {

20                 if (checkmonth < 1 || checkmonth > 12)

21                     return "月份有误!";

22                 else

23                 {

24

25                     //获取输入月份下该月份天数

26                     //判断是否闰年

27                     if (checkday < 0)

28                         return "日期有误";

29                     else

30                     {

31                         if (checkmonth == 1 || checkmonth == 3 || checkmonth == 5 || checkmonth == 7 || checkmonth == 9 || checkmonth == 11 || checkmonth == 12)

32                         {

33                             if (checkday > 31)

34                                 return "日期有误!";

35                         }

36                         if (checkmonth == 2)

37                         {

38                             if (cheakYear(checkyear) && checkday > 29)

39                             {

40                                 return "2月日期有误!";

41                             }

42                             if (!cheakYear(checkyear) && checkday > 28)

43                             {

44                                 return "2月日期有误!";

45

46                             }

47                         }

48                         if ((checkmonth == 4 || checkmonth == 6 || checkmonth == 8 || checkmonth == 10) && checkday > 30)

49                         {

50                             return "日期有误!";

51                         }

52                     }

53                     return "";

54                 }

55             }

56         }

View Code

 7.初始化省份,城市信息(级联表)

    我们的省份信息添加到字典了,城市信息也添加了,这会儿,是不是做一下将其添加到下拉列表前的准备呢。(PS:我真没想到我为什么还要定义一个ArrayList然后而不是ContainsKey判断直接传值,难道是为了绑定数据源方便么?因为写这个玩意过了去了三个月,忘了,有没有人帮我解释一下。)

1         ArrayList alpro = new ArrayList();

2         ArrayList alplace = new ArrayList();

 1         /// <summary>

 2         /// 初始化省份信息(添加到alpro中)

 3         /// </summary>

 4         /// <returns>返回省份<编号,省份>arraylist</returns>

 5         public ArrayList matchpro()

 6         {

 7             adddtpro();

 8             adddtplace();

 9             foreach (var item in dtpro)

10             {

11                 alpro.Add(new DictionaryEntry(item.Key, item.Value));

12             }

13             return alpro;

14         }

View Code

 1         /// <summary>

 2         /// 根据省份初始化城市信息(添加到alplace上)

 3         /// </summary>

 4         /// <param name="strpro">省份代号</param>

 5         /// <returns>返回城市<编号,城市>arraylist</returns>

 6         public ArrayList matchplace(string strpro)

 7         {

 8             alplace.Clear();//清空数据

 9             foreach (var item in dtplace)

10             {

11                 string itemkey = item.Key.ToString();

12                 if ((itemkey[0].ToString() + itemkey[1].ToString().ToString() == strpro))

13                 {

14                     //0000为省份代号

15                     if ((itemkey[0].ToString() + itemkey[1].ToString() + itemkey[2].ToString() + itemkey[3].ToString().ToString() != "0000"))

16                     {

17                         alplace.Add(new DictionaryEntry(item.Key, item.Value));

18                         //如果用hashtableforeach遍历再add之后会发现顺序被打乱

19                     }

20                 }

21             }

22             return alplace;

23         }

View Code

8.UI,真正的开始

以上方法我都将其保存到新建的一个类中,命名为ClassCheck.cs,仅仅作为准备工作,

下面,才算是真正的开始,看图如下:

 

其中命名

省份:cbpro

城市:cbplace

年、月、日:cbyear cbmonthcbday

性别:cbsex

生成结果的listboxlbresult

功能区:GetbtnGetcopybtnCopyRemovebtnRemoveCheckbtnCheckOutputbtnout

9.初始化省、城市、年月日、性别

初始化之前,我们先把我们刚才积累的一些方法用到这里,

实例化类,刚才我们不是把一些准备的方法放到了cs里面了么,现在先准备好:

1         ClassCheck clcheck = new ClassCheck();

2         int choseplace = 0;//当没选择城市时初始化为0,后面要用

先上简单点的年月日、性别 初始化

.添加年份:

 1         //添加年份

 2         private void beginyear()

 3         {

 4             //1950-当前年份

 5             int year = DateTime.Now.Year;

 6             for (int i = 1950; i <= year; i++)

 7             {

 8                 cbyear.Items.Add(i);

 9             }

10         }

View Code

.添加月份:

 1         //添加月份

 2         private void beginmonth()

 3         {

 4             //1-当前月

 5             //两种情况,当前年以前,1-12个月;算了,麻烦,又得判断,就用12个月吧,这样是不是还没出生的都有了

 6             //1-12

 7             //int month = DateTime.Now.Month;

 8             for (int i = 1; i <= 12; i++)

 9             {

10                 cbmonth.Items.Add(i);

11             }

12         }

View Code

.添加当月天数:

 1         //添加当月天数

 2         private void beginday()

 3         {

 4             //分为闰年 2月判断

 5             //这里是不是就用到了类中的方法了

 6             bool byear = clcheck.cheakYear(Convert.ToInt32(cbyear.Text.Trim()));

 7             switch (cbmonth.Text)

 8             {

 9                 case "4":

10                 case "6":

11                 case "8":

12                 case "10":

13                     for (int i = 1; i <= 30; i++)

14                     {

15                         cbday.Items.Add(i);

16                     }

17                     break;

18                 case "2":

19                     if (byear)

20                     {

21                         for (int i = 1; i <= 29; i++)

22                         {

23                             cbday.Items.Add(i);

24                         }

25                     }

26                     else

27                     {

28                         for (int i = 1; i <= 28; i++)

29                         {

30                             cbday.Items.Add(i);

31                         }

32

33                     }

34                     break;

35                 default:

36                     for (int i = 1; i <= 31; i++)

37                     {

38                         cbday.Items.Add(i);

39                     }

40                     break;

41

42             }

43         }

View Code

.添加性别:

1         //添加性别

2         private void beginsex()

3         {

4             cbsex.Items.Add("");

5             cbsex.Items.Add("");

6         }

View Code

.两级联动

 根据省份(编号)匹配城市(编号)(前两个数字匹配),绑定到下拉列表中

 1         /// <summary>

 2         /// 两级联动,根据省份编号匹配城市(前两个数字)

 3         /// </summary>

 4         /// <param name="strpro"></param>

 5         private void begindata(string strpro)

 6         {

 7             ArrayList alplace = clcheck.matchplace(strpro);

 8             cbplace.DataSource = alplace;

 9             cbplace.DisplayMember = "value";

10             cbplace.ValueMember = "key";

11         }

View Code

.界面真正的初始化(是不是用到了上面的两级联动的方法了,其实就是传参,没啥高明的)

改动省份城市变化

 1         /// <summary>

 2         /// 改动省份时城市变动

 3         /// </summary>

 4         private void cbpro_SelectedValueChanged(object sender, EventArgs e)

 5         {

 6             //窗体第一次加载时会自动调用该事件,因为窗体加载时初始化了数据,而此时文本框里是空的,所以调用不了数据

 7             cbplace.DataSource = null;

 8

 9             //begindata(cbpro.SelectedValue.ToString());

10             if (choseplace > 1)

11             {

12                 cbplace.DataSource = null;

13                 string strpro = cbpro.SelectedValue.ToString();

14                 begindata(strpro);

15             }

16             else

17             {

18                 choseplace++;

19             }

20         }

View Code

改动月份日期变化(如不写此变化会不会出现了个231日的情况呢)

 1         /// <summary>

 2         /// 改变月份时日期变动

 3         /// </summary>

 4         private void cbmonth_SelectedIndexChanged(object sender, EventArgs e)

 5         {

 6             cbday.DataSource = null;

 7             cbday.Items.Clear();

 8             beginday();

 9             //begindata(cbpro.SelectedValue.ToString());

10             //if (choseplace > 1)

11             //{

12             //    cbmonth.DataSource = null;

13             //    string strpro = cbpro.SelectedValue.ToString();

14             //    begindata(strpro);

15             //}

16             //else

17             //{

18             //    choseplace++;

19             //}

20         }

View Code

 改动年份时日期变化

1         /// <summary>

2         /// 改动年份时日期变动

3         /// </summary>

4         private void cbyear_SelectedIndexChanged(object sender, EventArgs e)

5         {

6             cbday.DataSource = null;

7             cbday.Items.Clear();

8             beginday();

9         }

View Code

.初始化我们的界面吧

 1         private void frmidentity_Load(object sender, EventArgs e)

 2         {

 3             //初始化省份数据源

 4             ArrayList alpro = clcheck.matchpro();

 5             cbpro.DataSource = alpro;

 6             cbpro.DisplayMember = "value";

 7             cbpro.ValueMember = "key";

 8             //设置默认省份

 9             cbpro.SelectedIndex = 0;

10             //设置默认城市

11             begindata(cbpro.SelectedValue.ToString());

12             //设置默认年份

13             beginyear();

14             cbyear.SelectedIndex = 0;

15             //设置默认月份

16             beginmonth();

17             cbmonth.SelectedIndex = 0;

18             //设置默认天数

19             beginday();

20             cbday.SelectedIndex = 0;

21             //设置默认性别

22             beginsex();

23             cbsex.SelectedIndex = 0;

24             //ComboBox控件的DrawMode属性为:OwnerDrawVariable ,然后设置ItemHeight属性你要求的高度。不然下拉下来太长岂不是很像那个...你懂得的...

25             //cbpro.Height = 20;

26             cbpro.DropDownHeight = 100;

27             cbplace.DropDownHeight = 100;

28             cbyear.DropDownHeight = 100;

29             cbmonth.DropDownHeight = 100;

30             cbday.DropDownHeight = 100;

31

32             this.Opacity = 0.95;

33         }

View Code

10.顺序码

      写到这里,我们是不是忘了身份证号码中一个重要的3位顺序码呢,好吧,这里加上,不习惯可以改到cs类中去。顺序码=2+性别1位。

 1         //顺序码=2+性别1

 2         //随机生成5个不重复的顺序码怎么玩?

 3         private string beginturn()

 4         {

 5             Random rm=new Random();

 6             int turnfirint = rm.Next(0, 100);

 7             string turnfirstr,turnsexstr;

 8             string[] str = new string[5];

 9             if (turnfirint < 10)

10             {

11                 turnfirstr = "0" + turnfirint.ToString();

12             }

13             else

14             {

15                 turnfirstr = turnfirint.ToString();

16             }

17

18             if (cbsex.SelectedIndex == 0)//

19             {

20                 turnsexstr = (2 * rm.Next(0, 5) + 1).ToString(); ;

21

22             }

23             else

24             {

25                 turnsexstr = (2 * rm.Next(0, 5)).ToString();

26             }

27

28             return turnfirstr + turnsexstr;

29         }

View Code

PS:每次 随机生成5 不同 顺序码是不是更刺激?不过貌似有点麻烦诶,有没有好的办法。

不要告诉我是把数字分成5等分,每次取出一个等份,连取5次,合起来5个。有兴趣的可以试试更高端的。

11.生成身份证号码(二代)

好了,总算把所有的准备工作做好,调用吧,生成结果,就是符合验证的号码。但是,不一定此号码存在,仅仅可以验证成功而已,其它的,就不在本篇博文范围了。

生成结果:

 1         //生成结果

 2         private string getresule()

 3         {

 4             string strplace= cbplace.SelectedValue.ToString();

 5             string strbir,strmonth,strday;

 6             if(cbmonth.Text.Length<2)

 7             {

 8                 strmonth="0"+cbmonth.Text.ToString();//选择的月是一位数要在前面加0

 9             }

10             else

11             {

12                 strmonth=cbmonth.Text.ToString();

13             }

14             if(cbday.Text.Length<2)

15             {

16                 strday="0"+cbday.Text.ToString();

17             }

18             else

19             {

20                 strday=cbday.Text.ToString();

21             }

22

23             strbir=cbyear.Text.ToString()+strmonth+strday;

24             string strfir=strplace+strbir+beginturn();

25             string strall=strfir+clcheck.checkcode(strfir);

26             return strall;

27         }

View Code

1 lbresult.Items.Add(getresule());

12.添加特效

    这样就结束了么,我们是不是还添加上一些小功能和特效呢?还有,cs中这个么多准备可不能浪费啊。

    添加透明的提示窗体,效果如图:

copy成功,或者导出成功,是不是要加点啥呢,总比MessageBox漂亮吧。

要实现的功能:弹出透明窗体 渐变提示,自动渐变消失。

好了,我们在项目中  添加=>用户控件 ,我的命名为 F_Sign.cs

给控件上添加上label标签:lbsign,添加时间控件(渐变功能)timer1

F_Sign.cs load添加如下代码:

1         private void Form_CopySign_Load(object sender, EventArgs e)

2         {

3             this.timer1.Enabled = true;//激活时间控件

4             this.Opacity = 1;//窗体透明度为1,即完全不透明

5         }

timerTick事件添加:

 1         private void timer1_Tick(object sender, EventArgs e)

 2         {

 3             if (this.Opacity > 0.5)

 4             {

 5                 this.Opacity = this.Opacity - 0.08;

 6             }

 7             else

 8             {

 9                 Close();

10             }

11             //意思就是当窗体的透明度大于0.5时透明度以0.08的速度递减;否则就关闭窗体

12         }

重载窗体函数,我们的提示信息狠多,肯定不能单一,所以,这就涉及到两个窗体之间的传参:

 1         public F_Sign(int sign)

 2         {

 3             InitializeComponent();

 4             this.Opacity = 0.9;

 5             if(sign==0)

 6             {

 7                 lbsign.Text = "Failed!";

 8             }

 9             else if (sign == 1)

10             {

11                 lbsign.Text = "Success!";

12             }

13             else if (sign == 2)

14             {

15                 lbsign.Text = "Wrong number!";

16             }

17             else if (sign == 3)

18             {

19                 lbsign.Text = "No chose!";

20             }

21         }

View Code

当传过来的是0,我们理解我操作失败;1是成功;2是号码错误(用于验证身份证号码);3是你没有选择(用户复制时没有选择生成的特定号码)

     窗体传值,从主窗体传到新建窗体,这个不难,大家可以自己学习。倒是从新窗体再把值传到主窗体,这个难度不小,用属性倒是不行的,这个需要深究了。好了,我们先上代码,萨后再在其它功能中添加主窗体和新窗体之间的传值,把你传晕。

     复制功能和小特效展示:

 1         /// <summary>

 2         /// 复制

 3         /// </summary>

 4         private void btnCopy_Click(object sender, EventArgs e)

 5         {

 6             try

 7             {

 8                 Clipboard.SetDataObject(lbresult.SelectedItem);

 9                 F_Sign frm = new F_Sign(1);//这不是就是上面的1

10                 frm.ShowDialog();

11             }

12             catch (Exception err)

13             {

14                 //出现错误就复制失败

15                 F_Sign frm = new F_Sign(0);//0在这里

16                 frm.ShowDialog();               

17             }

18         }

上图的提示效果完美完成,

13.添加移除功能

    之所以要说到移除,有的同学说,很简单的码,清空Listbox不就OK了,这里我们要实现的是选中一行移除,移除之后我们的焦点一定还要在选中的行上面。但是这时如果移除的下面行没了呢?我们是不是还得把选中的焦点上移呢?

    看代码:

 1         /// <summary>

 2         /// 移除选中

 3         /// </summary>

 4         private void btnRemove_Click(object sender, EventArgs e)

 5         {

 6             //try{}catch{}捕获异常,话说去年没毕业的时候面试,还得一个C++的面试官刁难了一次,很恶心,自己不懂还来和我抬杠,诶,没办法诶。

 7             try

 8             {

 9                 int indexbegin = lbresult.SelectedIndex;

10                 lbresult.Items.Remove(lbresult.SelectedItem);

11                 if (lbresult.Items.Count == 0)

12                 {

13                     return;

14                 }

15                 //MessageBox.Show(lbresult.SelectedIndex.ToString());

16                 if (indexbegin == 0)

17                 {

18                     lbresult.SelectedIndex = 0;

19                 }

20                 else

21                 {

22                     //选中的为最后一个

23                     if (indexbegin == lbresult.Items.Count - 1)

24                     {

25                         lbresult.SelectedIndex = indexbegin - 1;

26                     }

27                     else

28                     {

29                         //MessageBox.Show(lbresult.SelectedIndex.ToString());

30                         lbresult.SelectedIndex = indexbegin - 1;

31                     }

32                 }

33             }

34             catch (Exception err)

35             {

36                 F_Sign frm = new F_Sign(3);

37                 frm.ShowDialog();

38             }

39         }

View Code

14.添加导出文本功能

    看到生成的这些号码,不导出保存一下,难道要我们一个个复制么,人性化点吧,给个导出功能,就是界面上的OutPut

     上代码,自己可以去学习命名空间 IO 下的一些方法吧,或许你能懂得更多。

 1         /// <summary>

 2         /// 导出结果

 3         /// </summary>

 4         private void btnout_Click(object sender, EventArgs e)

 5         {

 6             if (lbresult.Items.Count > 0)

 7             {

 8                 string str = "";

 9                 StreamWriter sw = new StreamWriter("outid.txt");

10                 for (int i = 0; i < lbresult.Items.Count; i++)

11                 {

12                     //str += lbresult.Items[i] + "\n";

13                     sw.WriteLine(lbresult.Items[i]);

14                 }

15                

16                 sw.Close();

17             }

18         }

View Code

15.验证身份证号码

    最后再来点,好吧,没完没了了。只是自己做点小工具,此篇博文仅仅是自己的 这次联系的知识总结。好吧,我们生成了号码,但是在文章开始做的那个类cs中,我们的方法,岂不是浪费了,要不要加个验证 身份证号码的小窗体呢。

    添加一个新窗体:F_check.cs,相关控件如下图,不再一一说明。

 

这里涉及到的主要知识点:

     传值:主窗体传到新建窗体(见12.添加特效,本功能不再演示,自己可以添加上写写),新窗体传到主窗体。

     主窗体添加如下代码:

 1         /// <summary>

 2         /// Check

 3         /// </summary>

 4         private void btnCheck_Click(object sender, EventArgs e)

 5         {

 6             //cbplace.DataSource = null;

 7             //string strpro = cbpro.SelectedValue.ToString();

 8             //begindata(strpro);

 9             F_check f2 = new F_check();

10            

11             f2.Owner = this;//传值关键,新窗体往主窗体回传值不能用属性

12             f2.ShowDialog();

13         }

View Code

    验证号码信息,当然,我们这里不是从主窗体复制的,你可以自己仿照 12 试试将选中的号码传到 新窗体 来验证,我们这里直接输入吧,

    下面代码懒得整理,这不是重点,调用我们在文章开始写的方法即可。

 1 private void btnCheck_Click(object sender, EventArgs e)

 2         {

 3             string strid = txtid.Text.Trim();

 4             string strplace = "";

 5             string stryear="";

 6             string strmonth="";

 7             string strday="";

 8             string strturn="";

 9             string strsex="";

10

11             ClassCheck clck = new ClassCheck();

12             if(strid.Length==18)

13             {

14                 //校验码

15                 if( clck.checkcode(strid.Substring(0,17))!=strid[17].ToString())

16                 {

17                     lbplace.Text = "place : wrong number!";

18                     lbdate.Text = "";

19                     lbsex.Text = "";

20                     lbturn.Text = "";

21                     F_Sign frm = new F_Sign(2);

22                     frm.ShowDialog();

23                     return;

24                 }

25                

26

27                 strplace=clck.checkplace(strid.Substring(0,6));

28                 stryear=strid.Substring(6,4);

29                 //strplace=clck.checkplace(strid[0].ToString() + strid[1].ToString() + strid[2].ToString() +

30                 //                        strid[3].ToString() + strid[4].ToString() + strid[5].ToString());

31                 //stryear = strid[6].ToString() + strid[7].ToString() + strid[8].ToString() + strid[9].ToString();

32

33                 if (strid[10].ToString() == "0")

34                 {

35                     strmonth = strid[11].ToString();

36                 }

37                 else

38                 {

39                     strmonth = strid[10].ToString() + strid[11].ToString();

40                 }

41

42                 if (strid[12].ToString() == "0")

43                 {

44                     strday = strid[13].ToString();

45                 }

46                 else

47                 {

48                     strday = strid[12].ToString() + strid[13].ToString();

49                 }

50

51                 strturn = strid[14].ToString() + strid[15].ToString() + strid[16].ToString();

52

53                 if (strid[16].ToString() == "1" || strid[16].ToString() == "3" || strid[16].ToString() == "5" || strid[16].ToString() == "7" || strid[16].ToString() == "9")

54                 {

55                     strsex = "";

56                 }

57                 else

58                 {

59                     strsex = "";

60                 }

61

62                 lbplace.Text ="place : "+strplace;

63                 lbdate.Text = "date : " + stryear + "-" + strmonth + "-" + strday;

64                 lbturn.Text = "turn : "+strturn;

65                 lbsex.Text = "sex : " + strsex;

66             }

67            

68         }

View Code

    将我们输入的号码反填到主窗体的ListBox中,至于本号码对不对,想研究的童鞋可以自己做个判断。

1         private void btnAdd_Click(object sender, EventArgs e)

2         {

3             F_main frm = (F_main)this.Owner;

4             ((ListBox)frm.Controls["lbresult"]).Items.Add(this.txtid.Text.Trim());

5             this.Close();

6         }

View Code

这样,我们图上的功能就基本实现了。

16.总结

        实在受不了,一写,发现还有狠多需要实现,入坑了,坚决不继续写了,这孩子,越想越多了。

        本篇博文,仅仅是自己学习了一些字典和哈希表的小知识,顺便,想体验一下,没想到搞了这么多。

       知识总结如下,通过本文,你需要加深如下了解:

哈希表,字典,二维数组 的使用(超大数据的提取和写入中作为缓存,后面例子将用到);

文件写入和读取(后面将做个超简单的文件浏览器雏形);

下拉表绑定和多级联动;

窗体之间的传值,正传和反传;

其它

 

PS:请勿将文中工具用于非法用途,本人也不会提供下载。上面所有的省市信息和编码均是通过合法的网络文库获得而来,文中所有的代码也仅供学习与交流,如因此问题引起的法律问题,本人概不负连带责任。

声明:以上内容仅代表作者观点,不代表爱符号赞成此内容或立场
C#相关的分享
 
哈希表相关的分享
 
  • ·暂无相关分享
  •  
数组相关的分享
 
字典相关的分享
 
  • ·暂无相关分享
  •  
多级联动相关的分享
 
  • ·暂无相关分享
  •  
HashTable相关的分享
 
  • ·暂无相关分享
  •  
作者热播