标签:style blog http color os 使用 io strong 文件
一、前言介绍
中华人民共和国公民身份号码是中华人民共和国为中国大陆每个公民从出生之日起编定的唯一的、终身不变的身份代码,在中华人民共和国公民办理涉及政治、经济、社会生活等权益事务方面广泛使用。中华人民共和国公安部负责公民身份号码的编制和组织实施工作。
1999年8月26日中华人民共和国国务院发布《国务院关于实行公民身份号码制度的决定》(国发[1999]15号),这个文件规定自1999年10月1日起在全国建立和实行公民身份号码制度。
二、数字组成方式
1.地址码(身份证号码前六位)
表示编码对象常住户口所在县(市、镇、区)的行政区划代码。1-2位省、自治区、直辖市代码; 3-4位地级市、盟、自治州代码; 5-6位县、县级市、区代码。
关于行政区划代码具体的对应关系,可以从国家统计局网站上直接获取。
具体地址为:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/
2.生日期码(身份证号码第七位到第十四位)
表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。
3.顺序码(身份证号码第十五位到十七位)
地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。
4.校验码(身份证号码最后一位)
是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的。
三、校验码算法
1.将身份证号码从右到左标记为a1,a2,......,a18.a1即为校验码
2.计算权重系数Wi=2i-1 mod 11
i | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
Wi | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 |
3.计算S=(a2*W2)+(a3*W3)+......+(a17*W17)+(a18*W18)
4.a1=(12-(S mod 11))mod 11
四、程序实现
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 5 struct Birth 6 { 7 int year; 8 int month; 9 int day; 10 }; 11 12 struct Addr 13 { 14 int id; 15 char name[32]; 16 }; 17 18 struct Addr addr[4096];//保存行政区划代码 19 int count; 20 21 struct ID 22 { 23 char num18[18]; 24 char num15[15]; 25 char addr[32]; 26 struct Birth birth; 27 char sex[3]; 28 }; 29 30 int load() 31 { 32 FILE * fp=NULL; 33 int i=0; 34 //数据来自:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201401/t20140116_501070.html 35 fp=fopen("data","rb"); 36 while(!feof(fp)) 37 { 38 fscanf(fp,"%d %s",&addr[i].id,addr[i].name); 39 i++; 40 } 41 count=i; 42 fclose(fp); 43 return 0; 44 } 45 int get(int num,char *ch) 46 { 47 int i; 48 for(i=0;i<count;i++) 49 { 50 if(num==addr[i].id) 51 { 52 strcpy(ch,addr[i].name); 53 return 0; 54 } 55 } 56 strcpy(ch,"(未知的)"); 57 return 0; 58 } 59 60 // 012345678901234567 61 // 001122yyyymmdd333X 18位 62 // 001122yymmdd333 15位 63 //用于判断身份证号码是否符合标准 64 int identification(char *ch,struct ID *id) 65 { 66 int len,i; 67 int flag;//15表示15位 18表示18位 68 int W[18]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1}; 69 int S; 70 char di[32]; 71 len=strlen(ch); 72 /////////////判断个数 73 if(len!=15&&len!=18) 74 { 75 return 1; 76 } 77 if(len==15) 78 { 79 flag=15; 80 //15位转17位,最后一位为空。 81 for(i=14;i>=6;i--) 82 { 83 ch[i+2]=ch[i]; 84 } 85 ch[6]=‘1‘; 86 ch[7]=‘9‘; 87 ch[18]=0; 88 } 89 if(len==18) 90 { 91 flag=18; 92 } 93 ////////////判断字符 94 for(i=0;i<17;i++) 95 { 96 if(ch[i]<‘0‘||ch[i]>‘9‘) 97 return 2; 98 } 99 if(ch[17]<‘0‘||ch[17]>‘9‘) 100 { 101 if(ch[17]!=‘x‘&&ch[17]!=‘X‘) 102 { 103 return 2; 104 } 105 } 106 ////////////计算验证码 107 //校验码计算方法 108 //1.将身份证号码从右至左a1,a2,a3...a18,a1即为校验码 109 //计算权重系数Wi=2^(i-1) % 11 110 //i 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 111 //Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1 112 //计算S=(a2*W2)+(a3*W3)+(a4*W4)+...+(a18*W18) 113 // a1=(12-(S%11))%11 114 S=0; 115 for(i=0;i<17;i++) 116 { 117 S=S+(ch[i]-‘0‘)*W[i]; 118 } 119 i=(12-(S%11))%11; 120 if(flag==15) 121 { 122 if(i!=10) 123 ch[17]=i+‘0‘; 124 else 125 ch[17]=‘X‘; 126 } 127 if(flag==18) 128 { 129 if(ch[17]!=(i+‘0‘)) 130 { 131 if((ch[17]==‘x‘||ch[17]==‘X‘)&&i==10) 132 ; 133 else 134 return 3; 135 } 136 } 137 //////////填写ID结构体 138 strcpy(id->num18,ch); 139 //填写省级单位 140 i=(ch[0]-‘0‘)*10; 141 i=i+(ch[1]-‘0‘); 142 i=i*10000; 143 get(i,di); 144 strcpy(id->addr,di); 145 i=i+(ch[2]-‘0‘)*1000; 146 i=i+(ch[3]-‘0‘)*100; 147 get(i,di); 148 strcat(id->addr,di); 149 i=i+(ch[4]-‘0‘)*10; 150 i=i+(ch[5]-‘0‘); 151 get(i,di); 152 strcat(id->addr,di); 153 154 //处理出生日期 155 i=(ch[6]-‘0‘)*1000; 156 i=i+(ch[7]-‘0‘)*100; 157 i=i+(ch[8]-‘0‘)*10; 158 i=i+(ch[9]-‘0‘)*1; 159 id->birth.year=i; 160 i=(ch[10]-‘0‘)*10; 161 i=i+(ch[11]-‘0‘)*1; 162 id->birth.month=i; 163 i=(ch[12]-‘0‘)*10; 164 i=i+(ch[13]-‘0‘)*1; 165 id->birth.day=i; 166 if(checkbirth(id->birth)) 167 { 168 return 4; 169 } 170 if((ch[16]-‘0‘)%2==1) 171 { 172 strcpy(id->sex,"男"); 173 } 174 else 175 { 176 strcpy(id->sex,"女"); 177 } 178 return 0; 179 } 180 181 int checkbirth(struct Birth birth) 182 { 183 int day[12]={31,29,31,30,31,30,31,31,30,31,30,31}; 184 if(birth.year>2014||birth.year<1900) 185 return 1; 186 if(birth.month<=0||birth.month>12) 187 return 1; 188 if(birth.day<=0||birth.day>day[birth.month-1]) 189 return 1; 190 if(birth.day==29&&birth.month==2) 191 { 192 if((birth.year%4==0&&birth.year%100!=0)||(birth.year%400==0)) 193 return 0; 194 return 1; 195 } 196 197 return 0; 198 } 199 200 201 202 int main(int argc,char **argv) 203 { 204 char ch[32]; 205 struct ID per; 206 int id; 207 printf("请输入一个身份证号码:"); 208 scanf("%s",ch); 209 load(); 210 id=identification(ch,&per); 211 switch(id) 212 { 213 case 0: 214 printf("是一个合法的身份证号码\n"); 215 printf("18位身份证号码:%s\n",per.num18); 216 //printf("15位身份证号码:%s\n"); 217 printf("发证地址:%s\n",per.addr); 218 printf("出生日期:%d年%d月%d日\n",per.birth.year,per.birth.month,per.birth.day); 219 printf("性别:%s\n",per.sex); 220 break; 221 case 1: 222 printf("身份证号码个数不符\n"); 223 break; 224 case 2: 225 printf("身份证字符错误\n"); 226 break; 227 case 3: 228 printf("校验码错误\n"); 229 break; 230 case 4: 231 printf("生日错误\n"); 232 break; 233 case 5: 234 break; 235 default: 236 break; 237 } 238 return 0; 239 }
运行结果
下面这个是百度应用里面的结果
为什么会这样的呢,一开始以为是自己哪里错了??
下面这个是某个网站的结果
终于知道了,原来是由于历史原因。这个就没有办法了。我也不知道去哪里找这些以前的资料数据。所以就将就着用吧。
参看资料:
http://blogread.cn/it/article/6167?f=wb
http://zh.wikipedia.org/wiki/中华人民共和国公民身份号码
本文地址: http://www.cnblogs.com/wunaozai/p/3933978.html
标签:style blog http color os 使用 io strong 文件
原文地址:http://www.cnblogs.com/wunaozai/p/3933978.html