实验六 构造函数+拷贝构造

A. 身体评估(类与对象)

题目描述

评估成年人身体健康有多个指标,包括BMI、体脂率BFR等

设计一个身体健康类,包含私有成员:姓名、身高(米)、体重(公斤),腰围(厘米),实现两个公有方法如下:

BMI方法,返回BMI数值(整数),计算公式BMI= 体重 / 身高的平方

体脂率方法,返回体脂率数值(浮点数),计算过程如下:

1)参数a=腰围(cm)×0.74

2)参数b=体重(kg)×0.082+34.89

3)体脂肪重量(kg)=a-b

4)体脂率 = 体脂肪重量÷体重

其它方法根据需要自行定义

输入

第一行输入t表示有t个测试实例

第二行起,每行输入四个参数:姓名、身高、体重,腰围

依次输入t行

输出

输出t行,每行输入一个实例的BMI和体脂率,小数数值精确到小数点后2位,用空格隔开

输入样例

2
David 1.85 78.5 85.2
Sara 1.55 67.6 77.3

输出样例

David's BMI: 23--BFR: 0.28
Sara's BMI: 28--BFR: 0.25

参考代码

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
class Body
{
	string name;
	float lenth;
	float weight;
	float rou;
	public:
		Body(string nam,float len,float wei,float roug)
		{
			name=nam;
			lenth=len;
			weight=wei;
			rou=roug;
		}
		int BMI()
		{
			float bmi=weight/(lenth*lenth);
			int a=round(bmi);//四舍五入 
			return (a);
		}
		float BFR()
		{
			float a=rou*0.74;
			float bfr=(a-(weight*0.082+34.89))/weight;
			return bfr;
		} 
		void print()
		{
			cout<<name<<"'s BMI: ";
		}
};
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		string name;
		float lenth,weight,rou;
		cin>>name>>lenth>>weight>>rou; 
		Body body(name,lenth,weight,rou);
		int bm=body.BMI();
		float bf=body.BFR();
		body.print();
		cout<<bm<<"--BFR: "<<fixed<<setprecision(2)<<bf<<endl;
	}
}

B. 生日打折(复合类构造)

题目描述

定义一个日期类Date,包含数据成员year\month\day,还包含构造函数及其他函数(根据需要自己添加)

定义一个会员类VIP,包含数据成员id和birth,其中id是整数表示会员编号;birth是Date类型表示生日。

类VIP包含构造函数和其他函数(根据需要自己添加),还包含一个折扣函数Discount。函数Discount返回结果为浮点数表示折扣,函数包含1个参数为日期类型,函数功能是判断参数日期是否会员生日,是则折扣为0.5,不是则折扣为0.95

编写程序实现上述类功能并实现输入输出的要求

输入

第一行输入年、月、日,表示今天日期

第二行输入t表示有t个会员

第三行输入第1个会员的ID、生日的年、月、日

第四行输入第1个会员的消费金额

依次类推输入下一个会员的两行数据…

输出

根据会员的消费金额,调用Discount函数判断今天是否会员生日并得到折扣,然后计算会员打完折的消费金额

每一行先输出会员编号,再输出会员打完折的消费金额,消费金额只需要输出整数部分

提示把浮点数转整数:

double x = 123.456
cout<<int(x)<<endl;

输入样例

2017 4 20
2
1111 2000 4 20
136
2222 2000 3 30
125

输出样例

1111's consumption is 68
2222's consumption is 118

参考代码

#include<iostream>
using namespace std;
class Date
{
	int year;
	int month;
	int day;
	public:
		Date(){}
		Date(int y,int m,int d)
		{
			year=y;
			month=m;
			day=d;
		}
		int get_month(){return month;}
		int get_day(){return day;}	 
			
};
class VIP
{
	string id;
	Date birth;
	public:
	VIP(string i,Date &bir0)
	{
		id=i;
		birth=bir0;
	}
	float Discount(Date a)
	{
		float dis;
		if((a.get_month()==birth.get_month())&&(a.get_day()==birth.get_day())) 
			dis=0.5;
		else dis=0.95;
		return dis;
	}
	void print()
	{
		cout<<id<<"'s consumption is ";
	}
};

int main()
{
	int y1,m1,d1;//今天 
	int y2,m2,d2,t;
	string id;
	cin>>y1>>m1>>d1>>t;
	Date today(y1,m1,d1);
	double cost;
	while(t--)
	{
		cin>>id>>y2>>m2>>d2;
		Date bir(y2,m2,d2);
		VIP n(id,bir);
		float disc;
		cin>>cost;
		disc=n.Discount(today);
		
		cost=cost*disc;
		n.print();
		cout<<int(cost)<<endl;
	}
}

C. 电话号码升位(拷贝构造函数)

题目描述

定义一个电话号码类CTelNumber,包含1个字符指针数据成员,以及构造、析构、打印及拷贝构造函数。

字符指针是用于动态创建一个字符数组,然后保存外来输入的电话号码

构造函数的功能是为对象设置键盘输入的7位电话号码,

