中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。

问题描述:中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。

/*
 *  作者:cloud9
 *  日期:2019.2.27
 *
 *  问题描述:中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,
 *  问这个人在以后的某一天中是“打鱼”还是“晒网”。
 *
 *  
 *
 *
*/


我的思路是先算从2010.1.1日到给定年限的前一年共有多少天,再加上给定年的天数,得到总天数,再用总天数
对5求模,如果余1,2,3则说明在打渔否则说明在晒网。但是这么算有一个问题——在大于2010年后会多算一天。
原因在于我们会将给定日期的那一年的1月1日算两次。因为从2010.1.1到2011.1.1才有365天,但是我在单独
计算2011年到某月某日有多少天时又把2011.1.1这一天计算了一次。




#include<iostream>
#include<fstream>
#include<cstdlib>
const int MON_N = 13;
using namespace std;


int a[MON_N] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

ofstream out;
ifstream infile;

int main(int argc, char const *argv[])
{	
	int Judge(const int & year1,const int & month1,const int & day1);		//函数原型声明
	int year,month,day;
	infile.open("in.txt");
	if(infile.is_open())
	{
		cout << "infile打开文件成功" << endl;
	}
	out.open("out.txt");
	if (out.is_open())
	{
		cout << "out打开文件成功" << endl;
	}
	while (!infile.eof())
	{	
		infile >> year >> month >> day;
		if (year < 2010 || (month > 12 && month <= 0) || (day > 31 && day < 28))	//判断输入数据是否符合正常年月日的范围
		{
			out << "Error" << endl;
			break;
		}
		int flag = 0;
		flag = Judge(year, month, day);
		if (flag == 0)
		{
			out << "Fishing" << endl;
			cout << "Fishing" << endl;
		}
		else if (flag == 1)
		{
			out << "Sun net" << endl;
			cout << "Sun net" << endl;
		}
		else
			break;
	}
		infile.close();
		out.close();
		system("pause");
	return 0;
}



