最初看到這個是以爲比較有意思,記得讀書時候只寫過月曆,年曆要複雜一些,如今水平提升了,來從新寫一下吧。數組
看了網上的一些代碼,大都比較繁瑣,本文采用全新的思路完成年曆打印。函數
來看一下效果吧:spa
看了一下網上的代碼,思路大都是一行一行打印,這樣涉及到月份,星期以及月首的空格打印都很是複雜,致使代碼量龐大,而且邏輯很是複雜,本文旨在使用全新的思路,使用較好理解的代碼,以及較少的代碼量完成年曆打印。code
先講思路,咱們知道,每個月最多31天,打印出來5~6行(每行最多7個),傳統方法複雜的緣由在於只能逐行打印。本文使用一個21 X 24的二維數組(每月佔用7 X 6個空間),用來保存當月的日期,接下來上代碼。blog
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函數,略微複雜。table
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"); } }
代碼展現完畢,大約只有七、80行吧,歡迎留言討論。class