日期问题
这里带来两个日期问题:一是给定两个日期,输出相隔天数;二是给定日期输出星期;最后有一个一的扩展即给出日期输出一年的多少天。
日期间隔问题
输入两个日期如20200129—20191231八位数字字符串。输出两个日期的间隔天数。
我采用Buf[]year[month][day]三维数组来存放数组下标(即年月日)对应于原点日期间隔的天数。这是Hash的思想,同时也是解决后面几道题目关键,这里很重要。详细代码如下:
#include<iostream>
using namespace std;
//闰年1 平年0
//能被400整除。或者能被4整除但不能被100整除。
#define isLeapYear(x) ((x%4 == 0)&&(x%100 != 0))||(x%400 == 0)? 1 : 0
//列举出一年十二个月中的每个月的天数
int monthDay[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
class twoDate
{
public:
int year;
int month;
int day;
//从0年1月1日开始计算间隔天数,存放在buf三维数组中
void getDay()
{
day++;
if(day > monthDay[month][isLeapYear(year)])
{
month ++;
day = 1;
}
if(month > 12)
{
year++;
month = 1;
}
}
};
//求绝对值函数
int abs(int x)
{
return x<0 ? -x:x;
}
int buf[5001][13][32];
int main()
{
system("CLS");
int cnt = 0;
//创建类
twoDate date;
date.year = 0;
date.month = 1;
date.day = 1;
//开始计数
while (date.year != 5001)
{
buf[date.year][date.month][date.day] = cnt++;
date.getDay();
}
cout<<"Input:"<<endl;
int y1,y2,m1,m2,d1,d2;
scanf("%4d%2d%2d",&y1,&m1,&d1);
scanf("%4d%2d%2d",&y2,&m2,&d2);
// cin>>y1>>m1>>d1;
// cin>>y2>>m2>>d2;
cout<<"Output:"<<endl;
cout<<abs(buf[y2][m2][d2]-buf[y1][m1][d1]) + 1<<endl; //输出两个日期的天数之差
return 0;
}
日期转换星期问题
这里不知道该取什么名字,就用这个名字代替吧。因为输入的是日期,输出为星期X。
与问题一相似的是,仍然采用了Hash的思想存储间隔天数,将字符串转换成数值,从而便于进行%7(算数运算)操作。根据预设的原点日期的星期得出输入日期的星期。
#include<iostream>
#include<string.h>
using namespace std;
//判断闰平年
#define isLeapYear(x) ((x%4 == 0)&&(x%100 != 0))||(x % 400 == 0)?1:0
//每个月份的天数
int monthDay[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
//保存每个月的名字
char monthName[13][15] = {
"",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
//保存每个星期的名字
char weekName[8][15] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
//创建类,存储年月日
class DayOfWeek
{
public:
int year;
int month;
int day;
void getDay()
{
day ++;
if(day > monthDay[month][isLeapYear(year)])
{
day = 1;
month ++;
}
if(month > 12)
{
month = 1;
year ++;
}
}
};
//相对于原点日期1000年1月1日的间隔天数
int Buf[3001][13][32];
void countDay()
{
int cnt = 0;
DayOfWeek date;
date.year = 0;
date.month = 1;
date.day = 1;
while (date.year != 3001)
{
Buf[date.year][date.month][date.day] = cnt++;
date.getDay();
}
}
//此处无需用到绝对值函数,只需对负数对7取余得到-6 - 0的数后再加7从而再次取余即可
int abs(int x)
{
return (x < 0) ? -x : x;
}
int main()
{
system("CLS");
countDay();
int y,d;
int i;
char m[15];
scanf("%d%s%d",&d,m,&y);
for (i = 1; i < 13; i++)
{
//判断月份字符与月份字符比对
if (strcmp(m,monthName[i]) == 0)
{
break;
}
}
cout<<weekName[(((Buf[y][i][d] - Buf[2020][1][26]) % 7) + 7) % 7];
return 0;
}
拓展:一年第几天问题
本问题是问题一的延伸,输入为一个日期,输出便是一年的第几天。本问题求解思路是:将问题一的原点日期改成,输入年份的1月1日便可。因此这种解法,下面不多讲。我采用的是二维数组Buf[month][day]保存一年的多少天,和问题一相似,三维变二维,最后根据输入的年份判断闰平年即可(getYear成员函数)。
#include<iostream>
using namespace std;
//判断闰平年
#define isLeapYear(x) (((x % 4 == 0)&&(x % 100 != 0))||(x % 400 == 0)) ? 1 : 0
int Monthday[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
class printDay
{
public:
int year;
int month;
int day;
//编写此成员函数的目的是:通过传入参数决定year的值,从而根据isLeapYear()进行闰平年的判断
void getYear(int y)
{
year = y;
}
void getDay()
{
day++;
if(day > Monthday[month][isLeapYear(year)])
{
day = 1;
month ++;
}
}
};
int Buf[13][32];
void countDay(int y)
{
printDay date;
date.month = 1;
date.day = 1;
date.getYear(y); //year的值为输入的值
int cnt = 1;
while(date.month != 13 && date.day != 32)
{
Buf[date.month][date.day] = cnt++;
date.getDay();
}
}
int main()
{
system("CLS");
int y,m,d;
scanf("%4d%2d%2d",&y,&m,&d);
countDay(y);
cout<<Buf[m][d];
return 0;
}
说明
VS Code C++
为了便于对输入位数进行控制采用的scanf而为使用cin,如果有大佬会用cin进行输入位数控制,可以在下面评论指导一下。