利用C++实现“三天打鱼两天晒网”问题

新人的第一篇博客

问题描述

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

设计思路

根据题意可以将解题过程分为三步:
1)计算从2010年1月1日开始至指定日期共有多少天;
2)由于“打鱼”和“晒网”的周期为5天,所以将计算出的天数用5去除;
3)根据余数判断他是在“打鱼”还是在“晒网”;
计算两个日期之间天数的具体思路是:
假设2010年到输入年份都是平年,年份个数乘以365;
接着计算2010年到输入年份的闰年个数,和天数相加;
再来计算所在输入年份的天数,利用for语句叠加可得。其中需判断当前年份是否为闰年。
综上相加即为总天数。
上面判断闰年的方法是:能被100整除且要能被400整除 或者 不能被100整除且能被4整除。

算法设计

下面一程序流程图的方式介绍我的算法思路。用户输入日期,先判断日期输入的正确性,若输入有误或者不符合常理,提示输入错误,若输入正确则将日期存入in.txt文件中;接着进行天数的计算,该部分是代码的核心;然后根据总天数判断是“打鱼”还是“晒网”,并将判断结果存入out.txt文件。具体见以下程序流程如。
在这里插入图片描述

源代码

	/*三天打鱼两天晒网思路分析:
	*(1)根据输入年份判断是否输入正确;
	*(2)将年份转化为天数;
	*(3)利用天数取余,天数除以5,若余数为1,2,3则为打鱼,否则为晒网;
	*
	* 利用C++面向对象设计实现
	*/
#include"iostream"
#include"fstream"
#include"string"
using namespace std;

class Date{
	//定义年月日
private:
	int year;
	int month;
	int day;
public:
	//构造函数
	Date(int y,int m,int d)
	{
		year=y;
		month=m;
		day=d;
	}
	int calculatedays();//计算天数
	string judge();       //判断是打鱼还是晒网
	bool leapyear();    //判断是否为闰年

	void intxt();        //信息保存文件
	void outtxt();       //结果输出文件
};
	string Date::judge()     //判断是打鱼还是晒网
	{
		if(calculatedays()%5<=3)//求余判断打鱼还是晒网
				return"打鱼";
			else return"晒网";
	}

bool Date::leapyear()       //判断闰年
	{
		if((year%100!=0&&year%4==0)||year%100==0&&year%400==0)
			return true;
		else false;
	}
int Date::calculatedays()    //计算天数
	{
		int yeardays=0;  //累加天数

		/**从2010到前一年最后一天所有天数的累加
		*  计算2010到前一年的年数和闰年的个数即可求得天数,即:
		*  (所在年-2010)*365即为天数
		*  另外还得加上闰年多出的一天,即求出闰年的个数并加到天数中即可求得
		*/

		yeardays=(year-2010)*365;
		int m=0;       //闰年个数
		    //计算闰年个数
		for(int j=2010;j<year;j++)
			if(j%100!=0&&j%4==0||j%100==0&&j%400==0)
				m++;

		/**当前年份天数累加
		*  累加所在月前所有月的天数在加上日的天数
		*/
		int month1[12]={0,31,28,31,30,31,30,31,31,30,31,30};
		for(int i=1;i<=month;i++)    //前面月份天数累加
			yeardays+=month1[i-1];
		if(month>2&&leapyear()==true)         //判断所在年是否为闰年
			yeardays++;
		return yeardays+day+m;
	}
 
void Date::intxt()
	{
		ofstream intxt("in.txt",ios::app);
		if(!intxt)
		{
			cerr<<"open error!"<<endl;
			exit(1);
		}
		intxt<<year<<" "<<month<<" "<<day<<"   ";
		intxt.close();
	}

void Date::outtxt()
	{
		ofstream outtxt("out.txt",ios::app);
		if(!outtxt)
		{
			cerr<<"open error!"<<endl;
			exit(1);
		}
		outtxt<<judge();
		outtxt.close();
	}

	int main()
	{
		while(1)
		{
			cout<<"请输入年份(如2010 04 23)"<<endl;
			int year,month,day;  //输入年月日
			cin>>year;
			cin>>month;
			cin>>day;
			/**判断年月日输入的正确性
			*年份须大于等于2010
			*月份不得小于1或大于12
			*日需考虑所在年是否为闰年,所在月份是30或31
			*/
			if(year<2010)        //判断年份输入的正确性
				{
					cout<<year<<month<<day;
					cout<<"年份输入错误"<<endl;
					return 0;
				}
			if(month<=0||month>12)//判断月份输入正确性
				{
						cout<<year<<month<<day;
					cout<<"月份输入错误"<<endl;
					return 0;
				}
			switch(month)        //判断日输入的正确性
				{
					case 1:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 2://闰年的话,日不等低于0或高于29;不是闰年的话,日不等低于0或高于28
						if(year%100!=0&&year%4==0||year%100==0&&year%400==0)
							if(day<0||day>29)
								 { cout<<"日输入错误"<<endl;
								return 0;}
							else break;
						else
							{
								if(day<0||day>28)
								 { cout<<"日输入错误"<<endl;
								return 0;}
								else break;
							}
					case 3:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 4:if(day<0||day>30)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 5:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 6:if(day<0||day>30)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 7:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 8:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 9:if(day<0||day>30)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 10:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 11:if(day<0||day>30)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					case 12:if(day<0||day>31)
							  { cout<<"日输入错误"<<endl;
								return 0;}
						   break;
					default:break;
				}
			Date date(year,month,day);
			date.intxt();          //将年月日读入文本文件
			cout<<"一共经历了"<<date.calculatedays()<<"天"<<endl;
			date.outtxt();         //将判断结果读入文本文件
			cout<<date.judge()<<endl;    //在控制台输出判断结果
			int m=1;

		}
		return 0;
	}

学习心得

这是一道很基础的编程练习题,尽管没有涉及到太多的算法,但也在实践过程中或多或少有许多技巧上的收获。利用C++面向对象的程序设计进行了封装,但在I/O流、文件读写方面掌握不够好,对于提高要求第二点并没有完全得做出来。
另外在先代码过程中,出现了一些低级语法错误,以及逻辑错误
编译错误:
1> error C2628: “Date”后面接“bool”是非法的(是否忘记了“;”?)
改正:Date类后花括号少了问号,在花括号后添加分号;
逻辑错误:
1>输出的天数并非理想预期;
for(int i=1;i<=month;i++)
yeardays+=month1[i-1]+day;
原因:重复叠加日天数;
修改:去掉+day
2>月份数组的定义错误
int month1[12]={31,28,31,30,31,30,31,31,30,31,30,31};
原因:应叠加之前月份的天数
修改:int month1[12]={0,31,28,31,30,31,30,31,31,30,31,30};
本次最大的收获在于第一次学会使用调试的方法,通过设置断点(按F11),再按F5移动断点,观察局部变量的值和自己预期的值比较,大大提高了编程的效率。
在日期测试方面,本人只简单地将日期存入in文本和将判断结果存入out文本,并没有读取in文本的日期。似乎自己知道是怎么一回事,不过还是由于种种原因自己没有编写。
这是第一次发博客,希望通过以后的坚持,不断得规范自己的编程风格,提高编程技能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值