打印日历

输入一个年份然后打印日历,从书中修正得到

下面程序因为没有用蔡勒公式,选择了历史上已知的星期几的某一天进行计算。

#include <stdio.h>

/*
表示一周中的日子,对它进行了编号;这样编号有好处。
倘若你知道某天是星期几可以用(weekday(0~6) + k)% 7求出该天是星期几,其中k表示第几天;
例如:(5 + 10) % 7表示今天是星期五,今天后第十天是星期一;
还可以求出本周的下一天是星期几,可移动到那一天不会出现weekday++带来的困扰;
weekday = (weekday + 1) % 7;
*/

#define Sunday      0
#define Monday      1
#define Tuesday     2
#define Wednesday   3
#define Thursday    4
#define Friday      5
#define Saturday    6


/*函数声明*/
void GiveInstrutions(void);                    //提示函数;
int GetyearFromuser(void);                     //输入年份,打印日历;
void PrintCalendar(int year);                  //一年的1~12个月;
void PrintCalendarMonth(int month, int year);  //显示某个月的日历;
void IndentFirstLine(int weekday);             //输出日历的第一行,使第一天出现在正确的位置;
int Monthdays(int month, int year);            //计算某月的天数;
int FirstDayofMonth(int month, int year);      //计算某月的第一天是星期几;
char *MonthName(int month);                    //打印出该月的名字;
bool IsLeapyear(int year);                     //判断是不是闰年;

int main()
{
        int year;

        GiveInstrutions();

        year = GetyearFromuser();
        PrintCalendar(year);

        return 0;
}

/*提示说明函数*/
void GiveInstrutions(void)
{
        printf("This program displays a calendar for a full\n");
        printf("year.  The year must not be for 1900.\n");
}

/*输入年份*/
int GetyearFromuser(void)
{
        int year;
        while(true)
        {
                printf("Which year?\n");
                scanf("%d", &year);
                if (year >= 1900) return (year);             //因为后面是以已知1900年1月1日是星期一作为计算的起点的;
                printf("The year must be at least 1900.\n");
        }
}

/*打印函数*/
void PrintCalendar(int year)
{
        int month;
        printf("\n");
        for (month=1; month<=12; month++)       //该年的1~12月;
        {
                PrintCalendarMonth(month, year);//调用打印月的函数;要知道该月有多少天,第一天是星期几;
                printf("\n");                   //每个月之间要换行;
        }
}

/*打印月的函数*/
void PrintCalendarMonth(int month, int year)
{
        int weekday, nDays, day;

        printf("   %s %d\n", MonthName(month), year);
        printf(" Su Mo Tu We Th Fr Sa\n");
        nDays = Monthdays(month, year);              //计算月的天数;
        weekday = FirstDayofMonth(month, year);      //计算该月的第一天是星期几;
        IndentFirstLine(weekday);                    //打印空格,确保第一天出现在正确的位置;

        for (day=1; day<=nDays; day++)               //假设保存了星期几的记录,则用下面的循环打印;所以还要知道该月的天数、第一天是星期几、确保第一天在正确的位置;
        {
                printf(" %2d", day);
                if (weekday == Saturday)             //星期六之后换行;
                        printf("\n");
                weekday = (weekday + 1) % 7;
        }
        if (weekday != Sunday)   printf("\n");       //即使这个星期不是在星期日结束,最后一行也有换行符;换成星期六也行;
}

/*确保第一天出现在正确的位置*/
void IndentFirstLine(int weekday)
{
        int i;
        for (i=0; i<weekday; i++)
                printf("   ");          //在前面打印空格;
}

/*计算该月的天数*/
int Monthdays(int month, int year)      //因为闰年和平年的天数不一样,所以还要有一个判断闰年与否的函数;
{
       switch(month)
       {
                case 2:
                        if (IsLeapyear(year)) return (29);
                        return (28);
                case 4:  case 6:  case 9:  case 11:
                        return (30);
                default :
                        return (31);
       }
}

/*这个月的第一天是星期几*/
int FirstDayofMonth(int month, int year)
{
        int weekday, i;
        weekday = Monday;            //因为1900年1月1日是星期一;
        for (i=1900; i<year; i++)
        {
                weekday = (weekday + 365) % 7;
                if (IsLeapyear(i))
                        weekday = (weekday + 1) % 7;
        }
        /*此处计算出的是当年1月1日是星期几; 因为weekday = (weekday + k)% 7 计算的是从那天后的第k天,所以天数刚好多一*/
        //printf("%d\n", weekday);
        for (i=1; i<month; i++)
        {
                int sum = 0;
                sum += Monthdays(i, year);
                weekday = (weekday + sum) % 7;     //某月1号,所以要加上该年前几个月的天数;这里最重要;
        }
        return (weekday);
}
/*
这里采用了一个简单的方法,取历史上的已知星期几的某一天;
从那天开始算按闰年与否每年加365/366天;
对于要算当年的要处理的月份之前的月,加上这月的天数;
运用weekday = (weekday + k) % 7。
*/

/*该月份的名字*/
char *MonthName(int month)
{
        switch(month)
        {
                case  1: return ("January");
                case  2: return ("Fberuary");
                case  3: return ("March");
                case  4: return ("April");
                case  5: return ("May");
                case  6: return ("June");
                case  7: return ("July");
                case  8: return ("August");
                case  9: return ("September");
                case 10: return ("October");
                case 11: return ("November");
                case 12: return ("December");
                default: return ("Illegal month");
        }
}

/*判断闰年与否*/
bool IsLeapyear(int year)
{
        return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}

/*仅供参考,已经测试,修正于C语言的编程与艺术的译本*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值