目录
题目描述
需要开发一个系统,对宠物的生长状态进行管理。给出下面的基类框架:
class Pet
{ protected:
string name;//姓名
float length;//身长
float weight;//体重
CDate current;//开始记录时间
(日期类CDate包含年、月、日三个私有数据,其他方法根据需要自拟。)
public:
virtual void display(CDate day)=0;//输出目标日期时宠物的身长和体重
}
以Pet为基类,构建出Cat和Dog两个类:
Cat一天身长加0.1,体重加0.2。
Dog一天身长加0.2,体重加0.1。
生成上述类并编写主函数,要求主函数中有一个基类指针Pet *pt,用于测试子类数据。
主函数根据输入的信息,相应建立Cat类对象或Dog类对象,并给出测量日期时宠物的身长和体重。
输入
第一行为测试次数
第二行是开始记录日期
从第三行起,每个测试用例占一行,每行给出宠物的基本信息:宠物的类型(1为Cat,2为Dog)、名字、身长、体重、最后测量的日期。
输出
要求输出目标日期宠物姓名、身长和体重(结果要求保留小数点后2位)。若测量日期小于开始日期,输出”error”。
输入样例1
3
2019 5 5
1 tony 10 10 2018 12 30
2 jerry 5 6 2019 5 10
1 tom 3 4 2019 6 1
输出样例1
error
jerry after 5 day: length=6.00,weight=6.50
tom after 27 day: length=5.70,weight=9.40
思路分析
这道题顶着一个多态和虚函数的标头,但其实它考查的基础知识并不难,真正难的是如何计算两个日期间的天数,关于这个问题我想了很久,其实后来看后台数据并没有考虑到不同年份的情况,也没有考虑到闰年的情况,我这里把所有情况都考虑上,即任意两个日期之间的天数计算方法。
分析
对于输入进来的year、month和day,我们分三种情况计算。
最简单的情况,月份相同
直接两个day相减返回完事,从不拖泥带水。
然后是年份相同
首先判断一下是不是闰年,如果是闰年,把2月改成29天。
之后我们一个非常关键的函数必须用上,这个函数我们用来计算从当前日期开始直到过完本年的总天数,就是还有多少天过完这一年,即本年的剩余天数,我们把它暂时叫做remaindays,它的模样具体看代码。
有了这个函数之后呢,年份相同的情况就可以直接通过前一个日期本年剩余天数减去后一个日期本年剩余天数。
最后是年份不同的情况
首先我们先把这一年过完,即先调用remaindays函数计算本年剩余天数吗,然后年份自增直到和后一个年份相等,从整体来看到底差了多少年,差的每一年都来判断是否是闰年,是的话加上366天,不是的话就加上365天,这样一波下来,可以想到我们算多了天数,算多了后一个日期的本年剩余天数,最后把它减去完事。
额外
对于输入进来的前一个日期晚于后一个日期的情况,我们输出错误。
AC代码
#include"iostream"
#include"string"
#include"iomanip"
using namespace std;
class CDate
{
int year, month, day;
public:
CDate(int year,int month,int day) :year(year), month(month), day(day) {}
friend int days(CDate &a, CDate &b);
friend int remaindays(CDate &a);
};
class Pet
{
protected:
string name;//姓名
float length, weight;//体重
CDate current;//开始记录时间
public:
Pet(string name, float length, float weight, CDate current) :name(name), length(length), weight(weight), current(current) {}
virtual void display(CDate day) = 0;//输出目标日期时宠物的身长和体重
};
class Cat :public Pet
{
public:
Cat(string name, float length, float weight, CDate current) :Pet(name, length, weight, current) {
}
virtual void display(CDate day)
{
if (days(current, day)!=-1)
{
length += 0.1 * days(current, day);
weight += 0.2 * days(current, day);
cout << name << " after " << days(current, day) << " day: length=" << fixed << setprecision(2) << length << ",weight=" << weight << endl;
}
else
cout << "error" << endl;
}
};
class Dog :public Pet
{
public:
Dog(string name, float length, float weight, CDate current) :Pet(name, length, weight, current) {
}
virtual void display(CDate day)
{
if (days(current, day)!=-1)
{
length += 0.2 * days(current, day);
weight += 0.1 * days(current, day);
cout << name << " after " << days(current, day) << " day: length=" << fixed << setprecision(2) << length << ",weight=" << weight << endl;
}
else
cout << "error" << endl;
}
};
bool isleap(int year)
{
if (year % 400 == 0 || year % 4 == 0 && year % 100 != 0)
return 1;
return 0;
}
int remaindays(CDate &a)
{
long days;
int i,leapyear[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 },normalyear[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if (isleap(a.year))
{
days = leapyear[a.month - 1] - a.day;
for (i = a.month; i < 12; i++)
days += leapyear[i];
}
else
{
days = normalyear[a.month - 1] - a.day;
for (i = a.month; i < 12; i++)
days += normalyear[i];
}
return days;
}
int days(CDate &a, CDate &b)
{
if (a.year > b.year)
return -1;
if (a.year == b.year && a.month > b.month)
return -1;
if (a.year == b.year && a.month == b.month && a.day > b.day)
return -1;
long daysss = remaindays(a);
if (a.year < b.year)
{
for (int i = a.year+1; i <=b.year; i++)
if (isleap(i))
daysss += 366;
else
daysss += 365;
daysss -= remaindays(b);
}
else if (a.year == b.year)
daysss = remaindays(a) - remaindays(b);
else
daysss= b.day - a.day;
return daysss;
}
int main()
{
Pet* p;
int year, month, day, t,kind;
string name;
float length,weight;
cin>>t>>year>>month>>day;
CDate a(year,month,day);
while (t--)
{
cin>>kind>>name>>length>>weight>>year>>month>>day;
CDate b(year,month,day);
if(kind==1)
p=new Cat(name,length,weight,a);
else
p=new Dog(name,length,weight,a);
p->display(b);
}
}