一、目的(要求)日历程序(日历需包含以下三种功能):1.输出某年份的12个月2.输出某年某月3.输出某年某月某日是星期几二、概要设计1.程序运行的流程:开始运行的菜单可选择:(1)输出某年份的12个月(2)输出某年某月(3)输出某年某月某日是星期几当程序执行完成之后,可通过用户自己的意愿来选择是否再执行一次程序。2.所包含的函数如下:打印日历的函数:voidprintmonth(intm)构造日历的函数:voidprintheed(intm)intdaysofmonth(intm)intisleep()intfirstday(intm)voidreset()voidprintweek(intd)intisleep(ints)(重载函数)打印开关的函数:voidchoose(intc)三、设计要点1.每个函数的功能:voidprintmonth(intm)作用:实现对日历的打印。voidprintheed(intm)作用:构造出日历的头“月日一二三四五六”。intdaysofmonth(intm)作用:计算m月份的天数。intisleep()作用:判断当前年份是否为闰年。intfirstday(intm)作用:判断m月的第一天是星期几。voidreset()作用:全局变量归初始值。voidprintweek(intd)作用:将变量转化为用户可视的“星期一,星期二”等可视符号。intisleep(ints)作用:计算从N年到2012年中有多少个闰年,并且当N2012时不包含2012年,当N2012时包含2012年。voidchoose(intc)作用:构造程序内部菜单,面对计算机。2.关键代码分析:47~55:(此标注为代码行标,见四、源程序,下同)intk=firstday(m)If(k==7)k=0;for(inti=0;ik;i++)cout””;for(inti=1;i=daysofmonth(m);i++){cout””setw(2)i;if(k++==6){k=0;cout’\n’””;}}此代码中k(作用于为printmonth的局部变量)充当星期几的角色,由k控制当前输出的日期是星期几。64~82:{switch(m)case1:case3:case5:case7:case8:case10:case12:return31;case4:case6:case9:case11:return30;case:if(isleep())return29;elsereturn28;}}由此代码判断m月份有多少天,然后输出,构造日历。2月份通过isleep()函数判断是否为闰年。89~119:{If(m==1){If(yearN){ynn=isleep(0)*366+((N-year)isleep(0))*365;weekday=7-7nn%7;}else{ynn=(isleep(0))*366+((year-N)-isleep(0))*365;weekday=7+ynn%7;if(weekday7)weekday-=7;}}else{if(year=N){ynn+=daysofmonth(m-1);weekday=7+ynn%7;if(weekday7)weekday-=7;}else{ynn-=daysofmonth(m-1);weekday=7-ynn%7;}}returnweekday;}通过计算公式(总天数%7=距离2012年1月1日有几个星期单元)而算出m月的第一天是星期几。Isleep(0)通过计算之间有多少个闰年。通过对全局变量weekday的return(可省略)输出m月的第一天是星期几。121~123:{ynn=0;}对全局变量ynn归初始值,对第二遍的运行程序进行准备。138~153:{intsum=0;if(Nyear){for(inti=N;i=year;i++)if((i%4==0&&i&100!=0)||(i%400==0))sum+=1;returnsum;}elseif(Nyear){for(inti=N-1;i=year;i--)if((i%4==0&&i%100!=0)||(i%400==0))sum+=1;returnsum;}elsereturn0;}计算并返回sum(作用域为isleep(ints))的值(从N年到2012年不包括2012年(2012年到N年)有多少个闰年)。155~200:{switch(c){case1:{160~165}case2:{168~175}case3:{179~196}default:cout”ERROR!”;}}通过开关switch制造构建三个菜单(case1,case2,case3)以便程序能够清晰且分工明确地运行三个功能。3.重点代码注释:53~54:cout””setw(2)i;if(k++=6){k=0;cout’\n’””;}//用空格(””)和setw函数对日历进行塑形60~61:coutsetw(2)m”月日一二三四五六\n”;cout””;//用空格(””)和setw函数对日历进行塑形85~86:if((year%4==0&&year%100!=0)||(year%400==0))return1;elseruturn0;//用条件表达式与逻辑表达式进行闰年判断94~95:ynn=isleep(0)*366+((N-year)-isleep(0))*365;weekday=7-ynn%7;99~101:ynn=isleep(0)*366+((N-year)-isleep(0))*365;weekday=7+ynn%7;if(weekday7)weekday-=7;//当月份为1月份时,用isleep(0)计算并结合实际经验得出相差基准(2012年1月1日)总天数,由于年份大于基准和小于基准都会对计算产生影响,所以会有两个语句体。108~110:ynn+=daysofmonth(m-1);weekday=7+ynn%7;if(weekday7)weekday-=7;114~115:ynn-=daysofmonth(m-1);weekday=7-ynn%7;//当月份大于1月份时,直接用daysofmonth函数进行累加(注:函数的实参为m-1,因为需要包含1月份的31天),得出相差基准(2012年1月1日)总天数,由于年份大于基准和小于基准都会对计算产生影响,所以会有两个语句体。142~144:for(inti=N;i=year;i++)if((i%4==0&&i&100!=0)||(i%400==0))sum+=1;returnsum;148~150:for(inti=N-1;iyear;i--)if((i%4==0&&i&100!=0)||(i%400==0))sum+=1;returnsum;152:elseruturn0;//定义sum(作用域为isleep(ints)的局部变量)来记录N与基年(2012年)之间闰年的个数,由于小于基年的时候不应该算2012年的366天和大于基年的时候应该算2012年的366天的不同还有当2012年时不加不减,所以会出现三个语句体。172~173:for(inti=1;i=(month-1);i++)intk=firstday(i);183~184:for(inti=1;i=(month-1);i++)intk=firstday(i);//模拟运行:由于日历的形成是建立在累加的基础上的(详见daysofmonth(intm))所以当需要计算n月的值的时候,必须先累加1~n-1所有月所含的天数,所以需要进行一个模拟的运行。189~193:for(inti=1;i=day;i++){If(k++=6)k=0;}k-=1;//由于第191行的k++所以k的值会比实际需要输出的值大1,所以需要进行一个逆向操作k-=1。4.全局变量注释:intyear:用于记录年份intmonth:用于记录月份intweekday:用于记录m月的第一天intday:用于记录m月的第几日intynn:用于记录距离基点(2012年1月1日)的距离(日子)5.程序实现步骤:(1)先通过运行main()(主调函数)来显示可视字符,说明程序的功能和教程。(2)再通过用户输入的1、2、3(实参)运行choose(intc)函数,计算机内部选择需要执行的功能(1、2、3)。(3)当执行功能1的时候,用户输入year(实参)之后,便调用printmonth(intm)函数。printmonth(intm)函数内部-通过printheed(intm)打印m月份的头。-通过isleep()判断是否为闰年。-通过isleep(ints)判断基年与year之间差了多少闰年、-通过firstday(intm)判断且打印m月份第一天是星期几。-通过daysofmonth(intm)打印剩余天数。(4)当执行功能2的时候,用户输入year、month(实参)之后,便进行模拟运行,然后调用printmonth(intm)函数。(5)当执行功能3的时候,用户输入year、month、day(实参)之后,便进行模拟运行,通过定义k(定义域为choose的局部变量)来获取当前月的第一天是星期几,然后通过循环得到year年month月day日是星期几,调用printweek(intd)进行打印。(6)当用户输入的实参不正确时(不等于1、2、3),会输出”ERROR!”。(7)最后通过while循环判断是否需要再次使用该程序(输入’y’或者’n’)。(8)当输入’y’的时候再次运行程序。(9)当输入’n’的时候结束改程序,返回值0。四、源程序1.#includeiostream2.#includestdlib.h3.#includeiomanip4.#defineN2012//编译预处理:相当于const5.#defineT//条件编译:与cout一起利用,用于检查并修改程序错误6.usingnamespacestd;7.voidprintmonth(intm);8.voidprintheed(intm);9.intdaysofmonth(intm);10.intisleep();11.intfirstday(intm);12.voidreset();13.voidprintweek(intd);14.intisleep(ints);15.voidchoose(intc);16.intyear;//全局变量:年份17.intmonth;//全局变量:月份18.intweekday;//全局变量:月的第一天19.intday;//全局变量:日20.intynn;//全局变量:距离2012.1.1的日子21.intmain()22.{23.inti;24.chara='y';25.while(a=='y')//实现结束的时候again26.{27.cout********************************\n;28.cout1.输出某年的12个月的日历\n;29.cout2.输出某年某月的日历\n;30.cout3.输出某年某月某日的星期几\n;31.cout********************************\n;32.cout请输入(1,2,3):\n;33.cini;34.reset();35.choose(i);36.a='n';37.cout*****again?*****\n;38.cout请输入(y)或者(n);39.cina;40.}41.system(PAUSE);//MicrosoftVisualStudio2012需要system(PAUSE)来暂停控制台界面42.return0;43.}44.voidprintmonth(intm)45.{46.print