三天打鱼,两天晒网(c++编写)

题目描述
中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三 天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。用C或C++语言实
现程序解决问题。
基本要求:程序风格良好(使用自定义注释模板),提供友好的输入输出。
提高要求:(1)输入数据的正确性验证。
(2)使用文件进行数据测试。如将日期 20100101 20111214 等数据保存在in.txt文件中,程序读入in.dat文件进行判定,并将结果输出至out.txt文件。

想法思路
问题解决分两步:1.确定两日期相隔日期l。2.通过判断l%5的值确定是在“打鱼”还是“晒网”。
确定相隔日期实现流程图如下:
l是间隔天数,y是年,m是月,d是天。
图 1 流程图
注释:l是间隔天数,y是年,m是月,d是天。

代码展示
基础代码:

#include < iostream >
using namespace std;
int y,m,d;                    //定义初始的年,月,日
int y_2,m_2,d_2;              //定义查询的年,月,日
int l=0;   //l为间隔天数
void time_interval()  //计算输入时间与2010/1/1的时间间隔
{
 for(y=2010;y<=y_2;y++)
 {
	 //输入年份不为此前运行的年份
  if(y<y_2)
  {

      if((y%4==0&&y%100!=0)||y%400==0)   //是闰年
	  l+=366;

      if(!((y%4==0&&y%100!=0)||y%400==0)) //不是闰年
	  l+=365;
  }

  //已经运行到了输入年份
   if(y == y_2)
   {
  	      if((y%4 == 0&&y%100!=0)||y%400 == 0)   //是闰年
		  {
	           for(m=1;m<=m_2;m++)
			   {
	               if (m<m_2)
				   {
	                    if(m == 1||m == 3||m == 5||m == 7||m == 8||m == 10||m == 12)
						{
		                      l+=31;
						}
	                    if(m == 4||m == 6||m == 9||m == 11)
						{
	                          l+=30;
						}
	                    if(m == 2)
						{
		                      l+=29;
						}
				   }
		           if(m==m_2)
				   {
		                      for(d=1;d<=d_2;d++)
				              l++;
				   }

			   }
		  }
	if(!((y%4==0&&y%100!=0)||y%400==0)) //不是闰年
   {
                 for(m=1;m<=m_2;m++)
				 {
	                	if(m<m_2)
						{
	                         if(m == 1||m == 3||m == 5||m == 7||m == 8||m == 10||m == 12)
							  {
		                          l+=31;
							  }
	                          if(m == 4||m == 6||m == 9||m == 11)
							  {
	                              l+=30;
							  }
	                          if(m == 2)
							  {
		                          l+=28;
							  }
						}
		                if(m==m_2)
						{
		                      for(d=1;d<=d_2;d++)
		                      l++;
						}
				 }
	}
   }
 }
    cout<<"间隔天数为:"<<l<<endl; 
}

void f_s()       //判断打鱼还是晒网
{
	 int r;     //余数
	 r=l%5;
	 if(r == 1 || r == 2 || r == 3)
	 {
		 cout<<"这天是在打鱼"<<endl;
	 }
	 else 
		 cout<<"这天是在晒网"<<endl;
 }
int main()
{
	cout<<"请输入年,月,日,以空格隔开"<<endl;
    cin>>y_2>>m_2>>d_2;
	time_interval();
	f_s();
	return 0;
}

提高程序主要改变:

freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
 cin>>y_2>>m_2>>d_2;
 time_interval();
 int r;     //余数
 r=l%5;
 if(r==1||r==2||r==3)
	 cout<<"这天是在打鱼"<<endl;
 else
	 cout<<"这天是在晒网"<<endl;
 return 0;

测试调试与结果截图
在这里插入图片描述
图2 基础程序数据正确性验证

部分调试如下图:(测试用例:2011/6/7)
在这里插入图片描述
图 3 数据输入调试
在这里插入图片描述
图 4 调试至 年,月均已循环至输入年,月
在这里插入图片描述
图 5 调试相隔天数l输出结果
在这里插入图片描述
图 6 提高程序文件输入
在这里插入图片描述
图 7 提高程序文件输出

感悟
看到题目,首先想到用Excel解决(类似蓝桥杯2013年省赛第一题),因为开始日期是2010年,所以在Excel可进行计算的日期范围内。不得不说,Excel很方便地解决了这个问题(因为1月1日是第一天,所以计算天数时要加1;求余要用mod(),刚开始用的“%”)。
接下来用编程实现,主要的思路就是确定两个日期的间隔天数(闰年,2月份需要注意),以5天为循环周期,根据余数确定是在5天周期里的第几天。采用的方法是暴力枚举,在编程的过程中,大括号出现太多,导致会出现缺大括号,大括号范围不清晰,程序可读性较差等问题。在编程中,也优化了一些地方,比如在完整月里计算日期,由刚开始的for循环,变成了直接“+=”。暴力枚举法会有一些你没有考虑到的情况,但在调试的过程中可以慢慢完善。程序过程中出现一个问题,当把2月累加完之后,3月没有2月累加的次数,感觉程序逻辑没有问题,就进行单步调试,发现特别小一个问题,原来是将等号写成了赋值号,所以当程序运行到这里时没有进行判断,而是直接赋值,导致跳过了2月。运行当前年份没问题后,开始用其他年份测试,发现天数不对,于是检查了下代码,原来还是等号与赋值号的问题,修改了后程序就正确了。继续优化,发现输入年份不为此前运行的年份时,根本不需要用for循环,直接+=整年数,减少了很多行代码
在这里插入图片描述
图 8 Excel计算两日期相隔日期
在这里插入图片描述
图 9 Excel计算余数
在这里插入图片描述
图 10 优化前
在这里插入图片描述
图 11 优化后
接下来完成提高要求,实现使用文件进行数据测试。
通过 https://www.bilibili.com/video/av67998822?from=search&seid=14370889792309226044
视频学习文件的输入输出,完成了提高要求。
“三天打鱼,两天晒网”这个题目帮助我巩固了之前学习的内容,同时也学习了新的内容(文件的输入输出)。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值