int	Judge(const int & year1,const int & month1,const int & day1)		//判断从2010.1.1到指定日期共经过了多少天,再求5的模根据余数判断是在打渔还是晒网
{	
	int sum_year = 0;
	for (int i = 2010; i < year1; i++)		/*计算从2010年到指定年限的前一年有多少天*/
	{
		if (i % 400 == 0 || (i % 4 == 0 && i % 100 != 0))		/*判断某一年是否是闰年,是闰年则加上366,不是则加上365*/												 
		{
			sum_year += 366;
		}
		else
			sum_year += 365;
	}
	if(!(year1 % 400 == 0 || (year1 % 100 != 0 && year1 % 4 == 0 )))
	{	
		if (month1 == 2 && day1 == 29)    /*判断当不是闰年出现2月29的情况下重新输入*/
		{
			out << "Error" << endl;
			return 2;
		}
	}
	else
	{
		if(month1 > 2)
			sum_year++;
	}
	for (int j = 0;j < month1 ;j++)
		{
			sum_year += a[j];
		}
	sum_year += day1;
	if (year1 > 2010)		/*因为在计算总天数时将输入年份的1月1日这一天计算了两次,因此要减去一天*/
		sum_year--;
	if (sum_year % 5 <= 3 && sum_year % 5 >= 1)		 /*当余数是1,2,3时,说明在打渔,否则在晒网*/
		return 0;
	else
		return 1;
}
<think>嗯,用户想用C语言编写一个程序来判断某天是打鱼还是晒网。根据引用中的例子,他们提到的基本逻辑是对天数取余数,然后判断余数落在哪个区间。比如,如果输入的天数除以5的余数在1到3之间,就是打鱼,否则是晒网。不过,用户的题可能更复杂,因为实际应用中可能需要处理具体的期,而不仅仅是天数。比如,用户可能输入一个期,比如20235月10,然后程序需要计算从20101月1到该期的总天数,再根据总天数来判断状态。 首先,我需要确认用户的需求。用户的题描述中提到“某人20101月1开始三天打鱼两天晒网’”,所以程序需要处理从该起始期到输入期的总天数差。然后根据总天数进行判断。如果用户只是输入天数,比如第N天,那么题比较简单,可以直接取模。但如果需要处理具体的期输入,就需要计算两个期之间的天数差,这涉及到闰的判断和月份天数的累加。 根据引用[1]和[2]中的例子,之前的回答可能只是处理了直接输入天数的情况,如引用[2]中的代码直接读取天数,没有涉及期计算。但用户现在可能希望处理具体的期输入,所以需要扩展程序的功能。 接下来,我需要考虑如何计算两个期之间的天数。这包括以下几个步骤: 1. 验证输入期的合法性,比如份不能小于2010,月份在1-12之间,期不超过该月的最大天数。 2. 计算从2010到输入份之间的整天数,注意闰的判断(能被4整除但不能被100整除,或者能被400整除)。 3. 计算输入份中的月份到输入期的天数,累加之前各个月份的天数。 4. 总天数减去1,因为从20101月1当天算作第1天。 5. 对总天数取模5,余数为1-3则为打鱼,否则晒网。 另外,还需要处理输入期的正确性验证,比如月份是否超过12,期是否超过当月的最大天数,比如2月要考虑闰,4月是否有31天等。这部分需要编写函数来检查。 对于文件操作,用户提到的提高要求中希望从文件读取输入并将结果输出到文件,这可能也是用户的需求之一。但根据当前题,用户可能暂时只需要基本功能,但可以提示扩展的可能性。 现在,需要将这些步骤转化为C语言代码。首先,主函数可能分为几个部分:输入期,验证期,计算总天数,判断状态,输出结果。 可能的函数包括: - isLeapYear(int year): 判断是否为闰。 - isValidDate(int year, int month, int day): 验证期是否合法。 - calculateTotalDays(int year, int month, int day): 计算总天数。 在计算总天数时,需要注意每个月的天数,尤其是2月的天数根据闰变化。比如,非闰2月28天,闰29天。 例如,计算从20101月1到20235月10的天数,需要先计算2010到2022的总天数,然后加上20231月到5月10的天数。 在编写代码时,可能需要使用循环来累加每的天数,以及每月的天数。例如,对于份从2010到year-1,判断是否为闰,累加365或366天。然后,对于输入的year,累加从1月到month-1的天数,再加上day的天数。 然后,总天数 = 每的天数总和 + 当前的天数 - 1(因为20101月1是第一天)。 然后,总天数 %5的结果,如果余数是1、2、3,则为打鱼,否则晒网。 测试时需要注意边界情况,比如20101月1当天是打鱼,余数为1%5=1,所以打鱼。第3天余数3,打鱼;第4天余数4,晒网;第5天余数0,晒网;第6天余数1打鱼。 现在,需要处理输入的题。用户可能需要输入期,格式可能是YYYYMMDD,或者分成、月、三个部分输入。根据引用[1]中的例子,输入数据可能保存在文件中,如in.txt,然后输出到out.txt。但用户当前的题可能只需要控制台输入。 在代码中,可以使用scanf来读取、月、,然后进行验证。如果期不合法,提示重新输入。 例如,用户输入20232月29,程序需要检测到2023不是闰,2月最多28天,因此提示错误。 综上所述,程序的步骤大致如下: 1. 输入期,并验证合法性。 2. 计算总天数。 3. 判断余数,输出结果。 现在,编写代码的大纲: 首先,定义函数判断闰: int isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } 然后,定义函数判断期合法: int isValidDate(int year, int month, int day) { if (year < 2010 || month <1 || month>12 || day <1) return 0; int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (isLeapYear(year)) monthDays[1] = 29; if (day > monthDays[month-1]) return 0; return 1; } 然后,计算总天数: int calculateTotalDays(int year, int month, int day) { int total = 0; // 计算2010到year-1的天数 for (int y = 2010; y < year; y++) { total += isLeapYear(y) ? 366 : 365; } // 计算当month之前的月份天数 int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (isLeapYear(year)) monthDays[1] = 29; for (int m = 1; m < month; m++) { total += monthDays[m-1]; } // 加上当月天数 total += day; // 减去1,因为2010-1-1是第1天 total -= 1; return total; } 主函数: int main() { int year, month, day; printf("请输入期(,空格分隔): "); scanf("%d %d %d", &year, &month, &day); if (!isValidDate(year, month, day)) { printf("期不合法!\n"); return 1; } int totalDays = calculateTotalDays(year, month, day); int remainder = totalDays % 5; if (remainder >=1 && remainder <=3) { printf("%d%d月%d打鱼\n", year, month, day); } else { printf("%d%d月%d晒网\n", year, month, day); } return 0; } 测试用例: 比如输入20101月1,总天数是1-1=0?或者计算时totalDays=0,然后+ day=1,然后 total -=1,得到0?此时余数是0,会被判断为晒网,但这与预期不符,因为第一天应该是打鱼。 哦,这里有个错误。因为根据引用[4]中的说明,余数为0对应的是第五天的结束,即第五天之后的那天(第6天余数是1),所以余数为0时应该对应晒网的第5天。但根据题描述,20101月1是第一天,余数总天数是从20101月1算起的天数-1吗? 比如,20101月1,总天数是0(因为totalDays计算时总天数是:从2010到year-1(即2009,没有),加上month之前的月份(0),加上day=1,然后减1得到0)。余数0%5=0,此时应该对应晒网,但实际第一天应该打鱼。 这说明计算总天数的方法有误。正确的总天数应该是从20101月1到输入期的总天数,包括输入期当天。例如,20101月1是第1天,余数1%5=1打鱼。而当前代码中,totalDays的计算是: total += year部分的天数,然后加上month部分,再加上day,然后减1。这相当于计算的是从20101月1到输入期的前一天的总天数。比如,20101月1当天,totalDays=0,余数0%5=0,会被错误判断为晒网题出在总天数的计算逻辑上。正确的总天数应该是从20101月1到输入期的总天数,包括输入期当天。因此,计算时不需要减1。例如,20101月1,总天数为1天;20101月2,总天数为2天,依此类推。 因此,修改calculateTotalDays函数中的total计算方式: // 正确的方式是直接累加所有天数,不需要减1 int calculateTotalDays(int year, int month, int day) { int total = 0; for (int y = 2010; y < year; y++) { total += isLeapYear(y) ? 366 : 365; } int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (isLeapYear(year)) monthDays[1] = 29; for (int m = 1; m < month; m++) { total += monthDays[m-1]; } total += day; // 直接加上当月的天数 return total; } 这样,20101月1的总天数是1天,余数1%5=1打鱼;第3天余数3%5=3,打鱼;第4天余数4%5=4,晒网;第5天余数0,晒网;第6天余数1打鱼。这样符合预期。 因此,需要修正代码中的总天数计算部分,去掉最后的减1。这样,余数的判断就正确了。 另一个需要注意的地方是闰的判断。例如,2012是闰,2月有29天,而2010不是闰。 测试案例: 比如,输入20101月5,总天数5天,余数5%5=0,晒网,正确。 输入20101月4,余数4%5=4,晒网。 输入20101月3,余数3%5=3,打鱼。 输入20101月6,总天数6天,余数1打鱼。 这样判断正确。 现在,在代码中,当计算总天数时,正确的方式是不减1,所以需要修改函数。 另外,在验证期合法性时,当用户输入的月份是2,比如20122月29,是否是闰,要正确判断。 综上,修改后的代码应该可以正确处理期,并计算正确的总天数,然后判断余数。 现在,用户的题可能需要这个完整的解决方案,包括期处理。而之前的引用中的代码可能只是处理了输入天数的情况,而用户可能需要处理具体的期输入。因此,回答应该包含完整的C语言代码,处理期输入,验证期,计算总天数,并判断状态。 最后,关于文件操作的部分,用户可能希望将输入输出重定向到文件,这可以通过标准C的文件操作函数实现,比如fscanf和fprintf,或者读取in.txt并写入out.txt。但根据用户的题,可能只需要控制台输入输出,所以这部分可以作为扩展功能,在相关题中提出。</think>### 解决思路 要判断某天是打鱼还是晒网,需要计算从20101月1起到目标期的总天数,再对总天数取余判断状态: 1. **期合法性验证**:份≥2010,月份1-12,期符合当月天数 2. **闰判断**:闰2月有29天 3. **总天数计算**: - 整天数累加(注意闰) - 当月份天数累加 4. **状态判定**:总天数对5取余,余数1-3为打鱼,0/4为晒网 ### 完整C语言代码 ```c #include <stdio.h> // 判断闰 int isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } // 验证期合法性 int isValidDate(int year, int month, int day) { if (year < 2010 || month < 1 || month > 12 || day < 1) return 0; int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (isLeapYear(year)) monthDays[1] = 29; return day <= monthDays[month-1]; } // 计算总天数 int calculateTotalDays(int year, int month, int day) { int total = 0; // 整累加 for (int y = 2010; y < year; y++) { total += isLeapYear(y) ? 366 : 365; } // 当月前月份累加 int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (isLeapYear(year)) monthDays[1] = 29; for (int m = 1; m < month; m++) { total += monthDays[m-1]; } return total + day; // 包含当天 } int main() { int year, month, day; printf("请输入期():"); scanf("%d %d %d", &year, &month, &day); if (!isValidDate(year, month, day)) { printf("期不合法!\n"); return 1; } int total = calculateTotalDays(year, month, day); int remainder = total % 5; if (remainder >= 1 && remainder <= 3) { printf("%d-%02d-%02d:打鱼\n", year, month, day); } else { printf("%d-%02d-%02d:晒网\n", year, month, day); } return 0; } ``` ### 运行示例 ``` 请输入期():2010 1 5 2010-01-05:晒网 请输入期():2023 8 15 2023-08-15:晒网 ``` ### 代码说明 1. `isLeapYear()`:使用闰判断标准公式 2. `isValidDate()`:通过预设月份天数表验证期合法性 3. `calculateTotalDays()`:通过两次循环分别计算整和当天数 4. 输出结果时使用`%02d`保证期格式统一
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值