中国居民身份证号码检验程序

    技术2022-05-11  162

    功能:检查15位或18位的身份证号码的有效性运行环境:Red Hat Enterprise Linux  AS release 3AIX Version 5 操作系统上测试通过编译命令:cc -o personid_chk personid_chk.c执行命令:./personid_chk源代码:

    /************************************************************FileName:     personid_chke.cAuthor:       yuanfen127Date:         2005年01月01日Description:  中国居民身份证检验程序Version:      1.0Function List:   1. int chk_pid(unsigned char *v_idno)     检查身份证校验位   2. int ATOI(char *ptr, int len)           文本类型按位转化为数值类型   3. int chkdate(char *date)                检查日期有效性   4. int get_curr_time(char *out_time)      获取当前工作日期History:      <author>  <time>         <version >   <desc>***********************************************************/#include <stdio.h>#include <string.h>#include <time.h>#include <timeb.h>

    main(){    char l_tidno[19];                       /*定义19位的字符串*/

        printf("请输入15位或者18位身份证件号码:"); /*提示输入身份证号*/    scanf("s",l_tidno);                 /*输入身份证号码*/    if ( 0 == chk_pid(&l_tidno) )          /*调用chk_pid函数检查身份证号*/    {        printf("此身份证号码正确!/n");       /*如果校验后正确,显示在屏幕上*/    }

        return;                                /*返回空值*/}

    int chk_pid(unsigned char *v_idno){    char l_tbuf[1024];                        /*存放一些文本提示信息*/    char l_tmpdate[9];                        /*存放身份证中的出生日期*/    char l_check[2];                          /*存放18位身份证号的校验码*/    char l_today[9];                          /*存放系统当前日期*/    int  l_itmp=0;    int  l_inumber=0;    int  i;    unsigned char l_chk_code[] = {'1','0','X','9','8','7','6','5','4','3','2'};    short l_wi[] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1};

        /*定义省份地区数组*/    char l_tarea[92][10]={"null","null","null","null","null","null","null",                          "null","null","null","null","北京","天津","河北",                          "山西","内蒙古","null","null","null","null","null",                          "辽宁","吉林","黑龙江","null","null","null","null",                          "null","null","null","上海","江苏","浙江","安微",                          "福建","江西","山东","null","null","null","河南",                          "湖北","湖南","广东","广西","海南","null","null",                          "null","重庆","四川","贵州","云南","西藏","null",                          "null","null","null","null","null","陕西","甘肃",                          "青海","宁夏","新疆","null","null","null","null",                          "null","台湾","null","null","null","null","null",                          "null","null","null","null","香港","澳门","null",                          "null","null","null","null","null","null","null",                          "国外"};

        /*初始化变量*/    memset(l_tbuf,' ',sizeof(l_tbuf));    memset(l_tmpdate,' ',sizeof(l_tmpdate));    memset(l_check,' ',sizeof(l_check));

        /*判断身份证号码位数*/    if ( 15 != strlen(v_idno) &&  18 != strlen(v_idno) )    {        printf("身份证号码必须为15位或18位!/n");        return -1;    }

        /*判断是否全部为数字*/    if ( strlen(v_idno) == 15 )    {        for ( i=0;i<15;i++ )        {            if ( 0 == isdigit( v_idno[i] ) )            {                printf("身份证输入有误!/n");                return -1;            }        }    }    else    {        /*如果是18位的身份证,前面17位均为数字*/        for ( i=0;i<17;i++ )        {            if ( 0 == isdigit(v_idno[i]) )            {                printf("身份证输入有误!/n");                return -1;            }        }

            /*第18位如果不是数字,那么只可能是"x"或者"X"*/        if ( 0 == isdigit(v_idno[i]) &&             0 != memcmp(&v_idno[i],"x",1) &&             0 != memcmp(&v_idno[i],"X",1) )        {            printf("身份证输入有误!/n");            return -1;        }    }

        /*身份证号码前2位代表省份地区码*/    l_itmp = ATOI(v_idno,2);                 /*调用ATOI函数前面2位转换成int型*/

        /*组装显示信息字符串*/    sprintf(l_tbuf,"身份证号码:%s/n",v_idno);

        if ( memcmp(l_tarea[l_itmp],"null",4) == 0 || l_itmp > 91 )    {        sprintf(l_tbuf,"%s地区: 不详/n",l_tbuf);    }    else    {        sprintf(l_tbuf,"%s地区: %s/n",l_tbuf,l_tarea[l_itmp]);    }

        if ( strlen ( v_idno  ) == 18 )    {        l_itmp = 16;    }    else    {        l_itmp = 14;    }

        if ( (v_idno[l_itmp] - '0') % 2 == 0 )    {        sprintf(l_tbuf,"%s性别: 女/n",l_tbuf);    }    else    {        sprintf(l_tbuf,"%s性别: 男/n",l_tbuf);    }

        printf("%s",l_tbuf);

        /*判断出生日期*/    if ( strlen(v_idno) == 15 )                /*如果15身份证,默认为19XX年*/    {        sprintf(l_tmpdate,"19%.6s",&v_idno[6]);    }    else    {        sprintf(l_tmpdate,"%.8s",&v_idno[6]);    }

        get_curr_time(l_today);                    /*调用函数获取系统当前日期*/

        /*判断出生日期是否有效,并且不能晚于当前系统日期*/    if ( 0 != chkdate(&l_tmpdate) || memcmp( l_tmpdate, l_today, 8) > 0)    {        printf("身份证出生日期错误,请重新输入!/n");        return -1;    }

        /*如果是18位身份证号码,则需要判断校验位*/    if ( strlen(v_idno) == 18 )    {        l_inumber=0;        /*         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        S=a2*W2+a3*W3+...+ai*Wi (1<i<19)        Y=mod(S,11)        */

            /*        l_inumber=l_inumber + ATOI(&v_idno[0],1)*7;        l_inumber=l_inumber + ATOI(&v_idno[1],1)*9;        l_inumber=l_inumber + ATOI(&v_idno[2],1)*10;        l_inumber=l_inumber + ATOI(&v_idno[3],1)*5;        l_inumber=l_inumber + ATOI(&v_idno[4],1)*8;        l_inumber=l_inumber + ATOI(&v_idno[5],1)*4;        l_inumber=l_inumber + ATOI(&v_idno[6],1)*2;        l_inumber=l_inumber + ATOI(&v_idno[7],1)*1;        l_inumber=l_inumber + ATOI(&v_idno[8],1)*6;        l_inumber=l_inumber + ATOI(&v_idno[9],1)*3;        l_inumber=l_inumber + ATOI(&v_idno[10],1)*7;        l_inumber=l_inumber + ATOI(&v_idno[11],1)*9;        l_inumber=l_inumber + ATOI(&v_idno[12],1)*10;        l_inumber=l_inumber + ATOI(&v_idno[13],1)*5;        l_inumber=l_inumber + ATOI(&v_idno[14],1)*8;        l_inumber=l_inumber + ATOI(&v_idno[15],1)*4;        l_inumber=l_inumber + ATOI(&v_idno[16],1)*2;        */

            l_inumber = 0;        for ( i = 0 ; i < 17 ; i++ )        {           l_inumber += ATOI(&v_idno[i],1) * l_wi[i];        }

            l_itmp = l_inumber % 11;

            /*        l_itmp  0   1   2   3   4   5   6   7   8   9   10        校验码  1   0   X   9   8   7   6   5   4   3    2        */        /*switch ( l_itmp )        {            case 0:               sprintf(l_check,"%.1s","1");               break;            case 1:               sprintf(l_check,"%.1s","0");               break;            case 2:               sprintf(l_check,"%.1s","X");               break;            default:               i = 12 - l_itmp;               sprintf(l_check,"",i);               break;        }        */

            /*printf("%d/n",l_inumber);*/        /*printf("输入号码的校验位:%d/n",l_itmp);*/        /*printf("计算出正确的检验位:%d",l_check);*/

            if ( v_idno[17] == 'x')        {            v_idno[17] = 'X';        }

            if ( l_chk_code[l_itmp] != v_idno[17] )        {            printf("身份证校验位错误,请重新输入/n");            return -1;        }    }

        return 0;}

    int ATOI(char *ptr, int len){    char tmpbuf[80];    int  int_val;

        sprintf(tmpbuf,"%.*s",len,ptr);    tmpbuf[len]='/0';    int_val=atoi(tmpbuf);

        return(int_val);}

    int chkdate(char *date){    int day_tbl[2][13] ={ 0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,                          0,31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        int  yr,mon,day;    int  leap,i;

        for ( i=0; i<8; i++)    {        if( (date[i]<'0') || (date[i]>'9') )        {            return(-1);        }    }

        if (sscanf(date, "M - -", &yr, &mon, &day) != 3)    {        return(-1);    }

        if (mon < 1 || mon > 12 || day < 1 || day > 31)    {        return(-1);    }

        leap = (yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0);

        if (day > day_tbl[leap][mon])    {        return(-1);    }    else    {        return(0);    }}

    int get_curr_time(char *out_time){    struct tm *tm1;    time_t curr;    struct timeb  tm2;

        time(&curr);    ftime(&tm2);

        tm1 = localtime (&curr);

        /*返回毫秒级的当前时间*    sprintf(out_time," ddd d:d:d.d",    tm1->tm_year + 1900,tm1->tm_mon + 1,    tm1->tm_mday,tm1->tm_hour,    tm1->tm_min ,tm1->tm_sec,tm2.millitm);    */

        sprintf(out_time,"ddd",                     tm1->tm_year + 1900,                     tm1->tm_mon + 1,                     tm1->tm_mday);    return 0;}


    最新回复(0)