您的当前位置:首页正文

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

2022-06-15 来源:知库网


温馨提示

程序语言: 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) 输入一个年份,输出是在屏幕上显示该年的日历。假定输入的年份在

间。

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

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

1940-2040 年之

运行截图:

功能(一):

功能(二):

功能(三):

课程设计报告

题:

学专

院:业:

学生姓名:学

号:

指导老师:

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&&year%100!=0)||(year%400==0)) TWELVEMONTH12 // 数组大小

// 消除 Visual Stdio

// 宏函数,判断是否为闰年

#define

#pragma warning ( disable :4996) 编译环境的安全警告,其他编译环境可删除

//------------------------------ //----------

结构体定义区 ---------

//------------------------------ typedef

struct calendar

{

// 月末最后一天的数字

// 月初星期几 0 周日 1 周一 ......

// 打印完毕则为 1,没打印完成则为 0

int month_end; int first_day;

int printFinished; } Calendar ;

typedef {

struct date

int year; int month; int day;

} Date ;

//---------------------------- //----------

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

//---------------------------- void judgmentLeapYear(

int

year , Calendar * cal );

12

// 判断闰年

int calculateWeeks( void firstFun(

int

int y, int m, int d); // 计算该年月日是周几

// 第一功能

year , Calendar year , int year , int

cal []);

void secondFun( int void thirdFun(

month , Calendar cal []); // 第二功能

int struct

month , int day ); // 第三功能

date maxdate );

// 计算日期之间的间隔天数

int dateDiff( date mindate , struct

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;

else

fun = 0 == day ? 2 : 3;

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

int i = 0; for (i = 0; i <

TWELVEMONTH; i++)

13

);

cal[i].first_day = calculateWeeks(year, i + 1, 1);

switch (fun) {

case 1:firstFun(year, cal);

case 2:secondFun(year, month, cal); case 3:thirdFun(year, month, day); }

break ;

break ; break ;

return 0;

}

void judgmentLeapYear( {

int year , Calendar * cal )

if ((( year % 4 == 0) && (

cal ->month_end = 29;

else

year % 100 != 0)) || ( year % 400 == 0))

cal ->month_end = 28;

}

int calculateWeeks( {

int c, w, y;

int year , int month , int day )

y = year % 100; // 年 c = year / 100; if ( month == 1 ||

y--;

如2015 即年是 15 年

如2015 即 20

// 年份前两位

month == 2) { // 判断月份是否为 1或2

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

}

w = y + y / 4 + c / 4 - 2 * c + 13 * ( while (w < 0) w += 7; w %= 7; return w;

}

// 确保余数为正

month + 1) / 5 +

day - 1;

// 蔡勒公式

void firstFun( {

printf(

int year , Calendar cal [])

\"|===================The Calendar of Year %d ====================|\\n\" , year );

int month = 1;

for (month = 1; month <=

TWELVEMONTH/2; month++) {

printf( \"| %d SUN MON TUEWED THU FRI SAT %2d SUN MON TUE WEDTHU FRI SAT |\\n\" , month, month +

6);

int right = 1, left = 1;

14

int i = 0;

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

if (1 == left) {

printf(

\"| \"

/ / 左边首日打印 );

for (i = 0; i < calculateWeeks(

printf(

printf(

\" \"

);;

year , month, left); i++)

\"%4d\" , left);

if (6 == calculateWeeks(

printf(

}

}

\"

\"

);

year , month, left)) { // 既是首日也是周六

else if (left ==

printf(

cal [month - 1].month_end) { // 左边月末打印

\"%4d\" , left);

year , month, left); i++)

for (i = 0; i < 6 - calculateWeeks(

printf(

printf(

\"

\" \" \"

);

);

cal [month - 1].printFinished = 1;

}

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

else

calculateWeeks(

left

(6 ==

year , month, left) &&

<= cal [month - 1].month_end)

if

/ 左边日历的周六 , 则开始打印右边的日历 printf( \"%4d\" , left);

for (i = 0; i < 6 - calculateWeeks(

printf(

printf(

}

else if (1 ==

cal [month - 1].printFinished) {

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

\"

\" \" \"

);

);

year , month, left); i++)

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

printf(

printf(

} else

printf(

\"%4d\" , left);

\" \"

);

\"\" );

if (6 == calculateWeeks(

cal [month - 1].printFinished) {

for (;; right++) {

if (1 == right) {

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

// 右边首日打印

year , month + 6, right); i++)

for (i = 0; i < calculateWeeks(

printf(

printf(

\" \"

);;

\"%4d\" , right);

15

if (6 == calculateWeeks(

printf( right++; break ;

}

}

\" |\\n| \"

);

year , month + 6, right)) { // 既是首日也是周

else if (right ==

printf(

cal [month - 1 + 6].month_end) { // 右边月末打印

\"%4d\" , right);

year , month + 6, right); i++)

for (i = 0; i < 6 - calculateWeeks(

printf(

printf(

\" \"

); );

\" |\\n| \"

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

}

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

else if (6 == calculateWeeks(

- 1 + 6].month_end) {

year , month + 6, right) && right <= cal [month

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

}

\"%4d |\\n| \"

, right);

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

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

printf(

printf( right++; break ;

} else

printf(

}

\"%4d\" , right);

\" \"

); );

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

\" |\\n| \"

}

if ( cal [month - 1].printFinished&&

putchar( '\\r' break ;

}

}

}

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

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

putchar( '=' );

);

//

cal [month - 1 + 6].printFinished) {

将光标跳到本行的开头,消除多余的打印字符

16

putchar( '|' );

putchar( '\\n' );

}

void secondFun( int {

printf( printf(

year , int month , Calendar cal [])

\"|======The Year %d Month %d=====|\\n\" \"| %d SUN MON TUE WED THU FRI SAT |\\n\"

, year , month );

, month );

int i = 1, j = 1; for (i = 1; i <=

if (1 == i) {

printf(

\"| \"

cal [ month - 1].month_end; i++) {

// 首日打印 );

year , month , i); j++)

for (j = 0; j < calculateWeeks(

printf(

printf(

\" \"

);

\"%4d\" , i);

if

(6 == calculateWeeks(year , month , i)) { //

既是首日也是周六

printf(

}

\" |\\n| \"

);

}

else if (6 == calculateWeeks(

printf(

}

\"%4d |\\n| \"

, i);

year , month , i)) { // 周六换行

else if (i ==

printf(

cal [ month - 1].month_end) { \"%4d\" , i);

// 月末

for (j = 0; j < 6 - calculateWeeks(

printf(

printf(

} else

printf(

}

\"%4d\" , i);

\" \"

);

);

year , month , i); j++)

\" |\\n\"

putchar( '\\r'

);

putchar( '|' ); for (i = 0; i < 32; i++)

putchar( '=' );

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

}

void thirdFun( {

time_t t;

int year , int month , int day )

17

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\"

18

// 国际妇女节

); // 抗日战争胜利纪念日

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

strcpy(festival, \"Teachers day\" ); // 教师节

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

strcpy(festival,

else

\"National Day\"

);

// 国庆节

strcpy(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;

mindate .year ==

mindate .year ==

maxdate .year&& mindate .month ==

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

maxdate .year&& mindate .month> maxdate .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 =

是闰年 , 则flag=1, 后面调用 primeMonth[1][12]

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

mindate .month; j++)

for (j = 1; j<

19

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

days = days + return days;

}

maxdate .day - mindate .day;

20

因篇幅问题不能全部显示,请点此查看更多更全内容