前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >新旧身份证(继承)

新旧身份证(继承)

作者头像
叶茂林
发布2023-07-30 11:20:21
2670
发布2023-07-30 11:20:21
举报
文章被收录于专栏:叶子的开发者社区

题目描述

按下述方式定义一个日期类CDate和描述15位身份证号的旧身份证类COldID:

class CDate { private: int year, month, day; public: CDate(int,int,int); bool check(); //检验日期是否合法 bool isLeap(); void print(); }; class COldID { private: char *p_id15, *p_name; //15位身份证号码,姓名 CDate birthday; //出生日期 public: COldID(char *p_idval, char *p_nameval, CDate &day); bool check(); //验证15位身份证是否合法 void print(); ~COldID(); };

然后以COldID为基类派生18位身份证号的新身份证类CNewID,并增加3个数据成员:p_id18(18位号码)、issueday(签发日期)和validyear(有效期,年数),并重新定义check()和print()。

身份证第18位校验码的生成方法:

1、将身份证号码前17位数分别乘以7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2。然后将其相加。

2、将17位数字和系数乘加的和除以11,得到余数。

3、余数与校验码的对应关系为1,0,X,9,8,7,6,5,4,3,2。也即:如果余数是3,身份证第18位就是9。如果余数是2,身份证的最后一位号码就是X。

主函数定义一个派生类对象,并用派生类对象调用check(),若返回false则输出“illegal id”否则调用print()输出身份证信息。check()对身份证合法性进行验证的规则:

1. 确认15位身份证正确.

2. 确认18位号码是从15位号码扩展的,且第18位校验码正确.

3. 身份证中的出生日期合法.

4. 身份证号码中不含非法字符.

5. 身份证号码的长度正确.

6. 身份证目前处于有效期内. (2017年5月10日)

输入

测试数据的组数 t

第一个人姓名、出生日期年月日、15位身份证号码、18位身份证号码、签发日期年月日、有效期(100年按长期处理)

第二个人姓名、出生日期年月日、15位身份证号码、18位身份证号码、签发日期年月日、有效期(100年按长期处理)

......

输出

第一个人姓名

第一个人18位身份证号信息(号码、签发日期和有效期)或"illegal id"

第二个人姓名

第二个人18位身份证号信息(号码、签发日期和有效期)或"illegal id"

......

输入样例1

10 AAAA 1988 2 28 440301880228113 440301198802281133 2006 1 20 20 BBBB 1997 4 30 440301980808554 440301199808085541 2015 2 2 10  CCCC 1920 5 8 530102200508011 53010219200508011X 1980 3 4 30 DDDD 1980 1 1 340524800101001 340524198001010012 1998 12 11 20 EEEE 1988 11 12 110203881112034 110203198811120340 2007 2 29 20  FFFF 1964 11 15 432831641115081 432831196411150810 2015 8 7 100 GGGG 1996 12 10 44030196121010 44030119961210109 2014 6 7 20 HHHH 1988 7 21 440301880721X12 44030119880721X122 2006 5 11 20 IIII 1976 3 30 440301760330098 440301197603300983 2003 4 15 20 JJJJ 1955 9 5 440301550905205 440301195509051052 2004 6 4 100 

输出样例1

AAAA 440301198802281133 2006年1月20日 20年 BBBB illegal id CCCC illegal id DDDD illegal id EEEE illegal id FFFF 432831196411150810 2015年8月7日 长期 GGGG illegal id HHHH illegal id IIII illegal id JJJJ illegal id

思路分析

不仅仅是出生日期要判断合法性,签发日期也要判断合法性。

身份证号码里面的出生日期也要与所给出生日期相一致。

这里把出生日期变成字符串,month和day不是两位数的加个0,看看能不能在身份证号码里面找到。

还有一个地方,那就是新18位身份证号码必须是从15位基础上建立的,也就是说,除了添加的3位,其他的必须一样。

那我们就要把原本应该相同的地方拿出来比较,也就是提取子串进行比较。

AC代码

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
int leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int common[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int idpower[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
char checkcode[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
class CDate {
	private:
		int year, month, day;
	public:
		CDate() {};
		CDate(int, int, int);
		void datain() {
			cin >> year >> month >> day;
		}
		int getyear() {
			return year;
		}
		int getmonth() {
			return month;
		}
		int getday() {
			return day;
		}
		bool check() {
			if (year > 2017 || year == 2017 && month > 5 || year == 2017 && month == 5 && day > 10)
				return false;
			if (isLeap()) {
				if (leap[month - 1] < day)
					return false;
			} else {
				if (common[month - 1] < day)
					return false;
			}
			return true;
		} //检验日期是否合法
		string tostring() {
			string a = to_string(year), b = to_string(month), c = to_string(day);
			if (b.length() == 1)b.insert(b.begin(), '0');
			if (c.length() == 1)c.insert(c.begin(), '0');
			a.append(b);
			a.append(c);
			return a;
		}
		bool isLeap() {
			if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)return true;
			return false;
		}
		void print() {
			cout << year << "年" << month << "月" << day << "日 ";
		}
};
class COldID {
	protected:
		string p_id15, p_name; //15位身份证号码,姓名
		CDate birthday; //出生日期
	public:
		COldID() {}
		void datain() {
			cin >> p_name;
			birthday.datain();
			cin >> p_id15;
		}
//		COldID(char *p_idval, char *p_nameval, CDate &day){};
		bool check() {
			cout << p_name << endl;
			if (!birthday.check())
				return false;
			if (p_id15.length() != 15)
				return false;
			for (int i = 0; i < 15; i++) {
				if (!isdigit(p_id15[i]))
					return false;
			}
			return true;
		} //验证15位身份证是否合法
		void print() {}
		~COldID() {}
};
class CNewID: public COldID {
		string p_id18;
		CDate issueday;
		int validyear;
	public:
		CNewID() {
			COldID::datain();
			cin >> p_id18;
			issueday.datain();
			cin >> validyear;
		}
		bool check() {
			if (!COldID::check())
				return false;
			if (p_id18.substr(0, 5) != p_id15.substr(0, 5) || p_id18.substr(8, 8) != p_id15.substr(6, 8))//比较子串 
				return false;
			if (p_id18.find(birthday.tostring()) == -1)//判断身份证号码里面的出生日期是不是和所给的一样 
				return false;
			if (!issueday.check())//判断签发日期是不是有效的 
				return false;
			if (p_id18.length() != 18)
				return false;
			int temp = 0;
			for (int i = 0; i < 17; i++) {
				temp += (p_id18[i] - '0') * idpower[i];
			}
			temp %= 11;
			if (checkcode[temp] != p_id18[17])
				return false;
			if (issueday.getyear() + validyear < 2017 || issueday.getyear() + validyear == 2017 && issueday.getmonth() > 5 || issueday.getyear() + validyear == 2017 && issueday.getmonth() == 5 && issueday.getday() > 10)
				return false;
			return true;
		}
		void print() {
			COldID::print();
			cout << p_id18 << ' ';
			issueday.print();
			if (validyear < 100)
				cout << validyear << "年" << endl;
			else cout << "长期" << endl;
		}
};
int main() {
	int t;
	cin >> t;
	while (t--) {
		CNewID test;
		if (test.check())
			test.print();
		else cout << "illegal id" << endl;
	}
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 思路分析
  • AC代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档