我的C语言第一个项目:日历(深挖第八章及之前的基础)

fun.c文件

这段代码实现了一个日历打印功能,包含多个函数协同工作。下面对每个函数进行详细解释:

1. 判断闰年函数 isLeapyear

int isLeapyear(int year)
{
    return year%4==0&&year%100!=0||year%400==0;
}
  • 功能:判断一个年份是否为闰年
  • 闰年规则:
    • 能被4整除且不能被100整除,或者
    • 能被400整除
  • 返回值:如果是闰年返回1(真),否则返回0(假)

2. 获取月份天数函数 daysOfTheMonth

int daysOfTheMonth(int year,int month)
{
    int a[]={31,0,31,30,31,30,31,31,30,31,30,31};
    if(month<=0||month>=12)
    {
        return -1; // 月份无效返回-1
    }
    if(month!=2)
    {
        return a[month-1]; // 返回对应月份的天数(非2月)
    }
    else
    {
        return isLeapyear(year)?29:28; // 2月根据闰年判断28或29天
    }
}
  • 功能:计算指定年月的天数
  • 实现:
    • 用数组a存储1-12月的天数(2月用0占位)
    • 先判断月份是否有效(1-12月)
    • 非2月直接从数组获取天数
    • 2月调用isLeapyear判断是28天还是29天
  • 返回值:月份天数,无效月份返回-1

3. 计算自1900年以来的总天数 daysAfter1900

int daysAfter1900(int year,int month)
{
    int i;
    int days;
    int counter=0; // 计算闰年年数
    // 计算1900年到目标年份前一年的总天数
    for(i=1900;i<year;++i)
    {
        if(isLeapyear(i)!=0)
        {
            ++counter; // 统计闰年数量
        }				
    }
    // 计算完整年份的总天数:闰年366天,平年365天
    days=counter*366+(year-counter-1900)*365;
    
    // 计算目标年份中,到目标月份前一个月的总天数
    int j;
    int days2=0;
    int a[]={31,0,31,30,31,30,31,31,30,31,30,31};
    for(j=0;j<month-1;++j)
    {
        days2+=a[j]; // 累加前几个月的天数
    }
    // 加上2月的天数(根据闰年调整)
    if(isLeapyear(year)==1)
    {
        days2+=29;
    }
    else
    {
        days2+=28;
    }
    return days+days2; // 返回总天数
}
  • 功能:计算从1900年到指定年月的总天数(不含当月天数)
  • 实现步骤:
    1. 计算1900年到目标年份前一年的所有天数(区分闰年和平年)
    2. 计算目标年份中从1月到目标月份前一个月的总天数
    3. 累加两部分得到总天数
  • 用途:为计算月份第一天是星期几提供基础

4. 计算月份第一天是星期几 weekOfTheFirstDay

int weekOfTheFirstDay(int year,int month)
{
    int days;
    days=daysAfter1900(year,month);
    return (days+1)%7;
}
  • 功能:计算指定年月的第一天是星期几
  • 实现逻辑:
    • 基于daysAfter1900的结果(距离1900年的总天数)
    • 加1后对7取模(假设1900年1月1日是星期一)
  • 返回值:0表示星期日,1表示星期一,…,6表示星期六

5. 打印日历函数 printCalendar

void printCalendar(int year,int month)
{
    char str[20];
    sprintf(str,"%d",month);
    printf("    %s月 %4d年\n",str,year); // 打印月份和年份标题
    printf("日 一 二 三 四 五 六\n"); // 打印星期标题

    int a[6][7] = {0}; // 用6行7列数组存储日历数据
    int k, l = 0;
    int days = daysOfTheMonth(year, month); // 获取当月总天数
    int firstDay = weekOfTheFirstDay(year, month); // 当月第一天是星期几

    // 填充第一行数据
    for(k = 0; k < 7; ++k)
    {
        if(k < firstDay) {
            a[0][k] = 0; // 月初前的位置填0
        } else {
            if(l < days) {
                a[0][k] = ++l; // 填充日期
            } else {
                a[0][k] = 0;
            }
        }
    }

    // 填充剩余行
    for(int i = 1; i < 6; ++i)
    {
        for(int j = 0; j < 7; ++j)
        {
            if(l < days) {
                a[i][j] = ++l; // 继续填充日期
            } else {
                a[i][j] = 0; // 月末后的位置填0
            }
        }
        if(l >= days) break; // 所有日期已填完则退出
    }

    // 打印日历
    for(int o = 0; o < 6; ++o)
    {
        for(int p = 0; p < 7; ++p)
        {
            if(a[o][p] == 0) {
                printf("   "); // 0值显示为三个空格
            } else {
                printf("%2d ", a[o][p]); // 日期格式化输出
            }
        }
        printf("\n"); // 每行结束换行
    }
    printf("\n");
}
  • 功能:打印指定年月的日历
  • 实现步骤:
    1. 打印月份和年份标题,以及星期标题
    2. 创建6x7的二维数组存储日历数据(最多6行可容纳任何月份)
    3. 计算当月总天数和第一天是星期几
    4. 填充数组:
      • 第一行从第一天对应的星期位置开始填充
      • 后续行依次填充剩余日期
      • 非日期位置填充0
    5. 打印数组:0值显示为空格,日期格式化输出保持对齐

整个程序通过这几个函数的协作,能够准确计算并打印出指定年月的日历,考虑了闰年、每月不同天数以及星期几的正确对应关系。

fun.h

extern int isLeapyear(int year);
extern int daysOfTheMonth(int year,int month);
extern int daysAfter1900(int year,int month);
extern int weekOfTheFirstDay(int year,int month);
extern int printCalendar(int year,int month);

total.c

#include<stdio.h>
#include"fun.h"
int main(void)
{
	int year=2025;
	int month=10;
//	printf("%d\n",isLeapyear(year));
//	printf("%d\n",daysAfter1900(year,month));
//	printf("%d\n",weekOfTheFirstDay(year,month));
	printCalendar(year,month);
	return 0;

}


运行结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值