C++实验 构造函数与析构函数 记录

文章目录

  • 【id:32】【20分】B. Date(类与构造
  • 【id:33】【20分】C. 分数类(类与构造)
  • 【id:34】【20分】D. Point_Array(类+构造+对象数组)
  • 总结


【id:32】【20分】B. Date(类与构造

题目描述

下面是一个日期类的定义,请在类外实现其所有的方法,并在主函数中生成对象测试之。
C++实验 构造函数与析构函数 记录_第1张图片
注意,在判断明天日期时,要加入跨月、跨年、闰年的判断

例如9.月30日的明天是10月1日,12月31日的明天是第二年的1月1日

2月28日的明天要区分是否闰年,闰年则是2月29日,非闰年则是3月1日。


输入

测试数据的组数t

第一组测试数据的年 月 日

要求第一个日期的年月日初始化采用构造函数,第二个日期的年月日初始化采用setDate方法,第三个日期又采用构造函数,第四个日期又采用setDate方法,以此类推。

输出

输出今天的日期

输出明天的日期


输入样例

4
2012 1 3
2012 2 28
2012 3 31
2012 4 30

输出样例

Today is 2012/01/03
Tomorrow is 2012/01/04
Today is 2012/02/28
Tomorrow is 2012/02/29
Today is 2012/03/31
Tomorrow is 2012/04/01
Today is 2012/04/30
Tomorrow is 2012/05/01

解题思路:print函数用于单纯按照格式输出日期。本题的重点是addOneDay这里的算法设计。这里设计先令day++,然后判断本月是否是二月,若是,则判断本年是否为闰年,若是,则将局部变量dmax赋值为29,否则赋值为28。若不为二月,则判断是否为1、3、5、7、8、10、12月,若是,则将局部变量赋值为31;若不是则赋值为30。判断day与mday的大小关系,若day>mday(说明跨月份了)则令day = day - mday,且month++。然后再判断month是否大于12,若大于(说明跨年了),使month = month -12,year++。


代码如下:

#include
using namespace std;

class Date
{
	int year, month, day;
public:
	Date();
	Date(int y, int m, int d);
	int getYear();
	int getMonth();
	int getDay();
	void setDay(int y, int m, int d);
	void print();
	void addOneDay();
};
Date::Date()
{
	year = 1900;
	month = 1;
	day = 1;
}
Date::Date(int y, int m, int d)
{
	year = y;
	month = m;
	day = d;
}
int Date::getYear()//写完才发现题目根本没有用到下面这些函数,可以删掉
{
	return year;
}
int Date::getMonth()
{
	return month;
}
int Date::getDay()
{
	return day;
}
void Date::setDay(int y, int m, int d)  //此函数要用到
{
	year = y;
	month = m;
	day = d;
}
void Date::print()  //按照格式要求打印
{
	cout << " is " << year << "/";
	if (month < 10)
	{
		cout << "0" << month<<"/";
	}
	else
	{
		cout << month<<"/";
	}
	if (day < 10)
	{
		cout << "0" << day<<endl;
	}
	else
	{
		cout << day << endl;
	}
}

void Date::addOneDay()  //明天日期判断
{
	int dmax=0;   //设置局部变量,用于与增一天后日期作比较
	day++;
	if (month == 2)  //先判断是否为2月
	{
		if (year % 4 == 0 && year / 100 != 0 || year % 400 == 0)  //闰年判断
		{
			dmax = 29;
		}
		else
		{
			dmax = 28;
		}
	}
	else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)  //大月判断
	{
		dmax = 31;
	}
	else   //小月判断
	{
		dmax = 30;
	}
	if (day > dmax)  //跨月份判断
	{
		day = day - dmax;
		month++;
	}
	if (month > 12)  //跨年判断
	{
		month = month - 12;
		year++;
	}
}
int main()
{
	int t;
	cin >> t;
	for(int i=1;i<=t;i++)
	{
		int y, m, d;
		cin >> y >> m >> d;
		if (i % 2 != 0)   //选择用构造函数还是setDate
		{
			Date today(y, m, d);
			cout << "Today";
			today.print();
			today.addOneDay();
			cout << "Tomorrow";
			today.print();
		}
		else
		{
			Date today;
			today.setDay(y, m, d);
			cout << "Today";
			today.print();
			today.addOneDay();
			cout << "Tomorrow";
			today.print();
		}
		
	}

	//system("pause");
	return 0;
}

【id:33】【20分】C. 分数类(类与构造)

本题是此次实验难度最大的一题,分数该如何表示、如何计算。当时自己想了好久都没想到,一问,原来是这样做的!其实就是照我们分数计算写。这就是老师常挂在嘴边的“程序其实就是真实世界的一个映射。”吧。

题目描述

完成下列分数类的实现:

class CFraction
{
private:
int fz, fm;
public:
CFraction(int fz_val, int fm_val) ;
CFraction add(const CFraction &r);
CFraction sub(const CFraction &r);
CFraction mul(const CFraction &r);
CFraction div(const CFraction &r);
int getGCD(); // 求对象的分子和分母的最大公约数
void print();
};

求两数a、b的最大公约数可采用辗转相除法,又称欧几里得算法,其步骤为:

  1. 交换a, b使a > b;
  2. 用a除b得到余数r,若r=0,则b为最大公约数,退出.
  3. 若r不为0,则用b代替a, r代替b,此时a,b都比上一次的小,问题规模缩小了;
  4. 继续第2步。

注意:如果分母是1的话,也按“分子/1”的方式输出。


输入

测试数据的组数 t

第一组第一个分数

第一组第二个分数

第二组第一个分数

第二组第二个分数

输出

第一组两个分数的和

第一组两个分数的差

第一组两个分数的积

第一组两个分数的商

第二组两个分数的和

第二组两个分数的差

第二组两个分数的积

第二组两个分数的商


输入样例

3
1/2
2/3
3/4
5/8
21/23
8/13

输出样例

7/6
-1/6
1/3
3/4

11/8
1/8
15/32
6/5

457/299
89/299
168/299
273/184

代码如下:

#include
using namespace std;

class CFraction
{
private:
    int fz, fm;
public:
    CFraction();
    CFraction(int fz_val, int fm_val);
    CFraction add(const CFraction& r);
    CFraction sub(const CFraction& r);
    CFraction mul(const CFraction& r);
    CFraction div(const CFraction& r);
    int getGCD();   // 求对象的分子和分母的最大公约数
    void print();
};
CFraction::CFraction()
{

}
CFraction::CFraction(int fz_val, int fm_val)
{
    fz = fz_val;
    fm = fm_val;
}
int CFraction::getGCD()  //求最大公约数
{
    int a, b;   //不能改变原来的分子和分母,所以赋值给两个局部变量
    int r=0;
    a = fz;
    b = fm;
    if (a < 0)  //要注意负数取绝对值
    {
        a = -a;
    }
    if (b < 0)
    {
        b = -b;
    }
    while (1)    //辗转相除法
    {
        r = a % b;
        if (r == 0)
        {
            return b;
        }
        a = b;
        b = r;
    }
}
CFraction CFraction::add(const CFraction& r)
{
    CFraction result;
    int i=0;
    result.fz = fz * r.fm + r.fz * fm;  //分子同分后相加
    result.fm = fm * r.fm;  //分母通分
    i = result.getGCD();  //取分子分母的最大公约数
    result.fz = result.fz / i;  //分别除以最大公约数得到最简分式
    result.fm = result.fm / i;
    return result;
}
CFraction CFraction::sub(const CFraction& r)//减法与加法思路一样
{
    CFraction result;
    int i = 0;
    result.fz = fz * r.fm - r.fz * fm;
    result.fm = fm * r.fm;
    i = result.getGCD();
    result.fz = result.fz / i;
    result.fm = result.fm / i;
    return result;
}
CFraction CFraction::mul(const CFraction& r)//乘法
{
    CFraction result;
    int i = 0;
    result.fz = fz * r.fz;//分子相乘
    result.fm = fm * r.fm;//分母相乘
    i = result.getGCD();  //取最大公约数
    result.fz = result.fz / i;//除以最大公约数得到最简分式
    result.fm = result.fm / i;
    return result;
}CFraction CFraction::div(const CFraction& r)//除法
{
    CFraction result;
    int i = 0;
    result.fz = fz * r.fm;//除以一个分数等于乘该分数的倒数
    result.fm = fm * r.fz;
    i = result.getGCD();  //取最大公约数
    result.fz = result.fz / i;  //除以最大公约数
    result.fm = result.fm / i;  //同上
    return result;
}
void CFraction::print()  //按照格式要求输出
{
    cout << fz << "/" << fm << endl;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int fz1, fm1, fz2, fm2;
        char symbol;
        cin >> fz1 >>symbol>> fm1 >> fz2 >>symbol>> fm2;   //需要接收掉中间的“/”
        CFraction num1(fz1, fm1);
        CFraction num2(fz2, fm2);
        CFraction num3;
        num3 = num1.add(num2);
        num3.print();
        num3 = num1.sub(num2);
        num3.print();
        num3 = num1.mul(num2);
        num3.print();
        num3 = num1.div(num2);
        num3.print();
        cout << endl;
    }

	//system("pause");
	return 0;
}

