一、整体功能概述
使用 C 语言代码实现一个基本的日历查询并打印功能。用户可以通过输入指定的年份和月份,程序就能准确地输出该月对应的日历样式,展示出每一天以及对应的星期分布情况,就像我们平常查看纸质日历一样直观。
二、代码结构分析
(一)判断闰年函数 - isLeapYear
int isLeapYear(int year)
{
int flag = 0;
if (year % 4 == 0 && year % 100!= 0 || year % 400 == 0)
{
flag = 1;
}
return flag;
}
这个函数的功能就是判断给定的年份是否为闰年。按照闰年的规则,如果年份能被 4 整除但不能被 100 整除,或者能被 400 整除,那该年份就是闰年。在函数内部,通过定义一个标志变量 flag
,初始化为 0,当满足闰年条件时将其置为 1,最后返回这个标志值,后续其他函数会根据这个返回值来做相应的处理,比如涉及 2 月天数的计算等。
(二)获取月份对应天数函数 - getMonthDays
int getMonthDays(int year, int month)
{
int a[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return (month == 2)? a[month - 1] + isLeapYear(year) : a[month - 1];
}
它的主要作用是获取指定年份中某个月份对应的天数。首先定义了一个数组 a
,存储了非闰年情况下各个月份的天数。然后通过一个三目运算符来判断,如果当前月份是 2 月,那就需要根据该年份是否为闰年(通过调用 isLeapYear
函数判断)来决定 2 月的天数(闰年 29 天,非闰年 28 天),对于其他月份则直接返回数组中对应的天数。
(三)获取与 1990 年 1 月相差天数函数 - getAllDays
int getAllDays(int year, int month)
{
int i = 0, days = 0;
for (i = year; i > 1990; i--)
{
days += isLeapYear(i - 1) + 365;
}
for (i = 1; i < month; i++)
{
days += getMonthDays(year, i);
}
return days;
}
此函数用于计算输入的年份和月份与 1990 年 1 月相差的总天数。它通过两个循环来实现,第一个循环从输入的年份往前逐年递减到 1990 年,在每一年中把该年的天数(平年 365 天,闰年通过 isLeapYear
函数判断后加上 1 天)累加到 days
变量中;第二个循环则是从 1 月开始到输入月份的前一个月,将每个月的天数(通过调用 getMonthDays
函数获取)累加到 days
中,最终返回这个总天数,这个天数在后续判断起始星期时会起到关键作用。
(四)判断起始星期函数 - getWeekday
int getWeekday(int year, int month)
{
int begin = getAllDays(year, month) % 7;
return begin;
}
函数的目标是确定给定年份和月份对应的日历开头需要空出几个空格,也就是判断该月 1 号对应的是星期几。通过调用 getAllDays
函数获取与 1990 年 1 月相差的天数,然后对 7 取余,得到的余数就对应着星期几(0 代表星期日,1 代表星期一,以此类推),最后返回这个余数用于后续日历的排版打印。
(五)打印日历函数 - printMonthCal
void printMonthCal(int year, int month)
{
printf(" %d %d \n ", month, year);
printf("一 二 三 四 五 六 日\n");
int i = 0;
int j;
for (i = 0; i < getWeekday(year, month); i++)
{
printf(" ");
}
for (i = 1; i <= getMonthDays(year, month); i++)
{
printf(" %2d ", i);
if ((i + getWeekday(year, month)) % 7 == 0)
putchar('\n');
}
putchar('\n');
}
这是整个程序的 “展示窗口”,负责把日历真正打印出来呈现给用户。首先打印出年份和月份的标题信息,然后打印出星期的表头(从星期一到星期日)。接着通过循环,根据 getWeekday
函数返回的起始星期情况先输出相应数量的空格,来保证日历排版的整齐。之后再循环打印出该月每一天的日期数字,并且每当打印的天数与起始星期的和能被 7 整除时,就换行,实现了日历按星期排版的效果,最后再输出一个换行符保证整体格式的美观。
(六)主函数 - main
int main(void)
{
int year, month;
printf("请输入要查询日历的年份和月数:");
scanf("%d %d", &year, &month);
// printf("%d\n", getMonthDays(year, month));
// printf("%d\n", getAllDays(year, month));
// printf("%d\n", getWeekday(year, month));
printMonthCal(year, month);
return 0;
}
主函数作为程序的入口,先是提示用户输入想要查询日历的年份和月份,通过 scanf
函数接收用户的输入值,然后调用 printMonthCal
函数将对应年份和月份的日历打印出来,完成整个程序的功能流程。
三、总结与拓展
通过编写以上代码,可以看到 C 语言在实现逻辑相对复杂、涉及日期计算和排版打印等功能时的强大表现力。当然,这段代码还有很多可以优化和拓展的地方,比如可以增加输入合法性的判断,防止用户输入不合理的年份或月份数值;还可以进一步美化日历的输出格式,使其更加接近我们日常使用的精美日历样式等。通过分析问题和实践编写代码,我更好地掌握 C 语言中的函数调用、循环、条件判断等基础知识点,并且能够运用到自己的编程实践中去,开发出更多有趣又实用的小项目。