首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C/C++ 實現萬年曆:基姆拉爾森公式計算星期與日歷打印

     編輯:關於C語言

項目需求

輸入年份與月份,輸出該月份完整日歷(含星期對齊)。支援循環查詢,直到用戶退出。

核心算法:基姆拉爾森公式

計算任意日期對應星期幾(0=周一 ... 6=周日,或 1=周日 ... 7=周六):


// 輸入:year, month (1-12), day (1-31)
// 注意:1、2 月視作上一年的 13、14 月
if (month == 1 || month == 2) {
    month += 12;
    year--;
}
// 公式
int w = (day + 2*month + 3*(month+1)/5 + year + year/4 - year/100 + year/400) % 7;
// 結果:0=周一, 1=周二, ..., 6=周日
// 若需 1=周日: w = (w + 6) % 7 + 1;

閏年判斷


bool is_leap(int y) {
    return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}

完整 C 語言實現(標準庫版)


#include <stdio.h>
#include <stdlib.h>

int days_in_month(int year, int month) {
    static const int dim[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    if (month == 2 && ((year%4==0 && year%100!=0) || year%400==0))
        return 29;
    return dim[month - 1];
}

int weekday_kim_larsen(int year, int month, int day) {
    if (month <= 2) { month += 12; year--; }
    return (day + 2*month + 3*(month+1)/5 + year + year/4 - year/100 + year/400) % 7;
    // 返回 0=Mon ... 6=Sun
}

void print_calendar(int year, int month) {
    int dim = days_in_month(year, month);
    int w = weekday_kim_larsen(year, month, 1);  // 1號星期幾
    // 轉換為 1=Sun ... 7=Sat 以便打印對齊
    int start_col = (w + 6) % 7 + 1;  // 1=Sun, 7=Sat

    printf("\n     %d 年 %2d 月 日曆\n", year, month);
    printf(" 日 一 二 三 四 五 六\n");
    printf("=========================\n");

    // 打印前導空格
    for (int i = 1; i < start_col; i++)
        printf("   ");

    // 打印日期
    for (int d = 1; d <= dim; d++) {
        printf("%2d ", d);
        if ((d + start_col - 1) % 7 == 0)
            printf("\n");
    }
    printf("\n");
}

int main(void) {
    int year, month;
    while (1) {
        printf("請輸入年份 (0 退出): ");
        if (scanf("%d", &year) != 1 || year == 0) break;
        printf("請輸入月份 (1-12): ");
        if (scanf("%d", &month) != 1 || month < 1 || month > 12) {
            printf("月份無效\n");
            while (getchar() != '\n');  // 清緩衝區
            continue;
        }
        print_calendar(year, month);
    }
    return 0;
}

關鍵實現細節

1. 星期對齊邏輯

基姆拉爾森公式返回 0=周一。日歷習慣以周日為列首:


// 公式結果 w (0=Mon..6=Sun) -> 列號 1=Sun..7=Sat
int col = (w + 6) % 7 + 1;

2. 輸入緩衝區清理

`scanf` 失敗時殘留字符需清理,否則陷入死循環:


while (getchar() != '\n');

3. 邊界測試

年份月份1號星期天數驗證
20242周四29閏年
20232周三28平年
20001周六31世紀閏年
19001周一31非閏年

C++ 版本(iomanip 格式化)


#include <iostream>
#include <iomanip>
using namespace std;

void print_calendar_cpp(int year, int month) {
    // ... 同邏輯 ...
    cout << "\n     " << year << " 年 " << setw(2) << month << " 月 日曆\n";
    cout << " 日 一 二 三 四 五 六\n";
    cout << "=========================\n";
    for (int i = 1; i < start_col; i++) cout << "   ";
    for (int d = 1; d <= dim; d++) {
        cout << setw(2) << d << ' ';
        if ((d + start_col - 1) % 7 == 0) cout << '\n';
    }
    cout << '\n';
}

擴展:蔡勒公式

另一經典公式(結果 0=周六...6=周五):


int zeller(int y, int m, int d) {
    if (m < 3) { m += 12; y--; }
    int c = y / 100, k = y % 100;
    return (d + 13*(m+1)/5 + k + k/4 + c/4 + 5*c) % 7;
}

兩公式本質等價,基姆拉爾森無需分離世紀/年份,代碼更簡潔。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved