C++身份证号验证

Posted on 2008-09-01 17:41 RichardHe 阅读(4979) 评论(11)  编辑 收藏 引用
C++身份证号验证
由于项目需要,在网上的例子大多数都是C#的,所以添加了这个身份证号的验证的C++程序,想用正则表达式,但又不会,有哪个会的可以指点下,小弟我不胜感激啊!
可能有的地方写的不好,欢迎指点:
.H文件
 1#ifndef _CCHECKIDCARD_
 2#define _CCHECKIDCARD_
 3#include <string>
 4using namespace std;
 5
 6class cCheckIdCard
 7{
 8public:
 9    cCheckIdCard(void);
10    //身份证验证
11    bool CheckIDCard(const string& Id);
12    
13    //18位身份证验证
14    bool CheckIDCard18(const string& Id);
15
16    //15位身份证验证
17    bool CheckIDCard15(const string& Id);
18
19    //生日验证
20    bool   CheckDate(const string&   Year,   const string&   const Month,   const string&   Day);
21    
22    //最后一位校验
23    bool cCheckIdCard::VarifyCode(const string& Id);
24    
25    //实现身份证的15位转18位 
26    string per15To18(const string& Id);
27
28    //获得生日
29    string getBirthday(const string& Id);
30
31    virtual ~cCheckIdCard(void);
32
33}
;
34#endif//_CCHECKIDCARD_

CPP文件:
  1#include "cCheckIdCard.h"
  2
  3cCheckIdCard::cCheckIdCard(void)
  4{
  5}

  6
  7cCheckIdCard::~cCheckIdCard(void)
  8{
  9}

 10/// <summary>
 11/// 验证身份证号码
 12/// </summary>
 13/// <param name="Id">身份证号码</param>
 14/// <returns>验证成功为True,否则为False</returns>

 15bool cCheckIdCard::CheckIDCard(const string& Id)
 16{
 17    if (Id.length() == 18)
 18        {
 19            bool check = CheckIDCard18(Id);
 20            return check;
 21        }

 22        else if (Id.length()  == 15)
 23        {
 24            bool check = CheckIDCard15(Id);
 25            return check;
 26        }

 27        else
 28        {
 29            return false;
 30        }

 31}

 32
 33bool cCheckIdCard::CheckIDCard18(const string& Id)
 34{
 35    string address[] = {"11","22","35","44","53","12","23","36","45","54","13","31","37","46","61","14","32","41","50","62","15","33","42","51","63","21","34","43","52","64","65","71","81","82","91"};
 36    forint i = 0; i<= 34; i++)
 37    {
 38        if (!(Id.substr(0,2!= address[i]))
 39            break;//省份验证正确
 40        else if (i == 34)
 41            return false;//省份验证错误
 42    }

 43
 44    string birth = Id.substr(68);
 45    if(!CheckDate(birth.substr(0,4), birth.substr(4,2), birth.substr(6,2)))
 46        return false;//生日验证错误
 47
 48    if(!VarifyCode(Id))
 49        return false;//最后一位校验错误
 50    return true;
 51}

 52
 53bool cCheckIdCard::CheckIDCard15(const string& Id)
 54{
 55    string newID = per15To18(Id);
 56
 57    if(!CheckIDCard18(newID))
 58        return false;
 59    return true;
 60}

 61
 62string cCheckIdCard::getBirthday(const string& Id)
 63{
 64    if(!CheckIDCard(Id))
 65        return "";//生日验证错误
 66    else
 67    {
 68        string birth;
 69        if (Id.length() == 15)
 70        {
 71            string newID = per15To18(Id);
 72            birth = newID.substr(68);
 73            return birth.insert(6,"-").insert(4,"-");
 74        }

 75        else
 76            return Id.substr(6,8).insert(6,"-").insert(4,"-");
 77    }

 78}

 79
 80bool   cCheckIdCard::CheckDate(const string&   Year, const   string&   Month,   const string&   Day)
 81{
 82    int iYear  = atoi(Year.c_str());
 83    int  iMonth = atoi(Month.c_str());
 84    int iDay = atoi(Day.c_str());
 85    int   Days[12]={31,   28,   31,   30,   31,   30,   31,   31,   30,   31,   30,   31};
 86    if(iMonth<1   ||   iMonth>12)   return   false;  
 87
 88    bool   b_IsLeapYear=false;  
 89    if(iYear%4==0)    
 90    {  
 91        b_IsLeapYear=true;  
 92
 93        if(!(iYear%100==0   &&   iYear%400==0))   b_IsLeapYear=false;  
 94    }
  
 95
 96    if(b_IsLeapYear)   Days[1]=29;  
 97    else   Days[1]=28;  
 98
 99    if(iDay<0   ||   iDay>Days[iMonth-1])   return   false;  
100
101    return   true;  
102}
   
