三天打鱼两天晒网问题
文件名称:三天打鱼两天晒网
编程语言:C++
编译器:Visual Studio 2019
完成日期:2021年3月21日
一、问题:
中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。用C或C++语言实现程序解决问题。
基本要求:1.程序风格良好(使用自定义注释模板),提供友好的输入输出。
提高要求:
1.输入数据的正确性验证。
2.使用文件进行数据测试。如将日期 20100101 20111214 等数据保存在in.txt文件中,程序读入in.dat文件进行判定,并将结果输出至out.txt文件。
二、设计思路:
根据题意,本题可理解为一个与周期有关的问题,由于“打鱼晒网”一共5天。因此所求是总天数对5取余的结果,如果结果是1或2或3则是在打渔,其余就是在晒网。
故将该题分为以下两个板块:
(1)计算从2010.1.1到指定日期共有多少天(这一部分是关键部分,其中涉及到某一年与2010年间是否有闰年,平年2月28天,闰年2月29天),可按照以下方法进行计算:先算某一年的1.1到2010.1.1共多少天,再计算某一年的某月某日到这一年的1.1共多少天,再将这两个结果相加即为总天数。
(2)计算总天数对5取余的结果,余数为1,2,3是在打渔,其余是在晒网。
三、概要设计
-
流程图:
-
主要设计:
共设计4个函数:判断输入数据是否合法的shuru()函数;计算指定日期到2010.1.1总天数的sum()函数;在in.txt文件中读取数据在in.dat文件进行判定,并将结果输出至out.txt文件的file()函数;以及主函数main()函数,在其中调用file(),并实现一些输入输出。
首先第一步是判断输入的数据是否合法,从三个方面判断:(1)年份是否大于2010年;(2)月份是否大于一月小于十二月;(3)日期中的日数是否小于对应月份的总天数
if (year<2010 || (month < 1 || month>12) || (month == 2 && (year % 4 != 0 || year % 400 != 0) && day >= 29) || day>Y[month]) {
cout << "输入错误,请重新输入!" << endl;
exit(-1);
第二步是主要步骤,即计算从2010.1.1到指定日期共有多少天。分为三个部分计算,第一部分是计算某一年的1.1到2010.1.1的总天数;第二部分是计算指定日期到这一年的一月一日共多少天;总天数即将这两部分相加。
第一部分需要考虑的问题是某一年与2010年间是否有闰年,有多少个闰年。
for (t; t < year; t++) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) //判定year为闰年还是平年,x=1为闰年,0为平年
{
x = 1;
d1 += 366;
}
else
{
x = 0;
d1 += 365;
}
}
年份的天数计算完了,现在开始计算此年中指定日期到1.1的天数。需要考虑的是,这一年是否为闰年,以及指定的月份是否大于2月。
需要定义一个数组来存储一年中十二个月每个月对应的总天数:
int Y[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
第二部分天数计算:
if ((year % 400 == 0)|| ((year % 4 == 0)&&(year % 100 != 0))) //判断这一年是否为闰年,m=1表示这一年是闰年,m=0表示不是
m = 1;
else
m = 0;
for (int u = 1; u < month; u++)
d2 += Y[month];
if ((m = 1) && (month > 2))
d2 = d2 + day + 1;
else
d2 = d2 + day;
d1,d2都算好后,现在可以得到总天数:
d3 = d1 + d2;
第三步就是有关文件的操作了,需要用到ofstream类和ifstream类,通过文件流对象进行操作。通过键盘将年月日日期输入保存到in.txt文件里,然后通过文件流对象的操作,读取in.txt里的内容并放到in.dat文件里进行数据的判定,读取出来后进行操作,调用一二步的两个函数,在读取日期数据后分别进行数据合法性的判断以及总天数的计算 以及判断是在打渔还是晒网,通过总天数对5取余的结果,余数为1、2、3是在打渔,其余是在晒网,最后将结果输出到out.txt文件里。
ifstream f1;
ofstream f2;
ofstream f3;
f1.open("C:\\Users\\wang\\in.txt");
f2.open("C:\\Users\\wang\\in.dat");
f3.open("C:\\Users\\wang\\out.txt");
f1 >> year; //将年月日数据保存在in.txt
f1 >> month;
f1 >> day;
//在in.dat中进行数据的判定
if (year<2010 || (month < 1 || month>12) || (month == 2 && (year % 4 != 0 || year % 400 != 0) && day >= 29) || day>Y[month])
f2 << "输入数据错误";
else {
f2 << year << "年";
f2 << month << "月";
f2 << day << "日";
}
shuru(year, month, day);
sum(year, month, day);
if (year == 0 || month == 0 || day == 0) //读取数据不合适则结束读取
{
exit(-1);
}
cout << year << "年" << month << "月" << day << "日" << endl; //输出从文件中读取的结果
cout << "这一天与2020.1.1相差" << d3 - 1 << "天"; //输出相差的总天数
if ((s == 1) || (s == 2) || (s == 3)) //通过对5取余的结果判断是打渔还是晒网,结果为1或2或3时是打渔,其他是晒网
{
f3 << year << "年" << month << "月" << day << "日" << " " << "这一天在打渔" << endl;
}
else
{
f3 << year << "年" << month << "月" << day << "日" << " " << "这一天在晒网" << endl;
}
f3.close(); //关闭f3文件
以上都完成后,就是关于main()函数的操作了,在main()中调用定义的文件操作函数,并提供一些输出语句:
int main() {
file();
cout << endl;
if (s > 0 && s < 4)
cout << "这一天在打渔" << endl;
else
cout << "这一天在晒网" << endl;
}
四、结果展示
- 输入一个正确日期
在in.txt中输入数据,in.dat中进行判定:
在out.txt中读取结果以及结果显示
- 输入一个错误日期
在in.txt中输入数据,in.dat中进行判定:
在out.txt中读取结果以及结果显示,此时out.txt中不会显示数据
五、总结
本人认为此次总体设计还算良好,但有些方面仍需要完善。比如可以设计一个类,包括year、month、day等成员变量,以及判断、计算天数、文件操作等成员函数,最后通过类去构造对象调用函数,进行操作。如有错误也欢迎大家进行指正。
最后附上本程序的完整代码:
#include <iostream>
#include<string>
#include<fstream>
using namespace std;
int year, month, day, x, m, i;
int Y[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
int d1 = 0;
int d2 = 0;
int d3;
int s = d3 % 5;
int t = 2010;
void shuru(int year, int month, int day) {
//前提:输入数据必须正确
if (year<2010 || (month < 1 || month>12) || (month == 2 && (year % 4 != 0 || year % 400 != 0) && day >= 29) || day>Y[month]) {
cout << "输入错误,请重新输入!" << endl;
exit(-1);
}
}
void sum(int year, int month, int day) {
//判断某一年与2010年之间是否有闰年 并计算从2010年1月1日到某一年的1月1日共多少天
for (t; t < year; t++) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) //判定year为闰年还是平年,x=1为闰年,0为平年
{
x = 1;
d1 += 366;
}
else
{
x = 0;
d1 += 365;
}
}
//计算某年中的某月某日到1月1日共多少天
if ((year % 400 == 0)|| ((year % 4 == 0)&&(year % 100 != 0))) //判断这一年是否为闰年,m=1表示这一年是闰年,m=0表示不是
m = 1;
else
m = 0;
for (int u = 1; u < month; u++)
d2 += Y[month];
if ((m = 1) && (month > 2))
d2 = d2 + day + 1;
else
d2 = d2 + day;
d3 = d1 + d2;
}
void file() {
ifstream f1;
ofstream f2;
ofstream f3;
f1.open("C:\\Users\\wang\\in.txt");
f2.open("C:\\Users\\wang\\in.dat");
f3.open("C:\\Users\\wang\\out.txt");
f1 >> year; //将年月日数据保存在in.txt
f1 >> month;
f1 >> day;
//在in.dat中进行数据的判定
if (year<2010 || (month < 1 || month>12) || (month == 2 && (year % 4 != 0 || year % 400 != 0) && day >= 29) || day>Y[month])
f2 << "输入数据错误";
else {
f2 << year << "年";
f2 << month << "月";
f2 << day << "日";
}
shuru(year, month, day);
sum(year, month, day);
if (year == 0 || month == 0 || day == 0) //读取数据不合适则结束读取
{
exit(-1);
}
cout << year << "年" << month << "月" << day << "日" << endl; //输出从文件中读取的结果
cout << "这一天与2020.1.1相差" << d3 - 1 << "天"; //输出相差的总天数
if ((s == 1) || (s == 2) || (s == 3)) //通过对5取余的结果判断是打渔还是晒网,结果为1或2或3时是打渔,其他是晒网
{
f3 << year << "年" << month << "月" << day << "日" << " " << "这一天在打渔" << endl;
}
else
{
f3 << year << "年" << month << "月" << day << "日" << " " << "这一天在晒网" << endl;
}
f3.close(); //关闭f3文件
}
int main() {
file();
cout << endl;
if (s > 0 && s < 4)
cout << "这一天在打渔" << endl;
else
cout << "这一天在晒网" << endl;
}