【id:32】【20分】B. Date(类与构造
题目描述
下面是一个日期类的定义,请在类外实现其所有的方法,并在主函数中生成对象测试之。
注意,在判断明天日期时,要加入跨月、跨年、闰年的判断
例如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<iostream>
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的最大公约数可采用辗转相除法,又称欧几里得算法,其步骤为:
- 交换a, b使a > b;
- 用a除b得到余数r,若r=0,则b为最大公约数,退出.
- 若r不为0,则用b代替a, r代替b,此时a,b都比上一次的小,问题规模缩小了;
- 继续第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<iostream>
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(类+构造+对象数组)
题目描述
上面是我们曾经练习过的一个习题,请在原来代码的基础上作以下修改: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<iostream>
#include<iomanip>
#include<math.h>
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;
}
总结
希望能每天进步一点点。继续加油!