C++课程设计——万年历
功能要求:
(1)输入一个年份,输出是在屏幕上显示该年的日历。假定输入的年份在1940-2040年之间。
(2)输入年月,输出该月的日历。
(3)输入年月日,输出距今天还有多少天,星期几,是否是公历节日。
一.设计目的
1:要求学生能够熟练掌握C++语言的基本知识和技能。
2:基本掌握面向过程程序设计的基本思路和方法。
3:能够利用所学的基本知识和技能,解决简单的面向过程程序设计问题。
4:培养自己独立分析问题、解决问题、查阅资料以及自学能力,综合运用所学知识,解决实际问题,提高程序设计能力和开发能力。
二.总体设计
三.详细设计
(1)函数功能:判断是平年,还是润年
函数原型:int nyear(int year);
参数:year;
返回值:365||366;
(2)函数功能:根据年份和月份,判断是那一个月的天数
函数原型:int nmonth(int m,int y);
参数:m,y;
返回值:31,30,29,28;
(3)函数功能:输入年份和月份确定到1940年1月1日总共多少天
函数原型:int getDays(int year, int month);
参数:year,month;
返回值:sum(总天数);
(4)函数功能:输入年份和月份和日子确定到1940年1月1日总共多少天
函数原型:int getDays0(int year, int month,int t);
参数:year,month,t;
返回值:sum+t;
(5)函数功能:输出一年的日期
函数原型:void wnl1(int year)
参数:year
(6)函数功能:输出某年某月的日历
函数原型:void wnl2(int year,int month)
参数:year,month
(7)函数功能:求时间间隔,并判断是不是公历节日,星期几
函数原型:void wnl3(int m_year,int m_month,int m_day,int cz)
参数 m_year,m_month,m_day,cz
(8)循环
对于一般的循环,若不符合条件直接跳出;
do-while 循环中,第一次使用之后,若输入字符y或者Y可重新循环,输入其他字符就跳出循环,实现万年历功能多次使用
(9)switch语句
可以列一个功能清单,输入1/2/3便进入相应的功能区,同时在case里面可以写一些不方便计算的数值以此作为实参进入函数体中,或者直接输入实参进入函数体
四.调试与测试
五.实现方法:(源程序)
#include "StdAfx.h"
#include<iostream>
using namespace std;
//1940年1月1号是星期一
int nyear(int year)//判断是平年,还是闰年
{
if(year%400==0||(year%4==0&&year%100!=0))
return 366;
else
return 365;
}
int nmonth(int m,int y) //根据年份和月份,判断那一个月的天数
{
if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)
return 31;
else if(nyear(y)==366&&m==2)
return 29;
else if(nyear(y)==365&&m==2)
return 28;
else
return 30;
}
int getDays(int year, int month)//输入年份和月份确定到1940年1月1日总共多少天,1940.1.1是星期一
{
int i;
int sum=0;
if(year>1940)
for(i=1940;i<year;i++)
sum+=nyear(i);//此时sum为1940——year-1年的天数
if(month>1)
for(i=1;i<month;i++)
sum+=nmonth(i,year);
return sum; //返回上个月末距离1940.1.1的总天数
}
int getDays0(int year, int month,int t)//输入年 月 日确定到1940年1月1日总共多少天
{
int i;
int sum=0;
if(year>1940)
for(i=1940;i<year;i++)//此时sum为1940——year-1年的天数
sum+=nyear(i);
if(month>1)
for(i=1;i<month;i++)
sum+=nmonth(i,year);//上个月末到1940.1.1的天数,还差本月某日的天数
return sum+t;//t为当然月份的日历号数,此时sum+t即为1940——输入时间 的总天数
}
void wnl1(int year)//输出一年的日期
{
int month,daycount,k,sum,t,j;
char *t_month[13] = {0,"一月(Jan)","二月(Feb)","三月(Mar)","四月(Apr)","五月(May)","六月(Jun)","七月(Jul)","八月(Aug)","九月(Sep)","十月(Oct)","十一月(Nov)","十二月(Dec)"};
char *t_week[7] = {"Sun","Mon","Tue","Wen","Thru","Fri","Sat"};
for( month=1; month<=12; month++)//年循环,输出每年的每月
{
cout<<endl;
cout<<endl;
cout<<endl;
cout<<" "<<t_month[month]<<endl;
cout<<"☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆"<<endl;
cout<<"Sun Mon Tue Wed Thu Fri Sat"<<endl;
sum=getDays( year, month);
t=sum%7+1;//sum/7所得的整数表示轮回了多少个星期,所得的余数是已经过去了几天,+1是因为一般日历一周显示是从周日到周六,若日历表示从周一到周日,即不需要+1,但要注意每月一号前需要几个空格数
daycount=nmonth(month,year);//算出这个月的天数
if(t<7)
{for(j=0;j<t;j++)
cout<<" ";}//输出空格,找出每月1号是星期几。星期日是第一个,所以前面不需要空格
for(k=1;k<=daycount;k++)//开始循环,输出每月的天数
{ t++; //因为格式要对齐,所以要用空格来对齐
if(k<10)
cout<<k<<" ";
if(k>=10)
cout<<k<<" ";
if(t%7==0)
cout<<endl;
}
cout<<endl;
}
cout<<endl;
}
void wnl2(int year,int month)
{
int i,j,day,sum,daycount;
sum=getDays(year,month);
day=sum%7+1; //这里算出来这个月的一号前面需要几个空格;等于0的话,前面就不需要空格
daycount=nmonth(month,year);//算出这个月的天数
cout<<endl;
cout<<"☆☆★☆☆★☆ "<<year<<"年"<<month<<"月"<<" ☆★☆☆★☆☆"<<endl;
cout<<endl;
cout<<"Sun Mon Tue Wed Thu Fri Sat"<<endl;
if(day<7)
{for(j=0;j<day;j++)
cout<<" ";}
for(i=1,j=day+1;i<=daycount;i++,j++)//开始循环,输出每月的号
{
//因为,格式要对齐,所以要用空格来对齐
if(i<10)
cout<<i<<" ";
if(i>=10)
cout<<i<<" ";
if(j%7==0)
cout<<endl;
}
cout<<endl;
cout<<endl;
}
void wnl3(int m_year,int m_month,int m_day,int cz)
{ char m[8][50]={"周日","周一","周二","周三","周四","周五","周六"};
int i,j;
j=getDays( m_year,m_month);//计算当前时间的上个月末到1940.1.1的总天数差
i=((j%7)+m_day%7)%7;//j/7与m_day/7所得整数部分表示轮回了多少个星期,所得余数部分表示两个零碎的时间段,可能大于或者小于或者等于7,再%7即表示当前是星期几
cout<<" "<<endl;
cout<<"☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆"<<endl;
if(cz>=0)
cout<<" 期间相差:"<<cz<<endl;
else
cout<<" 期间相差:"<<(-1)*cz<<endl;//因为某一天 的日期可能小于当前时间,但是时间间隔不可能为负数,所以所得时间*(-1)即正数
cout<<" "<<endl;
while(m_month,m_day)//判断某一的日期是否是公立节日,如果是输出某一天的公立节日,如果不是,则判断下一个
//一月一日,元旦
{ if (m_month==1&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"元旦 ☆☆☆\n";
//2月十四,情人节
else if (m_month==2&&m_day==14)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"情人节 ☆☆☆\n";
//三月八日,妇女节
else if(m_month==3&&m_day==8)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"妇女节 ☆☆☆\n";
//三月十二,植树节
else if(m_month==3&&m_day==12)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"植树节 ☆☆☆\n";
//四月一日,愚人节
else if(m_month==4&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"愚人节 ☆☆☆\n";
//五月一日,劳动节
else if(m_month==5&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"劳动节 ☆☆☆\n";
//五月四日,青年节
else if(m_month==5&&m_day==4)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"青年节 ☆☆☆\n";
//六月一日,儿童节
else if(m_month==6&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"儿童节 ☆☆☆\n";
//七月一日,建党节
else if(m_month==7&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"建党节 ☆☆☆\n";
//七月七日,七夕节·
else if(m_month==7&&m_day==7)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"七夕节 ☆☆☆\n";
//八月一日,建军节
else if(m_month==8&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"建军节 ☆☆☆\n";
//九月十日,教师节
else if(m_month==9&&m_day==10)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"教师节 ☆☆☆\n";
//十月一日,国庆节
else if(m_month==10&&m_day==1)
cout<<"☆☆☆ "<<m[i]<<" ★ "<<"国庆节 ☆☆☆\n";
else
cout<<"☆☆ "<<m[i]<<" ★ "<<"不是公历节日 ☆☆\n";
break;
}
cout<<"☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆"<<endl;
}
void main()
{
int a,year,month,day,year1,month1,day1,k1,k2,cz;
char m;
cout<<endl;
cout<<"☆☆☆☆☆☆☆☆☆☆☆ 欢迎使用万年历 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ";
cout<<endl;
cout<<endl;
do
{
cout<<"☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆"<<endl;
cout<<"★ ★"<<endl;
cout<<"☆ 1.输入一个年份,并显示该年的日历.(1940~2040) ☆"<<endl;;
cout<<"★ ★"<<endl;
cout<<"☆ 2.输入年月,输出该月的日历 ☆"<<endl;
cout<<"★ ★"<<endl;
cout<<"☆ 3.计算两个日期的时间间隔 ☆"<<endl;
cout<<"★ ★"<<endl;
cout<<"☆ 4.退出 ☆"<<endl;
cout<<"★ ★"<<endl;
cout<<"☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆"<<endl;
cout<<endl;
cout<<" 请输入你要进行的操作:";
cin>>a;
switch(a)
{
case 1:
cout<<" 请输入1940~2040期间的年份"<<endl;
cin>>year;
cout<<endl;
wnl1(year);
break;
case 2:
cout<<"请输入查询的年份 月份"<<endl;
cin>>year>>month;
wnl2(year,month);break;
case 3:
cout<<"请输入今天的日期,年 月 日"<<endl;
cin>>year>>month>>day;
k1= getDays0( year,month,day) ;//计算1940.1.1——year.month.day的天数差
cout<<"请输入某一天的日期,年 月 日"<<endl;
cin>>year1>>month1>>day1;
k2= getDays0( year1,month1,day1) ;//计算1——的天数差
cz=k1-k2;/* 以1940.1.1为基准,两个日期分别与该日期取时间差,相减所得即为两个日期的时间间隔
数学表达式为:(year.month.day-1940.1.1)-(year1.month1.day1-1940.1.1)=(year.month.day)-(year1.month1.day1) */
wnl3(year1,month1,day1,cz);
default:
break;
}
cout<<"您要继续查询吗? (Y/ N)"<<endl;
cin>>m;
}
while(m=='y'||m=='Y') ;//控制该程序要不要继续循环
cout<<endl;
cout<<" ☆★☆ 谢谢您的使用 ☆★☆"<<endl;
cin.get();
cin.get();
}
六.课程设计总结
针对整个课程设计过程进行一个总结,比如过程中遇到的问题与解决办法,程序编写,调试运行过程与体会等。
总结:
(1):首先判断这一年是否为闰年,其次确定该年的每个月的天数;
(2):找到规律1900年的1月1日是周一,所以总天数/7所得的整数表示轮回了多少个星期,所得的余数是已经过去了几天,(+1是因为一般日历一周显示是从周日到周六,若日历表示从周一到周日,即不需要+1),但要注意每月一号前需要几个空格数余7,再加1就是星期几;按照此规律找到以后每一年每一月的1号星期几,然后利用循环打出每个月的日历,其中要注意每到周日要换行,所以定义t为每月的一号星期几,然后t%7==0时,换行,这样保证号与星期对上;
(3):每个日子之间要有空格,使它们的格式相同;同时需要计算每月一号是星期几,然后再计算前面需要多少空格;
(4):一维char型数组只能存一组字符串,二维可存多组字符串;
(5):计算某天是星期几的时候,要进行分步计算,利用getDays算出上个月末距离1940.1.1的天数,再加上输入的日期在该月过了多少天,所得的总天数除以7所得余数就是星期几;
(6)计算时间差值可以定一个基准,分别求出两次输入的时间与该基准相隔的天数k1和k2,差值即为k1-k2,其数学表达式为:(year.month.day-1940.1.1)-(year1.month1.day1-1940.1.1)=(year.month.day)-(year1.month1.day1)=cz。
问题
(1)变量比较多,有时候会忘记哪个是哪个;
(2)循环和条件if语句中很容易忘记{}的使用,导致莫名其妙的失误;
(3)对问题的解题思路有点迷茫,不知道如何去想每一个月的一号前面为什么空出来了,某天是星期几,时间间隔怎么计算;
(4)形参的个数有时候不统一,有时候不知道如何引用实参;
(5)对循环结束的条件不明确,导致进入死循环。