C语言课程设计万年历打印.doc

  • 格式:doc
  • 大小:322.82 KB
  • 文档页数:25

温馨提示程序语言:C、C++、C#、Python(红色字体表示本课设使用的程序设计语言)图形功能选项:Win32控制台程序(黑框、文本界面)、Win32程序、MFC、WinForm、DirectX10(黑体标明表示本课设的程序图形类别,默认为非图形界面Win32控制台程序)数据结构:基础类型、数组、链表、双向链表、搜索树(非平衡二叉树)、平衡二叉树、链表与平衡二叉树相结合、堆栈、队列、串、图(黑体标明表示本课设使用的数据结构)C++语言项:STL库(黑体标明表示使用C++的STL库)编译环境:Windows 7 64位旗舰版(Linux及其他环境请谨慎下载)集成开发环境:Visual C++ 6.0、DEVC++、CodeBlocks、Visual Studio 2015均可通过编译。

(若无法通过编译运行,则会用浅蓝色字体表示)分多头文件编译:否(所有代码基本都包含在一个文件内,如需试验头文件功能,请自行参考相关文献)内容说明:1、课设题目及预览内容将在第二页开始展示。

2、代码行数:333行3、目录所示内容,本文基本涵盖,如无内容,会在本页进行说明。

4、附录绝对包含用户使用手册及程序完整源代码和详细注释。

5、如需下载其他头文件(例如DirectX需另行配置),本文会在此进行说明。

6、本文撰写内容仅供学习参考,另外,由于本人水平有限,编写之处难免存在错误和纰漏,恳请各位老师或同学批评指正。

题目:万年历显示功能要求:(1)输入一个年份,输出是在屏幕上显示该年的日历。

假定输入的年份在1940-2040年之间。

(2)输入年月,输出该月的日历。

(3)输入年月日,输出距今天还有多少天,星期几,是否是公历节日。

功能(二):功能(三):课程设计报告课题:学院:专业:学生姓名:学号:指导老师:20XX年XX月XX日目录摘要万年历的主要功能是通过C语言编程实现查询某年的日历情况,并且可以查询某年月的日历情况,还可以对某年月日进行计算距今的天数和判断是否为公历节日,其功能和代码满足人性化设计和良好的编程规范要求。

关键词:万年历,C语言编程,人性化设计1总体设计1.1需求分析系统将以用户输入的信息进行功能的选择,提供某年日历的输出、某年某月日历的输出和距今天数的输出及节假日的判断这大三功能。

1.2功能流程图本程序主要通过获取屏幕输入,然后进行字符串处理,选择相应的功能执行,最后打印输出信息。

功能流程图如下:1.3功能模块图2详细设计2.1数据结构建立日历信息结构体,结构体成员变量包括月末、月初星期几、屏幕信息左半边日历是否打印完毕。

