C语言三天打鱼两天晒网(文件测试)

一.作业题目

三天打鱼两天晒网

二.作业内容

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

三.算法设计

1.检测输入时间的合法性
即年份需要不小于2010,月份不能大于12,日期不能大于31
2.设计函数用来判断闰年还是平年
闰年:能被4整除且不能被100整除或者能被400整除,闰年2月有29天
平年:2月28天
可以在算天数的函数中,定义一个二维数组来分开区别表示。

3.设计函数用来算2个时间之间的天数
3.1年份相同,月份相同,日期相减即可
3.2年份相同,月份不同。通过循环二维数组实现天数的累加,最后再加上本月的日期即可
3.3年份不同。
先算整年的天数进行累加,再算整月的天数进行累加,最后加上本月的日期
4.打鱼还是晒网
将天数除以5得余数
余数为1,2,3;则打鱼
余数为4,0;则晒网
代码如下:

#include <stdio.h> 
#include <stdlib.h>
struct Date
{
	int year;
	int month;
	int date;
};//声明结构体 

int main(void)
{
	struct Date maxDate;
	int days,tag,a,b,c;
	FILE *p,*f;
	 printf("请输入选择标志tag的值;tag为1是从键盘输入年月日,tag为0是从in.text中提取日期\n");
	 scanf("%d",&tag);
	 switch(tag)
	 {
	 	case 0:
	 		{
	 			FILE *p=fopen("in.txt","r");//用只读的方式打开文件in.txt
				FILE *f=fopen("out.txt","w");//用只写的方式打开文件out.txt
				while(!feof(p))
				{
					fscanf(p,"%d %d %d",&a,&b,&c);//从文件in.txt中读取数据年月日 
				    printf("%d年%d月%d日\n",a,b,c);
				    maxDate.year=a;
				    maxDate.month=b;
				    maxDate.date=c;
				   
					if (maxDate.year < 2010 || maxDate.month > 12 || maxDate.date > 31)
					printf("输入数据有误,请重新输入\n");
						else{
			                int Diff(struct Date maxDate);
							days = Diff(maxDate) + maxDate.date;//将Diff函数返回的day天数再加上本月的日期,即为2个时间之间的天数 
							printf("天数为:%d\n", days);//将天数输出 
							int yu = days % 5;
							switch (yu)   //利用switch语句,判断打鱼or晒网 
						   {
							case 1:
							case 2:
							case 3:
								printf("今天打鱼\n");
								fprintf(f,"%d %s %d %s %d %s",a,"年",b,"月",c,"日");//将判断及结果写入out.txt中                          
 								fprintf(f,"%s","他这天在打鱼\n");//输出打鱼 
								break;
							case 4:
							case 0:
								printf("今天晒网\n");//输出晒网 
								fprintf(f,"%d %s %d %s %d %s",a,"年",b,"月",c,"日");//将判断及结果写入out.txt中                          
 								fprintf(f,"%s","他这天在晒网\n");//输出晒网 
								break;	
							};
						
					};
					
			};
	 		break;
	 };
	 	case 1:{
	 		printf("请输入年月日\n");
	 		scanf("%d %d %d",&maxDate.year,&maxDate.month,&maxDate.date);
		 
		 if (maxDate.year < 2010 || maxDate.month > 12 || maxDate.date > 31)
					printf("输入数据有误,请重新输入\n");
		else
		{
			int Diff(struct Date maxDate);
							days = Diff(maxDate) + maxDate.date;//将Diff函数返回的day天数再加上本月的日期,即为2个时间之间的天数 
							printf("天数为:%d\n", days);//将天数输出 
							int n = days % 5;
							switch (n)   //利用switch语句,判断打鱼or晒网 
							{
							case 1:
							case 2:
							case 3:
								printf("今天打鱼");//输出打鱼 
								break;
							case 4:
							case 0:
								printf("今天晒网");//输出晒网 
								break;	
							};	
					};
			};
		}; 
};
				
	
int isPrime(int year)  //检查是否为闰年,闰年返回1,平年返回0
{
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
		return 0;
	else
		return 1;
};

int Diff(struct Date maxDate)  //计算日期 
{
	int day = 0, i, j;
	static int Month[2][13] = { {0,31,29,31,30,31,30,31,31,30,31,30,31},{0,31,28,31,30,31,30,31,31,30,31,30,31} };//设计一个二维数组来分开区别闰年和平年 
	if (maxDate.year == 2010)//将年份,月份都相同 和 年份相同,月份不同的两种情况进行合并 
		for (i = 1; i < maxDate.month; i++)//利用for循环二维数组,实现整月份天数累加 
			day += Month[1][i];
	else                                      //年份不同的情况相对复杂 
	{
		for (j = 2010; j < maxDate.year; j++)  //先从2010年向后到年份的前一年进行推算循环 
			day += isPrime(j) ? 365 : 366;     //利用双目条件运算符和判断闰年还是平年的函数,进行整年份的天数累加 
		for (i = 1; i < maxDate.month; i++)     //实现整月份的天数累加 
			day += Month[isPrime(maxDate.year)][i];
	};
	return day;                                
};

注意:输入in.txt文件和输出out.txt文件需要和.cpp文件放到一个工程中

四.心得体会

这个题目主要得难度是在天数得计算上,我开始想通过判断闰年就给day一个366,平年就给一个365,但是后来发现,如果年份是2011之后得年份,无法实现循环累加。然后通过查资料看到别人通过一个双目条件运算符?:对闰年平年进行0或1的标记,再结合for循环就可以很巧妙的实现整年份的累加。对于整月份的天数计算,我开始是定义了2个一维数组,然后根据闰年和平年来选择累加,这样也可以实现,不过比较繁琐,还需要写一个通过闰年平年标记选择用哪个数组的语句。看了别人的代码,觉得人家设计的很巧妙,只需要一个二维数组就可以了,对于闰年平年的标记0或1,再进行整年份的运算已经定义过了,就不需要再定义一边,而且为了方便在第一个数31前面加了一个0,这样处理之后,在后面循环的时候就不用再考虑数组的第一个索引值默认为0这个问题了。
在第一次运行的时候我发现天数总是不对,经过调试发现,通过scanf给值的时候,年份的值是对的,但是月份和日期都没有给上,都是0.原来的语句是这个样子scanf(“%d,%d,%d”,&maxDate.year,&maxDate.month,&maxDate.date); 后来将“”中的逗号改成空格之后就成功了。
代码就在Dev中运行成功了,然后我又把代码放到VS2019中跑一遍,结果显示scanf错误提示C4996,经过百度,已经将此问题解决,并整理了4种解决方案发布到了博客。
hexo+github博客:https://suyufan.github.io/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值