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)根据余数判断他是在“打鱼”还是在“晒网”;
在这三步中,关键是第一步。可以利用ctime中的tm结构体输入年月日,然后将结构体转换为time_t类型与20100101转换成的time_t求差值,差值再除以86400即为间隔天数。

流程图

c++与三天打鱼两天晒网相关

代码

头文件

#pragma once
#include<iostream>
#include<string>
#include<fstream>
#include<ctime>
using namespace std;

int judge(string);

int calculate(string);

int judgedate(int, int, int);

函数实现

#include"head.h"

int judge(string s)//判断字符串是否合法
{
	int len;
	int y, m, d;//定义年月日
	len = s.size();//求字符串长度
	if(len != 8) return 0;//正确的字符串长度应该为8
	for(int i=0;i<8;i++)
	{
		if (s[i] < 48 || s[i]>57) return 0;//判断字符串中是否有非数字
	}
	y = (s[0] - 48) * 1000 + (s[1] - 48) * 100 + (s[2] - 48) * 10 + (s[3] - 48);//数字ASCII码-48即为对应的数值
	m = (s[4] - 48) * 10 + (s[5] - 48);
	d = (s[6] - 48) * 10 + (s[7] - 48);
	if (judgedate(y, m, d)) return 1;
	else return 0;
}

int judgedate(int y, int m, int d)//判断年月日是否规范
{
	if (y < 2010) return 0;
	int leap;
	if (m < 1 || m>12) return 0;
	if ((y % 400 == 0) || (y % 4 == 0 && y % 100 != 0)) leap = 1;//判断是否闰年,leap为1则表示为闰年
	else leap = 0;//leap0为表示为平年
	if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12)  //1,3,5,7,8,10,12有31天。。
	{
		if (d<=0 || d > 31)
		{
			return 0;
		}
	}
	else if (m == 4 || m == 6 || m == 9 || m == 11)   //4,6,9,11有30天
	{
		if (d<= 0 || d > 30)
		{
			return 0;
		}
	}
	else 
	{
		if (leap)	
		{
			if (d <= 0 || d > 29) return 0;
		}
		else 
		{
			if (d <= 0 || d > 28) return 0;
		}
	}
}

int calculate(string s)//计算日期
{
	int y, m, d,sec,interval;
	tm t1 = { 0 };
	tm t2 = { 0 };
	y = (s[0] - 48) * 1000 + (s[1] - 48) * 100 + (s[2] - 48) * 10 + (s[3] - 48);
	m = (s[4] - 48) * 10 + (s[5] - 48);
	d = (s[6] - 48) * 10 + (s[7] - 48);
	t1.tm_year = 2010 - 1900; t1.tm_mon = 1; t1.tm_mday = 1;//  计算的日期是20100101
	t2.tm_year = y - 1900; t2.tm_mon = m; t2.tm_mday = d;//  将输入的日期转化为tm结构体

	sec = difftime(mktime(&t2), mktime(&t1));//转换结构体为time_t,利用difftime,计算时间差  

	interval= sec / 86400 ;//间隔秒数除以86400即为间隔天数,因为一天有86400秒(60*60*24)
	if (interval % 5 > 4 && interval % 5 < 3) return 0;
	else return 1;
}

主函数

#include"head.h"

int main()
{
	string a,b;
	fstream f1, f2;
	f1.open("in.txt", ios::app);
	f2.open("out.txt", ios::app);
	cout << "请输入要查询的日期" << endl;
	cin >> a;
	f1 << '\n' << a;//将字符串输入in.txt
	f1.close();
	f1.open("in.txt", ios::in);
	while(!f1.eof())
	{
		f1 >> b;
	}
	if (judge(b))//从in.txt读取刚才输入的字符串,判断是否合法
	{
		if (calculate(b))
		{
			f2 << '\n' << b << "打渔";
			cout << "打渔" << endl;
		}
		else
		{
			f2 << '\n' << b << "晒网";
			cout << "晒网" << endl;
		}
	}
	else
	{
		cout << "error" << endl;//提示错误信息
		f2 << '\n' << b << "查询日期不合规范";
		f2.close();
	}
	system("pause");
	return 0;
}

运行结果

c++与三天打鱼两天晒网相关

心得体会

采用了8位数字的字符串的形式进行字符串的输入,在将字符串还原为数字时,数字的值为ASCII码所代表的值,需要减去48才是本来的值。