想必大家应该做过这道题,我这边也是在做这道题的过程中将自己觉得易错的地方写下来方便大家创作,同时也可以当成错题方便日后查找。
题目描述
定义一个学生类Student,包含该学生的姓名、出生年、月、日 ,重定义 “-”号实现两个学生之间相差多少天的比较。并利用重载的“-”运算符,求所有学生中年龄相差最小的两个人的名字以及相差天数。
输入
第一行:输入所需要输入的学生个数;
第二行开始,依次输入每个学生的姓名、出生年、月、日。
输出
输出年龄相差最小的两个人的名字以及相差天数,名字的输出顺序按输入的先后,天数大于等于0。
输入样例1 <-复制
3\n
Tom 1995 1 1
Joe 1995 2 28
Jimmy 1996 1 8
输出样例1
Tom和Joe年龄相差最小,为58天。
/*
声明一下,这是我自己第一次没有改过的ac代码,
之后有什么地方我觉得可以改进的会注释
*/
#include<iostream>
#include<cstring>
#include<cmath>
int compare_min(int a, int b);
class Student {
private:
std::string name;
int year, month, day;
public:
Student() :name("\0"), year(0), month(0), day(0) {}
Student(std::string n,int y, int m, int d) :name(n), year(y), month(m), day(d) {}
int operator-(const Student& s);
bool judge_year(int y);
int judge_month(int m,int y);
std::string get_name() {
return name;
}
};
int Student::operator-(const Student& s) {
//这里是判断是否是s的出生日期比这个this对象日期后
int day = 0;
int y = 0,m = 0, d = 0;
if (this->year > s.year)
y = 1;
else if (this->year == s.year && this->month > s.month)
m = 1;
else if (this->year == s.year && this->month == s.month && this->day >= s.day)
d = 1;
if (y || m || d) {
//end是指到年末有多少天,start表示跟年初有多少天
//其实可以用365 - end得到start,但是要判断闰年和是否在2月29号前
int end = 0, start = 0;
end += (judge_month(s.month,s.year) - s.day);
for (int i = s.month + 1; i <= 12; i++)
end += judge_month(i,s.year);
start += this->day;
for (int i = 0; i < this->month; i++)
start += judge_month(i,this->year);
day += end + start;
if (y) {
for (int i = s.year + 1; i < this->year; i++) {
if (judge_year(s.year) && this->month < 2 && (this->month == 2 && day != 29)) {
day += 366;
}
else
day += 365;
}
}
if (m || d) {
if (judge_year(s.year))
day = 366 - day;
else
day = 365 - day;
}
return abs(day);
}
else
return 10000;
}
bool Student::judge_year(int y) {
if ((y % 4) == 0) {
if ((y % 100) == 0) {
if ((y % 400) == 0)
return true;
else
return false;
}
else
return true;
}
else
return false;
}
//这边的日期输入可以用数组来表示,我这里太复杂了
//比如可以定义一个数组month[12] = {31,28,31....}然后2月要判断闰年
int Student::judge_month(int m,int y) {
switch (m) {
case 1: {
return 31;
break;
}
case 2: {
if (judge_year(y))
return 29;
else
return 28;
break;
}
case 3: {
return 31;
break;
}
case 4: {
return 30;
break;
}
case 5: {
return 31;
break;
}
case 6: {
return 30;
break;
}
case 7: {
return 31;
break;
}
case 8: {
return 31;
break;
}
case 9: {
return 30;
break;
}
case 10: {
return 31;
break;
}
case 11: {
return 30;
break;
}
case 12: {
return 31;
break;
}
default:
return 0;
}
}
int main() {
int u = 0;
int t;
std::cin >> t;
int min = 0;
int time = 0;
Student* s = new Student[t];
for (int i = 0; i < t; i++) {
std::string name;
int y, m, d;
std::cin >> name >> y >> m >> d;
s[i] = Student(name, y, m, d);
}
for (int i = 0; i < t; i++) {
for (int j = 0; j < t; j++) {
if (i != j) {
if (time == 0) {
time++;
//我这边是取最小值,但是这是减法,所以可能有负值导致结果出错
//所以我在运算符重载中引用了abs函数(绝对值,需要cmath这个头文件)来让day总是为正
min = s[j] - s[i];
}
else
min = compare_min(s[j] - s[i], min);
}
}
}
for (int i = 0; i < t; i++) {
for (int j = 0; j < t; j++) {
if(i != j)
if (s[i] - s[j] == min) {
//由于题目是按照输入顺序来确定名字前后的,所以我这在这里加了一个判定
if(j < i)
std::cout << s[j].get_name() << "和" << s[i].get_name() << "年龄相差最小,为" << abs(min) << "天。" << std::endl;
else
std::cout << s[i].get_name() << "和" << s[j].get_name() << "年龄相差最小,为" << abs(min) << "天。" << std::endl;
//这里我定义了一个u和break是因为如果有两个人的差是一样的(tom和joe为一天,joe和jimme也是1天)
//会导致两次输出,我刚开始以为这是没有问题的,但是不出意外的话出意外了,所以我只让他输出一次
u = 1; break;
}
}
if (u)
break;
}
delete[]s;
return 0;
}
int compare_min(int a, int b) {
if (a > b)
return b;
else
return a;
}
思路:
最主要是要找到一个学生(这里用a来代表)a的到年末的时间,同时要考虑闰年,之后的加减要自己在草稿纸上推磨,这里很难讲清楚,讲出来也是繁杂
总的思路是不复杂的,但是要实践起来还是离不开草稿纸来整理思维,不然很容易头大
这里也可以定义一个时间类Date,网上其他人相似的题目里面有很多讲解了,这里我就不一一展开
希望同学们可以多多借鉴其他人优质的想法来完善自己的代码,在借鉴中进步也是一种不错的学习方法