C語言列印年曆

Dylan~發表於2019-06-14

摘要:使用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 ("                                       ******************\n");
    printf ("                                              %d        \n", year);
    printf ("                                       ******************\n");
    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\n");
            printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun\n");
        }
        if (6 == i)
        {
            printf ("              Apr                             May                             Jun\n");
            printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun\n");
        }
        if (12 == i)
        {
            printf ("              Jul                             Agu                             Sep\n");
            printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun\n");
        }
        if (18 == i)
        {
            printf ("              Oct                             Nov                             Dec\n");
            printf ("  Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun     Mon Tue Wen Thu Fir Sat Sun\n");
        }
        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 ("\n");
    }
}

   程式碼展示完畢,大約只有7、80行吧,歡迎留言討論。

相關文章