【id:34】【20分】D. Point_Array(类+构造+对象数组)

题目描述
C++实验 构造函数与析构函数 记录_第2张图片
上面是我们曾经练习过的一个习题,请在原来代码的基础上作以下修改:1、增加自写的析构函数;2、将getDisTo方法的参数修改为getDisTo(const Point &p);3、根据下面输出的内容修改相应的构造函数。

然后在主函数中根据用户输入的数目建立Point数组,求出数组内距离最大的两个点之间的距离值。


输入

测试数据的组数 t

第一组点的个数

第一个点的 x 坐标 y坐标

第二个点的 x坐标 y坐标

输出

输出第一组距离最大的两个点以及其距离(存在多个距离都是最大值的情况下,输出下标排序最前的点组合。比如如果p[0]和p[9]、p[4]和p[5]之间的距离都是最大值,那么前一个是答案,因为p[0]排序最前)


输入样例

2
4
0 0
5 0
5 5
2 10
3
-1 -8
0 9
5 0

输出样例

Constructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 10.44,between p[1] and p[3].
Distructor.
Distructor.
Distructor.
Distructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 17.03,between p[0] and p[1].
Distructor.
Distructor.
Distructor.

代码如下:

#include
#include
#include
using namespace std;

class Point
{
	double x, y;
public:
	Point();
	Point(double x_value, double y_value);
	~Point();
	double getX();
	double getY();
	void setXY(double x1, double y1);
	void setX(double x_value);
	void setY(double y_value);
	double getDisTo(const Point& p);
};

