You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻找计算指定月份首日的正确算法以修复C语言日历程序错误

日历程序修复方案

现有代码核心问题

  • 闰年判定错误:get_first_weekDay函数中遍历年份判断闰年时,误将输入的year作为判断对象,而非循环变量i,导致所有年份的闰年统计完全错误。
  • 前序月份天数统计错误:计算目标月份首日之前的总天数时,错误累加了当前月份的天数,且传参时仅传入了从目标月份开始的数组切片,读取前序月份天数时越界。
  • 基准值与计算逻辑不匹配:原设定1800年1月1日对应基准值beginning=3(对应表头中周三的偏移量),但错误的累加逻辑导致最终偏移值计算错误。

修复后的完整代码

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

// 修复后的计算首日星期几函数
int get_first_weekDay(int year, int target_month, int monthDays[])
{
    int total_days = 0;
    // 基准值:1800年1月1日是周三,对应表头Sun(0)的偏移为3
    int beginning = 3;
    // 累加目标月份之前所有月份的天数
    for(int i = 0; i < target_month; i++) {
        total_days += monthDays[i];
    }
    // 累加1800到输入年份前一年的总天数
    for (int i = 1800; i < year; i++)
    {
        if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
        {
            beginning += 366;
        }
        else
        {
            beginning += 365;
        }
    }
    return (beginning + total_days) % 7;
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        printf("Usage: ./calendar year month \n");
        return 1;
    }
    int year = atoi(argv[1]);
    int target_month = atoi(argv[2]) - 1;
    int day = 0, dayInMonth, weekDay = 0, startingDay, month;
    char *months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    int monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    // 处理闰年二月
    if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        monthDays[1] = 29;
    }
    // 传入完整的月份天数数组
    startingDay = get_first_weekDay(year, target_month, monthDays);
    for(month = 0; month < 12; month++)
    {
        if(target_month == month)
        {
            dayInMonth = monthDays[month];
            printf("           %s %d          \n ---------------------------", months[month], year);
            printf("\n Sun Mon Tue Wed Thu Fri Sat\n");
            for(weekDay = 0; weekDay < startingDay; weekDay++)
            {
                printf("    ");
            }
            for(day = 1; day <= dayInMonth; day++)
            {
                printf("%4d", day);
                if(++weekDay > 6)
                {
                    printf("\n");
                    weekDay = 0;
                }
            }
        }
    }
    printf("\n");
    return 0;
}

更高效的实现:蔡勒公式

如果不需要限制从1800年开始累加,可以使用专门计算星期几的蔡勒公式,代码更简洁且效率更高,不需要循环累加年份和月份:

// 蔡勒公式实现,返回值0=周日,1=周一...6=周六
int zeller(int year, int month) {
    if (month < 3) {
        month += 12;
        year--;
    }
    int c = year / 100;
    int y = year % 100;
    int m = month;
    int d = 1;
    int week = (y + y/4 + c/4 - 2*c + 26*(m+1)/10 + d - 1) % 7;
    // 处理负数结果
    return week < 0 ? week +7 : week;
}

直接替换get_first_weekDay函数调用即可使用。

内容的提问来源于stack exchange,提问作者Hyakkimaru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:36:05