首先 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