#以此类推,也许该出现年历了。
…或者周历?
来分析一下题目想让我们干什么吧:
提供年与月,输出月历,输出格式如上。
第一行是固定的,哪个月都是这样,所以无论如何就可以在打印的那个函数里第一行就写上这个:
printf(" SUN MON TUE WED THU FRI SAT\n");
然后是找那个月份开始的日期以及打印天数,两个问题。
要打印的天数好说,一年到头12个月份的天数基本上没变过,在2月判断一下就好。
所以嗦这道题的问题其实就是,找开始的那一天。
那么怎么找呢?不用担心,题目给的两个数据还没开始用。
通过 年与月 来找出 目标月份的第一周 从星期几开始,对吧?
那就要判断,从某一个确定的基准日期以后,一直到目标日期,过了多少天,把天数模个7就是多出来的部分了。其中还有些可以优化的部分,先不谈,这个就先可以。
bool leap(int year){
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
void print(int year,int month){
int y = year % 400; // 优化一下,400年一轮回,历法星期啥的一样的
int sumday = 0;
for (int i = 1;i < y;i++){ //公元一年一月一日开始,星期一。(比2000为基准舒服
if (leap(i))sumday = sumday + 366;
else sumday = sumday + 365;
}
//记 过了那么多年总共过的天数,最后再加上 目标月份那年 前面月份 的天数,最后%7
//其实可以边加边%7
int mon[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (leap(year)) mon[1] = 29;
for (int i = 0;i < month-1;i++){ //eg.求8月,累加1~7月的天数,0~6号数组位置
sumday = sumday + mon[i];
}
sumday = sumday % 7;
int blank = (sumday + 1) % 7; //公元1/1/1是星期一,月历的空格位保底有一个
//打印的空格数
for (int i = 1;i <= blank;i++){
printf(" ");
}
for (int i = 1;i <= mon[month-1];i++){
printf("%8d",i);
if ((i + blank) % 7 == 0) printf("\n");
}
}
补上一个main,完满了
int main(){
int y,m;
scanf("%d%d",&y,&m);
print(y,m);
return 0;
}
啊没什么麻烦的。那我们来试试那个吉姆拉尔森公式?
“通过年月日来判断那一天是星期几”
参考:吉姆拉尔森公式计算公式
这里修改一下,丢进来用,效果如下:
bool leap(int year){
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
int jier(int day,int month,int year){
if (month==1||month==2){
month+=12;
year--;
}
int week = (day + 2*month + 3 * (month+1)/5 + year + year/4 - year/100 + year/400 + 1) % 7;
return week;
}
void print(int year,int month){
printf(" SUN MON TUE WED THU FRI SAT\n");
int d = jier(1,month,year);
for (int i = 1;i <= d;i++){
printf(" ");
}
int mon[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (leap(year)) mon[1] = 29;
for (int i = 1;i <= mon[month-1];i++){
printf("%8d",i);
if ((i + d) % 7 == 0) printf("\n");
}
}
如果能记住公式,那代码逻辑又可以化简一丢丢了。可惜公式好长…
不过原来的思路经过轮回模法只需要加和最多四百次,数据量也不大,记不住公式可以用那个。
公式有个规律:(日 + 2 * 月 + 3 *(月 + 1)/ 5 + 年 + 年 / 4 - 年 / 100 + 年 / 400 + 1)% 7
关于年的部分与闰年的几个参数定义有关。
公式中的参数是用来调误差的。
…好像也不是很难记?
看这月历,一月份了,
可注意别感冒了嗷。