拷贝构造函数的功能是用原来7位号码的对象升位为8位号码对象,也就是说拷贝构造的对象是源对象的升级.电话升位的规则是原2、3、4开头的电话号码前面加8,原5、6、7、8开头的前面加2。

注意:合法的电话号码:1、长度为7位;2、电话号码的字符全部是数字字符;3、第一个字符只能是以下字符:2、3、4、5、6、7、8。与上述情况不符的输入均为非法

输入

测试数据的组数 t

第一个7位号码

第二个7位号码

输出

第一个号码升位后的号码

第二个号码升位后的号码

如果号码升级不成功,则输出报错信息,具体看示例

输入样例

3
6545889
3335656
565655

输出样例

26545889
83335656
Illegal phone number

参考代码

#include<iostream>
#include<cstring>
using namespace std;
class CTelNumber
{
	char *num;
	public:
		CTelNumber()
		{
			num=new char[8];
		}	
		CTelNumber(char *q)
		{
			num=new char[8];
			strcpy(num,q);
		}
		CTelNumber(CTelNumber &a)
		{
			int i;
			num=new char[9];//升级
			//已经知道他合法 
			if(a.num[0]=='2'||a.num[0]=='3'||a.num[0]=='4') num[0]='8'; 
			else  num[0]='2';
			for(i=0;i<7;i++)
			{
				num[i+1]=a.num[i];
			}
		}
		~CTelNumber()
		{
			delete num;
		}
		void print()
		{
			int i=0;
			for(i=0;i<8;i++)
			{
				cout<<num[i];
			}
			cout<<endl;
		}
		
};
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int flag=1;
		char *q=new char[8];
		cin>>q;
		for(int i=0;i<7;i++)
		{
			if(q[0]<'2'||q[0]>'8') 
			{
				flag=0;	
				break;
			}
			if(q[i]<'0'||q[i]>'9') 
			{
				flag=0;	
				break;
			}	
		}
		if(flag==0) cout<<"Illegal phone number"<<endl;
		else 
		{
			CTelNumber num1(q);//调用构造储存q
			CTelNumber num2(num1);//调用拷贝构造升级q
			num2.print(); 
		} 
		 
	}
	
}

D. 彩票复制(拷贝构造)

题目描述

假设每组彩票包含6个号码,设计一个彩票类lottery,数据成员包括第一组号码、其他组数、其他组号码,描述如下

1、第一组号码group1,整数数组,长度为6

2、其他组数num,表示以第一组号码为样本,创建num组其他号码

3、其他组号码groupn,整数指针(int **),,该数据将动态创建二维整数数组,共9行,每行包含6个号码。

彩票类的成员函数包括:构造函数、拷贝构造函数、打印,描述如下:

1、打印函数,输出彩票的所有组的号码

2、构造函数,两个参数,第一个参数为整数数组,对应第一组号码,第二个参数为整数,表示其他组数(不超过9)。注意在构造函数中,其他组号码groupn不动态分配空间,仍然为指针

3、拷贝构造函数,其他组号码groupn动态创建二维数组,根据其他组数创建其他组的号码,创建规则为:

a)第i组的第j个号码等于上一组第j-1个号码加1,首个号码等于上一组最后一个号码加1

例如第一组号码group1的号码是1、3、5、7、9、11,且其他组数为2

则groupn的第0组号码是12、2、4、6、8、10,第1组号码是11、13、3、5、7、9,以此类推

输入

第一行输入t表示有t个样例,每个样例对应一行数据

接着一行输入7个参数,前6个参数表示首张彩票的第一组6个号码,第7个参数表示其他组数,这时使用使用构造函数

然后采用拷贝构造方法生成第二张彩票,其中复制了首张彩票的第一组号码和其他组数,并且生成其他组号码

依此类推

输出

调用Print方法,输出每个样例中第二张彩票的所有组的号码

输入样例

2
1 3 5 7 9 11 2
22 44 66 88 100 122 3

输出样例

1 3 5 7 9 11
12 2 4 6 8 10
11 13 3 5 7 9
22 44 66 88 100 122
123 23 45 67 89 101
102 124 24 46 68 90
91 103 125 25 47 69

参考代码

