语言课程设计万年历_第1页
语言课程设计万年历_第2页
语言课程设计万年历_第3页
语言课程设计万年历_第4页
语言课程设计万年历_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C 语 言课 程 设 计 报 告设计题目:万年历学生姓名:叶磊学生学号:20101010125专业班级:数学与应用数学一班学院名称:数学与计量经济学院同组人姓名:胡凡指导老师:姚 兰2011年 6月15 日1 需求分析1.1 问题描述我们需要实现万年历的功能,那么如何实现这个功能呢?我们都很清楚,普通年份和闰年是有区别的,那么该怎么区分这种一天的差别对于万年历日期现实的影响呢?而且已知一个日期,那么我们怎么能够知道它是星期几?是不是需要一个参照物来比较呢?而且还有很多关于万年历的美化问题,占位符的考虑等等。另外我们还必须判断输入的万年历是否合法,这也需要一个子函数来实现。好吧,至于基础的判断闰

2、年也是不在话下了。1.2 输入数据要求 我们要考虑三种情况,这三种情况下是不能够实现这个万年历的功能的: /*如果给定的日期中年份部分为非正数*/ if(date.year<=0)printf("年份不符合要求!n" printf("请重新输入) /*如果给定的日期中月份部分为负数,为0或者大于12*/ if(date.month>12|date.month<1) printf("月份不符合要求!n"); printf("请重新输入"); getchar(); exit(0); /*如果给定的日期中天数部分

3、为非正数,或者大于31*/ a2=28+leap(date.year); if(date.day>adate.month|date.day<1)printf("日期不符合要求!n"); printf("请重新输入"); getchar(); exit(0);1.3 输出数据要求根据输入数据,输出数据必须严格的按照占位符进行逻辑的策划,然后得知一行万年历的日期的占位符是38个占位符,于是空格占位符和字符显示出来的那些占位符就需要有一个限定使得其不凌乱特别应该注意空格符的占位。1.4 开发环境和工具开发环境:WINDOWS 7开发工具:Dev-C

4、+ .21.5 成员分工叶磊:主调模块、万年历功能实现、数据测试、注释编写胡凡:总体设计、主调模块、备忘录功能实现、注释编写2 总体设计2.1总体设计思路1. 设计思路考虑到日期与备忘的一一对应,采用结构体来解决该题成为一个可行的思路。首先,定义结构体类型,使得年月日与备忘直接绑定在一起。通过程序中这一临时存放数据的变量,使用文件的读写功能向文件中写入文件以及读出信息以暂时使用。针对日历的输出,首要考虑的是当月1日的输出位置,即需要求出该月1日是星期几。针对这个问题,我们以2011年1月1日为基点,求所求日期与基点距离的天数之差,之后根据除以7取的余数来看星期。选择2011年1月1日为基点,是

5、因为其满足计算的两个条件:1.该日正好为年首,使得计算相差天数的计算变得更为简单。2.该日正好是星期六,使得相差的天数除以7所取出来的余数正好按日历从左至右显示(我们输出的日历从左往右依次为星期日、一、二、三、四、五、六)。我们考虑2011年前与后的两种情况。2011年后所需的即为正常余数,2011年前的则需要用7减去得到的余数才是所欲要的值。之后经过一定的输出格式即可将日历输出。针对备忘录的编写,考虑到定义了一个结构体使得年月日与备忘相连,因此可以将年月日与备忘一同存入文件。考虑到万年备忘录的庞大,为了节省时间和空间,我们想出了一个算法:在添加写入文件时,一律将数据内容写入文件末尾(即使用a

6、b+追加模式);而当读取文件时,则将文件内的年月日与外部参数输入的年月日相比较,不相同则位置指针下移,一直到年月日相同或者无法读取为止。这样编写可以避免考虑年份的上限大小(因为如果定义一个二维数组,虽然也可以将日期和备忘一一对应,但是这样的话处理这个数组的上限就不好操作了。如果数组开太大会直接影响运行速度),而且在存入的备忘不太多的情况下在时间和空间上都可以节省(空间只跟存入的备忘数目有关,而不是直接开很大的数组,这样即使年份很大也不会对空间大小有什么影响)。另外,我们设计了备忘修改功能、备忘删除(单日或全部),使得操作可以更人性化。最后,在自学了命令行参数之后,我们用argc和*argv将主

7、函数写出,并且用getopt函数来处理接收的参数并返回命令选项。之后便可以通过返回的命令选项用switch语句选择所需要实现的功能。以上即为我们对该课题的总体设计思路。2. 数据存储将年月日与对应的备忘放于同一结构体变量中,在使用文件读写时作为一个整体使用,也方便了添加功能、修改功能、删除功能的实现。2.2模块结构图根据需求将系统划分为四个功能模块,函数之间的调用关系如图2.1所示。memo_writtenmemo_modifymemo_deletememo_delete_allmemo_readleapcheckDateMainshow_calender箭头出发的函数调用箭头指向的函数图2.

8、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类型,表示

9、录入参数的个数*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模块函数原型:v

10、oid 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类

11、型,表示月份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

12、_delete_all ()功能:删除备忘(全部)输入参数:无输出参数:无3 详细设计为了实现输入日期知道其为星期几的功能,我们必须的选取一个参照日期“以2011年1月1日星期六为基点”那么如何知道我们想要知道的日期时星期几呢?“计算某月第一天距离基点的天数除以7取余*/”于是有“*加上整年的天数*”“加上整月的天数”“计算某月第一天是星期几”这就可以判断出来距离我们锁定的那天是有多少天,再利用上述的方法来进行计算,这是/*当某年不低于2011年*/的情况,还有/*当某年低于2011年*/的情况,其逻辑和这好似一样的,同理。于是就判断出了是星期几。那么关于输出,printf("ntt

13、 Sun Mon Tue Wed Thu Fri Satntt ");/*输出一定数量的空格*/这是重点,一行有占位符38格/*当一行已输出38个位数的时候换行(除每行开头的一堆空格外)*/这样就可以看到 这样的输出格式。然后判断输入是否合法以及判断是否是闰年都在课本上有过交代。4 测试结果及分析为了检验该程序的可行性以及正确性,我们选择了几组有代表的测试数据,与实际结果符合得很好。测试数据如下:1. 选择了2011年前的一天。我们选择了1949年10月1日,预期结果为星期一,先查看其备忘,预期结果为“该日暂无备忘!”。之后添加备忘“中华人民共和国成立!”下面为测试时所截的图。a.

14、在“命令提示行”中输入参数b. 敲回车,得到结果:c. 该日添加备忘“中华人民共和国成立!”。下为参数输入:d.敲回车后提示输入备忘。输入备忘。d. 按回车后e. 敲回车,得到成功信息,并输出修改后的日历及备忘。2. 还需要测试年份大于2011年的日期。考虑到这份日历为万年历,于是测试两份数据:大于一万年和小于一万年。以下测试小于一万年的数据:2012年12月24日,先添加备忘“世界末日?”再修改为“不可能是世界末日!”,最后删除该日备忘。a. 输入参数(添加)b. 添加备忘c. 添加成功信息d. 输入参数(修改)e. 输入修改内容f. 修改成功g. 输入参数(删除)h. 确认删除后3. 最后

15、测试一组大于一万年的日期:999999年9月9日.测试功能:添加功能、全部删除功能。a. 输入参数b. 输入备忘c. 添加成功d. 输入参数(删除全部)e. 确认删除后至此,数据测试完毕。所有的测试结果均与实际符合得很好,验证了该程序的正确性。5 总结1 算法与程序总结本程序定义了结构体类型,将年月日和备忘联系起来,在写入和读取的过程中均作为一个整体,并且在将写入的内容始终写在文件的末尾,而不是定义一一对应的备忘数组,节省了时间和空间。由于课题要求使用命令行参数,所以,没有使用菜单来实现功能,而是使用命令选项来选择所需要执行的功能。而由于使用了命令行参数,因此该程序必须在DOS环境下运行(命令

16、提示行)。万年历部分,采用定基点求相差的天数取7的余来确定当月首日是星期几,从而得到所需要的日历。2 改进方案我们附录以下为我们小组该课题的最终代码:/*-我是分割线-*/*命令行功能选项*/*-d:显示当月日历和当日备忘*/*-i:显示当月日历和添加当日备忘*/ /*-m:显示当月日历和修改当日备忘*/ /*-g:删除当日备忘*/*-t:删除全部备忘*/*-我是分割线-*/*头文件*/ #include<stdio.h>#include<stdlib.h>#include<conio.h>#include<unistd.h> /*调用getop

17、t函数*/*-我是分割线-*/*定义全局变量(各月所含天数)*/ 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 chec

18、kDate(); /*检查日期合法性*/ 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"

19、)!=-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_r

20、ead(); 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_calende

21、r(); 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; /*修改备忘*/

22、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();

23、 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,te

24、mp_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_year<date.year;te

25、mp_year+)sum+=365+leap(temp_year);a2=(leap(date.year)=1)?29:28;/*加上整月的天数*/ for(temp_month=1;temp_month<date.month;temp_month+)sum+=atemp_month;/*计算某月第一天是星期几*/ t=(sum%7>0)?sum%7:(sum%7+7);/*当某年低于2011年*/ if(date.year<2011) /*加上整年的天数*/ for(temp_year=2011;temp_year>date.year+1;temp_year-)sum

26、+=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+)print

