万年历及日期查询工具
齐鲁工业大学
信息学院
课程名称:面向对象程序设计
目名称:日期查询工具 学生姓名:刘胜军
学生学号:201203014036 专业班级:计科(高职)12-1 指导教师:任晓强 完成日期:2013年6月25日
目 录
一、课程设计目的与任务 2 二、课程设计
2
1 本设计题目的主要内容 2
2 设计思想与程序构架 3
3 软件使用说明书 14
4 程序测试及
15
5 设计总结 19 三、主要参考资料 19 四、附录 20
1 程序源代码及基本注释 20
1
一、 课程设计目的与任务
本课程设计是针对面向对象程序设计课程的实践教学项目,为学生提供一个既动手又动脑,针对C++面向对象语言的独立实践的机会,将课本上的理论知识和实际有机的结合起来,通过接近实际项目的训练,锻炼的分析解决实际问题的能力。提高学生面向应用的实践编程的能力。
二、 课程设计内容
1 本设计题目的主要内容
1. 设计内容
编写一个可以查询任意年的日历,任意月的日历;可以查询某天的对应星期,查询当前时间;可以计算两日期差的工具《日期查询工具》。
2. 具体功能及要求:
1).显示公元后任何年份的日历,日历以月份顺序排列,每月以星期顺序排列,类似于一般挂历上的格式。
2).显示公元后任何年份任何月份的日历,以星期顺序排列,类似于一般挂历上的格式。
3).可以查询某天的对应星期,查询当前时间。
4).可以计算指定的两日期间的时间(天数)差。
5).可以计算指定日期后,前后某天数对应的日期。
6).可以对年日历和月日历进行保存。
3. 最终程序样式
2
4. 运行环境
(1)Windows XP/7/8系统
(2)Microsoft Visual C++ 6.0编译环境
5. 开发工具
C语言
6. 实现方法
(1)定义一个Date类,使包含所有数据成员及函数,如数据成员年、月、日、星期,成员函数年份平润年的判断函数JudgeYear(int y),某日期到公元1年1月1日实有天数的计算函数GetYearDays(int y)等12个主要函数及主要函数中需要用到的12个辅助函数;
(2)在主函数中通过选择不同的功能,执行不同的模块,完成相应功能;
(3)画出所有模块的流程图;
(4)编写代码;
(5)程序分析与调试。
2 设计思想与程序构架
?. 程序类中主要成员函数的定义方式及解释(原代码详见附录>1)
1. 先分析一个实验所要完成的功能,发现中间需要有平润年的判断;任意年份的实有天数判断;任意月的实有天数判断;任意年到1年1月1日的实有天数;由到1年1月1日的实有天数计算对应日期;判断任意日期对应的星期;显示年日历,保存年日历;显示月日历,保存月日历等。
2. 根据分析定义一Date类,拥有Year,Month,Day,Week四个私有整形数
3
据成员,然后根据分析分别声明相应类型的成员函数,又因为数据成员为私有成员,若要调用或修改只能调用函数,所以另直接定义八个成员函数以实现这部分获取、修改功能。最后还要定义构造函数以实现对数据成员的快速赋值,包括没有参数,年月日皆为1,只一个参数对年赋值,月日为1,两个参数对年月赋值,日为1,三个参数对年月日赋值,星期直接通过函数计算可得。成员函数累计24个,基本如下:
class Date //定义日期类
{
private:
int Year;
int Month;
int Day;
int Week;
public:
Date(){Year=1;Month=1;Day=1;} //构造函数,经初始化数据成员
Date(int y){Year=y;Month=1;Day=1;}
Date(int y,int m){Year=y;Month=m;Day=1;}
Date(int y,int m,int d){Year=y;Month=m;Day=d;}
void SetYear(int y){Year=y;} //设置年份
void SetMonth(int m){Month=m;} //设置月份
void SetDay(int d){Day=d;} //设置日份
void SetWeek(int w){Week=w;} //设置星期
int GetYear() const {return Year;} //获取年份
int GetMonth() const {return Month;} //获取月份
int GetDay() const {return Day;} //获取日份
int GetWeek() const {return Week;} //设置星期
static bool JudgeYear(int y) //判断某年是否为润年(平年)
{
if(y%4==0 && y%100!=0 || y%400==0)
return true;
else
return false;
}
int GetMonthDays(int m); //判断某年某月实有天数
int GetYearDays(int y); //判断某年实有天数
4
int DateToNum(); //判断某年到1年1月1日实有天数 Date NumToDate(int); //由1年1月1日至指定日期实有天数返回日期 void OutMonth(int r); //月份输出
void OutWeek(int r); //星期输出
void AllShow(); //输出某年全年日历 void WAllShow(); //文件输出某年全年日历 void MonthShow(); //输出某年某月日历 void WMonthShow(); //输出某年某月日历 void WeekShow(); //输出某年某月某日星期日历 };
3. 定义平润年的判断,只需要获取指定的年份,能过“能被4整除不能被100整除是润年和能被400整除是润年”判断即可,是润年返回True,否则返回False,直接在类内定义。
static bool JudgeYear(int y) //判断某年是否为润年(平年) {
if(y%4==0 && y%100!=0 || y%400==0)
return true;
else
return false;
}
4. 定义任意年份的实有天数判断,只需要判断指定年份是否为润年,是则返回366,否则365。
int Date::GetYearDays(int y) //判断某年实有天数 {
if(JudgeYear(y)) //调用JudgeYear(int y)判断平润年
return 366;
else
return 365;
};
5. 定义任意月的实有天数判断,需要获取指定的年份与月份,能过判断月份,大月返回31天,小月返回30天,2月还需要通过判断年份是否为润年返回相应值,润年返回29天,平年返回28天。
int Date::GetMonthDays(int m) //判断某年某月实有天数 {
int n;
5
switch(m) //判断月份
{
case 1: case 3: case 5: case 7: case 8: case 10:case 12:
n=31;break;
case 4: case 6: case 9: case 11:
n=30;break;
case 2:
if(JudgeYear(GetYear())) //调用JudgeYear(int y)判断平润年
n=29; //是润年返回29年
else
n=28; //不是润年返回28年
break;
}
return n;
};
6. 定义任意年到1年1月1日的实有天数,定义一个用于存放总天数的
,通过循环先与指定年份前1年到公元1年所有年份的总天数n,赋初值为0
相加,每次循环都需要调用任意年份的实有天数判断函数获取某年的总天数;指定年份前x年所有年份总天数相加完成后,再通过循环与指定月份前1月到1月所有月份总天数相加,期间也要计算个个月的总天数;最后与指定日期的天数相加,返回n的值即可。
int Date::DateToNum() //判断某年到1年1月1日实有天数
{
int y,n=0;
for(y=1;y
GetYearDays(y);y++)
rest-=GetYearDays(y);
for(m=1,rest;rest>GetMonthDays(m);m++)
rest-=GetMonthDays(m);
d=rest;
return Date(y,m,d);
};
8. 定义判断任意日期对应的星期,此过程只需要计算出指定日期到公元1年1月1日的实有天数,然后除7取余即可,其余数就是对应的星期。
9. 定义显示年日历,此函数目的在于输入全年日历。具体实现如下:定义4个变量,分别存放指定年份的1月1日到公元1年1月1日的实有天数,可调用函数实现,此年份中某月1号对应的星期,可调用函数计算此年某月1号到公元1年1月1日的实有天数除7取余实现,另两个用于循环。共有两层循环,第一层循环共计12次,一年只有12个月,第二层循环次数由当前要输出的月份的总天数判断。第二层循环内又嵌套二个循环,第一个条件为某月1号是星期几则输出几个tab空格,第二层循环用于输出日历,能过输出的日期加上之前的空格数除7余0作为换行条件,以实现以星期布局。主要部分也就如此,另外日历前后的横线、星期、年月份直接输出,或调用函数输出即可。此次编写,也把月份的输出重定义了一个函数,由获取一个月份,输出大写月份,由switch语句实现。
void Date::AllShow() //输出某年全年日历
{
int n,morday,wek,j;
morday=DateToNum();
cout<<" "<12 || m<1 || da>d.GetMonthDays(m) || da<1;)
{
cout<<"对应日期有误,请重新输入:";
cin>>y>>m>>da;
d.SetYear(y);
d.SetMonth(m);
d.SetDay(da);
y=d.GetYear();
m=d.GetMonth();
da=d.GetDay();
}
};
?. 程序主函数中主要功能的实现方式及解释(代码详见附录>1) 1. 为实现循环,调用do„while语句。
11
2. 提示部分直接在do„while语句内最前面输出即可,如选择几,是什么功能。
cout<<"-------------------------------------------------------------------\n";
cout<<" 选择1:查看X年日历\n";
cout<<" 选择2:查看X年X月日历\n";
cout<<" 选择3:查看X年X月X日对应星期\n";
cout<<" 选择4:计算两日期间的天数差\n";
cout<<" 选择5:计算指定日期后X天的日期\n";
cout<<" 选择6:查看系统时间\n";
cout<<" 选择7:清屏并继续\n";
cout<<" 选择8:退出\n";
cout<<"-------------------------------------------------------------------\n";
3. 定义一整形变量jud,并赋初值为可满足do„while语句循环的值,这里为7.
do
{
„„
}while(jud==7);
4. 通过if判断jud的值,执行不同的功能,前5个功能都是依靠Date类及里面的函数实现的,这里就不多说了,主要说一下第6个,显示当前系统时间,需要用到函数库,定义time_t 变量now,使用time(&now)实现给now赋当前系统时间,定义tm型指针*tim=localtime(&now),然后按指定格式依次输出tim中对应的年月日时分秒。
if(jud==6)
{
time_t now;
time(&now);
tm *tim=localtime(&now);
cout<<"当前时间:"<tm_year+1900<<"-"<tm_mon+1
<<"-"<tm_mday <<" "<tm_hour<<":"<tm_min<<":"
<tm_sec<标准计算。在测试天数差的时候,有几组数据的运行结果为负值。后想到用户输入的日期先后顺序不固定,所以需要将两日期差取绝对值,所以将t2.DateToNum()-t1.DateToNum()修改为abs(t2.DateToNum()-t1.DateToNum())。第5个功能运行正常,且输入的数据有正负之分,正为向后推出查询,负为向前查询。
17
4. 第5~8个功能经测试可正常运行。
18
5 设计总结
程序设计类似于数学的研究,要求每一个环节都不能有问题,哪怕“一毫米的差池”。在此次的程序的编写中,使我不仅更加熟练了C++的使用与程序的编写,更使我懂得了对任何事情的严谨性。在此程序中判断闰年的条件,某月1日是星期几,输入的日期判断是否有误要求不能有一点错误,否则整个程序的大部分功能将无法使用。
除了严谨性外,还有就是要有耐心和足够的细心,程序的编写较为顺利,程序本身测试也没有问题,但在最后测试时,遇到星期的判断一直不变,主函数中do„while循环一直有部分不能用。一直以为是函数编写有误,可是查了好久,还是发现无误。最后,经过好长时间才发现if语句中的条件中“==”打成了“=”,小小的错误引起大的“波澜”,使的整个每次只能用一个功能,变得相当麻烦。
三、 主要参考资料
[1] 游洪跃, 伍良富, 王景熙. C++面向对象程序设计实验和课程设计
[M]. 第1版. 北京:清华大学出版社, 2009.2 :159-163.
[2] 谭浩强. C++面向对象程序设计[M]. 第1版. 北京:清华大学出版社, 2006.1.
[3] 明月科技. C语言函数参考手册[M]. 第1版. 北京:清华大学出版社, 2012.1 :376-379.
19
四、 附录
1. 程序源代码及基本注释
#include
//预处理命令 #include
#include
using namespace std; //使用标准命名空间std class Date //定义日期类 {
private:
int Year; //年
int Month; //月
int Day; //日
int Week; //星期
public:
Date(){Year=1;Month=1;Day=1;} //构造函数
Date(int y){Year=y;Month=1;Day=1;} Date(int y,int m){Year=y;Month=m;Day=1;}
Date(int y,int m,int d){Year=y;Month=m;Day=d;}
void SetYear(int y){Year=y;} //设置年份 void SetMonth(int m){Month=m;} //设置月份 void SetDay(int d){Day=d;} //设置日份 void SetWeek(int w){Week=w;} //设置星期 int GetYear() const {return Year;} //获取年份 int GetMonth() const {return Month;} //获取月份 int GetDay() const {return Day;} //获取日份 int GetWeek() const {return Week;} //设置星期 static bool JudgeYear(int y) //判断某年是否为润年(平年) {
if(y%4==0 && y%100!=0 || y%400==0)
return true;
else
return false;
}
int GetMonthDays(int m); //判断某年某月实有天数 int GetYearDays(int y); //判断某年实有天数
20
int DateToNum(); //判断某年到1年1月1日实有天数
Date NumToDate(int); //由1年1月1日至指定日期实有天数返回日期
void OutMonth(int r); //月份输出
void OutWeek(int r); //星期输出
void AllShow(); //输出某年全年日历
void WAllShow(); //文件输出某年全年日历
void MonthShow(); //输出某年某月日历
void WMonthShow(); //输出某年某月日历
void WeekShow(); //输出某年某月某日星期日历
};
int Date::DateToNum() //判断某年到1年1月1日实有天数
{
int y,n=0;
计算当前年份前一年到公元1for(y=1;yGetYearDays(y);y++) //计算总天数中最多含有的年份y
rest-=GetYearDays(y);
for(m=1,rest;rest>GetMonthDays(m);m++) //计算剩余天数中最多含有的月份m
rest-=GetMonthDays(m);
21
d=rest; //将最终剩余的天数赋给天数d return Date(y,m,d); //以日期型返回
};
int Date::GetMonthDays(int m) //判断某年某月实有天数 {
int n;
switch(m)
{
case 1: case 3: case 5: case 7: case 8: case
10:case 12://大月n=31天
n=31;break;
case 4: case 6: case 9: case 11: //
小月n=30天
n=30;break;
case 2:
if(JudgeYear(GetYear())) //判断平润年
n=29; //润年n=29天
else
n=28; //平年n=28天
break;
}
return n; //返回n
};
int Date::GetYearDays(int y) //判断某年实有天数 {
if(JudgeYear(y))
return 366;
else
return 365;
};
void Date::OutMonth(int r) //月份输出 {
switch(r)//根据月份的值,以“一(二、三、„„)月份”形式输出相
应的月份
22
{
case 1:cout<<"一月份"<<'\n';break; case 2:cout<<"二月份"<<'\n';break; case 3:cout<<"三月份"<<'\n';break; case 4:cout<<"四月份"<<'\n';break; case 5:cout<<"五月份"<<'\n';break; case 6:cout<<"六月份"<<'\n';break; case 7:cout<<"七月份"<<'\n';break; case 8:cout<<"八月份"<<'\n';break; case 9:cout<<"九月份"<<'\n';break; case 10:cout<<"十月份"<<'\n';break; case 11:cout<<"十一月份"<<'\n';break; default:cout<<"十二月份"<<'\n'; }
};
void Date::OutWeek(int r) //星期输出 {
switch(r)
{
case 1:cout<<"星期一"<<'\n';break; case 2:cout<<"星期二"<<'\n';break; case 3:cout<<"星期三"<<'\n';break; case 4:cout<<"星期四"<<'\n';break; case 5:cout<<"星期五"<<'\n';break; case 6:cout<<"星期六"<<'\n';break; default:cout<<"星期日"<<'\n';
}
};
void Date::AllShow() //输出某年全年日
历
{
int n,morday,wek,j;
morday=DateToNum();
cout<<" "<12 || m<1 || da>d.GetMonthDays(m) || da<1;)//判断条件 {
cout<<"对应日期有误,请重新输入:";//如果符合条件,提示日期
有误
cin>>y>>m>>da;//重新接收输入的日期
d.SetYear(y);//重新赋值
d.SetMonth(m);
d.SetDay(da);
y=d.GetYear();
m=d.GetMonth();
da=d.GetDay();
}
};
int main()
{
int jud=0;
do
{
cout<<"----------------------------------------------------------
---------\n";//菜单输出
cout<<" 选择1:查看X年日历\n";
cout<<" 选择2:查看X年X月日历\n";
28
cout<<" 选择3:查看X年X月X日对应星期\n";
cout<<" 选择4:计算两日期间的天数差\n";
cout<<" 选择5:计算指定日期后X天的日期\n";
cout<<" 选择6:查看系统时间\n";
cout<<" 选择7:清屏并继续\n";
cout<<" 选择8:退出\n";
cout<<"----------------------------------------------------------
---------\n";
cout<<"请选择:";
cin>>jud;//判断条件输入
if(jud==1)//年份查询与保存
{
int Y1;
char a;
cout<<"请输入查询年份:";
cin>>Y1;
Date d1(Y1);
d1.AllShow();
cout<<"是否保存此年历?(是:Y/否:All)";
cin>>a;
if(a=='Y' || a=='y')//判断是否保存
d1.WAllShow();//若保存调用WAllShow()函数
jud=7;continue;//跳出此次循环重新回到循环开始
}
if(jud==2)//月份查询与保存
{
char a;
int Y2,M2;
cout<<"请输入年月,中间用空格间隔:";
cin>>Y2>>M2;
Date d2(Y2,M2);
Datejudge(d2);//判断日期是否合法
d2.MonthShow();//屏幕输出月日历
cout<<"是否保存此月历?(是:Y/否:All)";
29
cin>>a;
if(a=='Y'||a=='y')//判断是否保存
d2.WMonthShow();//若保存调用WMonthShow()函数
jud=7;continue;//跳出此次循环重新回到循环开始
}
if(jud==3)
{
int Y3,M3,D3;
cout<<"请输入年月日,中间用空格间隔:";
cin>>Y3>>M3>>D3;
Date d3(Y3,M3,D3);
Datejudge(d3);//判断日期是否合法
d3.WeekShow();//屏幕输出星期
jud=7;continue;//跳出此次循环重新回到循环开始
}
if(jud==4)
{
int ty1,tm1,td1,ty2,tm2,td2;
cout<<"请输入首日期:";
cin>>ty1>>tm1>>td1;
Date t1(ty1,tm1,td1);
Datejudge(t1);//判断日期是否合法
cout<<"请输入尾日期:";
cin>>ty2>>tm2>>td2;
Date t2(ty2,tm2,td2);
Datejudge(t2);//判断日期是否合法
cout<>ty1>>tm1>>td1;
Date t(ty1,tm1,td1);
Datejudge(t);//判断日期是否合法
cout<<"请输入推迟天数(负为当前日期前,正为当前日期后):";
cin>>day;
day+=t.DateToNum();//计算日期实有天数与推迟天数的和
t=t.NumToDate(day);//通过天数和,计算日期
cout<<"推迟后日期为:"<tm_year+1900<<"-"<tm_mon+1<<"-"<tm_mday;//显示本地时间
cout<<"
"<tm_hour<<":"<tm_min<<":"<tm_sec<