zoukankan      html  css  js  c++  java
  • C语言打印年历

    使用C语言打印年历

      最初看到这个是觉得比较有意思,记得读书时候只写过月历,年历要复杂一些,现在水平提高了,来重新写一下吧。

      看了网上的一些代码,大都比较繁琐,本文采用全新的思路完成年历打印。

    整体思路:

      来看一下效果吧:

      

      看了一下网上的代码,思路大都是一行一行打印,这样涉及到月份,星期以及月首的空格打印都非常复杂,导致代码量庞大,并且逻辑非常复杂,本文旨在使用全新的思路,使用较好理解的代码,以及较少的代码量完成年历打印。

      先讲思路,我们知道,每月最多31天,打印出来5~6行(每行最多7个),传统方法复杂的原因在于只能逐行打印。本文使用一个21 X 24的二维数组(每个月占用7 X 6个空间),用来保存当月的日期,接下来上代码。

    代码解释:

      cal_first函数用来计算月首第一天是星期几,方便确定正确的打印位置。

    int cal_first(int y, int m)
    {
        int d = 1;
        if(m<=2) 
        {
            m += 12;
            y -= 1;
        }
        return (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7 + 1;
    }

      接下来是show_year函数,略微复杂。

    void show_year(int year)
    {
        int i,j,k,t,n;                           // 用来辅助计数
        int table[24][21] = {0};                     // 年历数组
        int month_day[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; // 每月上限天数
        if ((0 == year%4 || 0 == year%400) && 0 != year%100)    // 闰年检查,如果是闰年,2月上限天数改为29
        {   
            month_day[2] = 29;
        }
        printf ("                                       ******************
    ");
        printf ("                                              %d        
    ", year);
        printf ("                                       ******************
    ");
        for (i=0; i<12; i++)                        // 为了使逻辑更加清晰,一次循环只完成一个月的日期填写,i为当前月份
        {
            n = cal_first(i+1);                     // n为当前月份第一天的星期数,cal_first函数中的月数必须为1~12,
            for (j=(i/3)*6; j<(i/3)*6+6; j++)             // 所以这里传参时+1,j用来根据月数控制每个月在年历数组中的第一维坐标
            {                                // 坐标(纵坐标)的位置,同样的,用来根据月数控制每个月在年历数组中
                for (k=(i%3)*7; k<(i%3)*7+7; k++)          // 第二维坐标(横坐标)的位置
                {
                    t = (j%6)*7 + k%7 - n + 2;            // t用来临时记录当前位置应该填入年历数组的值,为了简化逻辑,这里通过
                    if (0 >= t)                     // 数学计算记录每一个位置应填入的值,(j%6)*7 + k%7计算出的值是本
                    {                           // 月的第几个位置,-n+2就会计算出当前格内正确的日期。这样做会导致得出
                        continue;                    // 负数或0,或炒熟每月天数上限,我们用if + continue将其跳过,这样
                    }                           // 不正确的日期就依然是年历数组初始化时的0
                    if (t <= month_day[i])
                    {
                        table[j][k] = t;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }
        for (i=0; i<24; i++)                      // 至此,年历数组已经全部填好,接下来是打印环节,相信已经比较好理解了
        {                                 //  每隔6行打印标头,7列多打印几个空格,遇到数组中为0则同样打印空格
            if (0 == i)
            {
                printf ("              Jan                             Feb                             Mar
    ");
                printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun
    ");
            }
            if (6 == i)
            {
                printf ("              Apr                             May                             Jun
    ");
                printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun
    ");
            }
            if (12 == i)
            {
                printf ("              Jul                             Agu                             Sep
    ");
                printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun
    ");
            }
            if (18 == i)
            {
                printf ("              Oct                             Nov                             Dec
    ");
                printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun
    ");
            }
            for (j=0; j<21; j++)
            {
                if (7 == j || 14 == j)
                {
                    printf ("    ");
                }
                if (0 == table[i][j])
                {
                    printf ("    ");
                    continue;
                }
                printf ("%4d", table[i][j]);
            }
            printf ("
    ");
        }
    }

       代码展示完毕,大约只有7、80行吧,欢迎留言讨论。

  • 相关阅读:
    hdu 1028 Ignatius and the Princess III (n的划分)
    CodeForces
    poj 3254 Corn Fields (状压DP入门)
    HYSBZ 1040 骑士 (基环外向树DP)
    PAT 1071 Speech Patterns (25)
    PAT 1077 Kuchiguse (20)
    PAT 1043 Is It a Binary Search Tree (25)
    PAT 1053 Path of Equal Weight (30)
    c++ 常用标准库
    常见数学问题
  • 原文地址:https://www.cnblogs.com/Dylan7/p/11025907.html
Copyright © 2011-2022 走看看