【C語言】第一個C語言小程式 —— 日期演算法和萬年曆
阿新 • • 發佈:2019-02-17
1. 寫了個萬年曆的功能練練手。還沒有寫互動的程式碼,只是把方法寫完了。先給出頭部和方法簽名
#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); //返回某年某月某日是當前年份第幾天 intdays_of_month(int, int); //返還某年某月有幾天 int day_of_week(int, int, int); //返回某年某月某日是星期幾,星期天返回0 _Bool is_leap_year(int); //返回當前年份是否為閏年 void print_date_of_month(int, int); // 列印某年某月的日曆
2.從最簡單的兩個方法開始
判斷閏年: 能整除400的年份 或者 能整除4,但是不能整除100的年份為閏年
//判斷是不是閏年 _Bool is_leap_year(int year) { return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); }
求某年莫個月份有多少天, 主要是閏年和平年在2月份的區別,閏年2月份有29天,平年2月份28天
//返回這個月一共有多少天 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]; //正常返回 }
從公元1年1月一日開始算,求某年某月某日是第幾天。
演算法:1.先算整年的部分:比如2018年,完整已經過了的年份有2017個,按平年算有 2017 * 365 天,但是其中閏年是366天,每個閏年少算了一天。1至2017有幾個閏年呢, 首先從閏年的定義:能整除400的年份 或者 能整除4,但是不能整除100的年份為閏年
閏年的數量 = 整除4的數量 - 整除100的數量 + 整除400的數量
所以最後的結果是 2017 * 365 + 閏年的數量 + 2018年1月1日到當前日期的天數
//返回這一天從公元元年算起是第幾天 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; }
從當前年份1月1日算起,某年某月某日是第幾天.
思路很簡單就是累加完整月的天數 + 當月日期
//返回這一天在當年是第幾天 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; }
計算某年某月某日是星際幾
因為公元元年1月1日是星期1,所以先算出從公元元年算起,當前日期是第幾天,然後對7求模,星期天的時候返回 0
int day_of_week(int year, int month, int day) { return get_days(year, month, day) % DAYS_PER_WEEK; }
列印某年某個月的日曆
//思路就是先確定當月1號是周幾,先列印1號,然後剩下的根據1號來推
//輸出某年某個月的日曆 void print_date_of_month(int year, int month) { //列印月份,為了讓月份顯示居中, 列印一些空格(根據列印星期的那行大概估算一下) printf(" "); switch(month) { case 1: printf("January\n"); break; case 2: printf("February\n"); break; case 3: printf("March\n"); break; case 4: printf("April\n"); break; case 5: printf("May\n"); break; case 6: printf("June\n"); break; case 7: printf("July\n"); break; case 8: printf("August\n"); break; case 9: printf("September\n"); break; case 10: printf("October\n"); break; case 11: printf("November\n"); break; case 12: printf("December\n"); break; default: printf("Bad input of month, please enter a right month.\n"); return; } //先把星期打印出來 printf("%s\n", 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("\n"); //列印剩下的日期 for(i = 1; i < days; i++) { printf("%6d", i + 1); //如果是星期六或者是最後一天,換行 if((first + i) % 7 == 6 || i + 1 == days) printf("\n"); } }
.最後附上完整程式碼
#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); // 列印某年某月的日曆 int main() { int days = get_days(2018, 5, 9) % DAYS_PER_WEEK; printf("%d\n", day_of_week(2018, 5, 9)); print_date_of_month(2018, 8); 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\n"); break; case 2: printf("February\n"); break; case 3: printf("March\n"); break; case 4: printf("April\n"); break; case 5: printf("May\n"); break; case 6: printf("June\n"); break; case 7: printf("July\n"); break; case 8: printf("August\n"); break; case 9: printf("September\n"); break; case 10: printf("October\n"); break; case 11: printf("November\n"); break; case 12: printf("December\n"); break; default: printf("Bad input of month, please enter a right month.\n"); return; } //先把星期打印出來 printf("%s\n", 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("\n"); //列印剩下的日期 for(i = 1; i < days; i++) { printf("%6d", i + 1); //如果是星期六或者是最後一天,換行 if((first + i) % 7 == 6 || i + 1 == days) printf("\n"); } }
跑起來測試結果, 列印的日曆是2018年8月的