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

package com.wener;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class HomeWork {
   public static void main(String[] args) throws IOException
   {
	  Scanner s = new Scanner(System.in);
	  
	   System.out.println("请输入年:");
	   int y =s.nextInt();
	   System.out.println("请输入月:");
	   int m =s.nextInt();
	   System.out.println("请输入日:");
	   int d =s.nextInt();
	   
	   if(y>=2010&&m<=12&&d<=31) {
		   FileWriter writer =new FileWriter("in.txt.txt",true);
		   writer.write(y+"-"+m+"-"+d);
		   writer.write("\r\n");
		   writer.close();
		   
	   int s0=0;//记录相差的天数
	   int s1=0;//记录这一年已经过去的天数
	   switch(m-1)
	   {
	   case 11:s1+=30;
	   case 10:s1+=31;
	   case 9: s1+=30;
	   case 8: s1+=31;
	   case 7: s1+=31;
	   case 6: s1+=30;
	   case 5: s1+=31;
	   case 4: s1+=30;
	   case 3: s1+=31;
	   case 2: if(y%4==0&&y%100!=0||y%400==0)
		       s1+=29;
	      else  s1+=28;
	   case 1: s1+=31;
	   }
	   s1+=d;
	  
	   if(y==2010)
	   {
		   s0=s1-1;
	   }else if(y>2010)
	   {
		  int s2=364;//计算2010年1月1日这一年还剩下多少天 (2010年为平年365天)
		  int s3=0;//统计相差的年份的整天数闰年366非闰年365
		  for(int i=2011;i<y;i++)
	      {
			  if(i%4==0&&i%100!=0||i%400==0) {
				  s3+=366;
		     }else {
			  s3+=365;
		     } 
	      }
		  s0=s1+s2+s3;
	   }
	   System.out.println(y+"-"+m+"-"+d+"与2010-1-1相差"+s0+"天");
	   if(s0%5==0||s0%5==1||s0%5==2)
	   { 
		   System.out.println(y+"年"+m+"月"+d+"日在打渔");
		   FileWriter writer1=new FileWriter("out.txt.txt",true);
		   writer1.write(y+"-"+m+"-"+d+"在打渔");
		   writer1.write("\r\n");
		   writer1.close();
	   }else {
		   System.out.println(y+"年"+m+"月"+d+"日在晒网");
		   FileWriter writer2 =new FileWriter("out.txt.txt",true);
		   writer2.write(y+"-"+m+"-"+d+"在晒网");
		   writer2.write("\r\n");
		   writer2.close();
	   }
	   }else {
		   System.out.println("输入日期有误,请输入2010-1-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,总数为120101月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、付费专栏及课程。

余额充值