【c/c++】机试中的日期类问题2

首先 string.h 中的字符串指的是char 型字符数组的一些操作,而不是 c++ 中的string 型变量,关于它们的区别,我们以后再进行分析,scanf 对字符型数组 用 %s 表示从第一个不为空格的开始,到空格或者换行符,tab符号结束,在用 %s 时不必使用&取址操作。

题目描述:

大意为给1个日期,判断出该日期是星期几,并输出。

输入数据的格式是:

12 October 2019 

第一个是天数,中间的月份要大写,输出的月份也要大写。

与上一个日期类问题相似,求是星期几,只需和已知星期几的一天对比,星期一最好对比,求出他们相差的天数,即可得知最后的结果。

代码为(与答案有些地方不同,答案weekday 数组是从Sunday 开始的, 所以有day+ 1 的操作):

#include<iostream>
//math.h 与algorithm 中有重复的功能,最好只用algorithm
//#include<math.h>
#include<cstdio>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;
//宏是没有返回值的,所以不能if(ISY(n))只能把它当做一个确定的值,或者是1或者是0
//而且也不能用if(ISY(n) == 1),只能用 int i = ISY(n),用i进行存储,也不能直接printf ISY(n)
//
#define ISYEAP(x) (x) % 100 != 0 && (x) % 4 == 0|| (x) % 400 == 0 ? 1:0;

int dayOfMonth[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 monthOfYear[13][20] =
{
	" ",
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December",
};

char dayOfWeek[7][20] =
{
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
	"Saturday",
	"Sunday",
};

struct Date {
	int day;
	int month;
	int year;

	void nextDay()
	{
		day++;
		int t = ISYEAP(year);
		//是否超出该闰年(平年)该月的天数
		if (day > dayOfMonth[month][t])
		{
			month++;
			day = 1;
			if (month > 12)
			{
				month = 1;
				year++;
			}
		}
	}

};
//对于函数的结尾不用加上分号,但是结构体是一种类型相当于一种数据类型的定义,所以要加上分号

int buf[50001][13][32];

int main()
{
	Date tmp;
	int cnt = 0;
	tmp.day = 1;
	tmp.month = 1;
	tmp.year = 0;
	//以空间换时间,因为有大量数据需要计算,可能还有重复的值
	while (tmp.year != 5001)
	{
		//将从起始年月日开始的所有日子都计算出一个距离
		//并且存储起来
		buf[tmp.year][tmp.month][tmp.day] = cnt;
		cnt++;
		tmp.nextDay();
	}
	int y1;
	char m1[20];
	int d1;
	while (scanf("%d%s%d", &d1, m1, &y1))
	{
		//只要输入一组数据即可
		//比较麻烦的是需要在数组中去寻找相应字符所对应的月份
		int targetMonth;
		for (int i = 1; i < 13; i++)
			if (strcmp(m1, monthOfYear[i]) == 0)
			{
				targetMonth = i;
				break;
			}
		//本题时间是2019年2月25日星期1,用m2存储
		int curY = 2019;
		int curD = 25;
		//注意下面m下标为2来表示
		int curM = 2;
		int dis = buf[y1][targetMonth][d1] - buf[curY][curM][curD];
		//调用的是algorithm中的abs函数,因为最后输出的是正值,最后要加上1,并且一般都是要求换行的
		//不能用dis = abs(dis);的abs了,因为与本天的差值为 + - 影响到从星期的左边还是右边数
		//此时就不必再 + 1了
		//printf("%d\n",abs(res) + 1);
		//下面式子的结果永远为正
		//最好用星期一来比较,周中要考虑的范围很多
		//星期1时,差 -1 天,结果为 6,恰好是星期天,差6天也是星期天
		//差一天为星期2,差0天为星期1,所以dayOfWeek下标从0 到 6比较合适
		int res = (dis % 7 + 7) % 7;
		printf("%s",dayOfWeek[res]);
	}
	
	return 0;
}

运行结果:

27 February 2019
Wednesday
9 October 2001
Tuesday
14 October 2001
Sunday
24 February 2019
Sunday

另外还有一种求某年某月某日是星期几的蔡勒公式,它可以求出16世纪以后的某天是星期几(16世纪某年被删除了几天,当然对相隔几天的计算不影响),运行下面的程序即可:

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;

int main()
{
	int y, c, m, d, w;
	while (scanf("%d%d%d", &y, &m, &d) != EOF)
	{
		if (m == 1 || m == 2) 
			m += 12, y = y - 1;
		w = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7;	
		printf("%d\n", (w % 7 + 7) % 7);
	}
	return 0;
}

运行结果:

2019 02 27
3
2019 2 25
1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值