码迷,mamicode.com
首页 > 其他好文 > 详细

身份证号码18个数字代表的意思

时间:2014-08-25 02:16:13      阅读:372      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   io   strong   文件   

  一、前言介绍

  中华人民共和国公民身份号码是中华人民共和国为中国大陆每个公民从出生之日起编定的唯一的、终身不变的身份代码,在中华人民共和国公民办理涉及政治、经济、社会生活等权益事务方面广泛使用。中华人民共和国公安部负责公民身份号码的编制和组织实施工作。

  1999年8月26日中华人民共和国国务院发布《国务院关于实行公民身份号码制度的决定》(国发[1999]15号),这个文件规定自1999年10月1日起在全国建立和实行公民身份号码制度。

  二、数字组成方式

bubuko.com,布布扣

  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 }

 

  运行结果

bubuko.com,布布扣

  下面这个是百度应用里面的结果

bubuko.com,布布扣

  为什么会这样的呢,一开始以为是自己哪里错了??

  下面这个是某个网站的结果

bubuko.com,布布扣

  终于知道了,原来是由于历史原因。这个就没有办法了。我也不知道去哪里找这些以前的资料数据。所以就将就着用吧。

 

  参看资料:

  http://blogread.cn/it/article/6167?f=wb

  http://zh.wikipedia.org/wiki/中华人民共和国公民身份号码

  本文地址: http://www.cnblogs.com/wunaozai/p/3933978.html

   

身份证号码18个数字代表的意思

标签:style   blog   http   color   os   使用   io   strong   文件   

原文地址:http://www.cnblogs.com/wunaozai/p/3933978.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!