zoukankan      html  css  js  c++  java
  • 【C语言】第一个C语言小程序 —— 日期算法和万年历2

    1. 上一篇我们只完成了

      a. 算出某年某月某日是星期几

      b. 打印出某年某月的日历

    这一次我写了一个打印某一年的日历。一开始我是不打算写的,因为可以调用之前的方法,分别打印出这一年12个月的日历。但是这样特别难看。所以写了一个算法。以一个月的日历为单位,打印成一个 4 * 3 的网格,像这样

    2. 程序除了 studio.h 没有用别的头文件,首先给出头和方法签名

    #include<stdio.h>
    
    #define DAYS_PER_WEEK 7
    #define MONTHS 12
    #define DATE_HEADER "   Sun   Mon   Tues  Wed   Thur  Fri   Sat"
    
    
    
    int get_days(int, int, int);   //返回从公元元年算起,某年某月某日是第几天, 用这个数字算星期几 
    int days_of_year(int, int, int);  //返回某年某月某日是当前年份第几天
    int days_of_month(int, int);  //返还某年某月有几天
    int day_of_week(int, int, int); //返回某年某月某日是星期几,星期天返回0 
    _Bool is_leap_year(int);    //返回当前年份是否为闰年
    void print_date_of_month(int, int);    // 打印某年某月的日历
    void print_date_of_week(int, int, int); //打印某年某月的某个星期日历(就是某个月的第几行日历)
    void print_date_of_year(int);  //打印某一年的日历 

    3. 加的第一个方法

    void print_date_of_week(int, int, int); //打印某年某月的某个星期日历(就是某个月的第几行日历)

    要实现这个方法是因为,我们自己的书写习惯是这样的

     

     但是程序的输出是这样的

                              

                               

     

                              

    我们的第一行要依次打印 3 个月的第一行日期,

       第二行   依次打印3个月的第二行日期

    因为一个月的日历最多只可能分布为6行,假设这个月1号是周六,并且这个月不是2月, 就可以写到6行

    所以没有6行的,我们输出空格来保持格式。直接上代码

    void print_date_of_week(int year, int month, int week)
    {
        int first_day_of_month = day_of_week(year, month, 1);
        int i;
        //第一周特殊处理 
        if(1 == week)
        {    for(i = 0; i < first_day_of_month; i++)
                printf("      ");
            printf("%6d", 1);
            
            for (i = 2; i + first_day_of_month < 8; i++)
                printf("%6d", i);
            return;
        }
        //计算该月第week周的星期天是几号
        int first_date_of_week = (week-2) * 7 + (7 - first_day_of_month + 1);
        
        //最多打印七天,且最大值不能超过这个月的天数
        int total_days = days_of_month(year, month); 
        if(first_date_of_week)
        for (i = 0; i < 7; i++)
        {
            int now = i + first_date_of_week;   //当前打印的日期
            if (now > total_days)
                printf("      ");   //日期超过了,就打印空格 
            else printf("%6d", now);
            
        } 
    }

    打印一年的日历,就是嵌套循环了。最后都是调用打印某年某月某一周的日历。其实功能并不复杂,复杂的是凑出想要的格式,所以还是花了一点时间的。

    void print_date_of_year(int year)
    {    
        printf("                                                              Dates of %d
    ", year);
        //期望的格式是以网格的形式,单位为一个月,分四行,每行打印一个季度,
        int i, j, k;
        
        for(i = 0; i < 4; i++)
        {      
            for(j = 1; j <= 6; j++)
            {    
                if( 1 == j)
                {
                    for(k = 1; k <= 3; k++)
                    {
                        printf("                  ");
                        int month = i * 3 + k;
                        switch(month)
                        {
                            case 1: printf("January  ");    break;
                            case 2: printf("February ");    break;
                            case 3: printf("March    ");    break;
                            case 4: printf("April    ");    break;
                            case 5: printf("May      ");    break;
                            case 6: printf("June     ");    break;
                            case 7: printf("July     ");    break;
                            case 8: printf(" August  ");    break;
                            case 9: printf("September");    break;
                            case 10: printf("October  ");    break;
                            case 11: printf("November ");    break;
                            case 12: printf("December ");    break;
                            default: printf("Bad input of month, please enter a right month.
    "); return;
                        }
                        printf("                    ");        
                    }
                    printf("
    ");
                    printf("%s    ", DATE_HEADER);
                    printf("%s    ", DATE_HEADER);
                    printf("%s    ", DATE_HEADER);
                    printf("
    ");
                }
            
                for (k = 1; k <= 3; k++)
                {    
                    print_date_of_week(year, i * 3 + k, j);
                    printf("    ");
                    if (3 == k) printf("
    ");
                }
                printf("
    ");
            }
        } 
        
    }

    交互的代码,我就不打算写了。

    目前这些方法应该算可以完成一本公历的功能了。我国农历的算法太复杂了,什么时候抽风了可能会研究一下?

    最终的代码

    #include<stdio.h>
    
    #define DAYS_PER_WEEK 7
    #define MONTHS 12
    #define DATE_HEADER "   Sun   Mon   Tues  Wed   Thur  Fri   Sat"
    
    
    
    int get_days(int, int, int);   //返回从公元元年算起,某年某月某日是第几天, 用这个数字算星期几 
    int days_of_year(int, int, int);  //返回某年某月某日是当前年份第几天
    int days_of_month(int, int);  //返还某年某月有几天
    int day_of_week(int, int, int); //返回某年某月某日是星期几,星期天返回0 
    _Bool is_leap_year(int);    //返回当前年份是否为闰年
    void print_date_of_month(int, int);    // 打印某年某月的日历
    void print_date_of_week(int, int, int); //打印某年某月的某个星期日历(就是某个月的第几行日历)
    void print_date_of_year(int);  //打印某一年的日历 
    
    int main()
    {
    //    printf("%d年%d月%d日是星期 %d
    ", 2018, 5, 9, day_of_week(2018, 5, 9));
    //    
    //    print_date_of_month(2018, 8);
        
    //    printf("%s
    ", DATE_HEADER);
    //    print_date_of_week(2018, 8, 2);
        
        print_date_of_year(1997);
        
        return 0;
     }
    
    
    
    //返回这一天从公元元年算起是第几天
     
    int get_days(int year, int month, int day)
    {
        int days = days_of_year(year, month, day);
        int temp = year-1;
        return temp * 365 + temp / 4 - temp / 100 + temp / 400 +  days;
    }
     
     
    
     //返回这一天在当年是第几天 
    int days_of_year(int year, int month, int day)
    {
         int i;
         int days = 0;
         for(i = 1; i < month; i++)
         {
             days += days_of_month(year, i);
             
         }
         return days + day;
    }
    
    //返回这个月一共有多少天 
    int days_of_month(int year, int month)
    {
        //存储平年每月的天数 
        const int  month_days[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if(2 == month && is_leap_year(year))
            return 29; // 如果是闰年2月,返回29天 
        else
            return month_days[month-1];  //正常返回 
    }
    
    //判断是不是闰年 
    _Bool is_leap_year(int year)
    {
        return (year % 400 == 0 ) || (year % 4 == 0 && year % 100 != 0);
    }
    
    int day_of_week(int year, int month, int day)
    {
        return get_days(year, month, day) % DAYS_PER_WEEK;
     } 
    
    //输出某年某个月的日历 
    void print_date_of_month(int year, int month)
    {
        //打印月份,为了让月份显示居中, 打印一些空格(根据打印星期的那行大概估算一下) 
        printf("               ");
        switch(month)
        {
            case 1: printf("January
    ");    break;
            case 2: printf("February
    ");    break;
            case 3: printf("March
    ");    break;
            case 4: printf("April
    ");    break;
            case 5: printf("May
    ");    break;
            case 6: printf("June
    ");    break;
            case 7: printf("July
    ");    break;
            case 8: printf("August
    ");    break;
            case 9: printf("September
    ");    break;
            case 10: printf("October
    ");    break;
            case 11: printf("November
    ");    break;
            case 12: printf("December
    ");    break;
            default: printf("Bad input of month, please enter a right month.
    "); return;
            
        }
        //先把星期打印出来 
        printf("%s
    ", DATE_HEADER);
        
        //先求出这个月第一天星期几 
        int day_of_week = get_days(year, month, 1) % DAYS_PER_WEEK;
        
        //因为星期天是在第一个位置,所以对星期求模(求余),比如星期天,其实是第一个位置,所以它应该是 7 % 7 = 0; 
        int first = day_of_week % DAYS_PER_WEEK;
        
        //求出这个月一共有几天 
        int days = days_of_month(year, month);
        
        int i, j;
        //先打印第一天的位置 
        for(i = 0; i < first; i++) {
            printf("      ");
        }
        printf("%6d", 1);
        //如果今天是星期六,换行 
        if(first == 6)
            printf("
    ");
        
        //打印剩下的日期 
        for(i = 1; i < days; i++)
        {
            printf("%6d", i + 1);
            //如果是星期六或者是最后一天,换行 
            if((first + i) % 7 == 6 || i + 1 == days)
                printf("
    ");
        } 
    }
    
    void print_date_of_week(int year, int month, int week)
    {
        int first_day_of_month = day_of_week(year, month, 1);
        int i;
        //第一周特殊处理 
        if(1 == week)
        {    for(i = 0; i < first_day_of_month; i++)
                printf("      ");
            printf("%6d", 1);
            
            for (i = 2; i + first_day_of_month < 8; i++)
                printf("%6d", i);
            return;
        }
        //计算该月第week周的星期天是几号
        int first_date_of_week = (week-2) * 7 + (7 - first_day_of_month + 1);
        
        //最多打印七天,且最大值不能超过这个月的天数
        int total_days = days_of_month(year, month); 
        if(first_date_of_week)
        for (i = 0; i < 7; i++)
        {
            int now = i + first_date_of_week;   //当前打印的日期
            if (now > total_days)
                printf("      ");   //日期超过了,就打印空格 
            else printf("%6d", now);
            
        } 
    }
    
    void print_date_of_year(int year)
    {    
        printf("                                                              Dates of %d
    ", year);
        //期望的格式是以网格的形式,单位为一个月,分四行,每行打印一个季度,
        int i, j, k;
        
        for(i = 0; i < 4; i++)
        {      
            for(j = 1; j <= 6; j++)
            {    
                if( 1 == j)
                {
                    for(k = 1; k <= 3; k++)
                    {
                        printf("                  ");
                        int month = i * 3 + k;
                        switch(month)
                        {
                            case 1: printf("January  ");    break;
                            case 2: printf("February ");    break;
                            case 3: printf("March    ");    break;
                            case 4: printf("April    ");    break;
                            case 5: printf("May      ");    break;
                            case 6: printf("June     ");    break;
                            case 7: printf("July     ");    break;
                            case 8: printf(" August  ");    break;
                            case 9: printf("September");    break;
                            case 10: printf("October  ");    break;
                            case 11: printf("November ");    break;
                            case 12: printf("December ");    break;
                            default: printf("Bad input of month, please enter a right month.
    "); return;
                        }
                        printf("                    ");        
                    }
                    printf("
    ");
                    printf("%s    ", DATE_HEADER);
                    printf("%s    ", DATE_HEADER);
                    printf("%s    ", DATE_HEADER);
                    printf("
    ");
                }
            
                for (k = 1; k <= 3; k++)
                {    
                    print_date_of_week(year, i * 3 + k, j);
                    printf("    ");
                    if (3 == k) printf("
    ");
                }
                printf("
    ");
            }
        } 
        
    }

      

  • 相关阅读:
    viewpager切换时底下的背景图标动画切换
    hdu 1594水题
    hdu 4256大水题
    hdu 1856并查集
    hdu4247水题
    hdu 4252单调栈
    hdu 4248排列问题
    hdu 1210
    hdu4245
    hdu 1593找规律题
  • 原文地址:https://www.cnblogs.com/yeyeck/p/9537220.html
Copyright © 2011-2022 走看看