新人的第一篇博客
问题描述
中国有句俗语叫“三天打鱼两天晒网”。某人从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文本的日期。似乎自己知道是怎么一回事,不过还是由于种种原因自己没有编写。
这是第一次发博客,希望通过以后的坚持,不断得规范自己的编程风格,提高编程技能。