1. 程式人生 > >【C語言】第一個C語言小程式 —— 日期演算法和萬年曆

【C語言】第一個C語言小程式 —— 日期演算法和萬年曆

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);  //返回某年某月某日是當前年份第幾天
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); // 列印某年某月的日曆

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月的