385 lines
10 KiB
C++
385 lines
10 KiB
C++
#include<bits/stdc++.h>
|
||
//需求:
|
||
//1.设计判断闰年函数
|
||
//2.设计查询某年某日日期星期几,
|
||
//3.日历的输出(单双列)
|
||
//4.菜单选择要有纠错功能 ,也就是说每个菜单要有一个函数可供返回 ,即每个最好要有一个单独的函数来满足
|
||
//5.1528年少了十天,据查证是因为罗马教皇决定在1582年10月4日后使用格利戈里历法,英国是在1752年9月3日后才接受使用格利戈里历法
|
||
|
||
//1.闰年判断函数,思路:常见判断闰年条件
|
||
int isLeapyear(int year)
|
||
{
|
||
return(year%400==0)||(year%4==0&&year%100!=0);//如果是闰年,则为真
|
||
}
|
||
int monthsday(int year,int month)
|
||
{
|
||
int monthsday[]={31,28,31,30,31,30,31,31,30,31,30,31};
|
||
if (month==2&&isLeapyear(year))//如果是闰年,二月有二十九天
|
||
{
|
||
return 29;
|
||
}
|
||
return monthsday[month-1];
|
||
}
|
||
int getFirstDayOfYear(int year)//今年的第一天是周几
|
||
{
|
||
int d=(year-1)*365+(year-1)/4-(year-1)/100+(year-1)/400;
|
||
if (year>1582)
|
||
{
|
||
if (year==1583)
|
||
{
|
||
d-=10;
|
||
}
|
||
}
|
||
return d%7;
|
||
}
|
||
int getDaysInMonth(int year,int month)
|
||
{
|
||
int daysInMonth[]={31,28,31,30,31,30,31,31,30,31,30,31};
|
||
if(month==2&&isLeapyear(year))
|
||
{
|
||
return 29;//闰年二月有29天
|
||
}
|
||
if (year == 1582 && month == 10) {
|
||
return 21; // 1582年十月只有21天
|
||
}
|
||
return daysInMonth[month-1];//返回对应月份的天数
|
||
}
|
||
//计算给定日期是星期几(0表示星期日1-6表示周一到周六)
|
||
int getDayOfWeek(int year, int month, int day)
|
||
{
|
||
int t[]={0,3,2,5,0,3,5,1,4,6,2,4};//调整不同月在不同年中的偏移
|
||
if (month<3)
|
||
{
|
||
year--;
|
||
}
|
||
return(year+year/4-year/100+year/400+t[month-1]+day)%7;
|
||
}
|
||
//2.查询哪年哪月是周几
|
||
int week(int year,int month,int day)//运用泰勒公式
|
||
{
|
||
if(month<3)
|
||
{
|
||
month+=12;
|
||
year--;
|
||
}
|
||
if(year<1583)
|
||
{
|
||
int h=(day+1+2*month+3*(month+1)/5+year+year/4+5)%7;
|
||
return h; //h表示某时间是星期几
|
||
}
|
||
else{
|
||
int h=(day+2*month+3*(month+1)/5+year+year/4-year/100+year/400)%7;//蔡勒公式w=(d + 1+ 2*m+3*(m+1)/5+y+y/4-y/100+y/400(闰年调整))%
|
||
return h+1;//h+1是因为1582年以后,蔡勒公式计算会少一天
|
||
}
|
||
}
|
||
//3.日历的输出
|
||
int runnian(int n)//记录闰年月份日期
|
||
{
|
||
switch(n)
|
||
{
|
||
case 1:return 31;
|
||
case 2:return 29;
|
||
case 3:return 31;
|
||
case 4:return 30;
|
||
case 5:return 31;
|
||
case 6:return 30;
|
||
case 7:return 31;
|
||
case 8:return 31;
|
||
case 9:return 30;
|
||
case 10:return 31;
|
||
case 11:return 30;
|
||
case 12:return 31;
|
||
}
|
||
}
|
||
int pingnian(int year,int month)//记录平年月份日期
|
||
{
|
||
if (year==1582&&month==10)
|
||
{
|
||
return 21;//1582年10月只有21天
|
||
}
|
||
switch(month)
|
||
{
|
||
case 1:return 31;
|
||
case 2:return 28;
|
||
case 3:return 31;
|
||
case 4:return 30;
|
||
case 5:return 31;
|
||
case 6:return 30;
|
||
case 7:return 31;
|
||
case 8:return 31;
|
||
case 9:return 30;
|
||
case 10:return 31;
|
||
case 11:return 30;
|
||
case 12:return 31;
|
||
}
|
||
}
|
||
void run(int week)//闰年日历输出
|
||
{
|
||
int n=0;//记录换行次数
|
||
int w=week;
|
||
for(int i=1;i<=12;i++)
|
||
{
|
||
printf("%d月\n",i);
|
||
printf("日 一 二 三 四 五 六\n") ;
|
||
for(int k=0;k<w;k++)//空格对齐
|
||
{
|
||
printf(" ");
|
||
n++;
|
||
}
|
||
for(int j=1;j<=runnian(i);j++){//输出每月的天
|
||
if(n%7==0){
|
||
|
||
printf("\n");
|
||
}
|
||
printf("%d ",j);
|
||
n++;
|
||
}
|
||
w=(w+runnian(i))%7;//周数
|
||
n=n-w;
|
||
printf("\n\n");
|
||
}
|
||
}
|
||
void ping(int year)//平年日历输出
|
||
{
|
||
int n=0;//记录换行
|
||
int w=getFirstDayOfYear(year);//获取该年第一天是星期几
|
||
for(int i=1;i<=12;i++)
|
||
{
|
||
printf("%d月\n", i);
|
||
printf("Sun Mon Tue Wed Thu Fri Sat\n");
|
||
for (int k=0;k<w;k++)
|
||
{
|
||
printf(" ");
|
||
n++;
|
||
}
|
||
for (int j=1;j<=pingnian(year,i);j++)
|
||
{//输出每月的天
|
||
if(n%7==0) // 七天换行
|
||
{
|
||
printf("\n");
|
||
}
|
||
printf("%d ",j);
|
||
n++;
|
||
}
|
||
w=(w+pingnian(year,i))%7;
|
||
n=n-w;
|
||
printf("\n\n");
|
||
}
|
||
}
|
||
//两个月的日历
|
||
void printTwoMonths(int year)
|
||
{
|
||
static int printed=0;//静态变量检测是否打印过日历
|
||
if(printed)
|
||
{
|
||
return;//如果打印过直接返回
|
||
}
|
||
int start_day[12];
|
||
start_day[0]=getFirstDayOfYear(year);
|
||
for (int month=1;month<12;month++)//计算每月起始星期几
|
||
{
|
||
start_day[month]=(start_day[month-1]+getDaysInMonth(year,month))%7;
|
||
}
|
||
const char *months[]={ "一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};
|
||
for (int i=0;i<6;i++)
|
||
{
|
||
printf("\n");
|
||
for (int j=0; j < 2; j++)
|
||
{
|
||
int month=i*2+j+1;
|
||
printf(" %s %d ", months[month-1],year);
|
||
}
|
||
printf("\n");
|
||
for (int j=0;j<2;j++)
|
||
{
|
||
printf("Sun Mon Tue Wed Thu Fri Sat ");
|
||
}
|
||
printf("\n");
|
||
int max_days[2]={getDaysInMonth(year,i*2+1),getDaysInMonth(year,i*2+2)};//获取两个月的最大天数和起始星期几
|
||
int start_days[2]={start_day[i*2],start_day[i*2+1]};
|
||
//打印日期
|
||
int day[2]={1,1};//每个月的当前日期
|
||
int printed_anything=1;//标记是否有剩余日期可打印
|
||
while(printed_anything)
|
||
{
|
||
printed_anything=0;
|
||
|
||
for(int j=0;j<2;j++)
|
||
{
|
||
if(day[j]==1)//打印月初的空格
|
||
{
|
||
for(int k=0;k<start_days[j];k++)
|
||
{
|
||
printf(" ");
|
||
}
|
||
}
|
||
while(day[j]<=max_days[j]&&((day[j]+start_days[j]-1)%7)!=6) // 打印日期
|
||
{
|
||
printf(" %2d ",day[j]);
|
||
day[j]++;
|
||
printed_anything=1;
|
||
}
|
||
if(day[j] <= max_days[j]) // 打印最后一个日期,换行并跳到下一个月
|
||
{
|
||
printf(" %2d ",day[j]);
|
||
day[j]++;
|
||
printed_anything=1;
|
||
}
|
||
else
|
||
{
|
||
printf(" ");// 对齐
|
||
}
|
||
printf(" ");//每月之间的间隔
|
||
}
|
||
printf("\n");//换行到下一个星期
|
||
}
|
||
}
|
||
printed = 1; // 表示已经打印过日历
|
||
}
|
||
//4.菜单,设这个仅仅是为了能够返回,而且方便点。
|
||
void Menu1()
|
||
{
|
||
printf("请输入一个数字来表示你要进行的操作喵~:\n");
|
||
printf("1.让我看看这年的日历吧~\n");
|
||
printf("2.我想看看这天是星期几捏?\n");
|
||
printf("3.我要看看这个年是不是闰年!\n");
|
||
printf("4.不看了nya\n");
|
||
}
|
||
int main()
|
||
{
|
||
int year,month,day,menu;
|
||
const char* week_days[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
|
||
|
||
while (1)
|
||
{
|
||
Menu1();//菜单选项
|
||
if(scanf("%d",&menu)!=1)//检查输入是否成功
|
||
{
|
||
while (getchar()!='\n');//清除输入缓冲区,这样输入中文就会返回了
|
||
printf("输入的格式不对,请重新输入:\n");
|
||
continue;
|
||
}
|
||
if(menu==1)
|
||
{
|
||
printf("你想看的形式是什么呢?输入以下数字查看相应方式。\n1.我要看单列输出!\n2.请给我看双列输出。\n");
|
||
int ds;
|
||
if(scanf("%d",&ds)!=1)//检查输入是否成功
|
||
{
|
||
while(getchar()!='\n');
|
||
printf("输入的格式不对,请重新输入:\n");
|
||
continue;
|
||
}
|
||
if(ds==1)//单列输出
|
||
{
|
||
printf("输入你想查询的年份吧:");
|
||
if (scanf("%d",&year)!=1)
|
||
{
|
||
while(getchar() != '\n');
|
||
printf("您输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
if (year<1)
|
||
{
|
||
printf("您输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
if (isLeapyear(year))
|
||
{
|
||
run(year);
|
||
}
|
||
else
|
||
{
|
||
if (year==1582)
|
||
{
|
||
ping(year);
|
||
}
|
||
else
|
||
{
|
||
ping(year);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if(ds==2)//双列输出
|
||
{
|
||
printf("输入你想查询的年份吧: ");
|
||
if (scanf("%d",&year)!=1)//检查输入是否成功
|
||
{
|
||
while (getchar()!='\n');
|
||
printf("您输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
if (year<=0)
|
||
{
|
||
printf("您输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
int startDay=getFirstDayOfYear(year);
|
||
for (int i=1;i<12;i+=2)
|
||
{
|
||
printTwoMonths(year);
|
||
startDay=(startDay+(i==2?(isLeapyear(year)?29:28):(i==4||i==6||i==9?30:31)))%7;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
printf("输入的格式不对,请重新输入:\n");
|
||
continue;
|
||
}
|
||
}
|
||
else if (menu == 2)
|
||
{
|
||
printf("请输入你想看的日期,格式是年-月-日哦:");
|
||
if (scanf("%d %d %d",&year,&month,&day)!=3)
|
||
{
|
||
while (getchar()!='\n');
|
||
printf("输入的日期有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
int weekday=week(year,month,day);
|
||
const char* week[]={"周日","周一","周二","周三", "周四","周五","周六"};
|
||
if (year<1||month<1||month>12||day<1||day>getDaysInMonth(year,month))
|
||
{
|
||
printf("输入的日期有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
printf("%d年%d月%d日是%s\n",year,month,day,week[weekday]);
|
||
}
|
||
}
|
||
else if (menu == 3)
|
||
{
|
||
printf("你想看看哪一年呢:");
|
||
if(scanf("%d", &year) != 1)
|
||
{
|
||
while(getchar() != '\n');
|
||
printf("输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
if(year<1)
|
||
{
|
||
printf("输入的年份有误,请重新输入:\n");
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
printf("%d年%s是闰年哦\n",year,isLeapyear(year)?"":"不");
|
||
}
|
||
}
|
||
else if(menu==4)
|
||
{
|
||
printf("加纳~\n");
|
||
return 0;//退出
|
||
}
|
||
else
|
||
{
|
||
printf("输入的格式不对,请重新输入:\n");
|
||
continue;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|