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

更新时间:2023-12-13 23:24:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

温馨提示

程序语言: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日

目录

摘要 ...................................................................................................................................................... 1 1总体设计 ........................................................................................................................................... 2

1.1需求分析 ................................................................................................................................ 2 1.2功能流程图 ............................................................................................................................ 2 1.3功能模块图 ............................................................................................................................ 3 2详细设计 ........................................................................................................................................... 4

2.1数据结构 ................................................................................................................................ 4 2.2函数功能设计 ........................................................................................................................ 4 3调试分析 ........................................................................................................................................... 7

3.1程序测试 ................................................................................................................................ 7 3.2 程序缺陷 ............................................................................................................................... 9 4总结与体会 ..................................................................................................................................... 10 参考文献 ............................................................................................................................................ 11 附录 .................................................................................................................................................... 12

摘要

万年历的主要功能是通过C语言编程实现查询某年的日历情况,并且可以查询某年月的日历情况,还可以对某年月日进行计算距今的天数和判断是否为公历节日,其功能和代码满足人性化设计和良好的编程规范要求。

关键词:万年历,C语言编程,人性化设计

1

1总体设计

1.1需求分析

系统将以用户输入的信息进行功能的选择,提供某年日历的输出、某年某月日历的输出和距今天数的输出及节假日的判断这大三功能。

1.2功能流程图

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

图1.1 功能流程图

2 判断年月日 开始 输入 处理输入信息 年月日运算,计算距今的天数 年月运算,准备打印某年某月日历 年运算,准备打印某年日历 输出 结束

1.3功能模块图

计算距今天数和判断节日模块 图1.2 功能模块图

打印某年日历模块 提示信息 打印某年某月日历模块 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); //第三功能

各程序流程图如下:

4

firstFun()函数 开始 判断是否打印了6和12月份的日历 是 否 打印某月日历 结束 图2.1 程序流程图(一)

判断是否月末的secondFun()函数 开始

是 天数 否 打印某月某日的日历 结束 图2.2 程序流程图(二) 5

thirdFun()函数 开始 计算距今天数 判断是否节假日 打印信息 结束 图2.3 程序流程图(三) 6

3调试分析

3.1程序测试

运行程序之后,会进入主界面,如图3.1所示。

图3.1 主界面图

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

图3.2 打印某年日历图

7

图3.3 打印某年月日历图

图3.4 计算距今天数图

8

3.2 程序缺陷

1、该程序每次运行,只能执行一次,不能重复选择功能,属于设计缺陷。

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

图3.5 BUG展示图

9

4总结与体会

这个课程设计的难度在于打印输出日历,在设计过程中遇到问题,可以说是困难重重,因为毕竟是第一次做的,难免会遇到各种各样的问题,同时在设计过程中我也发现了自己的不足之处,对以前所学过的知识理解的不够深刻,掌握的不够牢固。通过这次课程设计之后,我觉得以前学过的知识要重新温习才能够达到查漏补缺的效果。我会在今后的日子里,努力学好程序设计,成为一名出色的工程师。

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

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

10

参考文献

[1] 谭浩强著.C程序设计(第四版).北京:清华大学出版社,2010 [2] 林锐著.高质量C编程指南.北京:电子工业出版社,2001

[3]Stephen A.Maguire.编程精粹:编写高质量C语言代码.人民邮电出版社,2009

11

附录

用户使用手册

1、根据屏幕提示,输入即可。

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

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

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

程序源代码

#include #include #include #include

#define isPrime(year) ((year%4==0&&year0!=0)||(year@0==0)) //宏函数,判断是否为闰年 #define TWELVEMONTH 12 //数组大小

#pragma warning(disable:4996)

//------------------------------ //----------结构体定义区--------- //------------------------------ typedef struct calendar {

typedef struct date {

//---------------------------- //----------函数声明区--------- //----------------------------

void judgmentLeapYear(int year, Calendar *cal); //判断闰年

12

//消除 Visual Stdio编译环境的安全警告,其他编译环境可删除

int month_end; //月末最后一天的数字

int first_day; //月初星期几 0周日 1周一 ...... int printFinished; //打印完毕则为1,没打印完成则为0

}Calendar;

