基于C++的关于时间操作的OJ题
都是比较经典的题目,基于C++实现
累加天数
问题
输入描述:
输入第一行表示样例个数m,接下来m行每行四个整数分别表示年月日和累加的天数。
输出描述:
输出m行,每行按yyyy-mm-dd的个数输出。
例如:
输入
1
2008 2 3 100
输出
2008-05-13
答案
#include<iostream>
using namespace std;
int main()
{
int roll;
int year, month, day, add;
while (cin >> roll)
{
for (int i = 0; i < roll; i++)
{
int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31 };
cin >> year >> month >> day >> add;
while (add > days[month-1])
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
days[1] = 29;
else
days[1] = 28;
//add -= days[month-1] - day;
add = add - days[month - 1] + day;
day = 0;
month++;
if (month == 13)
{
month = 1;
year++;
}
}
printf("%4d-%02d-%02d\n", year, month, add);
}
}
}
这道题可以说是为接下来的几道题目铺垫的,一个简单的加天数里面包含了多个需要注意的要点:
- 首先是闰年判断
- 其次是日期加起来超过当月的天数需要天数进位
- 以及月份超过了12月需要进位到月份进位,年份加一
- 月份的存储问题,能否将月份保存到数组中存储。
代码是基于以上三点进行展开的。首先是闰年判断:
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
这是闰年的判断方法,主要分为两个点,一个是能被4整除并且不能被100整除,其次是能被400整除。这两点只需要满足一点就可以了,所以要用并运算。
其次是月份的存储,因为闰年的判断是要落实到修改月份的。这里的月份存储使用数组的方式,即:
days[12] = {31,28,31,30,31,30,31,31,30,31,30,31 };
只需要根据闰年修改月份即可。
除此之外是月份的累加,也就是代码最重要的部分。
add = add - days[month - 1] + day;
day = 0;
其中add为添加的天数,month为月份,day为天数。此时在打印的时候是需要将add进行打印即可。
打印日期
问题
题目描述
给出年分m和一年中的第n天,算出第n天是几月几号。
输入描述:
输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。
输出描述:
可能有多组测试数据,对于每组数据,按 yyyy-mm-dd的格式将输入中对应的日期打印出来。
答案
#include<iostream>
using namespace std;
int main()
{
int year, num;
while (cin >> year >> num)
{
int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
{
days[1] = { 29 };
}
int i = 0;
int month = 1, day;
while (num > days[i] )
{
num = num - days[i];
month++;
i++;
if (month == 13)
{
month = 1;
day = days[1];
}
}
day = num;
printf("%4d-%02d-%02d\n", year, month, num);
}
return 0;
}
这道题目和之前的相比反而更加简单,依旧是基于之前的想法,唯一的不同在于day和month本身就是0,而add的输入变得更大。
日期差值
问题
题目描述
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天
输入描述:
有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
输出描述:
每组数据输出一行,即日期差值
答案
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
int mon[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };//字典
int cal(int y, int m, int d)//给出年月日,计算距离0000年0月1日的天数和
{
return y * 365 + y / 4 - y / 100 + y / 400 + mon[m - 1] + d - 1 + (y / 100 != 0 && y / 4 == 0 || y / 400 == 0 && m>2);
}
int main()
{
int x[2], year, month, day;
for (int k = 0; k<2; k++)//循环两次读入两个日期
{
scanf("%4d%2d%2d", &year, &month, &day);
x[k] = cal(year, month, day);
}
cout << abs(x[0] - x[1]) + 1;
}
这道题目和之前的情况有所不同,这里采用的方式是将相对的时间转成绝对的时间,即和0000年0月1日相比,二者的天数的差值,将相对的时间转换成绝对的时间进行计算,但是需要注意的是,计算成绝对时间也需要考虑一年是有365天还是366天,这里的判断方式为:
y * 365 + y / 4 - y / 100 + y / 400//y是年份
月份的加法如果单靠用月份乘以30或者31的话判断价位复杂,甚至可能比年份的判断要复杂的多,所以在存储月份的时候索性就直接村上月份的累加天数:
int mon[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
这里的mon[]
里的元素从mon[2]
开始是否需要每一项都加上1本质上还是闰年判断,所以当月份比2月大的时候还是在后面加上闰年判断进行补齐,最后再加上天数减1即可。
y * 365 + y / 4 - y / 100 + y / 400 + mon[m - 1] + d - 1 + (y / 100 != 0 && y / 4 == 0 || y / 400 == 0 && m>2)
计算一年的第几天
题目
题目描述
根据输入的日期,计算是这一年的第几天。。
测试用例有多组,注意循环输入
输入描述:
输入多行,每行空格分割,分别是年,月,日
输出描述:
成功:返回outDay输出计算后的第几天;
失败:返回-1
答案
#include<iostream>
using namespace std;
int main()
{
int year, month, day;
while (cin >> year >> month >> day)
{
if (day > 31 || month > 12 || month < 1)
{
cout << -1;
}
int days[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
{
for (int i = 2; i < 12; i++)
{
days[i]++;
}
}
int cnt = days[month - 1];
cnt = cnt + day;
cout << cnt << endl;
}
return 0;
}
这道题和上一道题本质上是一样的,只不过将输入和输出反过来而已,其日期的数组还是一样的。