万年历
软件基础实践报告
( 2013 / 2014 学年 第 二 学期)
题目: 万年历
专 业 软件工程
学 生 姓 名
班 级 学 号
指 导 教 师 陈云芳
指 导 单 位 计算机学院软件工程系
日 期 2014.5
指导教师成绩评定表
学生姓名 | 班级学号 | 专业 | ||||||||||
评分内容 | 评分标准 | 优秀 | 良好 | 中等 | 差 | |||||||
平时成绩 | 认真对待课程设计,遵守实验室规定,上机不迟到早退,不做和设计无关的事 | |||||||||||
设计成果 | 设计的科学、合理性 | |||||||||||
功能丰富、符合题目要求 | ||||||||||||
界面友好、外观漂亮、大方 | ||||||||||||
程序功能执行的正确性 | ||||||||||||
程序算法执行的效能 | ||||||||||||
设计报告 | 设计报告正确合理、反映系统设计流程 | |||||||||||
文档内容详实程度 | ||||||||||||
文档格式规范、排版美观 | ||||||||||||
验收答辩 | 简练、准确阐述设计内容,能准确有条理回答各种问题,系统演示顺利。 | |||||||||||
评分等级 | ||||||||||||
指导教师 简短评语 | ||||||||||||
指导教师签名 | 日期 | |||||||||||
备注 | 评分等级有五种:优秀、良好、中等、及格、不及格 | |||||||||||
万年历
一、 课题概述
【问题描述】
该系统要求实现一个简单、实用的日历打印程序。主要功能为在屏幕上显示任意年月的月历,且要按指定的格式输出。通过此课题,熟练掌握数组、格式输出、文件的各种操作,以及基本的日期算法思想的应用。
【功能要求】
(2)月历输出重要节假日要在该日期后用*号标注出来
(3)需要实现的功能
1) 输入日期,显示该日期所在月的月历。
2) 可选择显示下一月、上一月的日历。
3) 可选择显示下一年、上一年的日历。
4) 重要节假日需用一个文本文件进行设置,文件格式自定。程序应通过读取节假日文件的信息来对日历上的节假日日期进行标注。
(4)界面功能要求:
1) 采用友好的字符界面,实现一个功能控制菜单。
2) 每次操作都从该菜单选择,利用循环结构使得一次运行程序可进行多次操作。
二、 软件设计
程序模块:
本程序主要由各种功能的函数来实现所要求的功能,具体函数名称及具体作用如下表所示:
函数名称及重要变量 | 具体功能 |
void checkFestvals(int month,int nowDay) | 检查输出日期是否为重要节假日 |
int runyear(int year) | 判断年份是闰年还是平年 |
struct tm * getDay() | 结构体时间指针函数 |
int dayExame(int year,int month,int day) | 日期格式、数值检查函数 |
int getwDay(int year,int month,int day) | 由日期获取星期函数 |
void printCalender(int year,int month,int day) | 月历打印函数 |
void setDay(int year,int month,int day) | 调整日期函数 |
void checkCalender() | 查询日历函数 |
void backMenu() | 任意键返回主菜单函数 |
int year,month,day | 年月日全局变量 |
int daysOfMonth[][] | 闰、平年每月天数的二维数组 |
void mainMenu(int year,int month,int day) | 主菜单函数 |
流程图:
程序代码:
#include
#include
#include
#include
#include
#define KEYNUMUp 0x48 //定义键盘输入
#define KEYNUMDown 0x50
#define KEYNUMLeft 0x4b
#define KEYNUMRight 0x4d
#define KEYNUMPageUp 0x49
#define KEYNUMPageDown 0x51
int year,month,day; //全局变量记录时间
void checkFestvals(int month,int nowDay)//检查是否节日
{
switch(month)
{
case 1:
case 5:
case 6:
case 7:
case 8:
case 10:
if(nowDay==1) printf("*");break;
case 2:
if(nowDay==14) printf("*");break;
case 3:
if(nowDay==8) printf("*");break;
case 4:
if(nowDay==5) printf("*");break;
case 9:
if(nowDay==10) printf("*");break;
case 12:
if(nowDay==25) printf("*");break;
case 11:
break;
}
}
int daysOfMonth[2][12]={{31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31, 30,31}};//闰年平年的各月天数
int runYear(int year) //判断是否是闰年
{
int flag=0;
if(year%400==0||(year%4==0&&year%100!=0))
flag=1;
return flag;
}
struct tm * getDay() //从系统取得当前时间
{
struct tm* gmt;
time(&timer);//把秒数换算成年月日(世界标准时)
gmt=localtime(&timer); //换算为当前时区时间
return gmt;
}
int dayExame(int year,int month,int day) //检查日期是否正确
{
if(year<0||month<1||month>12||day<1||day>31)
return 0;
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(day>31)return 0;break; //大月case入口
case 4:
case 6:
case 9:
case 11:
if(day>30)return 0;break;//小月case入口
default:
if(runYear(year)&&day>29) //二月入口
return 0;
else
if(runYear(year)==0&&day>28)
return 0;
}
return 1;
}
int getwDay(int year,int month,int day)//取得星期
{
//根据当前日期计算任意日期的星期
int nday=0,nDay,i,w;
for(i=0;i
nday+=daysOfMonth[runYear(year)][i];
nday+=day;
nDay=year-1+(year-1)/4-(year-1)/100+(year-1)/400+nday;
w=nDay%7;
return w;
}
void printCalender(int year,int month,int day);//提前声明月历打印函数
void mainMenu(int year,int month,int day); //提前声明主菜单函数
void setDay(int year,int month,int day)//调节日期
{
char k;
printf("%c:上一年 %c:下一年\n",24,25);
printf("%c:上个月 %c:下个月\n",27,26);
printf("PageUp:昨天 PageDown:明天\n");
printf("其他:返回主菜单\n");
getch();
k=getch();
switch(k) //通过方向键和PageUp、PageDown键来调整日期
{
case KEYNUMUp: year--;
if(dayExame(year,month,day)==0){year++; printf("%c",7);} //检查日期 的合法性,若错误,保持日期不变, 并警告
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
case KEYNUMDown: year++;
if(dayExame(year,month,day)==0){year--;printf("%c",7);}
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
case KEYNUMLeft: month--;
if(dayExame(year,month,day)==0){month++;printf("%c",7);}
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
case KEYNUMRight: month++;
if(dayExame(year,month,day)==0){month--;printf("%c",7);}
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
case KEYNUMPageUp: day--;
if(dayExame(year,month,day)==0){day++;printf("%c",7);}
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
case KEYNUMPageDown: day++;
if(dayExame(year,month,day)==0){day--;printf("%c",7);}
system("cls");printCalender(year,month,day);setDay(year,month,day);break;
default:
system("cls");mainMenu(year,month,day);break; //其他指令跳回主菜单
}
}
void printCalender(int year,int month,int day)//打印月历
{
int i;
int w;
int nowDay=1;
int n;
char wday[7][4]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
printf("\n");
printf("%10d",year);
switch(month)//根据当前月份输出英文版
{
case 1: printf(" January");break;
case 2: printf(" February");break;
case 3: printf(" March");break;
case 4: printf(" April");break;
case 5: printf(" May");break;
case 6: printf(" June");break;
case 7: printf(" July");break;
case 8: printf(" August");break;
case 9: printf(" September");break;
case 10: printf(" October");break;
case 11: printf(" November");break;
case 12: printf(" December");break;
}
printf("%5d\n",day);
printf("\n");
printf("***********************************\n");
printf("\n");
for(i=0;i<7;i++)
printf("%5s",wday[i]);
printf("\n");
w=getwDay(year,month,nowDay);//找到第一天的星期
n=daysOfMonth[runYear(year)][month-1];
switch(w) //放置第一天
{
case 0:printf("%5d",nowDay);break;
case 1:printf("%9d",nowDay);break;
case 2:printf("%14d",nowDay);break;
case 3:printf("%19d",nowDay);break;
case 4:printf("%24d",nowDay);break;
case 5:printf("%29d",nowDay);break;
default:printf("%34d\n\n",nowDay);
}
switch(month)//检查每月第一天是否节日并控制输出*
{
case 1:
case 4:
case 5:
case 6:
case 7:
case 8:
case 10:
printf("*");break;
}
nowDay++;
for(i=1;i
{
w=getwDay(year,month,nowDay);
printf("%5d",nowDay);
checkFestvals(month,nowDay);
if(w==6) //如果是星期六则换行打印
puts("\n");
nowDay++;
}
printf("\n***********************************\n\n");
}
void checkCalender()//查询日历
{
int year,month,day;
system("cls");
printf("请输入你要查询的日期(格式为年月日,如2009 11 3):");
scanf("%d%d%d",&year,&month,&day);
while(!dayExame(year,month,day)) //如果日期输入不正确,则重新输入
{
printf("你输入的日期错误,请重新输入:");
fflush(stdin);//清除缓冲区, 防止错误输入导致溢出
scanf("%d%d%d",&year,&month,&day);
}
system("cls");
if(runYear(year))
printf("\n 闰年\n\n");
else
printf("\n平年\n\n");
printCalender(year,month,day);
}
void backMenu()
{
printf("请按任意字符键返回主菜单:");
getch();
system("cls");
}
void mainMenu(int year,int month,int day)//主菜单
{
char menu[100];
int flag=0;
int f=0;
printf("************主菜单************\n");
printf(" * 1、日历显示 *\n");
printf(" * 2、日历查询 *\n");
printf(" * 3、修改日期 *\n");
printf(" * 4、 帮助 *\n");
printf(" * 5、 退出 *\n");
printf("******************************\n");
do //控制主菜单的循环
{
do
{
printf("\n 请输入相应数字:");
scanf("%s",menu);
if(strlen(menu)>2)
f=1;
}while(f==1);
switch(*menu)
{
case '1':
system("cls"); //清屏
printCalender(year,month,day);
backMenu(); //实现任意键返回主菜单
mainMenu(year,month,day);
break;
case '2':
system("cls");
checkCalender();
backMenu();
mainMenu(year,month,day);
break;
case '3':
system("cls");
printCalender(year,month,day);
setDay(year,month,day);
printf("请按任意字符键返回主菜单:");
getch();
system("cls");
mainMenu(year,month,day);
break;
case '4':
system("cls");
printf("在主菜单中输入相应的数字就可以完成以下功能:\n\n");
printf("* 1、显示今天所在月的月份\n\n");
printf("* 2、输入日期,判断该年是否是闰年,并显示所在月份的月历\n\n");
printf("* 3、用%c %c %c %c PageUp PageDown 进行日期的调整\n\n",24,25,27,26);
printf("* 4、显示功能及操作方法\n\n");
printf("* 5、退出程序\n\n");
backMenu();
mainMenu(year,month,day);
break;
case '5':
system("cls");
printf("程序已退出!\n");
exit(0);
default:
printf("%c 输入错误!\n",7);
flag=1;
}
}while(flag);
}
void main()
{
struct tm *gmt=getDay(); //获取当前时间并赋值给指针
year=gmt->tm_year+1900; //把库函数中的时间变量换算成为正确时间格式
month=gmt->tm_mon+1;
day=gmt->tm_mday;
printCalender(year,month,day);//用系统时间进行初始化,打印当前月历
backMenu();
mainMenu(year,month,day);
}
测试数据及其结果分析
总结
此次实验让我们回顾和巩固了大一所学的各种编程知识, 实验总体来说比较顺利, 题目难易程度适中。 遗憾的是所编写的程序并没能完成所有的题目要求, 通过文件读取特定节假日的功能未能实现, 只是通过循环完成了节假日标记。由此可见我们的编程能力还有一定的欠缺, 希望通过这次实验能让我们的编程能力得到更大提升。
----------THE END, THERE IS NO TXT FOLLOWING.------------
本文来源:https://www.2haoxitong.net/k/doc/de5f3147ac51f01dc281e53a580216fc700a5386.html
文档为doc格式