三天打渔两天晒网(带流程图,及文件读取输出)
国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。用C或C++语言实现程序解决问题。
1.算法分析:
对于该问题的求解,以及整体的算法设计可分为以下几部分:
1.首先判断输入的年月日信息是否符合规定,若符合则计算给定的年月日到2010年1月1日共经过了多少天。在此步骤中,要注意判断到用户输入的日期之间有没有闰年。
如果: (year%400=0||(year %4==0 && year%100!=0))
则:该年份为闰年 2月有29天 Days[2]+=1
否则:该年份为平年 2月有28天
2.由于三天打渔,两天晒网。一个轮回的周期一共是五天,所以要判断是在打渔还是晒网只需要判断总天数除以5的余数。
If totalDays%5=1,2,3
则:该天打渔中
否则:该天晒网中
使用文件进行数据测试,如将日期 20100101 20111214 等数据保存在in.txt文件中
#include <iostream>
#include <fstream>
using namespace std;
class Date {
public :
int year; //在Date类中定义年月日,总天数变量
int month;
int day;
int totalDays;
int Days[13]; //利用Days数组保存每个月对应的天数
int res;
Date(); //定义构造函数
int RunNian(); //判断是否为闰年函数
int KeyboardInput(); //键盘输入函数
int FileInput(); //文件输入函数
};
Date::Date() //构造函数对Date类中的变量进行初始化
{
year = 0;
month = 0;
day = 0;
totalDays = 0;
res = 0;
int Days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //Days[0]赋值0便于下标对应月份
}
int Date::RunNian() //判断是否为闰年的函数
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) //当输入年份是闰年时,在二月份日期基础上加一天
{
Days[2] += 1;
}
for (int i = 2010; i < year; i++) //利用for循环判断给定的日期是否为闰年
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
totalDays += 366; //闰年的总天数
} else {
totalDays += 365; //平年总天数
}
}
for (int i = 1; i < month; i++) {
totalDays += Days[i]; //总天数加上对应月的天数
}
totalDays += day; //加上day
//1 cout<<"test:totaldays"<<totalDays<<endl; //测试总
res = totalDays % 5; //res来存储总天数除5后的余数
totalDays = 0;
return res;
}
int Date::KeyboardInput() { //键盘输入函数
cout << "请输入年份" << endl;
cin >> year;
cout << "请输入月份" << endl;
cin >> month;
cout << "请输入日" << endl;
cin >> day;
if (year < 2010 || month <= 0 || month > 12 || day < 1) //判断输入的年月日是否合法
{
cout << "日期输入有误" << endl;
cout << "请重新输入年份,请输入2010以后的某年(包含2010)" << endl;
cin >> year;
cout << "请输入月份,请输入1-12的有效月份(包含1和12)" << endl;
cin >> month;
cout << "请输入日,请输入对应月份天数范围内的数字" << endl;
cin >> day;
}
RunNian(); //调用判断闰年函数
if (res > 0 && res < 4) {
cout << "打渔中" << endl;
} else {
cout << "晒网中" << endl;
}
return res;
}
int Date::FileInput() { //文件读取函数
int a, b;
FILE *fin = fopen("in.text", "w");
FILE*fout=fopen("out.text","w");
cout << "请向文件中输入年月日信息" << endl;
cout << "输入日期(格式201056)";
cin >> a;
fprintf(fin, "%d", a); //向文件中写入日期的值
fscanf(fin, "%d", &a); //从文件中读取数值并赋值给变量a
//cout<<a<<endl; //测试a的值
year = a / 100; //由于写入文件的数据是整行所以利用位数分解的思想分解为年月日赋值
month = a / 10 % 10;
day = a % 10;
//cout<<year<<" "<<month<<" "<<day<<endl;
if (year < 2010) //判断年
{
cout << "年份输入有误,请输入2010以后的某年(包含2010)" << endl;
cin >> year;
} else if (month <= 0 || month > 12) //判断月
{
cout << "月份输入有误,请输入1-12的有效月份(包含1和12)" << endl;
cin >> month;
} else if (day < 1) //判断日
{
cout << "天数输入有误,请输入对应月份天数范围内的数字" << endl;
cin >> day;
}
int t = RunNian();
if (t > 0 && t < 4) {
cout << "打渔中" << endl;
fprintf(fout, "%s", "打渔中"); //输出渠道,将字符串打渔中写入out.txt文件
} else {
cout << "晒网中" << endl;
fprintf(fout, "%s", "晒网中");
}
return 0;
}
int main() {
Date d; //生成Date类对象
int a; //用于存放选项
cout << "请选择数据输入方式" << endl;
cout << "1.键盘输入" << endl;
cout << "2.文件输入" << endl;
cin >> a;
switch (a) {
case 1:
d.KeyboardInput();
break;
case 2:
d.FileInput();
break;
default:
cout << "请选择有效的选项" << endl;
}
return 0;
}
程序流程图
3.测试(设计测试用例或测试代码的设计与实现,测试结果截屏))
Test1:键盘输入数据测试程序
输入数据:2020年5月6日
运行结果:打渔中
Test2:测试如果输入不合法的日期,系统是否可以发现异常,并进行相应的处理
测试输入:
根据Degbug结果,程序在接收到非法数据时,成功进行的判断,并提示用户重新输入,对年份的非法数据,进行了合法的更新。
Test3:文件输入测试
选择文件输入模式,为文件写入年月日,经过判断后将结果写回文件
文件中成功的写入数据,保存了判断后的结果,说明文件输入输出功能正常运行。
4.调试
对于该程序中需要调试及判断的有以下几个方面:
a.totalDays的计算是否正确
b.年月日是否可正确赋值
采用Debug 在RunNian()函数中totalDays处设置断点,测试相应变量的值是否正确
根据调试结果年月日皆被正确赋值,totalDays的计算结果也正确。
c.依据totalDays的值,测试闰年的判断是否正确
在判断闰年循环体中设置断点,输入年份为2020
根据Debug结果可以清楚看到,再输入值2020时,成功判断为闰年,totalDays的值为366
心得体会
在本次程序的编写中,更清晰的了解到程序编写的流程与思想。首先对问题要进行分析,对解题的算法进行设计,根据算法的需求进行代码编写,最后进行数据测试和程序调试。在出现问题后积极思考。在此次的实践中,了解和掌握了Debug的使用,对程序的健壮性有了更全面的认识。