/*
* 我採用偷吃步的方法,找了3個定位點,再
* 根據輸入年與定位點的差,再算出calendar的縮排(indent)
* 我採用的曆法規則為:1752年前4年一潤,
* 1752年後4年一潤,100年不潤,400年一潤。
*/
#include<stdio.h>
void display(int,int);
main()
{
int year, month;
printf("輸入年(1到9999),月(1到12):\n");
scanf("%d%d",&year,&month);
while(year>9999 || year<1 || month>12 || month<1){
printf("Out of range! Input again.\n"
" 輸入年(1到9999),月(1到12):\n");
scanf("%d%d",&year,&month);
}
display(year,month);
return 0;
}
void display(int yy, int mm)
{
int indent(int, int, int*);
int dd[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int i,cols=0;
printf("\nYear:%d Month:%d\n",yy,mm);
printf("^^Sun^^Mon^^Tue^^Wed^^Thu^^Fri^^Sat^^\n");
for(i=1 ; i<=indent(yy, mm, dd) ; ++i){
printf(" ");
++cols;
}
if(yy!=1752 || mm!=9)
for(i=1 ; i<=dd[mm-1] ; ++i){
printf("%5d",i);
++cols;
if(cols%7==0)
putchar('\n');
}
else{//西元1752年9月
printf("%5d%5d",1,2);
cols+=2;
for(i=14 ; i<=30 ; ++i){
printf("%5d",i);
++cols;
if(cols%7==0)
putchar('\n');
}
}
putchar('\n');
}
int indent(int year, int month, int*d)
{
void after_Jan(int*, int, int*);
int idt;
if(year>=1753){
idt=(year-1753)*497/400+1;
/*
* 上面一行是由下式化簡而來,
* diff=year-1753;
* idt=diff+diff/4-diff/100+diff/400+1;
* 我採用1753年1月1日星期1為基準點,故加1
*/
if(month>=2){
if((year%4==0 && year%100!=0) || year%400==0)
d[1]=29;
after_Jan(&idt, month, d);
}
}
else if(year<=1751){
idt=year-1+(year-1)/4+6;
//上式是採用西元1年1月1日星期六為基準,故加6
if(month>=2){
if(year%4==0)
d[1]=29;
after_Jan(&idt, month, d);
}
}
else{//year==1752
idt=3;//西元1752年1月1日為星期3
if(month>=2){
d[1]=29;
d[8]=19;//西元1752年的9月只有19天
after_Jan(&idt, month, d);
}
}
return idt%7;
}
void after_Jan(int*space, int m, int*d)
{
int*p=d;
while(p-d<=m-2)
*space+=*p++;
/*用指標寫可讀性差了一點,上面的敘述用陣列改寫:
* for(int i=0 ; i<=m-2 ; ++i)
* *space+=d[i];
*/
}
/* cakewalks
* miracle@ms3.url.com.tw
* 1999.10.29
*/
--
※ 發信站: 批踢踢實業坊(ptt.twbbs.org)
◆ From: 140.116.28.163