typedef struct calendar {int month_end; //月末最后一天的数字int first_day; //月初星期几0周日1周一 ......int printFinished; //打印完毕则为1,没打印完成则为0}Calendar;建立年月日信息结构体,结构体成员变量包括年份、月份、天数。

typedef struct date{int year;int month;int day;}Date;2.2函数功能设计本万年历系统主要分为三大功能,分别是打印某年日历、打印某年某月日历、打印距今天数和判断是否节假日,故分别设计三个函数实现三大功能,如下所示。

void firstFun(int year, Calendar cal[]); //第一功能void secondFun(int year, int month, Calendar cal[]); //第二功能void thirdFun(int year, int month, int day); //第三功能各程序流程图如下:图2.1 程序流程图(一)是否firstFun()函数开始判断是否打印了6和12月份的日历打印某月日历结束图2.2 程序流程图(二)是否secondFun()函数开始判断是否月末的天数打印某月某日的日历结束图2.3 程序流程图(三)thirdFun()函数开始判断是否节假日3调试分析3.1程序测试运行程序之后,会进入主界面,如图3.1所示。

图3.1 主界面图随后,可分别通过输入年、年月、年月日实现三个功能的输出,具体如图3.2~3.4所示。

图3.2 打印某年日历图图3.3 打印某年月日历图图3.4 计算距今天数图3.2 程序缺陷1、该程序每次运行,只能执行一次,不能重复选择功能,属于设计缺陷。

2、对年份的不规范输入,可能出现与预期结果不一致的情况,如图3.5所示,理论应该输出12345年的日历,然而只是输出了12345年5月的日历,属于程序漏洞。

图3.5 BUG展示图4总结与体会这个课程设计的难度在于打印输出日历,在设计过程中遇到问题,可以说是困难重重,因为毕竟是第一次做的,难免会遇到各种各样的问题,同时在设计过程中我也发现了自己的不足之处,对以前所学过的知识理解的不够深刻,掌握的不够牢固。

通过这次课程设计之后,我觉得以前学过的知识要重新温习才能够达到查漏补缺的效果。

我会在今后的日子里,努力学好程序设计,成为一名出色的工程师。

最后,这次的课程设计终于得以圆满完成。

其中,我在设计中也遇到了许许多多的问题,但在老师的指导和同学们的帮助下得到了解决,总的来说还不是这个程序还不是很完善,但我不会放弃继续完善这份程序,我会在课余时间里继续修改完善这份程序。

在此,感谢所有帮助过我的同学和指导老师。

参考文献[1] 谭浩强著.C程序设计(第四版).北京:清华大学出版社,2010[2] 林锐著.高质量C编程指南.北京:电子工业出版社,2001[3]Stephen A.Maguire.编程精粹:编写高质量C语言代码.人民邮电出版社,2009附录用户使用手册1、根据屏幕提示,输入即可。

2、输入年份,例如2018年,则会打印2018年的日历。

3、输入年月,例如2018 10(也可以尝试其他的分隔符,例如2018,10),则会打印2018年10的日历。

4、输入年月日,例如2018 10 1(同上),则会输出距今的天数和输出具体的节假日。

程序源代码#include<stdio.h>#include<stdlib.h>#include<time.h>#include<string.h>#define isPrime(year) ((year%4==0&&year%100!=0)||(year%400==0)) //宏函数,判断是否为闰年#define TWELVEMONTH 12 //数组大小#pragma warning(disable:4996) //消除Visual Stdio编译环境的安全警告,其他编译环境可删除//------------------------------//----------结构体定义区---------//------------------------------typedef struct calendar {int month_end; //月末最后一天的数字int first_day; //月初星期几0周日1周一 ......int printFinished; //打印完毕则为1,没打印完成则为0}Calendar;typedef struct date{int year;int month;int day;}Date;//----------------------------//----------函数声明区---------//----------------------------void judgmentLeapYear(int year, Calendar *cal); //判断闰年int calculateWeeks(int y, int m, int d); //计算该年月日是周几void firstFun(int year, Calendar cal[]); //第一功能void secondFun(int year, int month, Calendar cal[]); //第二功能void thirdFun(int year, int month, int day); //第三功能int dateDiff(struct date mindate, struct date maxdate); //计算日期之间的间隔天数int main(void){Calendar cal[TWELVEMONTH] = {{ 31 }, //1月{ 28 }, //2月{ 31 }, //3月{ 30 }, //4月{ 31 }, //5月{ 30 }, //6月{ 31 }, //7月{ 31 }, //8月{ 30 }, //9月{ 31 }, //10月{ 30 }, //11月{ 31 } //12月}; //初始化月份int year = 2000, month = 0, day = 0;int fun = 0;char calendar[30] = { '\0' }; //用来处理输入printf("Please input the your whose calendar you want to know:");fgets(calendar, 30, stdin);year = atoi(calendar); //得到年份if (calendar[4] != '\0')month = atoi(calendar + 4); //得到月份if (strlen(calendar) >= 8)day = atoi(calendar + strlen(calendar) - 2);if (0 != year && 0 == month && 0 == day)fun = 1;elsefun = 0 == day ? 2 : 3;judgmentLeapYear(year, &cal[1]); //调整闰年平年2月的天数int i = 0;for (i = 0; i < TWELVEMONTH; i++)cal[i].first_day = calculateWeeks(year, i + 1, 1);switch (fun) {case 1:firstFun(year, cal); break;case 2:secondFun(year, month, cal); break;case 3:thirdFun(year, month, day); break;}return 0;}void judgmentLeapYear(int year, Calendar *cal){if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))cal->month_end = 29;elsecal->month_end = 28;}int calculateWeeks(int year, int month, int day){int c, w, y;y = year % 100;//年如2015 即年是15年c = year / 100;//年份前两位如2015即20if (month == 1 || month == 2) { //判断月份是否为1或2y--;month += 12;//某年的1、2月要看作上一年的13、14月来计算}w = y + y / 4 + c / 4 - 2 * c + 13 * (month + 1) / 5 + day - 1;//蔡勒公式while (w < 0) w += 7;//确保余数为正w %= 7;return w;}void firstFun(int year, Calendar cal[]){printf("|===================The Calendar of Year %d====================|\n", year);int month = 1;for (month = 1; month <= TWELVEMONTH / 2; month++) {printf("| %d SUN MON TUE WED THU FRI SAT %2d SUN MON TUE WEDTHU FRI SAT |\n", month, month + 6);int right = 1, left = 1;int i = 0;for (right = 1, left = 1; 1; left++) {if (1 == left) { //左边首日打印printf("| ");for (i = 0; i < calculateWeeks(year, month, left); i++)printf(" ");;printf("%4d", left);if (6 == calculateWeeks(year, month, left)) { //既是首日也是周六printf(" ");}}else if (left == cal[month - 1].month_end) { //左边月末打印printf("%4d", left);for (i = 0; i < 6 - calculateWeeks(year, month, left); i++)printf(" ");printf(" ");cal[month - 1].printFinished = 1; //月末,则表示左边日历打印完毕}else if (6 == calculateWeeks(year, month, left) && left <= cal[month -1].month_end) { //左边日历的周六,则开始打印右边的日历printf("%4d", left);for (i = 0; i < 6 - calculateWeeks(year, month, left); i++)printf(" ");printf(" ");}else if (1 == cal[month - 1].printFinished) { //左边打印完毕则补齐空格for (i = 0; i < 8; i++)printf(" ");printf(" ");}elseprintf("%4d", left);if (6 == calculateWeeks(year, month, left) && left <= cal[month - 1].month_end || cal[month - 1].printFinished) {for (;; right++) {if (1 == right) { //右边首日打印for (i = 0; i < calculateWeeks(year, month + 6, right); i++)printf(" ");;printf("%4d", right);if (6 == calculateWeeks(year, month + 6, right)) { //既是首日也是周六printf(" |\n| ");right++;break;}}else if (right == cal[month - 1 + 6].month_end) { //右边月末打印printf("%4d", right);for (i = 0; i < 6 - calculateWeeks(year, month + 6, right); i++)printf(" ");printf(" |\n| ");cal[month - 1 + 6].printFinished = 1; //月末,则表示右边日历打印完毕right++;break;}else if (6 == calculateWeeks(year, month + 6, right) && right <=cal[month - 1 + 6].month_end) { //右边日历的周六,则开始打印左边的日历printf("%4d |\n| ", right);right++;break;}else if (cal[month - 1 + 6].printFinished) { //右边打印完毕则补齐空格for (i = 0; i < 7; i++)printf(" ");printf(" |\n| ");right++;break;}elseprintf("%4d", right);}}if (cal[month - 1].printFinished&&cal[month - 1 + 6].printFinished) {putchar('\r'); // 将光标跳到本行的开头,消除多余的打印字符break;}}}putchar('|');int i = 0;for (i = 0; i < 65; i++)putchar('=');putchar('|');putchar('\n');}void secondFun(int year, int month, Calendar cal[]){printf("|======The Year %d Month %d=====|\n", year, month);printf("| %d SUN MON TUE WED THU FRI SAT |\n", month);int i = 1, j = 1;for (i = 1; i <= cal[month - 1].month_end; i++) {if (1 == i) { //首日打印printf("| ");for (j = 0; j < calculateWeeks(year, month, i); j++)printf(" ");printf("%4d", i);if (6 == calculateWeeks(year, month, i)) { //既是首日也是周六printf(" |\n| ");}}else if (6 == calculateWeeks(year, month, i)) { //周六换行printf("%4d |\n| ", i);}else if (i == cal[month - 1].month_end) { //月末printf("%4d", i);for (j = 0; j < 6 - calculateWeeks(year, month, i); j++)printf(" ");printf(" |\n");}elseprintf("%4d", i);}putchar('\r');putchar('|');for (i = 0; i < 32; i++)putchar('=');putchar('|');putchar('\n');}void thirdFun(int year, int month, int day){time_t t;struct tm * timeinfo;Date d1 = { year,month,day };Date d2;char ch[20] = { '\0' }; //用于存储周几char festival[20] = { '\0' }; //用于存储节日int iDayNum = 0;time(&t); //获取今天的日期timeinfo = localtime(&t);d2.year = timeinfo->tm_year + 1900;d2.month = timeinfo->tm_mon + 1;d2.day = timeinfo->tm_mday;iDayNum = (dateDiff(d1, d2));switch (calculateWeeks(d1.year, d1.month, d1.day)){case 0:strcpy(ch, "Sunday"); break;case 1:strcpy(ch, "Monday"); break;case 2:strcpy(ch, "Tuesday"); break;case 3:strcpy(ch, "Wednesday"); break;case 4:strcpy(ch, "Thursday"); break;case 5:strcpy(ch, "Friday"); break;case 6:strcpy(ch, "Saturday"); break;}if (1 == d1.month && 1 == d1.day)strcpy(festival, "New year's Day"); //元旦else if (3 == d1.month && 8 == d1.day)strcpy(festival, "International Women's Day"); //国际妇女节else if (3 == d1.month && 12 == d1.day)strcpy(festival, "Arbor Day"); //植物节else if (4 == d1.month && 5 == d1.day)strcpy(festival, "Qingming Festival"); //清明节else if (5 == d1.month && 1 == d1.day)strcpy(festival, "Labor Day"); //劳动节else if (5 == d1.month && 4 == d1.day)strcpy(festival, "Youth Day"); //青年节else if (6 == d1.month && 1 == d1.day)strcpy(festival, "Children's Day"); //儿童节else if (7 == d1.month && 1 == d1.day)strcpy(festival, "Party Building"); //建党节else if (8 == d1.month && 1 == d1.day)strcpy(festival, "Army Day"); //建军节else if (9 == d1.month && 3 == d1.day)strcpy(festival, "Anti Japanese War Victory Day"); // 抗日战争胜利纪念日else if (9 == d1.month && 10 == d1.day)strcpy(festival, "Teachers day"); //教师节else if (10 == d1.month && 1 == d1.day)strcpy(festival, "National Day"); //国庆节elsestrcpy(festival, "No Festival"); //非节日printf("The output is %d days away today, %s , %s.\n\n", iDayNum, ch, festival); }int dateDiff(struct date mindate, struct date maxdate){int days = 0, j, flag;const int primeMonth[][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 } };/************************************************************************//* 交换两个日期函数,将小的日期给mindate,将大的日期给maxdate */ /************************************************************************/struct date tmp;if ((mindate.year>maxdate.year) || (mindate.year ==maxdate.year&&mindate.month>maxdate.month) || (mindate.year ==maxdate.year&&mindate.month == maxdate.month&&mindate.day>maxdate.day)) {tmp =mindate;mindate=maxdate;maxdate= tmp;}/************************************************************************//* 从mindate.year开始累加到maxdate.year */ /************************************************************************/for (j = mindate.year; j<maxdate.year; ++j)days += isPrime(j) ? 366 : 365;//如果maxdate.year是闰年,则flag=1,后面调用primeMonth[1][12]flag = isPrime(maxdate.year);//加上maxdate.month到1月的天数for (j = 1; j<maxdate.month; j++)days += primeMonth[flag][j - 1];//减去mindate.month到1月的天数flag = isPrime(maxdate.year);for (j = 1; j<mindate.month; j++)days -= primeMonth[flag][j - 1];days = days + maxdate.day - mindate.day;return days;}。