27、f(" ");/*计数一行中已输出多少个位数*/count+;/*逐行输出日历中的日期部分*/for(temp_day=1;temp_day<=adate.month;temp_day+) /*如果有输入日期则特别标出*/if(temp_day=date.day) if(date.day<10)printf("b%d ",date.day); else printf("b%d ",date.day); /*普通日期无特别表示*/else printf("%-5d",temp_day);/*计数增加*/c

28、ount+=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&quo

29、t;,"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) /*当天备忘个数的计数*/ co

30、unt_memo+; for(i=0;i<300;i+) date.memoi=temp.memoi; printf("nttt备忘%d:%sn",count_memo,date.memo); /*如果没有相同日期的话*/ if(count_memo=0) printf("tttt该日暂无备忘nn"); printf("n"); fclose(fp); /*-我是分割线-*/*备忘写入*/void memo_written() /*定义文件指针*/ FILE *fp; /*打开文件*/ if(fp=fopen("cal

31、ender.txt","ab+")=NULL) printf("ntttt 打开文件失败nnttt "); return; /*输入备忘*/ scanf("%s",date.memo); /*写入备忘*/ if(fwrite(&date,sizeof(struct date_message),1,fp)=1) system("cls"); printf("ntttt 备忘存入成功nnttt "); else system("cls"); printf(&qu

32、ot;ntttt 备忘存入失败nnttt "); fclose(fp); /*-我是分割线-*/*备忘修改*/void memo_modify() /*定义文件指针*/ FILE *fp; /*定义变量*/ int i=0,t,count=0; struct date_message temp; /*打开文件*/ if(fp=fopen("calender.txt","rb+")=NULL) printf("nnnnnnnnnttt 打开文件失败nn"); return; printf("请输入要修改第几条备忘n&

33、quot;); /*输入需要修改第几条备忘*/ scanf("%d",&t); if(!(t>0&&t<=count_memo) printf("输入错误!该次操作失败n!"); getch(); system("cls"); exit(0); printf("请输入要修改的内容n"); /*输入备忘*/ scanf("%s",&date.memo); /*在文件中寻找该日期*/ while(1) /*移动指针位置*/ fseek(fp,i*sizeo

34、f(struct date_message),0); /*到文件无法读取时退出*/ if(fread(&temp,sizeof(struct date_message),1,fp)!=1)break; /*如果文件中的时间与所求时间相同*/ if(temp.year=date.year)&&(temp.month=date.month)&&(temp.day=date.day) /*备忘计数+1*/ count+; /*对应上同一个备忘的时候*/ if(count=t) fseek(fp,i*sizeof(struct date_message),0);

35、 /*覆盖*/ fwrite(&date,sizeof(struct date_message),1,fp); break; i+; printf("ntttt 修改成功!nn"); getch(); system("cls"); fclose(fp); /*-我是分割线-*/*当日备忘删除*/void memo_delete() /*定义文件指针*/ FILE *fp; /*定义变量*/ int i=0,t,choice,count=0; struct date_message temp1=0,0,0,"0" struct

36、date_message temp2; /*确认信息*/ printf("确认要删除当日备忘吗(y/n)? "); /*如果输入y的话删除*/ if(!(getchar()='y'|'Y') printf("未删除该日任何备忘n"); getch(); system("cls"); exit(0); printf("(1)删除单条备忘 or (2)删除当日所有备忘?n请输入1或2进行选择n"); scanf("%d",&choice); switch(ch

37、oice) case 1:printf("请输入要删除第几条备忘n"); /*输入要删除第几条备忘*/ scanf("%d",&t); if(!(t>0&&t<=count_memo) printf("输入错误!该次操作失败!"); getch(); system("cls"); exit(0); /*打开文件*/ if(fp=fopen("calender.txt","rb+")=NULL) printf("打开文件失败nn&q

38、uot;); 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

39、); /*将空的覆盖上去*/ 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; /*在文件中查找输入的年月日的信息*/ wh

40、ile(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_message),0); fwrite(&temp1,sizeof(struct date_message),1,fp); i+; printf("当日所有备忘删除成功!n"); getch(); system("cls"); fclose

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论