int year; int month; int day;

}Date;

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) {

int i = 0;

for (i = 0; i < TWELVEMONTH; i++)

13

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(\); fgets(calendar, 30, stdin); year = atoi(calendar); //得到年份 if (calendar[4] != '\\0')

month = atoi(calendar + 4); //得到月份 day = atoi(calendar + strlen(calendar) - 2); if (strlen(calendar) >= 8)

if (0 != year && 0 == month && 0 == day)

fun = 1;

fun = 0 == day ? 2 : 3; else

judgmentLeapYear(year, &cal[1]); //调整闰年平年2月的天数

}

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) { }

int calculateWeeks(int year, int month, int day) { }

void firstFun(int year, Calendar cal[]) {

int right = 1, left = 1;

14

if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))

cal->month_end = 29; cal->month_end = 28; else

int c, w, y;

y = year % 100;//年 如2015 即年是15年 c = year / 100;//年份前两位 如2015即20

if (month == 1 || month == 2) { //判断月份是否为1或2 }

w = y + y / 4 + c / 4 - 2 * c + 13 * (month + 1) / 5 + day - 1;//蔡勒公式 while (w < 0) w += 7;//确保余数为正 w %= 7; return w;

y--;

month += 12;//某年的1、2月要看作上一年的13、14月来计算

printf(\, year); int month = 1;

for (month = 1; month <= TWELVEMONTH / 2; month++) {

printf(\%d SUN MON TUE WED THU FRI SAT - SUN MON TUE WED THU FRI SAT |\\n\, month,

month + 6);

{

int i = 0;

for (right = 1, left = 1; 1; left++) {

if (1 == left) { //左边首日打印 }

else if (left == cal[month - 1].month_end) { //左边月末打印 }

else if (6 == calculateWeeks(year, month, left) && left <= cal[month - 1].month_end) }

else if (1 == cal[month - 1].printFinished) { } else

printf(\, left); for (i = 0; i < 8; i++)

printf(\); printf(\);

//左边打印完毕则补齐空格

printf(\, left);

for (i = 0; i < 6 - calculateWeeks(year, month, left); i++)

printf(\); printf(\); printf(\, left);

for (i = 0; i < 6 - calculateWeeks(year, month, left); i++)

printf(\);

//月末,则表示左边日历打印完毕

printf(\);

cal[month - 1].printFinished = 1; printf(\);

for (i = 0; i < calculateWeeks(year, month, left); i++)

printf(\);; printf(\, left);

if (6 == calculateWeeks(year, month, left)) { }

printf(\);

//既是首日也是周六

//左边日历的周六,则开始打印右边的日历

if (6 == calculateWeeks(year, month, left) && left <= cal[month - 1].month_end ||

for (;; right++) {

if (1 == right) {

//右边首日打印

for (i = 0; i < calculateWeeks(year, month + 6, right); i++)

printf(\);; printf(\, right);

cal[month - 1].printFinished) {

15

}

}

}

}

}

if (6 == calculateWeeks(year, month + 6, right)) { //既是首日也是周 }

//右边月末打印

printf(\); right++; break;

else if (right == cal[month - 1 + 6].month_end) { }

printf(\, right);

for (i = 0; i < 6 - calculateWeeks(year, month + 6, right); i++)

printf(\);

//月末,则表示右边日历打印完毕

printf(\);

cal[month - 1 + 6].printFinished = 1; right++; break;

else if (6 == calculateWeeks(year, month + 6, right) && right <= cal[month

//右边日历的周六,则开始打印左边的日历 printf(\, right); right++; break; }

else if (cal[month - 1 + 6].printFinished) { //右边打印完毕则补齐空格 } else

printf(\, right); for (i = 0; i < 7; i++)

printf(\); printf(\); right++; break;

- 1 + 6].month_end) {

if (cal[month - 1].printFinished&&cal[month - 1 + 6].printFinished) { }

putchar('\\r'); // 将光标跳到本行的开头,消除多余的打印字符 break;

putchar('|'); int i = 0;

for (i = 0; i < 65; i++)

putchar('=');

16

}

putchar('|'); putchar('\\n');

void secondFun(int year, int month, Calendar cal[]) { }

void thirdFun(int year, int month, int day) {

time_t t;

17

printf(\, year, month); printf(\, month); int i = 1, j = 1;

for (i = 1; i <= cal[month - 1].month_end; i++) { }

putchar('\\r'); putchar('|');

for (i = 0; i < 32; i++)

putchar('='); putchar('|'); putchar('\\n');

if (1 == i) { }

else if (6 == calculateWeeks(year, month, i)) { //周六换行 }

else if (i == cal[month - 1].month_end) { } else

printf(\, i); printf(\, i);

for (j = 0; j < 6 - calculateWeeks(year, month, i); j++)

printf(\); printf(\);

//月末

printf(\, i);

//首日打印

printf(\);

for (j = 0; j < calculateWeeks(year, month, i); j++)

printf(\); printf(\, i);

if (6 == calculateWeeks(year, month, i)) { //既是首日也是周六 }

printf(\);

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, \); break; case 1:strcpy(ch, \); break; case 2:strcpy(ch, \); break; case 3:strcpy(ch, \); break; case 4:strcpy(ch, \); break; case 5:strcpy(ch, \); break; case 6:strcpy(ch, \); break; }

if (1 == d1.month && 1 == d1.day)

strcpy(festival, \); //元旦

strcpy(festival, \); //国际妇女节 strcpy(festival, \); //植物节

strcpy(festival, \); //清明节 strcpy(festival, \); //劳动节 strcpy(festival, \); //青年节 strcpy(festival, \); //儿童节 strcpy(festival, \); //建党节 strcpy(festival, \);

//建军节

else if (3 == d1.month && 8 == d1.day) else if (3 == d1.month && 12 == d1.day) else if (4 == d1.month && 5 == d1.day) else if (5 == d1.month && 1 == d1.day) else if (5 == d1.month && 4 == d1.day) else if (6 == d1.month && 1 == d1.day) else if (7 == d1.month && 1 == d1.day) else if (8 == d1.month && 1 == d1.day) else if (9 == d1.month && 3 == d1.day)

strcpy(festival, \); // 抗日战争胜利纪念日

18

//用于存储节日

}

else if (9 == d1.month && 10 == d1.day)

strcpy(festival, \); strcpy(festival, \);

//教师节 //国庆节

else if (10 == d1.month && 1 == d1.day) else

strcpy(festival, \); //非节日

printf(\, iDayNum, ch, festival);

int dateDiff(struct date mindate, struct date maxdate) {

int days = 0, j, flag; const int primeMonth[][12] =

/************************************************************************/ /* 交换两个日期函数,将小的日期给mindate,将大的日期给maxdate */ /************************************************************************/ struct date tmp;

if ((mindate.year>maxdate.year) || (mindate.year ==

{ { 31,28,31,30,31,30,31,31,30,31,30,31 },{ 31,29,31,30,31,30,31,31,30,31,30,31 } };

maxdate.year&&mindate.month>maxdate.month) || (mindate.year == maxdate.year&&mindate.month == maxdate.month&&mindate.day>maxdate.day))

flag = isPrime(maxdate.year); for (j = 1; j

19

{ }

/************************************************************************/ /* 从mindate.year开始累加到maxdate.year */ /************************************************************************/ for (j = mindate.year; j

days += isPrime(j) ? 366 : 365; tmp = mindate; mindate = maxdate; maxdate = tmp;

//如果maxdate.year是闰年,则flag=1,后面调用primeMonth[1][12] flag = isPrime(maxdate.year); //加上maxdate.month到1月的天数 for (j = 1; j

days += primeMonth[flag][j - 1];

//减去mindate.month到1月的天数

}

days -= primeMonth[flag][j - 1];

days = days + maxdate.day - mindate.day; return days;

20

本文来源:https://www.bwwdw.com/article/ys45.html

Top