关于时间的经典OJ题目

这篇博客详细解析了四道基于C++的时间操作题目,包括累加天数、打印日期、日期差值和计算一年的第几天。通过闰年判断、日期进位和天数计算等方法,展示了C++在日期操作中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于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);
		}
	}

}

这道题可以说是为接下来的几道题目铺垫的,一个简单的加天数里面包含了多个需要注意的要点:

  1. 首先是闰年判断
  2. 其次是日期加起来超过当月的天数需要天数进位
  3. 以及月份超过了12月需要进位到月份进位,年份加一
  4. 月份的存储问题,能否将月份保存到数组中存储。
    代码是基于以上三点进行展开的。首先是闰年判断:
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;
}

这道题和上一道题本质上是一样的,只不过将输入和输出反过来而已,其日期的数组还是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值