Point::Point()
{
	cout << "Constructor." << endl;
}
Point::Point(double x_value, double y_value)  //没有用到的构造函数
{
	x = x_value;
	y = y_value;
	cout << "Constructor." << endl;
}
Point::~Point()
{
	cout << "Distructor." << endl;
}
double Point::getX()  //下面几个为没有用到的函数,可删
{
	return x;
}
double Point::getY()
{
	return y;
}
void Point::setXY(double x1, double y1)//有用,不可删
{
	x = x1;
	y = y1;
}
void Point::setX(double x_value)  //下面几个为没有用到的函数,可删
{
	x = x_value;
}
void Point::setY(double y_value)
{
	y = y_value;
}
double Point::getDisTo(const Point& p)//有用,不可删
{
	return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
int main()
{
	int t,x,y;
	double max;
	cin >> t;
	while (t--)
	{
		int n;
		double dis;
		int maxindex = 0;
		int	minindex=0;
		cin >> n;
		Point* p = new Point[n];  //对象数组只能用无参构造函数(所以一定要确保有无参构造函数)
		for (int i = 0; i < n; i++)
		{
			cin >> x >> y;
			p[i].setXY(x, y);
		}
		max = 0;
		for (int i = 0; i < n; i++)
		{
			for (int j = i + 1; j < n; j++)//循环,找出距离最远的两点,并记录两点下标
			{
				dis = p[i].getDisTo(p[j]);
				if (dis > max)
				{
					max = dis;
					maxindex = i;
					minindex = j;
				}
			}
		}
		cout << "The longeset distance is " << fixed << setprecision(2) << max <<
			",between p[" << maxindex << "]" << " and p[" << minindex << "]." << endl;
		delete[]p;  //别忘了delete!!!
	}

	//system("pause");
	return 0;
}

总结

希望能每天进步一点点。继续加油!

你可能感兴趣的:(c++)