103
104bool cCheckIdCard::VarifyCode( const string& Id)
105{
106    char perIDSrc[19];
107    strcpy(perIDSrc,Id.c_str());
108    int iS = 0;
109    int const iW[]={7910584216379105842};
110    char const  LastCode[]="10X98765432";
111
112    for(int i=0;i<17;i++)
113    {
114        iS += (int)(perIDSrc[i]-'0'* iW[i];
115    }

116
117    int iY = iS%11;
118    char   ch   =   LastCode[iY];  
119    string   lastChar;  
120    lastChar.insert(lastChar.begin(),   ch   );   
121    
122    if(lastChar != Id.substr(17,1))
123        return false;
124    return true;
125}
 
126
127//实现身份证的15位转18位
128string cCheckIdCard::per15To18(const string& Id)
129{
130    if(Id.length() != 15)
131        return "";
132    char perIDSrc[19];
133    strcpy(perIDSrc,Id.c_str());
134    int iS = 0;
135
136    //加权因子常数
137    int const iW[]={7910584216379105842};
138    //校验码常数
139    char const LastCode[]="10X98765432";
140    //新身份证号
141    char perIDNew[19];
142
143    forint i = 0; i < 6; i++ )
144    {
145        perIDNew[i] = perIDSrc[i];
146    }

147
148    //填在第6位及第7位上填上‘1’,‘9’两个数字
149    perIDNew[6= '1';
150    perIDNew[7= '9';
151
152    forint i = 8; i < 17; i++ )
153    {
154        perIDNew[i] = perIDSrc[i - 2];
155    }

156
157    //进行加权求和
158    forint i=0; i<17; i++)
159    {
160        iS += (perIDNew[i]-'0'* iW[i];
161        /**//*
162        对于perIDNew[i]-'0'解释一下:
163            perIDNew[i]->ASCII码,取得它的值实际是十进制数;
164            '0' ->ASCII码,同上;
165            perIDNew[i]-'0' -> 得到具体的十进制数值;
166            对于这里面的为什么会进行转换,具体去看C++PRIMER,呵呵。
167          */

168    }

169    
170    //取模运算,得到模值
171    int iY = iS%11;
172    //从LastCode中取得以模为索引号的值,加到身份证的最后一位,即为新身份证号。
173    perIDNew[17= LastCode[iY];
174    //加上结束符
175    perIDNew[18= '\0';
176
177    string tempstr = perIDNew;
178    return tempstr;
179}
 

测试:
#include "stdafx.h"
#include 
"cCheckIdCard.h"
#include 
<iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    cCheckIdCard tempID;
    
bool b = tempID.CheckIDCard("");//身份证号

    
string birthday = tempID.getBirthday("12345678901234567");//12345678901234567表示你要验证的身份证号
    cout << birthday << endl;
    
return 0;
}

Feedback

# re: C++身份证号验证  回复  更多评论   

2008-09-01 18:29 by 陈梓瀚(vczh)
nnnnnnyyyymmddnnn(n|x)
这个不是正则表达式
n代表0-9
yyyymmdd代表合法日期
x代表字符'x'

很好判断的吧,那么整齐的设计。

# re: C++身份证号验证  回复  更多评论   

2008-09-01 18:30 by 陈梓瀚(vczh)
用正则表达式判断合法日期无论从开发成本、运行成本来说都是得不偿失的。不过其实是可以的。

# re: C++身份证号验证  回复  更多评论   

2008-09-01 19:11 by RichardHe
@陈梓瀚(vczh)
不是很明白,可以有个详细的说明吗?或者写个正则表达式的身份证号验证程序吧!
谢谢!

# re: C++身份证号验证  回复  更多评论   

2008-09-01 21:25 by adcx
boost::Regex,自己看下资料

# re: C++身份证号验证  回复  更多评论   

2008-09-03 15:11 by RichardHe
@adcx
看是可以看,但就是不会用啊,哥哥!

# re: C++身份证号验证  回复  更多评论   

2008-09-04 10:40 by 崔友志
代码写的很清晰啊

# re: C++身份证号验证  回复  更多评论   

2008-09-04 13:14 by RichardHe
@崔友志
呵呵..谢谢!!!

# re: C++身份证号验证  回复  更多评论   

2008-09-04 13:21 by winzheng
不支持二代身份证校验!!!

# re: C++身份证号验证  回复  更多评论   

2008-09-04 21:29 by RichardHe
@winzheng
不会吧哥们..号码是统一的啊...第一代的号和第二代的号难道不一样?

不可能吧..每个人的号一上户口就有了的..固定了的呢!

# re: C++身份证号验证  回复  更多评论   

2008-09-05 10:21 by linxp
CheckDate出错,判断闰年时

# re: C++身份证号验证  回复  更多评论   

2008-09-05 11:01 by RichardHe
@linxp
CheckDate哪错了啊??

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe