用户输入: 年 月 日 及天数 程序运行后打印出具体的日期

用户输入: 年 月 日 及天数 程序运行后打印出具体的日期 例如:输入 1989 11 20 20 输出 1989 12 10

大一小白第一次写博文感觉这个对自己有点绕,写下来理下思路,还请各位路过的大佬多多指点。

主要思路:
(用老师的一句话,这应该是 “大力出奇迹” 的算法)

一、解题思路来源于另一个题:
给出一个年份以及天数,输出对应的年、月、日
这个题目

首先先理解上面这个题目:
1.初始日期:输入的年份–1月–1日
从这里分析年份就有两种情况 闰年和非闰年
因而,可以通过建立一个二维数组,把每个月的天数情况直接表示出来,第一个元素放零是为了方便后面直接用下标代表月份

monthdays[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
			      {0,31,29,31,30,31,30,31,31,30,31,30,31} };  //定义数组存放费闰年和闰年每个月天数 

2.闰年的判别:

leap = (year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;   //判断是否为闰年

不用if语句是因为可以直接用leap的真值代表数组的行标

3.天数与月份的确定:
通过用所需加的天数,对每个月天数逐次作差,直到
天数的值 <= 该轮循环的月数的天数
就求出当月的天数以及月份

for (k = 1; days >= monthdays[leap][k] ; k++)
	days -= monthdays[leap][k];
	//不满足循环条件时的 days 就是 日的值,k 就是 月的值

———————————分割线—————————————
二、现在开始回归正题:
这道题的区别在于初始日期不固定,因而会带来两个主要问题:

(1)跨年月份变换问题
如:12月—>1月

(2)跨年后是否闰年问题
如:2000年(闰年)—>2001(非闰年)

由此我的解题思路主要就是围绕解决这两个问题。
1.首先开始解决天数为正数的时候
先把代码单独列出来吧

//days 要加的天数 ,year,month,day输入的年月日
void howday1(int days, int year, int month, int day)
{
	int monthdays[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
						  {0,31,29,31,30,31,30,31,31,30,31,30,31} };  //定义数组存放费闰年和闰年每个月天数  
	int leap, k;
	int i = 0;               //用于判段初始月             
	days += day;                   //将起始月的天数归零 
	do                            //外层循环计算年 
	{
		leap = (year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;   //判断是否为闰年 
	
		for (k = 1; days >= monthdays[leap][k] ; k++)     //计算月和当月日期            
		{
			
			if (i == 0 && k == 1)       //由初始月份开始 
				k = month;
			i++;                        //i增加后面就不可能出现初始月 
			
			days -= monthdays[leap][k]; //用总天数减去对应月的天数 
			if (k == 12)
			{
				k = 1;
				year++;
				break;                  //k=12时离开内循环年数加1,回到1月
			}
		}	
	}while( days >= monthdays[leap][k] );
	printf("%d %d %d", year, k, days);
}

与开始描述的那道题目类似,这个题主要症结在于没有确定的起始日期,由此我首先想到的是将给的起始日期全部清零变成当年的1月1日,但想了一下这样做有点麻烦运算量会更大,所以选择让当月的天数归零变成1日,保留月份以及年份;(我感觉可能就是我这个想法导致了我觉得我写的代码太绕了)
所以有了这个操作

days += day;                   //将起始月的天数归零 

然后和先前一样直接用总天数 减 接下来每个月的天数
但这个时候跨年问题就出现了当算到12月时年份就需要加一,并且还要考虑接下来的一年是否为闰年,所以我想到了两层循环外层当用来对年递增,并判断是不是闰年,内层就对月还有天数进行计算,当计算至12月时,days还不满足循环结束条件时就
跳出内层循环—>年数+1—>判断闰年—>从1月开始再进入内层循环
2.负数(和正数相似)
区别点:起始月需要-1从上一个月开始计算

总的思路就是如此
代码也试了很多数据暂时没找出bug
有的话请多多指教

**

下面是完整代码

**

#include<stdio.h>

void howday1(int days, int year, int month, int day);//正数 
void howday2(int days, int year, int month, int day);//负数 

int main()
{
	int year,month,day;           //输入的年月日 
	int days;                     //将要加的天数 
	scanf("%d %d %d", &year, &month, &day);
	getchar();                    //吃回车 
	scanf("%d", &days);
	if (days == 0)
		printf("%d %d %d", year, month, day);
	else if(days > 0)
		howday1(days, year, month, day);
	else         //调用函数计算加了天数后的日期 
    	howday2(days, year, month, day);         
}
void howday1(int days, int year, int month, int day)
{
	int monthdays[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},
						  {0,31,29,31,30,31,30,31,31,30,31,30,31} };  //定义数组存放费闰年和闰年每个月天数  
	int leap, k;
	int i = 0;               //用于判段初始月             
	days += day;                   //将起始月的天数归零 
	do                            //外层循环计算年 
	{
		leap = (year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;   //判断是否为闰年 
	
		for (k = 1; days >= monthdays[leap][k] ; k++)     //计算月和当月日期            
		{
			
			if (i == 0 && k == 1)       //由初始月份开始 
				k = month;
			i++;                        //i增加后面就不可能出现初始月 
			
			days -= monthdays[leap][k]; //用总天数减去对应月的天数 
			if (k == 12)
			{
				k = 1;
				year++;
				break;                  //k=12时离开内循环年数加1,回到1月
			}
		}	
	}while( days >= monthdays[leap][k] );
	printf("%d %d %d", year, k, days);
}
void howday2(int days, int year, int month, int day)
{
	int monthdays[2][13]={{31,31,28,31,30,31,30,31,31,30,31,30,31},
					      {31,31,29,31,30,31,30,31,31,30,31,30,31} };  //定义数组存放费闰年和闰年每个月天数  
	int leap, k;
	int i = 0;           
	days += day;                   //将起始月的天数归零 
	do                 //外层循环计算年 
	{
		leap = (year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0;   //判断是否为闰年
	
		for (k = 12; days <= 0 ; k--)              
		{
			if (i == 0 && k == 12)       //由初始月份开始 
				k = month;
			i++;
			days += monthdays[leap][k-1]; //用总天数加上上一个月的天数 
			if (k == 1)
			{
				k = 12;
				year--;
				break;                  //k=1时离开内循环年数减1,回到12月
			}
		}	
	}while( days <= 0);
	printf("%d %d %d", year, k, days);
}

总的来说就是感觉很不对,太绕了,希望有大佬指点一下,推荐一下更优化的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值