一 、实现的功能
注意:此日历只能用于计算1982年10月15日以及以后的日期
1、日期 +/- 天数 = 返回日期
(1)如果 +/- 一个负的天数的情况
(2)如果返回日期非法
2、两个日期之间间隔的天数,日期 - 日期 = 返回的天数(返回的天数不能为负)
3、打印某年某月的日历
二、测试
1、功能测试
(1)对输入日期合法性的测试(边界值、等价类)
1、年份是否合法
2、月份是否合法
3、天数是否合法
4、年份月份天数结合是否合法
(2)对“计算某个日期加、减天数得到另一个日期”功能的测试
1、对于普通月份加、减的测试
2、对于平年/闰年2月份加、减的测试
3、对于加、减一个负数,是否可以处理
4、如果加、减上一个数,日期小于1582年10月15,是否处理
(3)对于“计算两个日期之间间隔的天数”功能的测试
1、测试相减之后的日期是否合法
(4)对于“打印指定日期当月的日历”功能的测试(边界值、等价类)
1、对“输入1582年10月的日历打印”的测试
2、对“输入大于1582年10月的日历打印”的测试
3、对“输入小于1582年10月即非法日期日历打印”的测试
2、界面测试
(1)界面是否美观,清楚
(2)如果输入错误,错误提示字样是否正常输出
(3)如果输入错误,是要重新输入本次,还是要全部重新输入
三、源码
class Date
{
friend ostream& operator<<(ostream& os, const Date& d);
friend istream& operator>>(istream& is, Date& d);
public:
Date(int year = 1582, int month = 10, int day = 4)
{
_year = year;
_month = month;
_day = day;
}
void PrintfMonth()//打印该日期所在月份日历
{
if (_year == 1582 && _month == 10)
{
_PrintfMonthSpecial();
}
else
{
_PrintfMonth();
}
}
//d+10
Date operator+(int day)
{
Date ret(*this);
ret += day;
return ret;
}
Date operator-(int day)
{
Date ret(*this);
ret -= day;
return ret;
}
int operator-(const Date& d) //日期-日期=返回天数
{
int ret = DayNum( d);
return ret;
}
bool operator==(const Date& d)const //只要实现> ==其他的都可以全部复用
{
return _year == d._year&&_month == d._month&&_day == d._day;
}
bool operator >(const Date& d)const
{
if (_year > d._year)
{
return true;
}
else if (_year == d._year)
{
if (_month > d._month)
{
return true;
}
else if (_month == d._month)
{
if (_day > d._day)
{
return true;
}
}
return false;
}
}
bool operator<(const Date& d)const
{
return !(*this >= d);
}
bool operator >=(const Date& d)const
{
return *this > d || *this == d;
}
bool operator<=(const Date& d)const
{
return !(*this>d);
}
int judge()
{
if (_year < 1581 || _month<1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))//GetMonthDay不一定要写在前面,和C语言不一样,类是在类里面都会找
{
return 1;
}
if (_year == 1582)
{
if (_month < 10 || _month >12)
{
return 1;
}
if (_month == 10 && (_day <15 || _day >= GetMonthDay(_year, _month)))
{
return 1;
}
}
return 0;
}
private:
Date& operator++()//前置 返回加加之后的值
{
*this += 1;
return *this;
}
//d++ d.opeartor++(&d,0)
Date operator++(int i)//后制
{
Date ret(*this);
*this += 1;
return ret;
}
int DayNum(const Date& d)
{
//int flag = 1;
//Date* max=this;
// Date* min= &d ;
//if (*this < d)
//{
// swap(max, min);
// flag = -1;
//}
//int day = 0;
//while (*min < *max)//自定义类型前置++好
//{
// ++(*min);
// ++day;
//}
//return day*flag;//判断是正数,负数。
Date max = *this;
Date min = d;
if (*this < d)
{
max = d; min = *this;
//flag = -1;
}
int day = 0;
while (min < max)
{
++min;
++day;
}
return day;
}
Date& operator+=(int day)
{
if (day<0)//处理加一个负数的情况
{
return*this -= -day;
}
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
Date& operator-=(int day)
{
if (day < 0)//处理减一个负数的情况
{
return *this += -day;
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
_month = 12;
--_year;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
void _PrintfMonth()//打印某个日期当月日历
{
cout.width(5);
cout << "日";
cout.width(5);
cout << "一";
cout.width(5);
cout << "二";
cout.width(5);
cout << "三";
cout.width(5);
cout << "四";
cout.width(5);
cout << "五";
cout.width(5);
cout << "六" << endl;
int year = _year;
int month = _month;
if ((_month == 1) || (_month == 2))
{
year -= 1;
month += 12;
}
//******************以下代码只考虑1582年10月4日之后的月历打印***************
//蔡勒公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
//w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六
//y:年(年数后两位数)c:世纪-1(年数前两位数)d:日
//m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)
int c = int(year / 100);
int y = year - 100 * c;
//计算当前月份第一天为星期几,d==1
int w = y + int(y / 4) + int(c / 4) - 2 * c + (26 * (month + 1) / 10) + 1 - 1;//***一定要注意带方括号取整数的算式,要加上int的强制类型转换
w = (w % 7 + 7) % 7;//处理负数的情况
for (int i = 0; i<w; i++)//处理第一行空白处
{
cout.width(5);
cout << " ";
}
for (int i = 0; i<7 - w; i++)//处理第一行日期
{
cout.width(5);
cout << i + 1;
}
cout << endl;
int count = 0;
for (int i = 7 - w; i< GetMonthDay(_year, _month); i++)
{
cout.width(5);
cout << i + 1;
count++;
if ((count) / 7 == 1)
{
cout << endl;
count = 0;
}
}
cout << endl;
}
void _PrintfMonthSpecial()
{
cout.width(5);
cout << "日";
cout.width(5);
cout << "一";
cout.width(5);
cout << "二";
cout.width(5);
cout << "三";
cout.width(5);
cout << "四";
cout.width(5);
cout << "五";
cout.width(5);
cout << "六" << endl;
for (int i = 0; i<1; i++)//处理第一行空白处
{
cout.width(5);
cout << " ";
}
for (int i = 0; i < 6; i++)//处理第一行日期
{
if (i >= 4)
{
cout.width(5);
cout << i + 11;
}
else{
cout.width(5);
cout << i + 1;
}
}
cout << endl;
int count = 0;
for (int i = 16; i< GetMonthDay(_year, _month); i++)
{
cout.width(5);
cout << i + 1;
count++;
if ((count) / 7 == 1)
{
cout << endl;
count = 0;
}
}
cout << endl;
}
int GetMonthDay(int year, int month)
{
static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//每次来都不动
int day = days[month];
if ((month == 2) && ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))//如果不是二月就不用走后面了
{
day += 1;
}
return day;
}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& os, const Date& d)
{
os << d._year << "-" << d._month << "-" << d._day;
return os;
}
istream& operator>>(istream&is, Date& d)
{
is >> d._year >> d._month >> d._day;
return is;
}
void menu()
{
cout << "===================欢迎使用日期计算器==================="<<endl;
cout << "==============请根据如下提示输入相应编号选择功能=========="<<endl;
cout << "=================1>计算此天多少天之后的日期=============="<<endl;
cout << "=================2>计算此天多少天之前的日期=============="<< endl;
cout << "=================3>打印两个日期中间相隔天数=============="<<endl;
cout << "=================4>打印输入日期所在月的日历=============="<<endl;
cout << "========================0>退出========================"<<endl;
}
void test()
{
menu();
int n = 1;
while (n)
{
end6:
cout << "请按键选择相应的服务:";
cin >> n;
switch (n)
{
case 1:
{
Date d1;
int n = 0;
end1:
cout << "请输入开始日期:";
cin >> d1;
int ret= d1.judge();
if (ret == 1)
{
cout << "非法日期,重新输入"<<endl;
goto end1;
}
cout << "请输入天数:";
cin >> n;
ret= (d1 + n).judge();
if (ret == 1)
{
cout << n << "天以后的日期是非法日期" << endl;
break;
}
cout << n << "天以后的日期是:" << (d1 + n) << endl;
cout << "请继续使用" << endl;
break;
}
case 2:
{
Date d2;
int n = 0;
end2:
cout << "请输入开始日期:";
cin >> d2;
int ret= d2.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end2;
}
cout << "请输入天数:";
cin >> n;
ret = (d2- n).judge();//判断减之后的日期是否合法
if (ret == 1)
{
cout << n << "天以前的日期是非法日期" << endl;
break;
}
cout << n << "天以前的日期是:" << ret << endl;
cout << "请继续使用" << endl;
break;
}
case 3:
{
Date d3;
Date d4;
end3:
cout << "请输入开始日期:";
cin >> d3;
int ret= d3.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end3;
}
end4:
cout << "请输入终止日期:";
cin >> d4;
ret=d4.judge();
if (ret == 1)
{
cout << "非法日期,重新输入" << endl;
goto end4;
}
cout << "两个日期之前相差:" << d4 - d3 << "天" << endl;
cout << "请继续使用" << endl;
break;
}
case 4:
{
Date d5;
end5:
cout << "请输入日期:";
cin >> d5;
int ret = d5.judge();
if (ret == 1)
{
goto end5;
}
cout << "本月的日历为:" << endl;
d5.PrintfMonth();
break;
}
case 0:
break;
default:
cout << "输入错误!" << endl;
goto end6;
}
}
}
int main()//测试用例 +一个负数
{
test();
Date d;
system("pause");
return 0;
}