在编程练习中学会设计和使用测试程序

开发 架构 测试
本文给出一个示例,展示在程序设计过程中,怎样做到一边写程序,一边开展测试的过程,这样得到的程序中的各个“部件”可靠性得以保证。

这是我和我的学生们C++程序设计课程中的一个练习。程序编写得越来越大了,测试显得越来越重要,如果还是照着以前一直对照练习要求写程序,而不是按照工程要求去写,永远无法和实际工作去接轨。本文给出一个示例,展示在程序设计过程中,怎样做到一边写程序,一边开展测试的过程,这样得到的程序中的各个“部件”可靠性得以保证。

练习要求

【项目5-玩日期】

定义一个表示时间(包括年、月、日、时、分、秒)的结构体,然后完成下面的功能(可以在一个main函数中完成,也可以用函数求解,main函数调用即可):

(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;

(2)输出该日在本年中是第几天(注意闰年问题);

(3)输出这是这一天中的第几秒;

(4)输出这是这一年中的第几秒;

(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出;(你的万天日期靠这个功能了)——插讲一个故事。当年老贺由小孩儿过百日,想到自己的万日在哪天。编程计算,结果刚过了十几天,那个懊恼啊。第二个万日得再等26年多,第三个万日,谁敢说一定能过上?20岁左右的你,要算清楚了。在第(1)问中输入你的生日及时辰,d值取为10000,可以算出你的万日,大概在26岁多。

(6)求你输入的时间s秒后是何日何时,将结果保存在一个结构体变量中输出;

整体的考虑

***编好的程序的结构应该如下所示,其中所需要设计,一是存储数据所用的数据结构——结构体,二是整个程序的框架,除了main()函数之外,还要有一系列的其他函数作为支撑。在严格的软件工程中,需要提前将所需要的函数(工程中称之为模块)设计出来,而在学习语法阶段,不妨也便宜行事,需要什么写什么,这样做更快一些。在此基础上,main()函数只要按照题目中的要求,或输入,或调用函数,逐个地写出来即可。

所以,这个程序***的结构会是:

  1. #include <iostream>    
  2. using namespace std;    
  3. struct Time    
  4. {    
  5.     int year;    
  6.     int month;    
  7.     int day;    
  8.     int hour;    
  9.     int minute;    
  10.     int second;    
  11. };    
  12.     
  13.     
  14. //待设计的一大堆函数,是哪些,暂不考虑    
  15.     
  16. int main()    
  17. {    
  18.     Time t;    
  19.     //(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;    
  20.     cout<<"请输入一个时间(包括年,月,日,时,分,秒):"<<endl;    
  21.     getTime(t);  //输入将不会是很简单的一两条语句,写个函数完成    
  22.     outputTime(t);   //马上验证输入,很自地完成    
  23.     
  24.     
  25.     //(2)输出该日在本年中是第几天(注意闰年问题);    
  26.     cout<<"这是这一年中的第"<<dayOfYear(t)<<"天。"<<endl; //设计专门的函数完成    
  27.     
  28.     
  29.     //(3)输出这是这一天中的第几秒;    
  30.     cout<<"这是这一天中的第"<<secondOfDay(t)<<"秒。"<<endl;//设计专门的函数完成    
  31.     
  32.     
  33.     //(4)输出这是这一年中的第几秒;    
  34.     cout<<"这是这一年中的第"<<dayOfYear(t)*24*3600+secondOfDay(t)<<"秒。"<<endl;     
  35.     
  36.     
  37.     //(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出;    
  38.     cin>>d;    
  39.     cout<<"这一天后 ”<<d<<” 天是:"    
  40.     outputTime(afterDays(t,d));        
  41.     
  42.     
  43.     //(6)求你输入的时间s秒后是何日何时,将结果保存在一个结构体变量中输出;    
  44.     cin>>d;    
  45.     cout<<"这一时的后 ”<<s<<” 秒是:"    
  46.     outputTime(afterSeconds(t,s));        
  47.     
  48.     
  49.     //到此任务完成    
  50.     return 0;    
  51. }   
胖子是一口一口吃出来的,程序得一点一点写出来,做一些,就测试一点,保证局部不要出问题。不要妄图全写完了才去测试,医生说食物摄取过量,老百姓讲是吃撑了。

#p#

完成第(1)个要求,测试通过键盘输入进行即可

在这样一种指导思想下,先完成第(1)个要求,主要是写出自定义函数来。将需要多次用到的功能,例如,输入中要保证范围的要求,也“抽象”一下,做成函数getNum()。不少成员的取值范围是确定的,但每月的天数并不都一样有些麻烦,设计一个函数daysOfMonth()实现,将有利于整个程序的简洁。

参考代码可以如下:

  1. #include <iostream>    
  2. using namespace std;    
  3. struct Time    
  4. {    
  5.     int year;    
  6.     int month;    
  7.     int day;    
  8.     int hour;    
  9.     int minute;    
  10.     int second;    
  11. };    
  12.     
  13.     
  14. //输入一个限定范围内的整型数值    
  15. int getNum(char *prompt, int min, int max)    
  16. {    
  17.     int value=-1;    
  18.     cout<<"输入"<<prompt<<",范围["<<min<<","<<max<<"]:";    
  19.     do    
  20.     {    
  21.         cin>>value;    
  22.     }    
  23.     while(value<min || value>max);    
  24.     return value;    
  25. }    
  26.     
  27.     
  28. //返回y年m月的天数    
  29. //返回y年m月的天数    
  30. int daysOfMonth(int m,int y)    
  31. {    
  32.     int days;    
  33.     switch(m)    
  34.     {    
  35.     case 1:    
  36.     case 3:    
  37.     case 5:    
  38.     case 7:    
  39.     case 8:    
  40.     case 10:    
  41.     case 12:    
  42.         days=31;    
  43.         break;    
  44.     case 4:    
  45.     case 6:    
  46.     case 9:    
  47.     case 11:    
  48.         days=30;    
  49.         break;    
  50.     case 2:    
  51.         if((y%4==0&&y%100!=0)||y%400==0)    
  52.             days=29;    
  53.         else    
  54.             days=28;    
  55.     }    
  56.     return days;    
  57. }    
  58.     
  59.     
  60. //输入时间,参数为引用类型,可以影响实参的值    
  61. void getTime(Time &t)    
  62. {    
  63.     t.year=getNum("年",0,3000); //getNum()用于输入一定范围内的数    
  64.     t.month=getNum("月",1,12);    
  65.     t.day=getNum("日",1,daysOfMonth(t.month, t.year));    
  66.     t.hour=getNum("时",0,24);    
  67.     t.minute=getNum("分",0,59);    
  68.     t.second=getNum("秒",0,59);    
  69. }    
  70.     
  71.     
  72. //输出时间,参数也用作引用是对结构常见的处理办法    
  73. void outputTime(Time &t)    
  74. {    
  75.     cout<<"时间为: "<<t.year<<"年"<<t.month<<"月"<<t.day<<"日"<<t.hour<<"时"<<t.minute<<"分"<<t.second<<"秒"<<endl;    
  76. }    
  77.     
  78.     
  79. int main()    
  80. {    
  81.     Time t;    
  82.     //(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;    
  83.     cout<<"请输入一个时间(包括年,月,日,时,分,秒):"<<endl;    
  84.     getTime(t);    
  85.     outputTime(t);    
  86.     return 0;    
  87. }    

就写作业而言,从做练习的角度,程序就是完成了。要完成测试,关键是保证输入时数据取值范围是否能够得到保证,于是需要多次地启动程序,输入各种不同的时间,看是否能体现设计时的限制。需要考虑到的情形包括:

  • 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()函数这样写。

  1. int main()    
  2. {    
  3.     Time t;    
  4.     do    
  5.     {    
  6.         cout<<"请输入一个时间(包括年,月,日,时,分,秒):"<<endl;    
  7.         getTime(t);    
  8.         outputTime(t);    
  9.     }while(t.year>0); //输入0年某月某日测试即结束,测试过程由人可控    
  10.     return 0;    
  11. }    

这样,程序运行中的界面如下图,这只是测试所需要的一部分内容。这样测试出的程序,质量信心必涨!好产品得经过严格的测试,放在程序设计中也是这样。

 

#p#

完成第(2)个要求,测试通过不能再靠键盘输入

实现功能角度,增加一个函数dayOfYear()即可。涉及到测试时,要靠着键盘输入,那可就烦恼大了:改一点程序,输入若干数据测试,发现错误,改程序,再运行,输入测试数据。这时,可以采用的方法是,用测试用到的数据直接初始化结构体。再进一步,一组测试数据,一起测试,用结构体数组保存数据,测试过程做一个循环。

实现了的函数和测试用的main()函数如下所示,实现任务(1)中的函数保留不动,它们是整个任务中的一部分,况且(2)任务可能会用到前面的劳动成果,删除不必要。

参考程序如下:

  1. #include <iostream>    
  2. using namespace std;    
  3. struct Time    
  4. {    
  5.     int year;    
  6.     int month;    
  7.     int day;    
  8.     int hour;    
  9.     int minute;    
  10.     int second;    
  11. };    
  12.     
  13.     
  14. //输入一个限定范围内的整型数值    
  15. int getNum(char *prompt, int min, int max)    
  16. {    
  17.     int value=-1;    
  18.     cout<<"输入"<<prompt<<",范围["<<min<<","<<max<<"]:";    
  19.     do    
  20.     {    
  21.         cin>>value;    
  22.     }    
  23.     while(value<min || value>max);    
  24.     return value;    
  25. }    
  26.     
  27.     
  28. //返回y年m月的天数    
  29. int daysOfMonth(int m,int y)    
  30. {    
  31.     int days;    
  32.     switch(m)    
  33.     {    
  34.     case 1:    
  35.     case 3:    
  36.     case 5:    
  37.     case 7:    
  38.     case 8:    
  39.     case 10:    
  40.     case 12:    
  41.         days=31;    
  42.         break;    
  43.     case 4:    
  44.     case 6:    
  45.     case 9:    
  46.     case 11:    
  47.         days=30;    
  48.         break;    
  49.     case 2:    
  50.         if((y%4==0&&y%100!=0)||y%400==0)    
  51.             days=29;    
  52.         else    
  53.             days=28;    
  54.     }    
  55.     return days;    
  56. }    
  57.     
  58.     
  59. //输入时间,参数为引用类型,可以影响实参的值    
  60. void getTime(Time &t)    
  61. {    
  62.     t.year=getNum("年",0,3000); //用于输入一定范围内的数    
  63.     t.month=getNum("月",1,12);    
  64.     t.day=getNum("日",1,daysOfMonth(t.month, t.year));    
  65.     t.hour=getNum("时",0,24);    
  66.     t.minute=getNum("分",0,59);    
  67.     t.second=getNum("秒",0,59);    
  68. }    
  69.     
  70.     
  71. //输出时间,参数也用作引用是对结构常见的处理办法    
  72. void outputTime(Time &t)    
  73. {    
  74.     cout<<"时间为: "<<t.year<<"年"<<t.month<<"月"<<t.day<<"日"<<t.hour<<"时"<<t.minute<<"分"<<t.second<<"秒"<<endl;    
  75. }    
  76.     
  77.     
  78. //这天是这一年的第几天    
  79. int dayOfYear(Time &t)    
  80. {    
  81.     int days=0;    
  82.     int m=1;    
  83.     while(m<t.month)  //前若干月的天数加起来    
  84.     {    
  85.         days+=daysOfMonth(m,t.year);  //充分利用已经设计的函数    
  86.         ++m;    
  87.     }    
  88.     days+=t.day; //再加上本月的天数    
  89.     return days;    
  90. }    
  91.     
  92.     
  93. int main()    
  94. {    
  95.     //任务(2)输出该日在本年中是第几天(注意闰年问题);    
  96.     Time t[]=   //测试数据放在结构体数组中    
  97.     {    
  98.         {1971,1,8,14,25,48},  //最简单的一个测试数据,期望输出8    
  99.         {2011,2,27,14,25,48}, //2月,天数要加上1月的31天,期望输出31+27    
  100.         {2012,3,2,14,25,48},  //这个输入很敏感,看2月究竟算多少天,期望输出31+29+2=62    
  101.         {2013,3,2,14,25,48},  //这个期望输出是31+28+2=61    
  102.         {2013,4,10,14,25,48}  //期望结果100,这样的测试数据还可以继续列一些,期望结果要列出来,这是测试的依据    
  103.     };    
  104.     
  105.     
  106.     for(int i=0; i<5; ++i)   //测试过程用一个循环完成    
  107.     {    
  108.         outputTime(t[i]);    
  109.         cout<<"这是这一年中的第"<<dayOfYear(t[i])<<"天。"<<endl<<endl;    
  110.     }    
  111.     return 0;    
  112. }    

体会上面测试数据设计和测试程序(main()函数)设计中的用心,看下面运行测试的结果,生产好产品,需要这样做。

 

#p#

第(3)和(4)个任务容易实现,测试过程类似进行

只需要增加一个自定义函数

  1. //这天是这一天的第几秒    
  2. int secondOfDay(Time &t)    
  3. {    
  4.     return t.hour*3600+t.minute*60+t.second;    
  5. }    

相应的测试函数定义为:

  1. int main()    
  2. {    
  3.     Time t[]=    
  4.     {    
  5.         {1971,1,8,0,0,2},    
  6.         {2011,2,27,0,25,10},    
  7.         {2012,3,2,10,20,20},    
  8.         {2013,3,2,10,20,20},    
  9.         {2013,4,10,10,20,20}    
  10.     };    
  11.     
  12.     
  13.     for(int i=0; i<5; ++i)    
  14.     {    
  15.         outputTime(t[i]);    
  16.         //(3)输出这是这一天中的第几秒;    
  17.         cout<<"这是这一天中的第"<<secondOfDay(t[i])<<"秒。"<<endl;    
  18.         //(4)输出这是这一年中的第几秒;    
  19.         cout<<"这是这一年中的第"<<dayOfYear(t[i])*24*3600+secondOfDay(t[i])<<"秒。"<<endl<<endl;    
  20.     }    
  21.     return 0;    
  22. }    

请体会上面的测试数据的设计,也可以设计出更好的来

再来第(5)个要求,测试数据的设计需要更动动脑子

关于实现功能而言,主体在Time afterDays(Time t,int d)函数,这个求解有些麻烦,但是采用的算法统一从1月0日开始的思路,还是可以将复杂性降下来一些。

先上程序:

  1. #include <iostream>    
  2. using namespace std;    
  3. struct Time    
  4. {    
  5.     int year;    
  6.     int month;    
  7.     int day;    
  8.     int hour;    
  9.     int minute;    
  10.     int second;    
  11. };    
  12.     
  13.     
  14. //输入一个限定范围内的整型数值    
  15. int getNum(char *prompt, int min, int max)    
  16. {    
  17.     int value=-1;    
  18.     cout<<"输入"<<prompt<<",范围["<<min<<","<<max<<"]:";    
  19.     do    
  20.     {    
  21.         cin>>value;    
  22.     }    
  23.     while(value<min || value>max);    
  24.     return value;    
  25. }    
  26.     
  27.     
  28. //返回y年m月的天数    
  29. int daysOfMonth(int m,int y)    
  30. {    
  31.     int days;    
  32.     switch(m)    
  33.     {    
  34.     case 1:    
  35.     case 3:    
  36.     case 5:    
  37.     case 7:    
  38.     case 8:    
  39.     case 10:    
  40.     case 12:    
  41.         days=31;    
  42.         break;    
  43.     case 4:    
  44.     case 6:    
  45.     case 9:    
  46.     case 11:    
  47.         days=30;    
  48.         break;    
  49.     case 2:    
  50.         if((y%4==0&&y%100!=0)||y%400==0)    
  51.             days=29;    
  52.         else    
  53.             days=28;    
  54.     }    
  55.     return days;    
  56. }    
  57.     
  58.     
  59. //输入时间,参数为引用类型,可以影响实参的值    
  60. void getTime(Time &t)    
  61. {    
  62.     t.year=getNum("年",0,3000); //用于输入一定范围内的数    
  63.     t.month=getNum("月",1,12);    
  64.     t.day=getNum("日",1,daysOfMonth(t.month, t.year));    
  65.     t.hour=getNum("时",0,24);    
  66.     t.minute=getNum("分",0,59);    
  67.     t.second=getNum("秒",0,59);    
  68. }    
  69.     
  70.     
  71. //输出时间,参数也用作引用是对结构常见的处理办法    
  72. void outputTime(Time &t)    
  73. {    
  74.     cout<<"时间为: "<<t.year<<"年"<<t.month<<"月"<<t.day<<"日"<<t.hour<<"时"<<t.minute<<"分"<<t.second<<"秒"<<endl;    
  75. }    
  76.     
  77.     
  78. //这天是这一年的第几天    
  79. int dayOfYear(Time &t)    
  80. {    
  81.     int days=0;    
  82.     int m=1;    
  83.     while(m<t.month)  //前若干月的天数加起来    
  84.     {    
  85.         days+=daysOfMonth(m,t.year);  //充分利用已经设计的函数    
  86.         ++m;    
  87.     }    
  88.     days+=t.day; //再加上本月的天数    
  89.     return days;    
  90. }    
  91.     
  92.     
  93. //这天是这一天的第几秒    
  94. int secondOfDay(Time &t)    
  95. {    
  96.     return t.hour*3600+t.minute*60+t.second;    
  97. }    
  98.     
  99.     
  100. //返回一年有多少天(365或366天)    
  101. int daysOfYear(int y)    
  102. {    
  103.     return ((y%4==0&&y%100!=0)||y%400==0)?366:365;    
  104. }    
  105.     
  106.     
  107. //求你输入的时间d天后是哪年哪月哪日    
  108. Time afterDays(Time t,int d)    
  109. {    
  110.     Time t1=t;    
  111.     int d1=d+dayOfYear(t); //dayOfYear(t)求出t是当年第几天    
  112.     t1.month=1;    
  113.     t1.day=0;  //这样,将问题转换为在当年1月0日基础上加d1天(这个0有意思),避免以后老为2月操心,以及剩余天数一加以后持续进位    
  114. //    cout<<"转换为";    
  115. //    outputTime(t1);    
  116. //    cout<<"这一天后"<<d1<<"天。";    
  117.     while(d1>daysOfYear(t1.year))  //天数还够一个整年    
  118.     {    
  119.             d1-=daysOfYear(t1.year);    
  120.             ++t1.year;    
  121.     }    
  122.     //天数不够一整年后,再考虑月,因为从1月1日开始,不用担心Nt.year再加1年    
  123.     while(d1>daysOfMonth(t1.month,t1.year))  //天数还够一个整月    
  124.     {    
  125.             d1-=daysOfMonth(t1.month,t1.year);    
  126.             ++t1.month;    
  127.     }    
  128.     //剩全天数加到日上    
  129.     t1.day+=d1;    
  130.     return t1;    
  131. }    
  132.     
  133.     
  134. int main()    
  135. {    
  136.     int d[]={68,365,366,798} ; //分别在一年内、恰1年(闰或不闰)、798(365+365+68)天时要复杂也最有说服力,考虑跨年、跨月,尤其有闰年时    
  137.     Time nt,t[]=    
  138.     {    
  139.         {2001,1,8,0,0,0},   //没有时分秒的事,都0    
  140.         {2012,2,20,0,0,0},   //2月是个敏感的月份    
  141.         {2014,2,20,0,0,0},   //直接遇到闰年    
  142.         {2013,4,20,0,0,0},   //过了2月    
  143.         {2013,4,20,0,0,0},   //过了2月    
  144.         {2013,12,10,0,0,0},   //近年关,稍加一点就下一年了,也测试下    
  145.     };    
  146.     
  147.     
  148.     //(5)求你输入的时间d天后是哪年哪月哪日    
  149.     for(int i=0; i<7; ++i)    
  150.     for(int j=0;j<4;++j)    
  151.     {    
  152.         nt=afterDays(t[i],d[j]);    
  153.         outputTime(t[i]);    
  154.         cout<<"这是这一年中的第"<<dayOfYear(t[i])<<"天。";    
  155.         cout<<"这一天后"<<d[j]<<"天是:";    
  156.         outputTime(nt);    
  157.         cout<<"这是这一年中的第"<<dayOfYear(nt)<<"天。";    
  158.         cout<<endl<<endl;    
  159.     }    
  160.     return 0;    
  161. }    

接着看测试程序,将时间与要经过的天数进行组合,从输出中可以发现问题。当需要很多的测试数据时,期望结果实际上不能再由人手工计算,可以用一些辅助工具去完成。在一些数据库系统中,有类似的现成的函数(在写这个程序时企图用Wps 表格的公式,但不支持,记得Excel里有),还可以用系统函数计算的结果作对比,本文中,对用前面已经测试正确的函数dayOfYear(),通过输出日期是该年的第几天帮助找到线索。

另外,在上面的程序中,第114 - 116行加了注释的部分,体现出的也是一种调试的手段:运行过程中适当输出中间结果,进而判断计算过程是否达到预期。这种方法与单步执行相比,信息会来得快一些,不足之处是,信息有时有些太多,适宜于对程序内在执行机制很清楚的程序员,需要有志做这些工作的同学追求。有些编程环境中,缺乏调试工具的支持,这样的措施更显得必要了。用这种方式,***应将这些输出信息加上注释,不要成为代码中的一部分,或者干脆删除了事。

第(6)个任务和测试不再写,作为选做吧。

#p#

***,给出任务的***解答

有了经过测试的实现各功能的函数,只是将main()函数按要求写出即可,这样不管有什么样的输入,都不怕它耍着小脾气,输出错结果了。

贴程序:

  1. #include <iostream>    
  2. using namespace std;    
  3. struct Time    
  4. {    
  5.     int year;    
  6.     int month;    
  7.     int day;    
  8.     int hour;    
  9.     int minute;    
  10.     int second;    
  11. };    
  12.     
  13.     
  14. //输入一个限定范围内的整型数值    
  15. int getNum(char *prompt, int min, int max)    
  16. {    
  17.     int value=-1;    
  18.     cout<<"输入"<<prompt<<",范围["<<min<<","<<max<<"]:";    
  19.     do    
  20.     {    
  21.         cin>>value;    
  22.     }    
  23.     while(value<min || value>max);    
  24.     return value;    
  25. }    
  26.     
  27.     
  28. //返回y年m月的天数    
  29. int daysOfMonth(int m,int y)    
  30. {    
  31.     int days;    
  32.     switch(m)    
  33.     {    
  34.     case 1:    
  35.     case 3:    
  36.     case 5:    
  37.     case 7:    
  38.     case 8:    
  39.     case 10:    
  40.     case 12:    
  41.         days=31;    
  42.         break;    
  43.     case 4:    
  44.     case 6:    
  45.     case 9:    
  46.     case 11:    
  47.         days=30;    
  48.         break;    
  49.     case 2:    
  50.         if((y%4==0&&y%100!=0)||y%400==0)    
  51.             days=29;    
  52.         else    
  53.             days=28;    
  54.     }    
  55.     return days;    
  56. }    
  57.     
  58.     
  59. //输入时间,参数为引用类型,可以影响实参的值    
  60. void getTime(Time &t)    
  61. {    
  62.     t.year=getNum("年",0,3000); //用于输入一定范围内的数    
  63.     t.month=getNum("月",1,12);    
  64.     t.day=getNum("日",1,daysOfMonth(t.month, t.year));    
  65.     t.hour=getNum("时",0,24);    
  66.     t.minute=getNum("分",0,59);    
  67.     t.second=getNum("秒",0,59);    
  68. }    
  69.     
  70.     
  71. //输出时间,参数也用作引用是对结构常见的处理办法    
  72. void outputTime(Time &t)    
  73. {    
  74.     cout<<"时间为: "<<t.year<<"年"<<t.month<<"月"<<t.day<<"日"<<t.hour<<"时"<<t.minute<<"分"<<t.second<<"秒"<<endl;    
  75. }    
  76.     
  77.     
  78. //这天是这一年的第几天    
  79. int dayOfYear(Time &t)    
  80. {    
  81.     int days=0;    
  82.     int m=1;    
  83.     while(m<t.month)  //前若干月的天数加起来    
  84.     {    
  85.         days+=daysOfMonth(m,t.year);  //充分利用已经设计的函数    
  86.         ++m;    
  87.     }    
  88.     days+=t.day; //再加上本月的天数    
  89.     return days;    
  90. }    
  91.     
  92.     
  93. //这天是这一天的第几秒    
  94. int secondOfDay(Time &t)    
  95. {    
  96.     return t.hour*3600+t.minute*60+t.second;    
  97. }    
  98.     
  99.     
  100. //返回一年有多少天(365或366天)    
  101. int daysOfYear(int y)    
  102. {    
  103.     return ((y%4==0&&y%100!=0)||y%400==0)?366:365;    
  104. }    
  105.     
  106.     
  107. //求你输入的时间d天后是哪年哪月哪日    
  108. Time afterDays(Time t,int d)    
  109. {    
  110.     Time t1=t;    
  111.     int d1=d+dayOfYear(t); //dayOfYear(t)求出t是当年第几天    
  112.     t1.month=1;    
  113.     t1.day=0;  //这样,将问题转换为在当年1月0日基础上加d1天(这个0有意思),避免以后老为2月操心,以及剩余天数一加以后持续进位    
  114. //    cout<<"转换为";    
  115. //    outputTime(t1);    
  116. //    cout<<"这一天后"<<d1<<"天。";    
  117.     while(d1>daysOfYear(t1.year))  //天数还够一个整年    
  118.     {    
  119.         d1-=daysOfYear(t1.year);    
  120.         ++t1.year;    
  121.     }    
  122.     //天数不够一整年后,再考虑月,因为从1月1日开始,不用担心Nt.year再加1年    
  123.     while(d1>daysOfMonth(t1.month,t1.year))  //天数还够一个整月    
  124.     {    
  125.         d1-=daysOfMonth(t1.month,t1.year);    
  126.         ++t1.month;    
  127.     }    
  128.     //剩全天数加到日上    
  129.     t1.day+=d1;    
  130.     return t1;    
  131. }    
  132.     
  133.     
  134. int main()    
  135. {    
  136.     Time t,nt;    
  137.     //(1)输入一个时间(注意各部分数据的取值范围)将输入的时间保存在一个结构体变量中;    
  138.     cout<<"请输入一个时间(包括年,月,日,时,分,秒):"<<endl;    
  139.     getTime(t);    
  140.     outputTime(t);    
  141.     //(2)输出该日在本年中是第几天(注意闰年问题);    
  142.     cout<<"这是这一年中的第"<<dayOfYear(t)<<"天。"<<endl;    
  143.     //(3)输出这是这一天中的第几秒;    
  144.     cout<<"这是这一天中的第"<<secondOfDay(t)<<"秒。"<<endl;    
  145.     //(4)输出这是这一年中的第几秒;    
  146.     cout<<"这是这一年中的第"<<dayOfYear(t)*24*3600+secondOfDay(t)<<"秒。"<<endl;    
  147.     //(5)求你输入的时间d天后是哪年哪月哪日,将结果保存在一个结构体变量中输出;    
  148.     int d;    
  149.     cout<<"请输入一个天数";    
  150.     cin>>d;    
  151.     nt=afterDays(t,d);    
  152.     cout<<"这一天后10000天是:";    
  153.     outputTime(nt);    
  154.     //(6)求你输入的时间s秒后是何日何时,将结果保存在一个结构体变量中输出;    
  155.     
  156.     
  157.     return 0;    
  158. }    

看下面的运行结果,老贺自己错过了1万天的庆祝,弟子们要记着老贺过2万天请客的时候,都来随个份子。

 

【项目5扩展(选做】用结构体变量给定两个时间,求(1)相差多少天?(2)相差多少秒?(略)

原文链接:http://blog.csdn.net/sxhelijian/article/details/8655466

责任编辑:林师授 来源: 迂者-贺利坚的博客
相关推荐

2009-06-17 09:01:29

Linuxshell特殊字符

2024-08-07 08:40:46

2014-12-23 11:16:43

程序员

2022-07-22 10:09:28

架构设计

2022-07-26 12:33:38

架构设计场景

2015-11-10 12:32:58

编程快乐程序员

2011-11-07 09:56:17

HTML 5

2024-11-08 08:56:01

2012-07-11 11:05:16

编程

2023-10-26 09:17:48

算法编程

2017-12-06 08:01:52

程序员编程代码

2023-08-01 07:27:42

Mockito测试Callback

2011-08-24 09:13:40

编程

2010-03-26 17:34:29

Python历史

2016-03-21 10:33:01

编程浪费时间

2009-07-01 18:05:54

JSP中文乱码

2019-07-01 11:16:08

Google程序员编程

2022-12-22 08:01:09

Vue测试库测试

2023-11-10 00:05:50

GORM分页排序

2018-03-09 12:41:46

人工智能雨花台中学雨中
点赞
收藏

51CTO技术栈公众号