




已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C 语 言课 程 设 计 报 告设计题目:万年历学生姓名:叶磊学生学号:20101010125专业班级:数学与应用数学一班学院名称:数学与计量经济学院同组人姓名:胡凡指导老师:姚 兰 2011年 6月 15 日1 需求分析1.1 问题描述我们需要实现万年历的功能,那么如何实现这个功能呢?我们都很清楚,普通年份和闰年是有区别的,那么该怎么区分这种一天的差别对于万年历日期现实的影响呢?而且已知一个日期,那么我们怎么能够知道它是星期几?是不是需要一个参照物来比较呢?而且还有很多关于万年历的美化问题,占位符的考虑等等。另外我们还必须判断输入的万年历是否合法,这也需要一个子函数来实现。好吧,至于基础的判断闰年也是不在话下了。1.2 输入数据要求 我们要考虑三种情况,这三种情况下是不能够实现这个万年历的功能的: /*如果给定的日期中年份部分为非正数*/ if(date.year12|date.monthadate.month|date.day1) printf(日期不符合要求!n); printf(请重新输入); getchar(); exit(0);1.3 输出数据要求根据输入数据,输出数据必须严格的按照占位符进行逻辑的策划,然后得知一行万年历的日期的占位符是38个占位符,于是空格占位符和字符显示出来的那些占位符就需要有一个限定使得其不凌乱特别应该注意空格符的占位。1.4 开发环境和工具开发环境:WINDOWS 7开发工具:Dev-C+ 4.9.9.21.5 成员分工叶磊:主调模块、万年历功能实现、数据测试、注释编写胡凡:总体设计、主调模块、备忘录功能实现、注释编写2 总体设计2.1总体设计思路1. 设计思路考虑到日期与备忘的一一对应,采用结构体来解决该题成为一个可行的思路。首先,定义结构体类型,使得年月日与备忘直接绑定在一起。通过程序中这一临时存放数据的变量,使用文件的读写功能向文件中写入文件以及读出信息以暂时使用。针对日历的输出,首要考虑的是当月1日的输出位置,即需要求出该月1日是星期几。针对这个问题,我们以2011年1月1日为基点,求所求日期与基点距离的天数之差,之后根据除以7取的余数来看星期。选择2011年1月1日为基点,是因为其满足计算的两个条件:1.该日正好为年首,使得计算相差天数的计算变得更为简单。2.该日正好是星期六,使得相差的天数除以7所取出来的余数正好按日历从左至右显示(我们输出的日历从左往右依次为星期日、一、二、三、四、五、六)。我们考虑2011年前与后的两种情况。2011年后所需的即为正常余数,2011年前的则需要用7减去得到的余数才是所欲要的值。之后经过一定的输出格式即可将日历输出。针对备忘录的编写,考虑到定义了一个结构体使得年月日与备忘相连,因此可以将年月日与备忘一同存入文件。考虑到万年备忘录的庞大,为了节省时间和空间,我们想出了一个算法:在添加写入文件时,一律将数据内容写入文件末尾(即使用ab+追加模式);而当读取文件时,则将文件内的年月日与外部参数输入的年月日相比较,不相同则位置指针下移,一直到年月日相同或者无法读取为止。这样编写可以避免考虑年份的上限大小(因为如果定义一个二维数组,虽然也可以将日期和备忘一一对应,但是这样的话处理这个数组的上限就不好操作了。如果数组开太大会直接影响运行速度),而且在存入的备忘不太多的情况下在时间和空间上都可以节省(空间只跟存入的备忘数目有关,而不是直接开很大的数组,这样即使年份很大也不会对空间大小有什么影响)。另外,我们设计了备忘修改功能、备忘删除(单日或全部),使得操作可以更人性化。最后,在自学了命令行参数之后,我们用argc和*argv将主函数写出,并且用getopt函数来处理接收的参数并返回命令选项。之后便可以通过返回的命令选项用switch语句选择所需要实现的功能。以上即为我们对该课题的总体设计思路。2. 数据存储将年月日与对应的备忘放于同一结构体变量中,在使用文件读写时作为一个整体使用,也方便了添加功能、修改功能、删除功能的实现。2.2模块结构图根据需求将系统划分为四个功能模块,函数之间的调用关系如图2.1所示。memo_writtenmemo_modifymemo_deletememo_delete_allmemo_readleapcheckDateMainshow_calender箭头出发的函数调用箭头指向的函数图2.1 晚年备忘录的模块结构图1)Main:主函数。2)leap:闰年判断。3)checkDate:检查日期合法性4)show_calender:显示当日的日历(未输入日时显示当月1日的日历)。5)memo_read:备忘的读取。6)memo_written:备忘的写入。7)memo_modify:备忘的修改。8)memo_delete:备忘的删除(当日)。9)memo_delete_all:备忘的删除(全部)。2.3模块说明(以从上至下,从左至右的顺序说明)1. MathPath模块函数原型:int main(int argc,char *argv)功 能:主函数输入参数:argcint类型,表示录入参数的个数 *argvchar类型,各元素记录各种录入字符串的首地址输出参数:0int类型,返回给系统一个值,说明程序正常终止2. leap模块函数原型:int leap(int t_year)功 能:闰年判断输入参数:t_yearint类型,表示需要判断闰年的年份输出参数:1int类型,如果是闰年则返回1;0int类型,如果是非闰年则返回0;3. checkDate模块函数原型:void checkDate()功 能:检查输入年月日的合法性输入参数:yearint类型,表示年份 monthint类型,表示月份 dayint类型,表示日期输出参数:无4. show_calender模块函数原型:void show_calender()功 能:显示日历输入参数:date.yearint类型,表示年份 date.monthint类型,表示月份 date.dayint类型,表示日期输出参数:无5. memo_read模块函数原型:void memo_read()功 能:从文件读取备忘输入参数:date.yearint类型,表示年份 date.monthint类型,表示月份 date.dayint类型,表示日期输出参数:无6. memo_written模块函数原型:void memo_written ()功 能:将备忘写入文件输入参数:date.yearint类型,表示年份 date.monthint类型,表示月份 date.dayint类型,表示日期输出参数:无7. memo_modify模块函数原型:void memo_modify ()功 能:修改备忘输入参数:date.yearint类型,表示年份 date.monthint类型,表示月份 date.dayint类型,表示日期输出参数:无8. memo_delete模块函数原型:void memo_delete ()功 能:删除备忘(当日)输入参数:date.yearint类型,表示年份 date.monthint类型,表示月份 date.dayint类型,表示日期输出参数:无9. memo_delete_all模块函数原型:void memo_delete_all ()功 能:删除备忘(全部)输入参数:无输出参数:无3 详细设计为了实现输入日期知道其为星期几的功能,我们必须的选取一个参照日期“以2011年1月1日星期六为基点”那么如何知道我们想要知道的日期时星期几呢?“计算某月第一天距离基点的天数除以7取余*/ ”于是有“*加上整年的天数*” “加上整月的天数”“ 计算某月第一天是星期几”这就可以判断出来距离我们锁定的那天是有多少天,再利用上述的方法来进行计算,这是/*当某年不低于2011年*/的情况,还有/*当某年低于2011年*/的情况,其逻辑和这好似一样的,同理。于是就判断出了是星期几。那么关于输出,printf(ntt Sun Mon Tue Wed Thu Fri Satntt );/*输出一定数量的空格*/这是重点,一行有占位符38格/*当一行已输出38个位数的时候换行(除每行开头的一堆空格外)*/这样就可以看到 这样的输出格式。然后判断输入是否合法以及判断是否是闰年都在课本上有过交代。4 测试结果及分析为了检验该程序的可行性以及正确性,我们选择了几组有代表的测试数据,与实际结果符合得很好。测试数据如下:1. 选择了2011年前的一天。我们选择了1949年10月1日,预期结果为星期一,先查看其备忘,预期结果为“该日暂无备忘!”。之后添加备忘“中华人民共和国成立!”下面为测试时所截的图。a. 在“命令提示行”中输入参数b. 敲回车,得到结果:c. 该日添加备忘“中华人民共和国成立!”。下为参数输入:d.敲回车后提示输入备忘。输入备忘。d. 按回车后e. 敲回车,得到成功信息,并输出修改后的日历及备忘。2. 还需要测试年份大于2011年的日期。考虑到这份日历为万年历,于是测试两份数据:大于一万年和小于一万年。以下测试小于一万年的数据:2012年12月24日,先添加备忘“世界末日?”再修改为“不可能是世界末日!”,最后删除该日备忘。a. 输入参数(添加)b. 添加备忘c. 添加成功信息d. 输入参数(修改)e. 输入修改内容f. 修改成功g. 输入参数(删除)h. 确认删除后3. 最后测试一组大于一万年的日期:999999年9月9日.测试功能:添加功能、全部删除功能。a. 输入参数b. 输入备忘c. 添加成功d. 输入参数(删除全部)e. 确认删除后至此,数据测试完毕。所有的测试结果均与实际符合得很好,验证了该程序的正确性。5 总结1 算法与程序总结本程序定义了结构体类型,将年月日和备忘联系起来,在写入和读取的过程中均作为一个整体,并且在将写入的内容始终写在文件的末尾,而不是定义一一对应的备忘数组,节省了时间和空间。由于课题要求使用命令行参数,所以,没有使用菜单来实现功能,而是使用命令选项来选择所需要执行的功能。而由于使用了命令行参数,因此该程序必须在DOS环境下运行(命令提示行)。万年历部分,采用定基点求相差的天数取7的余来确定当月首日是星期几,从而得到所需要的日历。2 改进方案 我们附录以下为我们小组该课题的最终代码:/*-我是分割线-*/*命令行功能选项*/*-d:显示当月日历和当日备忘*/*-i:显示当月日历和添加当日备忘*/ /*-m:显示当月日历和修改当日备忘*/ /*-g:删除当日备忘*/*-t:删除全部备忘*/*-我是分割线-*/*头文件*/ #include#include#include#include /*调用getopt函数*/*-我是分割线-*/*定义全局变量(各月所含天数)*/ int a=0,31,0,31,30,31,30,31,31,30,31,30,31;/*定义全局变量(已获取的备忘个数)*/int count_memo;/*定义结构体*/ struct date_message int year; /*年*/ int month; /*月*/ int day; /*日*/ char memo300; /*备忘*/ date=1,1,1,0;/*-我是分割线-*/*主函数*/ int main(int argc,char *argv) /*函数声明*/ void checkDate(); /*检查日期合法性*/ void show_calender(); /*显示日历*/ void memo_written(); /*写入备忘*/ void memo_modify(); /*修改备忘*/ void memo_delete(); /*删除当日备忘*/ void memo_delete_all(); /*删除全部备忘*/ void memo_read(); /*读取备忘*/*定义变量*/ char choice;/*使用getopt函数分析命令行参数,识别选项*/while(choice=getopt(argc,argv,d:i:m:g:t)!=-1) /*选项*/ switch(choice) /*选项为d时,显示当月日历和当日备忘*/ case d:/*调用atoi函数,将字符型数字转化为整型*/ date.year=atoi(argv2); /*如果没有输入月份则不赋值*/ if(atoi(argv3)!=0)date.month=atoi(argv3); /*如果没有输入日期则不赋值*/ if(atoi(argv4)!=0)date.day=atoi(argv4); /*检查日期合法性*/ checkDate(); /*显示当日日历*/ show_calender(); /*显示备忘*/ memo_read(); break; /*选项为i时,显示当月日历和添加当日备忘*/ case i:date.year=atoi(argv2); date.month=atoi(argv3); if(atoi(argv4)!=0)date.day=atoi(argv4); checkDate(); show_calender(); memo_read(); printf(请输入要添加的备忘n); /*写入备忘*/ memo_written(); /*添加之后*/ printf(添加之后的日历与对应的备忘为n); show_calender(); memo_read(); break; /*选项为m时,显示当月日历和修改当日备忘*/ case m:date.year=atoi(argv2); date.month=atoi(argv3); if(atoi(argv4)!=0)date.day=atoi(argv4); checkDate(); show_calender(); memo_read(); /*如果该日无备忘,则给出提示*/ if(count_memo=0) printf(无法修改,因为该日无备忘。n如需添加备忘,请使用备忘添加功能n); break; /*修改备忘*/ memo_modify(); /*修改之后*/ printf(修改之后的日历为n); show_calender(); memo_read(); break; /*选项为g时,删除当日备忘*/ case g:date.year=atoi(argv2); date.month=atoi(argv3); if(atoi(argv4)!=0)date.day=atoi(argv4); checkDate(); show_calender(); memo_read(); memo_delete(); show_calender(); memo_read(); break; /*选项为t时,删除全部备忘*/ case t:memo_delete_all(); getch(); break; printf(tt Please any key to continue); getch(); system(cls); return 0; /*-我是分割线-*/*显示当月日历*/void show_calender() /*函数调用声明*/ int leap(int t_year); /*定义函数*/ int sum=0,count=0,i,t,temp_year,temp_month,temp_day=-1; /*输出年月日*/ printf(ntttt%d年%d月,date.year,date.month);if(date.day!=0)printf(%d日n,date.day);else printf(1日n);/*计算某月第一天是星期几,以2011年1月1日星期六为基点,计算某月第一天距离基点的天数除以7取余*/ /*当某年不低于2011年*/ if(date.year=2011) /*加上整年的天数*/ for(temp_year=2011;temp_yeardate.year;temp_year+)sum+=365+leap(temp_year);a2=(leap(date.year)=1)?29:28;/*加上整月的天数*/ for(temp_month=1;temp_month0)?sum%7:(sum%7+7);/*当某年低于2011年*/ if(date.yeardate.year+1;temp_year-)sum+=365+leap(temp_year-1); a2=(leap(date.year-1)=1)?29:28;/*加上整月的天数*/ for(temp_month=12;temp_month=date.month;temp_month-)sum+=atemp_month;/*计算某月第一天是星期几*/ t=(sum%7=0)?(7-sum%7):(-sum%7);/*输出当月日历*/ printf(ntt Sun Mon Tue Wed Thu Fri Satntt );/*输出一定数量的空格*/for(i=1;i=5*t-2;i+)printf( );/*计数一行中已输出多少个位数*/count+;/*逐行输出日历中的日期部分*/for(temp_day=1;temp_day=adate.month;temp_day+) /*如果有输入日期则特别标出*/if(temp_day=date.day) if(date.day10)printf(b%d ,date.day); else printf(b%d ,date.day); /*普通日期无特别表示*/else printf(%-5d,temp_day);/*计数增加*/count+=5;/*当一行已输出38个位数的时候换行(除每行开头的一堆空格外)*/if(count=38)printf(n );count=3;printf(n);/*-我是分割线-*/*备忘读取*/void memo_read() /*定义文件指针*/ FILE *fp; /*定义变量*/ int i; struct date_message temp=0,0,0,0; /*总是在读取备忘之前令备忘数归零*/ count_memo=0; /*打开文件*/ if(fp=fopen(calender.txt,ab+)=NULL) printf(tttt打开文件失败ttttn); return; /*查找文件中是否有相同的日期*/ while(1) /*文件读到不能读取为止*/ if(fread(&temp,sizeof(struct date_message),1,fp)!=1)break; /*如果文件该位置的时间与所求时间相同*/ if(temp.year=date.year)&(temp.month=date.month)&(temp.day=date.day) /*当天备忘个数的计数*/ count_memo+; for(i=0;i0&t0&t=count_memo) printf(输入错误!该次操作失败!); getch(); system(cls); exit(0); /*打开文件*/ if(fp=fopen(calender.txt,rb+)=NULL) printf(打开文件失败nn); return; /*在文件中查找输入的年月日的信息*/ while(1) fseek(fp,i*sizeof(struct date_message),0); if(fread(&temp2,sizeof(struct date_message),1,fp)!=1)break; if(temp2.year=date.year)&(temp2.month=date.month)&(temp2.day=date.day) count+; if(count=t) fseek(fp,i*sizeof(struct date_message),0); /*将空的覆盖上去*/ fwrite(&temp1,sizeof(struct date_message),1,fp); break; i+; printf(单条备忘删除成功!n); getch(); system(cls); fclose(fp); break; case 2:/*打开文件*/ if(fp=fopen(calender.txt,rb+)=NULL) printf(打开文件失败nn); return; /*在文件中查找输入的年月日的信息*/ while(1) fseek(fp,i*sizeof(struct date_message),0); if(fread(&temp2,sizeof(struct date_message),1,fp)!=1)break; if(temp2.year=date.year)&(temp2.month=date.month)&(temp2.day=date.day) fseek(fp,i*sizeof(struct date_messa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 江苏省淮安市淮阴区2025-2026学年数学高三上期末教学质量检测模拟试题
- 江西省抚州市临川实验学校重点班2025-2026学年数学高三上期末考试试题
- 四川省绵阳市2025年数学高三第一学期期末质量跟踪监视模拟试题
- 静脉插管技术在儿科重症新2讲课文档
- 苏武传重点字词翻译课件
- 护理知识竞赛试题及答案
- 押韵古诗考试题及答案
- 2025河南南阳财和投资有限公司招聘工作人员(第十号)备考练习题库及答案解析
- 糖皮质激素在呼吸系统疾病的应用讲课文档
- 住宅室内装饰装修工程施工合同
- 投标报价说明范本
- 露天矿山危险源辨识(汇总)
- 放射科质控汇报
- 医院超声科管理制度汇编
- Q3D学习体会课件
- 眼科学教学课件:绪论
- 中医运动养生 中医养生学课件
- GB/T 5563-2013橡胶和塑料软管及软管组合件静液压试验方法
- GB/T 31091-2014煤场管理通用技术要求
- GB/T 24218.1-2009纺织品非织造布试验方法第1部分:单位面积质量的测定
- GB/T 1192-1999农业轮胎
评论
0/150
提交评论