OJ题之OOP身份证扩展(类构造与析构)

目录

题目描述

思路分析

基本要求

遇到的一些问题

原本想法

改进

AC代码

题目描述

定义一个身份证类,将 15 位的旧版身份证号扩充为 18 位。

在 15 位身份证号中,第 7、8 两位为出生年份,例如,1980 年出生的人,身份证号码的第 7、8 位的值是 80,在 18 位身份证号中,将 7~10 四位的值改为 1980,并将原身份证号码第 9 位开始以后的所有数字依次向右平移 2 位。在 18 位身份证号中, 最后增加一位校验码,校验码的计算方法如下(只考虑 20 世纪出生的公民):

(1)将已扩展出的 17 位身份证号按各位上的数字进行加权求和,结果为 S。自左到右各位上的数字的权值依次为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}。

(2)将 S 对 11 取余运算,结果为 Y。

(3)根据 Y 的取值大小顺序{0,1,2,3,4,5,6,7,8,9,10}取对应的校验码{1,0,X,9,8,7,6,5,4,3,2}。

例如,当 15 位身份证号为 340524800101001 时,扩展年份后成 17 位:34052419800101001,各位上的数字的加权和 S=3*7+4*9+0*10+5*5+2*8+4*4+1*2+9*1+8*6+0*3+0*7+1*9+0*10+1*5+0*8+0*4+1*2=189,S对11取余,即 S%11=189%11=2,则校验码为“X”。

要求类定义中包含完整的含参构造函数,默认构造函数,以及析构函数。

输入

测试组数t

以下t行,输入15位身份证号

输出

每个实例包含三行输出

第1行,在构造函数输出原身份证号,看样例

第2行,调用类方法输出扩展后的身份证号,看样例

第3行,在析构函数输出提示信息,包含扩展后身份号末4位,看样例

输入样例1

2
340524800101001
310001000101452

输出样例1

construct ID=340524800101001
upgrade ID=34052419800101001X
destruct ID=001X
construct ID=310001000101452
upgrade ID=310001190001014527
destruct ID=4527

思路分析

基本要求

首先是带参数的构造函数,用参数列表初始化的方法:

ID::ID(string id):pastID(id){cout<<"construct ID="<<pastID<<endl;}

然后是要输出提示信息包含扩展后身份证号末4位的析构函数:

ID::~ID()
{
	cout<<"destruct ID=";
	int i=0;
	for(i=14;i<18;i++)
	cout<<nowID[i];
	cout<<endl;
}

遇到的一些问题

题目主要内容就是对15位旧身份证号进行18位扩展,这应该要用到字符串处理。

用char型也可以处理,但习惯了用string类。

但用string类的时候遇到了一些问题。

原本想法

定义两个string类对象,一个ID读入15位旧身份证号,另一个nowID没有初始化,准备用来装18位扩展的。

但在我处理完字符串存进第二个string对象,在它末尾加\0时,发现\0并不能让它结束,但去查了一下,string类的结束符也是\0,但自己添加的\0却不能结束它,啊这……

改进

没有办法,只能改变思路,用char型肯定可以解决问题,但我死活要用string类。

那就只能上insert函数了:

先让第二个string类对象nowID初始化为15位旧身份证号,即直接把第一个string类对象pastIDcopy到nowID,这样我们的nowID就会自动在字符串末尾加结束符\0了,它自己加的可以结束自己。

然后我们在nowID的第7位(从0开始是下标为6)插入“19”:

nowID.insert(6,"19");

对于校验码,之前是分几种情况加数学逻辑解决的,这次想到了一个好办法, 直接把校验码存进一个字符串里面,让下标来对应它:

    string codelist="10X98765432";
    char code=codelist[y];
    nowID.insert(nowID.end(),code);

然后在nowID的末尾插进去,完事。 

AC代码

#include"iostream"
#include"string"
using namespace std;
class ID
{
	private:
		string pastID,nowID;
	public:
		ID(string id);
		void extend_output();
		~ID();
};
ID::ID(string id):pastID(id){cout<<"construct ID="<<pastID<<endl;}
void ID::extend_output()
{
	int s,y;
	nowID=pastID;
	nowID.insert(6,"19");
	s=7*(nowID[0]-'0')+9*(nowID[1]-'0')+10*(nowID[2]-'0')+5*(nowID[3]-'0')+8*(nowID[4]-'0')+4*(nowID[5]-'0')+2*(nowID[6]-'0')+1*(nowID[7]-'0')+6*(nowID[8]-'0')+3*(nowID[9]-'0')+7*(nowID[10]-'0')+9*(nowID[11]-'0')+10*(nowID[12]-'0')+5*(nowID[13]-'0')+8*(nowID[14]-'0')+4*(nowID[15]-'0')+2*(nowID[16]-'0');
	y=s%11;
	string codelist="10X98765432";
	char code=codelist[y];
	nowID.insert(nowID.end(),code);
	cout<<"upgrade ID="<<nowID<<endl;
}
ID::~ID()
{
	cout<<"destruct ID=";
	int i=0;
	for(i=14;i<18;i++)
	cout<<nowID[i];
	cout<<endl;
}
int main()
{
	int t;
	string id;
	cin>>t;
	while(t--)
	{
		cin>>id;
		ID member(id);
		member.extend_output();
	}
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaolinYe(叶茂林)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值