在本程序中使用了结构体数组来存储多个月份的信息,结构体中除包含月份的二维数组外,还有记录模式以及其所对应的年份和月份。
程序输入的话有四个参数,第一个参数是字符串为指令,第二个参数为要查看的年份和月份,注意这里的月份占位为二,第三个参数为想从当前的月份查看后几个月,第四个参数为日期的模式,按照“一、二、三···日”的顺序还是“日、一、二···六”的顺序。(参数已经实现校验功能,后两个参数有默认值,可不用输入~)tips:
1.日历的表头”一“”二“”三“···使用二维字符数组来存储
2.ASC码为32的时候输出的是空格
程序运行结果展示:
程序源代码:
#include<stdio.h>
#include<time.h>
#include<string.h>
//定义日历结构体
struct calendar {
//参数p3,1为从周一开始,0为从周日开始, 默认从周一开始
int p3=1;
//当前日历的年份和月份
int year;
int month;
//声明数组并初始化
int data[5][7]= {{32,32,32,32,32,32,32},{32,32,32,32,32,32,32},{32,32,32,32,32,32,32},{32,32,32,32,32,32,32},{32,32,32,32,32,32,32}};
};
//按照格式打印输出
void print(struct calendar calendarList[],int count);
//计算与原点相差的天数
int week();
//填充数据
void fill(struct calendar calendarList[],int count,int week);
//判断是闰年还是平年的函数
int judge(int year);
//全局变量 年,月,与相差的天数
int year,month,sum=0;
//闰年和平年每个月的天数
int leap[12]= {31,29,31,30,31,30,31,31,30,31,30,31};
int ordinary[12]= {31,28,31,30,31,30,31,31,30,31,30,31};
int main() {
long start,end;//定义计时变量
char s[66];
char mode[66];
//记录输出几个月
int count;
int check;
char c1,c2,c3;
while(1) {
sum=0;
check=1;
//传入参数,用字符数组接收
scanf("%s",&s);
c3=getchar();
if (c3=='\n') {
printf("--help:mycalendar 202203 5 mon(P3 P4默认值为:12 mon)\n");
} else {
//输入开始的年份和月份
scanf("%4d%2d",&year,&month);
c1=getchar();
if (c1=='\n') {
//赋初值
count=12;
mode[0]='m',mode[1]='o',mode[2]='n',mode[3]='\0';
} else {
//输入要从当前月份开始几个月
scanf("%d",&count);
c2=getchar();
if (c2!='\n') {
//输入模式
scanf("%s",&mode);
} else {
mode[0]='m',mode[1]='o',mode[2]='n',mode[3]='\0';
}
}
//直接声明数量为count的结构体数组
if (strcmp(s,"mycalendar")!=0) {
printf("%s不是内部命令\n--help:mycalendar 202203 5 mon(P3 P4默认值为:12 mon)\n",s);
check=0;
}
if (year<=0||month<=0) {
printf("输入的年份或月份不合法\n--help:mycalendar 202203 5 mon(P3 P4默认值为:12 mon)\n");
check=0;
}
if (count<=0) {
printf("输入的count不合法\n--help:mycalendar 202203 5 mon(P3 P4默认值为:12 mon)\n");
check=0;
}
if ((strcmp(mode,"mon")!=0)&&(strcmp(mode,"sun")!=0)) {
printf("输入的mode不合法\n--help:mycalendar 202203 5 mon(P3 P4默认值为:12 mon)\n--help:mycalendar 202203 5 sun(P3 P4默认值为:12 mon)\n");
check=0;
}
if (check) {
struct calendar calendarList[count];
//如果要从周日开始的话,需要改变一下参数
if (strcmp(mode,"sun")==0) {
for (int i=0; i<count; i++) {
calendarList[i].p3=0;
}
}
//程序开始
start=clock();
//由已知原点算出当前的原点
fill(calendarList,count,week());
print(calendarList,count);
//程序结束
end=clock();
printf("执行时长:%ldms\n",end-start);
}
}
}
return 0;
}
//打印
void print(struct calendar calendarList[],int count) {
int i=0;
//若为mon模式
if (calendarList[0].p3==1) {
while(count!=0) {
if (count>=3) {
printf("\n%d年%d月\t\t\t%d年%d月\t\t\t%d年%d月",calendarList[i].year,calendarList[i].month,calendarList[i+1].year,calendarList[i+1].month,calendarList[i+2].year,calendarList[i+2].month);
printf("\n一 二 三 四 五 六 日\t一 二 三 四 五 六 日\t一 二 三 四 五 六 日\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+1].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+1].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+2].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+2].data[j][k]);
}
}
printf("\n");
}
i+=3;
count-=3;
} else if (count==1) {
printf("\n%d年%d月",calendarList[i].year,calendarList[i].month);
printf("\n一 二 三 四 五 六 日\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\n");
}
count-=1;
} else if (count==2) {
printf("\n%d年%d月\t\t\t%d年%d月",calendarList[i].year,calendarList[i].month,calendarList[i+1].year,calendarList[i+1].month);
printf("\n一 二 三 四 五 六 日\t一 二 三 四 五 六 日\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+1].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+1].data[j][k]);
}
}
printf("\n");
}
count-=2;
}
}
}
//若为sun模式
else {
while(count!=0) {
if (count>=3) {
printf("\n%d年%d月\t\t\t%d年%d月\t\t\t%d年%d月",calendarList[i].year,calendarList[i].month,calendarList[i+1].year,calendarList[i+1].month,calendarList[i+2].year,calendarList[i+2].month);
printf("\n日 一 二 三 四 五 六\t日 一 二 三 四 五 六\t日 一 二 三 四 五 六\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+1].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+1].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+2].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+2].data[j][k]);
}
}
printf("\n");
}
i+=3;
count-=3;
} else if (count==1) {
printf("\n%d年%d月",calendarList[i].year,calendarList[i].month);
printf("\n日 一 二 三 四 五 六\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\n");
}
count-=1;
} else if (count==2) {
printf("\n%d年%d月\t\t\t%d年%d月",calendarList[i].year,calendarList[i].month,calendarList[i+1].year,calendarList[i+1].month);
printf("\n日 一 二 三 四 五 六\t日 一 二 三 四 五 六\n");
for (int j=0; j<5; j++) {
for (int k=0; k<7; k++) {
if (calendarList[i].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i].data[j][k]);
}
}
printf("\t");
for (int k=0; k<7; k++) {
if (calendarList[i+1].data[j][k]==32) {
printf(" ");
} else {
printf("%-4d",calendarList[i+1].data[j][k]);
}
}
printf("\n");
}
count-=2;
}
}
}
}
int week() {
//2021年1月1日是星期五,初始化为星期五
int day=5;
//定义余数和星期的对照表
int y1[7]= {5,6,7,1,2,3,4};
int y2[7]= {5,4,3,2,1,7,6};
//如果是在2021年1月之后的时间的话,那么正着算
if ((year>2021)||((year==2021)&&(month>1))) {
//首先计算年天数
for (int i=2021; i<year; i++) {
if (judge(i)) {
sum+=366;
} else {
sum+=365;
}
}
//然后计算月份天数
for (int i=0; i<month-1; i++) {
if (judge(year)) {
sum+=leap[i];
} else {
sum+=ordinary[i];
}
}
//计算余数,根据对照表来计算出星期几
day=y1[sum%7];
return day;
}
//如果正好是2021年的1月的话,直接返回day
else if ((year==2021)&&(month==1)) {
return day;
}
//如果在2021年之前的话,倒着算
else {
//首先计算月份
for (int i=month-1; i<12; i++) {
if (judge(year)) {
sum+=leap[i];
} else {
sum+=ordinary[i];
}
}
//然后计算年份
for (int i=year+1; i<2021; i++) {
if (judge(i)) {
sum+=366;
} else {
sum+=365;
}
}
//计算余数,根据对照表来计算出星期几
day=y2[sum%7];
return day;
}
}
int judge(int year) {
if (((year%4==0)&&(year!=100))||(year%400==0)) {
return 1;
} else {
return 0;
}
}
void fill(struct calendar calendarList[],int count,int week) {
//定义池子变量
int pond;
int o;
int week2;
//若填充模式为mon的话
if (calendarList[0].p3==1) {
for (int i=0; i<count; i++) {
//此时的池子为模式1的池子
pond=36-week;
//如果当前年份是闰年的话
if (judge(year)) {
//如果池子能装下的话
if (pond>=leap[month-1]) {
//首先填充第一行
o=1;
for (int n=week-1; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
if (o>leap[month-1]) {
break;
}
calendarList[i].data[m][n]=o;
o++;
}
if (o>leap[month-1]) {
break;
}
}
} else {
//首先填充第一行
o=pond+1;
for (int n=0; n<leap[month-1]-pond; n++) {
calendarList[i].data[0][n]=o;
o++;
}
o=1;
for (int n=week-1; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行,不用考虑填不满的情况
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
calendarList[i].data[m][n]=o;
o++;
}
}
}
//更新week变量
week=((leap[month-1]%7)+week)%7;
if (week==0) {
week=7;
}
}
//如果是平年的话
else {
//如果池子能装下的话
if (pond>=ordinary[month-1]) {
//首先填充第一行
o=1;
for (int n=week-1; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
if (o>ordinary[month-1]) {
break;
}
calendarList[i].data[m][n]=o;
o++;
}
if (o>ordinary[month-1]) {
break;
}
}
} else {
//首先填充第一行
o=pond+1;
for (int n=0; n<ordinary[month-1]-pond; n++) {
calendarList[i].data[0][n]=o;
o++;
}
o=1;
for (int n=week-1; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行,不用考虑填不满的情况
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
calendarList[i].data[m][n]=o;
o++;
}
}
}
//更新week变量
week=((ordinary[month-1]%7)+week)%7;
if (week==0) {
week=7;
}
}
//如果是第一年的话,直接赋值
calendarList[i].year=year;
calendarList[i].month=month;
month++;
//若月份大于12的话,新的一年开始
if (month>12) {
year++;
month=1;
}
}
}
//如果填充模式为sun的话
else {
for (int i=0; i<count; i++) {
//此时的池子为模式0的池子
if(week!=7) {
pond=35-week;
} else {
pond=35;
}
//如果当前年份是闰年的话
if (judge(year)) {
//如果池子能装下的话
if (pond>=leap[month-1]) {
//首先填充第一行
o=1;
week2=week;
if (week2==7) {
week2=0;
}
for (int n=week2; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
if (o>leap[month-1]) {
break;
}
calendarList[i].data[m][n]=o;
o++;
}
if (o>leap[month-1]) {
break;
}
}
} else {
//首先填充第一行
o=pond+1;
for (int n=0; n<leap[month-1]-pond; n++) {
calendarList[i].data[0][n]=o;
o++;
}
o=1;
week2=week;
if (week2==7) {
week2=0;
}
for (int n=week2; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行,不用考虑填不满的情况
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
calendarList[i].data[m][n]=o;
o++;
}
}
}
//更新week变量
week=((leap[month-1]%7)+week)%7;
if (week==0) {
week=7;
}
}
//如果是平年的话
else {
//如果池子能装下的话
if (pond>=ordinary[month-1]) {
//首先填充第一行
o=1;
week2=week;
if (week2==7) {
week2=0;
}
for (int n=week2; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
if (o>ordinary[month-1]) {
break;
}
calendarList[i].data[m][n]=o;
o++;
}
if (o>ordinary[month-1]) {
break;
}
}
} else {
//首先填充第一行
o=pond+1;
for (int n=0; n<ordinary[month-1]-pond; n++) {
calendarList[i].data[0][n]=o;
o++;
}
o=1;
week2=week;
if (week2==7) {
week2=0;
}
for (int n=week2; n<7; n++) {
calendarList[i].data[0][n]=o;
o++;
}
//填充下边四行,不用考虑填不满的情况
for (int m=1; m<5; m++) {
for (int n=0; n<7; n++) {
calendarList[i].data[m][n]=o;
o++;
}
}
}
//更新week变量
week=((leap[month-1]%7)+week)%7;
if (week==0) {
week=7;
}
}
//如果是第一年的话,直接赋值
calendarList[i].year=year;
calendarList[i].month=month;
month++;
//若月份大于12的话,新的一年开始
if (month>12) {
year++;
month=1;
}
}
}
}