《C语言及程序设计》实践参考——玩转日期和时间
2015-07-04 15:14
603 查看
返回:贺老师课程教学链接
【项目2-玩转日期和时间】
定义一个表示时间(包括年、月、日、时、分、秒)的结构体,然后完成下面的功能。
提示:将各个功能分别设计成函数实现,在main函数中调用,进行测试。可以设计一个函数,即刻进行测试,以降低复杂度。
要实现的功能是:
(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;
(2)输出该日在本年中是第几天(注意闰年问题);
(3)输出这是这一天中的第几秒;
(4)输出这是这一年中的第几秒;(不要认为这个数荒唐,在计算中需要取随机数时需要一个不会重复的“种子数”,这个秒数是常用的。)
(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出。
[参考解答]
所以,这个程序最后的结构会是:
胖子是一口一口吃出来的,程序得一点一点写出来,做一些,就测试一点,保证局部不要出问题。不要妄图全写完了才去测试,医生说食物摄取过量,老百姓讲是吃撑了。
参考代码可以如下:
从做练习的角度,程序就是完成了。要完成测试,关键是保证输入时数据取值范围是否能够得到保证,于是需要多次地启动程序,输入各种不同的时间,看是否能体现设计时的限制。需要考虑到的情形包括:
2013年1月20日3时4分5秒 //中规中矩的输入
2012年3月31日3时4分5秒 //重点考察取日期的“边界值”是否接受,类似地可以用其他月份检查,还可以设计出多种情形
……
2013年2月29日3时4分5秒 //2013不是闰年,这个输入会如何处理
2012年2月29日3时4分5秒 //2012是闰年,这个输入会如何处理
2013年13月45日33时4分5秒 //各种的“捣乱”,这在测试中是必须的
通过这样的多次运行多次输入查看结果是可行的。但是,如果考虑一次运行程序,可以支持多次输入对不同情形进行测试,那自然是更方便的事了。其实,写一个循环,那也不是难事。事实上,这是工程中更常用的方式。
在这种思路下,main()函数这样写。
这只是测试所需要的一部分内容。这样测试出的程序,质量信心必涨!好产品得经过严格的测试,放在程序设计中也是这样。
实现了的函数和测试用的main()函数如下所示,实现任务(1)中的函数保留不动,它们是整个任务中的一部分,况且(2)任务可能会用到前面的劳动成果,删除不必要。
参考程序如下:
体会上面测试数据设计和测试程序(main()函数)设计中的用心,查看运行测试的结果,生产好产品,需要这样做。
请体会上面的测试数据的设计,也可以设计出更好的来
int main()
{
struct Time t,nt;
//(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;
printf(“请输入一个时间(包括年,月,日,时,分,秒):\n”);
getTime(&t);
outputTime(t);
//(2)输出该日在本年中是第几天(注意闰年问题);
printf(“这是这一年中的第%d天。\n”, dayOfYear(t));
//(3)输出这是这一天中的第几秒;
printf(“这是这一天中的第%d秒。\n”, secondOfDay(t));
//(4)输出这是这一年中的第几秒;
printf(“这是这一年中的第%d秒。\n”, dayOfYear(t)*24*3600+secondOfDay(t));
//(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出;
int d;
printf(“请输入一个天数: “);
scanf(“%d”, &d);
nt=afterDays(t,d);
printf(“再过%d天, “, d);
outputTime(nt);
return 0;
}
“`
【项目2-玩转日期和时间】
定义一个表示时间(包括年、月、日、时、分、秒)的结构体,然后完成下面的功能。
提示:将各个功能分别设计成函数实现,在main函数中调用,进行测试。可以设计一个函数,即刻进行测试,以降低复杂度。
要实现的功能是:
(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;
(2)输出该日在本年中是第几天(注意闰年问题);
(3)输出这是这一天中的第几秒;
(4)输出这是这一年中的第几秒;(不要认为这个数荒唐,在计算中需要取随机数时需要一个不会重复的“种子数”,这个秒数是常用的。)
(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出。
[参考解答]
整体的考虑
最后编好的程序的结构应该如下所示,其中所需要设计,一是存储数据所用的数据结构——结构体,二是整个程序的框架,除了main()函数之外,还要有一系列的其他函数作为支撑。在严格的软件工程中,需要提前将所需要的函数(工程中称之为模块)设计出来,而在学习语法阶段,不妨也便宜行事,需要什么写什么,这样做更快一些。在此基础上,main()函数只要按照题目中的要求,或输入,或调用函数,逐个地写出来即可。所以,这个程序最后的结构会是:
#include <stdio.h> struct Time { int year; int month; int day; int hour; int minute; int second; }; //待设计的一大堆函数,是哪些,暂不考虑 int main() { struct Time t; //(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中; printf("请输入一个时间(包括年,月,日,时,分,秒):\n"); getTime(&t); //输入将不会是很简单的一两条语句,写个函数完成 outputTime(t); //马上验证输入,很自地完成 //(2)输出该日在本年中是第几天(注意闰年问题); printf("这是这一年中的第%d天。\n", dayOfYear(t)); //设计专门的函数完成 //(3)输出这是这一天中的第几秒; printf("这是这一天中的第%d秒。\n", secondOfDay(t));//设计专门的函数完成 //(4)输出这是这一年中的第几秒; printf("这是这一年中的第%d秒。\n", dayOfYear(t)*24*3600+secondOfDay(t)); //(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出; scanf("%d", &d); printf("这一天后%d天是:", d); outputTime(afterDays(t,d)); //(6)求你输入的时间s秒后是何日何时,将结果保存在一个结构体变量中输出; scanf("%d", &d); printf("这一时的后%d秒是:", s); outputTime(afterSeconds(t,s)); //到此任务完成 return 0; }
胖子是一口一口吃出来的,程序得一点一点写出来,做一些,就测试一点,保证局部不要出问题。不要妄图全写完了才去测试,医生说食物摄取过量,老百姓讲是吃撑了。
完成第(1)个要求,测试通过键盘输入进行即可
在这样一种指导思想下,先完成第(1)个要求,主要是写出自定义函数来。将需要多次用到的功能,例如,输入中要保证范围的要求,也“抽象”一下,做成函数getNum()。不少成员的取值范围是确定的,但每月的天数并不都一样有些麻烦,设计一个函数daysOfMonth()实现,将有利于整个程序的简洁。参考代码可以如下:
#include <stdio.h> struct Time { int year; int month; int day; int hour; int minute; int second; }; //输入一个限定范围内的整型数值 int getNum(char *prompt, int min, int max) { int value=-1; printf("输入%s,范围[%d, %d]:", prompt, min, max); do { scanf("%d", &value); } while(value<min || value>max); return value; } //返回y年m月的天数 int daysOfMonth(int m,int y) { int days; switch(m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days=31; break; case 4: case 6: case 9: case 11: days=30; break; case 2: if((y%4==0&&y%100!=0)||y%400==0) days=29; else days=28; } return days; } //输入时间,参数为指针,可以影响实参的值 void getTime(struct Time *p) { p->year=getNum("年",0,3000); //getNum()用于输入一定范围内的数 p->month=getNum("月",1,12); p->day=getNum("日",1,daysOfMonth(p->month, p->year)); p->hour=getNum("时",0,24); p->minute=getNum("分",0,59); p->second=getNum("秒",0,59); } //输出时间 void outputTime(struct Time t) { printf("时间为: %d年%d月%d日%d时%d分%d秒\n",t.year,t.month,t.day,t.hour,t.minute,t.second); } int main() { struct Time t; //(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中; printf("请输入一个时间(包括年,月,日,时,分,秒):\n"); getTime(&t); outputTime(t); return 0; }
从做练习的角度,程序就是完成了。要完成测试,关键是保证输入时数据取值范围是否能够得到保证,于是需要多次地启动程序,输入各种不同的时间,看是否能体现设计时的限制。需要考虑到的情形包括:
2013年1月20日3时4分5秒 //中规中矩的输入
2012年3月31日3时4分5秒 //重点考察取日期的“边界值”是否接受,类似地可以用其他月份检查,还可以设计出多种情形
……
2013年2月29日3时4分5秒 //2013不是闰年,这个输入会如何处理
2012年2月29日3时4分5秒 //2012是闰年,这个输入会如何处理
2013年13月45日33时4分5秒 //各种的“捣乱”,这在测试中是必须的
通过这样的多次运行多次输入查看结果是可行的。但是,如果考虑一次运行程序,可以支持多次输入对不同情形进行测试,那自然是更方便的事了。其实,写一个循环,那也不是难事。事实上,这是工程中更常用的方式。
在这种思路下,main()函数这样写。
int main() { struct Time t; do { printf("请输入一个时间(包括年,月,日,时,分,秒):\n"); getTime(&t); outputTime(t); }while(t.year>0); //输入0年某月某日测试即结束,测试过程由人可控 return 0; }
这只是测试所需要的一部分内容。这样测试出的程序,质量信心必涨!好产品得经过严格的测试,放在程序设计中也是这样。
完成第(2)个要求,测试不再靠键盘输入
实现功能角度,增加一个函数dayOfYear()即可。涉及到测试时,要靠着键盘输入,那可就烦恼大了:改一点程序,输入若干数据测试,发现错误,改程序,再运行,输入测试数据。这时,可以采用的方法是,用测试用到的数据直接初始化结构体。再进一步,一组测试数据,一起测试,用结构体数组保存数据,测试过程做一个循环。实现了的函数和测试用的main()函数如下所示,实现任务(1)中的函数保留不动,它们是整个任务中的一部分,况且(2)任务可能会用到前面的劳动成果,删除不必要。
参考程序如下:
#include <stdio.h> struct Time { int year; int month; int day; int hour; int minute; int second; }; //输入一个限定范围内的整型数值 int getNum(char *prompt, int min, int max) { int value=-1; printf("输入%s,范围[%d, %d]:", prompt, min, max); do { scanf("%d", &value); } while(value<min || value>max); return value; } //返回y年m月的天数 int daysOfMonth(int m,int y) { int days; switch(m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days=31; break; case 4: case 6: case 9: case 11: days=30; break; case 2: if((y%4==0&&y%100!=0)||y%400==0) days=29; else days=28; } return days; } //这天是这一年的第几天 int dayOfYear(struct Time t) { int days=0; int m=1; while(m<t.month) //前若干月的天数加起来 { days+=daysOfMonth(m,t.year); //充分利用已经设计的函数 ++m; } days+=t.day; //再加上本月的天数 return days; } //输入时间,参数为指针,可以影响实参的值 void getTime(struct Time *p) { p->year=getNum("年",0,3000); //getNum()用于输入一定范围内的数 p->month=getNum("月",1,12); p->day=getNum("日",1,daysOfMonth(p->month, p->year)); p->hour=getNum("时",0,24); p->minute=getNum("分",0,59); p->second=getNum("秒",0,59); } //输出时间 void outputTime(struct Time t) { printf("时间为: %d年%d月%d日%d时%d分%d秒\n",t.year,t.month,t.day,t.hour,t.minute,t.second); } int main() { //任务(2)输出该日在本年中是第几天(注意闰年问题); struct Time t[]= //测试数据放在结构体数组中 { {1971,1,8,14,25,48}, //最简单的一个测试数据,期望输出8 {2011,2,27,14,25,48}, //2月,天数要加上1月的31天,期望输出31+27 {2012,3,2,14,25,48}, //这个输入很敏感,看2月究竟算多少天,期望输出31+29+2=62 {2013,3,2,14,25,48}, //这个期望输出是31+28+2=61 {2013,4,10,14,25,48} //期望结果100,这样的测试数据还可以继续列一些,期望结果要列出来,这是测试的依据 }; int i; for(i=0; i<5; ++i) //测试过程用一个循环完成 { outputTime(t[i]); printf("这是这一年中的第%d天。\n\n", dayOfYear(t[i])); } return 0; }
体会上面测试数据设计和测试程序(main()函数)设计中的用心,查看运行测试的结果,生产好产品,需要这样做。
第(3)和(4)个任务容易实现,测试过程类似进行
只需要增加一个自定义函数//这天是这一天的第几秒 int secondOfDay(struct Time t) { return t.hour*3600+t.minute*60+t.second; } 相应的测试函数定义为: [int main() { struct Time t[]= { {1971,1,8,0,0,2}, {2011,2,27,0,25,10}, {2012,3,2,10,20,20}, {2013,3,2,10,20,20}, {2013,4,10,10,20,20} }; int i; for(i=0; i<5; ++i) { outputTime(t[i]); //(3)输出这是这一天中的第几秒; printf("这是这一天中的第%d秒。\n", secondOfDay(t[i])); //(4)输出这是这一年中的第几秒; printf("这是这一年中的第%d秒。\n", dayOfYear(t[i])*24*3600+secondOfDay(t[i])); } return 0; }
请体会上面的测试数据的设计,也可以设计出更好的来
再来第(5)个要求,测试数据的设计需要更动动脑子
关于实现功能而言,主体在Time afterDays(struct Time t,int d)函数,这个求解有些麻烦,但是采用的算法统一从1月0日开始的思路,还是可以将复杂性降下来一些。#include <stdio.h> struct Time { int year; int month; int day; int hour; int minute; int second; }; //输入一个限定范围内的整型数值 int getNum(char *prompt, int min, int max) { int value=-1; printf("输入%s,范围[%d, %d]:", prompt, min, max); do { scanf("%d", &value); } while(value<min || value>max); return value; } //返回y年m月的天数 int daysOfMonth(int m,int y) { int days; switch(m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days=31; break; case 4: case 6: case 9: case 11: days=30; break; case 2: if((y%4==0&&y%100!=0)||y%400==0) days=29; else days=28; } return days; } //这天是这一年的第几天 int dayOfYear(struct Time t) { int days=0; int m=1; while(m<t.month) //前若干月的天数加起来 { days+=daysOfMonth(m,t.year); //充分利用已经设计的函数 ++m; } days+=t.day; //再加上本月的天数 return days; } //输入时间,参数为指针,可以影响实参的值 void getTime(struct Time *p) { p->year=getNum("年",0,3000); //getNum()用于输入一定范围内的数 p->month=getNum("月",1,12); p->day=getNum("日",1,daysOfMonth(p->month, p->year)); p->hour=getNum("时",0,24); p->minute=getNum("分",0,59); p->second=getNum("秒",0,59); } //输出时间 void outputTime(struct Time t) { printf("时间为: %d年%d月%d日%d时%d分%d秒\n",t.year,t.month,t.day,t.hour,t.minute,t.second); } //这天是这一天的第几秒 int secondOfDay(struct Time t) { return t.hour*3600+t.minute*60+t.second; } //返回一年有多少天(365或366天) int daysOfYear(int y) { return ((y%4==0&&y%100!=0)||y%400==0)?366:365; } //求你输入的时间d天后是哪年哪月哪日 struct Time afterDays(struct Time t,int d) { struct Time t1=t; int d1=d+dayOfYear(t); //dayOfYear(t)求出t是当年第几天 t1.month=1; t1.day=0; //这样,将问题转换为在当年1月0日基础上加d1天(这个0有意思),避免以后老为2月操心,以及剩余天数一加以后持续进位 while(d1>daysOfYear(t1.year)) //天数还够一个整年 { d1-=daysOfYear(t1.year); ++t1.year; } //天数不够一整年后,再考虑月,因为从1月1日开始,不用担心Nt.year再加1年 while(d1>daysOfMonth(t1.month,t1.year)) //天数还够一个整月 { d1-=daysOfMonth(t1.month,t1.year); ++t1.month; } //剩全天数加到日上 t1.day+=d1; return t1; } int main() { int d[]= {68,365,366,798} ; //分别在一年内、恰1年(闰或不闰)、798(365+365+68)天时要复杂也最有说服力,考虑跨年、跨月,尤其有闰年时 struct Time nt,t[]= { {2001,1,8,0,0,0}, //没有时分秒的事,都0 {2012,2,20,0,0,0}, //2月是个敏感的月份 {2014,2,20,0,0,0}, //直接遇到闰年 {2013,4,20,0,0,0}, //过了2月 {2013,4,20,0,0,0}, //过了2月 {2013,12,10,0,0,0}, //近年关,稍加一点就下一年了,也测试下 }; //(5)求你输入的时间d天后是哪年哪月哪日 int i, j; for(i=0; i<7; ++i) for(j=0; j<4; ++j) { outputTime(t[i]); printf("这是这一年中的第%d天。\n", dayOfYear(t[i])); printf("这一天后%d天是:", d[j]); nt=afterDays(t[i],d[j]); outputTime(nt); printf("\n"); } return 0; }
最后的测试
在以上对函数的详细测试基础上,完成本项目中的工作,只需要下面的mian函数:int main()
{
struct Time t,nt;
//(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;
printf(“请输入一个时间(包括年,月,日,时,分,秒):\n”);
getTime(&t);
outputTime(t);
//(2)输出该日在本年中是第几天(注意闰年问题);
printf(“这是这一年中的第%d天。\n”, dayOfYear(t));
//(3)输出这是这一天中的第几秒;
printf(“这是这一天中的第%d秒。\n”, secondOfDay(t));
//(4)输出这是这一年中的第几秒;
printf(“这是这一年中的第%d秒。\n”, dayOfYear(t)*24*3600+secondOfDay(t));
//(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出;
int d;
printf(“请输入一个天数: “);
scanf(“%d”, &d);
nt=afterDays(t,d);
printf(“再过%d天, “, d);
outputTime(nt);
return 0;
}
“`
相关文章推荐
- 《C语言及程序设计》实践参考——学生成绩统计
- C++atoi与atof
- Introduce to algorithm-----pseudo code to C/C++ code (chapter 11)
- C语言中可变参数的用法
- C++ Primer学习笔记(8)——形参、局部变量、静态局部变量
- C++ 类的反汇编
- 《C语言及程序设计》实践项目——结构体应用
- 【c语言】 模拟实现库函数的atoi函数
- C++ 类中特殊的成员变量(常变量、引用、静态)的初始化方法 --转
- c语言 内存对齐用法
- 《C语言及程序设计》实践参考——紧急救援
- Ubuntu下用终端编译运行c++程序
- 《C语言及程序设计》实践参考——日期结构体
- 使用C++11thread实现的一道面试题(一)
- c++ 适配器
- 【C/C++相关】论程序员写技术博客的重要性
- c++函数解析
- stl之multiset容器的应用
- C语言之自定义__DATE__格式
- C++ && 汇编