#include<iostream>
using namespace std;
class lottery{
	int group1[6];
	int num;
	int **grounpn;
	public:
		lottery(){grounpn=NULL;}
		lottery(int a[6],int n)
		{
			for(int i=0;i<6;i++)
			{
				group1[i]=a[i];
			}
			num=n;
			grounpn=NULL;
		}
		lottery(lottery &l1)
		{
			num=l1.num;
			for(int i=0;i<6;i++)
			{
				group1[i]=l1.group1[i];
			}
			grounpn=new int*[num];
			for(int i=0;i<num;i++)
			{
				grounpn[i]=new int[6];
			}
			for(int i=0;i<6;i++)
			{
				if(i==0) grounpn[0][i]=group1[5]+1;
				else grounpn[0][i]=l1.group1[i-1]+1;
			}
			for(int i=1;i<num;i++)
			{
				grounpn[i][0]=grounpn[i-1][5]+1;
				for(int j=1;j<6;j++)
				{
					grounpn[i][j]=grounpn[i-1][j-1]+1;
				}
			}
		}
		void print()
		{
			for(int i=0;i<6;i++)
			{
				if(i<5) cout<<group1[i]<<' ';
				else cout<<group1[i]<<endl;
			}
				for(int i=0;i<num;i++)
			{
				for(int j=0;j<6;j++)
				{
					if(j<5) cout<<grounpn[i][j]<<' ';
					else cout<<grounpn[i][j]<<endl;
				}
			}
		}
		~lottery()
		{
			if(grounpn!=NULL)
			{
				for(int i=0;i<num;i++)
					delete []grounpn[i];
				delete []grounpn;
			}
		}	
};
int main()
{
	int t;
	cin>>t;
	int nu[6],num;
	while(t--)
	{
		for(int i=0;i<6;i++)
		{
			cin>>nu[i];
		}
		cin>>num;
		lottery lo1(nu,num);
		lottery lo2(lo1);
		lo2.print();
	}
}

E. 身份证设定(复合类+拷贝构造)

题目描述

定义一个身份证类PID,包含私有属性:身份证类型、身份证号码、出生日期;另外包含方法:构造、拷贝构造打印等。

身份证类型表示一代身份证或者二代身份证,分别用1和2表示

身份证号码是一个字符串,长度为15或者18

出生日期是一个类,包含私有属性年、月、日,以及构造函数等(根据需要添加其他方法)

构造函数要注意是复合类,要考虑复合类成员的构造

打印函数把身份证的所有属性都输出,输出格式看示例

拷贝构造作用:如果身份证号码是15位的就升级为18位,包括把身份证类型改为2,然后把号码扩展,规则如下:

  1. 原15位身份证的第7位到12位表示出生年月日,每个两位;把年份的2位扩展为四位。

  2. 把扩展后的17个数字求和,取总和的末尾数字,如果末尾数字是0,则将0改为X,然后把这个数字作为第18位

3.如果身份证号码已经是18位,就无需升级

例如身份证123456910203000,表示91年2月3日出生,然后根据类属性出生日期知道是1991年,不是2091年。因此扩展为12345619910203000

接着把17个数字相加得到46,取末尾6,最终扩展为123456199102030006

输入

第一行输入t表示t个示例

第二行输入一个身份证的5个属性,顺序为:类型、号码、出生年、月、日

依次输入t行

输出

采用拷贝构造函数的方法对身份证号码升级,然后输出

输入样例

3
1 123456910203000 1991 2 3
2 654321200001018889 2000 1 1
1 234567001217000 2000 12 17

输出样例

type=2 birth=1991.02.03
ID=123456199102030006
type=2 birth=2000.01.01
ID=654321200001018889
type=2 birth=2000.12.17
ID=23456720001217000X

参考代码

#include <iostream>
#include<string.h>
using namespace std;
class birthday
{
	int year,month,day;
	public :
		birthday(int y=0,int m=0,int d=0)
		{
			year=y;month=m;day=d;
		}
		void set(int yy,int mm,int dd)
		{
			year=yy;month=mm;day=dd;
		}
		int getyear()
		{
			return year;
		}
		int getmonth()
		{
			return month;
		}
		int getday()
		{
			return day;
		}
		void print()
		{
			printf("%d.%02d.%02d",year,month,day);
		}
};
class PID
{
	int lei;
	char *num;
	birthday th;
	public:
	PID(int l,char *ch,int y,int m,int d)
	{
		lei=l;
		num=new char [strlen(ch)+1];
		strcpy(num,ch);
		th.set(y,m,d);
	}
	PID(PID &r)
	{
		num=new char [19];
		lei=2;
		th.set(r.th.getyear(),r.th.getmonth(),r.th.getday());
		if(strlen(r.num)==18) strcpy(num,r.num);
		else {
			int s=0;
			for(int i=0;i<6;i++)
			{
				num[i]=r.num[i];
				s+=num[i]-'0';
			}
			for(int i=8;i<=16;i++)
			{
				num[i]=r.num[i-2];
				s+=num[i]-'0';
			}
			int k=th.getyear();
			num[6]=k/1000+'0';
			num[7]=k/100%10+'0';
			s+=num[6]-'0';
			s+=num[7]-'0';
			if(s%10==0) num[17]='X';
			else num[17]=s%10+'0';
		}
		num[18]='\0';
	}
	
	
	void out()
	{
		cout<<"type=2"<<" birth=";
		th.print();
		cout<<endl;
		cout<<"ID="<<num<<endl;
	}
	~PID()
	{
		delete[] num;
	}
		
};
int main()
{
	int t,a,b,c,d;
	char k[30];
	cin>>t;
	while(t--)
	{
		cin>>a>>k>>b>>c>>d;
		PID p(a,k,b,c,d);
		PID q(p);
		q.out();
	}
	return 0;
}
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值