摘要:使用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行吧,歡迎留言討論。