#include <iostream>
#include <string>
using namespace std;
//作者:sbfqmq E-Mail:[email protected]
/*
公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成.排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
1、地址码
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按 GB/T 2260 的规定执行。
2、出生日期码
表示编码对象出生的年、月、日,按 GB/T 7408 的规定执行。年、月、日代码之间不用分隔符。
例:某人出生日期为 1966年10月26日,其出生日期码为 19661026。
3、顺序码
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数千分配给女性。
4 、校验码
校验码采用ISO 7064:1983,MOD 11-2 校验码系统。
(1)十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0, ... , 16 ,先对前17位数字的权求和 Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
(2)计算模 Y = mod(S, 11)
(3)通过模得到对应的校验码 : 0 1 2 3 4 5 6 7 8 9 10
校验码: 1 0 X 9 8 7 6 5 4 3 2
*/
int IsRight(string card);
bool BirthdayIsRight(string cardId);
int GetDay(int year,int month);
int main(int argc,char ** argv)
{
string card_id,sex,year,month,day;
while(1)
{
cin>>card_id;
int flag=IsRight(card_id);
cout<<flag<<endl;
}
getchar();
return 0;
}
int IsRight(string card)
{
int error=0;
int length=(int)card.length();
cout<<length<<endl;
int index=card.find_first_not_of("1234567890");
if(index!=card.npos)
{
error=-1; //号码中有非数字字符
}
if(!BirthdayIsRight(card))
{
error=-4; //出生年月错误
}
if(length==18) //验证18位身份证号码
{
int no[]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char id[]={'1','0','X','9','8','7','6','5','4','3','2'};
//1 0 X 9 8 7 6 5 4 3 2 校验码
const char *p=card.c_str();
int i=0,wi=0,sum=0;
for(;i<length-1;i++)
{
wi=(*(p+i)-'0')*no[i];
sum+=wi;
}
if(*(p+i)<'0'||*(p+i)>'9')
{
if (*(p+i)!='X'&&*(p+i)!='x')
{
error=-2;//身份证最后一位输入错误
}
}
wi=sum%11;
if(*(p+17)=='x'||*(p+17)=='X') //最后一位为'x'或'X';
{
if(id[wi]!='x'&&id[wi]!='X')
error=-3;
}
else if(id[wi]!=*(p+17)) //判断计算出的身份证校验码与输入是否相符
{
error=-3;
}
}
return error;
}
//判断身份证号码中的年月日是否正确
bool BirthdayIsRight(string cardId)
{
string year,month,day;
bool flag=false;
int length=cardId.length();
if(length==18){
year=cardId.substr(6,4);//取18位身份证中的年
month=cardId.substr(10,2); // 月
day=cardId.substr(12,2); //日
}
else
{
year=cardId.substr(6,2);//取15位身份证中的年
month=cardId.substr(8,2); // 月
day=cardId.substr(10,2); //日
year="19"+year;
}
if(atoi(year.c_str())==0||atoi(month.c_str())==0||atoi(day.c_str())==0)
{
flag=false;
}
else if(GetDay(atoi(year.c_str()),atoi(month.c_str()))>=atoi(day.c_str()))
{
flag=true;
}
return flag;
}
//得到指定年跟月的天数
int GetDay(int year,int month)
{
int day=0;
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
{
day=31;
break;
}
case 4:
case 6:
case 9:
case 11:
{
day=30;
break;
}
case 2:
{
if(year%4==0&&year%100!=0||year%400==0)
day=29;
else
day=28;
break;
}
default : {
day=-1;
break;
}
}
return day;
}