日历的各种C语言实现方法
方法一:基础版日历(指定年月)
cpp
#include <stdio.h>
// 判断是否为闰年
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 获取某年某月的天数
int getDaysInMonth(int year, int month) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) {
return 29;
}
return days[month - 1];
}
// 计算某年某月1日是星期几 (0=周日, 1=周一, ..., 6=周六)
int getFirstDayOfWeek(int year, int month) {
int day = 1;
// 使用Zeller公式
if (month < 3) {
month += 12;
year--;
}
int k = year % 100;
int j = year / 100;
int h = (day + 13*(month + 1)/5 + k + k/4 + j/4 + 5*j) % 7;
return (h + 6) % 7; // 转换为0=周日, 1=周一, ..., 6=周六
}
// 打印日历
void printCalendar(int year, int month) {
printf("\n %d年%d月\n", year, month);
printf("日 一 二 三 四 五 六\n");
int firstDay = getFirstDayOfWeek(year, month);
int daysInMonth = getDaysInMonth(year, month);
// 打印前面的空格
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
// 打印日期
for (int day = 1; day <= daysInMonth; day++) {
printf("%2d ", day);
if ((day + firstDay) % 7 == 0) {
printf("\n");
}
}
printf("\n");
}
int main() {
int year, month;
printf("请输入年份: ");
scanf("%d", &year);
printf("请输入月份: ");
scanf("%d", &month);
if (month < 1 || month > 12) {
printf("月份输入错误!\n");
return 1;
}
printCalendar(year, month);
return 0;
}
方法二:全年日历显示
cpp
#include <stdio.h>
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int getDaysInMonth(int year, int month) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) {
return 29;
}
return days[month - 1];
}
int getFirstDayOfWeek(int year, int month) {
int day = 1;
if (month < 3) {
month += 12;
year--;
}
int k = year % 100;
int j = year / 100;
int h = (day + 13*(month + 1)/5 + k + k/4 + j/4 + 5*j) % 7;
return (h + 6) % 7;
}
void printMonthCalendar(int year, int month) {
char *monthNames[] = {"一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"};
printf("\n %s %d\n", monthNames[month-1], year);
printf("日 一 二 三 四 五 六\n");
int firstDay = getFirstDayOfWeek(year, month);
int daysInMonth = getDaysInMonth(year, month);
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
for (int day = 1; day <= daysInMonth; day++) {
printf("%2d ", day);
if ((day + firstDay) % 7 == 0) {
printf("\n");
}
}
printf("\n");
}
void printYearCalendar(int year) {
printf("\n========== %d年日历 ==========\n", year);
for (int month = 1; month <= 12; month++) {
printMonthCalendar(year, month);
if (month % 3 == 0) {
printf("\n");
}
}
}
int main() {
int year;
printf("请输入年份: ");
scanf("%d", &year);
printYearCalendar(year);
return 0;
}
方法三:季度日历显示
cpp
#include <stdio.h>
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int getDaysInMonth(int year, int month) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) {
return 29;
}
return days[month - 1];
}
int getFirstDayOfWeek(int year, int month) {
int day = 1;
if (month < 3) {
month += 12;
year--;
}
int k = year % 100;
int j = year / 100;
int h = (day + 13*(month + 1)/5 + k + k/4 + j/4 + 5*j) % 7;
return (h + 6) % 7;
}
void printQuarterCalendar(int year, int quarter) {
char *monthNames[] = {"一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"};
printf("\n========== %d年第%d季度 ==========\n", year, quarter);
int startMonth = (quarter - 1) * 3 + 1;
int endMonth = startMonth + 2;
for (int month = startMonth; month <= endMonth; month++) {
printf("\n %s %d\n", monthNames[month-1], year);
printf("日 一 二 三 四 五 六\n");
int firstDay = getFirstDayOfWeek(year, month);
int daysInMonth = getDaysInMonth(year, month);
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
for (int day = 1; day <= daysInMonth; day++) {
printf("%2d ", day);
if ((day + firstDay) % 7 == 0) {
printf("\n");
}
}
printf("\n");
}
}
int main() {
int year, quarter;
printf("请输入年份: ");
scanf("%d", &year);
printf("请输入季度(1-4): ");
scanf("%d", &quarter);
if (quarter < 1 || quarter > 4) {
printf("季度输入错误!\n");
return 1;
}
printQuarterCalendar(year, quarter);
return 0;
}
方法四:带当前日期标记的日历
cpp
#include <stdio.h>
#include <time.h>
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int getDaysInMonth(int year, int month) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) {
return 29;
}
return days[month - 1];
}
int getFirstDayOfWeek(int year, int month) {
int day = 1;
if (month < 3) {
month += 12;
year--;
}
int k = year % 100;
int j = year / 100;
int h = (day + 13*(month + 1)/5 + k + k/4 + j/4 + 5*j) % 7;
return (h + 6) % 7;
}
void printCalendarWithToday(int year, int month) {
// 获取当前日期
time_t t = time(NULL);
struct tm *today = localtime(&t);
int current_year = today->tm_year + 1900;
int current_month = today->tm_mon + 1;
int current_day = today->tm_mday;
printf("\n %d年%d月", year, month);
if (year == current_year && month == current_month) {
printf(" (当前月份)");
}
printf("\n");
printf("日 一 二 三 四 五 六\n");
int firstDay = getFirstDayOfWeek(year, month);
int daysInMonth = getDaysInMonth(year, month);
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
for (int day = 1; day <= daysInMonth; day++) {
// 标记当前日期
if (year == current_year && month == current_month && day == current_day) {
printf("[%2d]", day); // 用方括号标记今天
} else {
printf("%2d ", day);
}
if ((day + firstDay) % 7 == 0) {
printf("\n");
}
}
printf("\n");
}
int main() {
int year, month;
printf("请输入年份: ");
scanf("%d", &year);
printf("请输入月份: ");
scanf("%d", &month);
if (month < 1 || month > 12) {
printf("月份输入错误!\n");
return 1;
}
printCalendarWithToday(year, month);
return 0;
}
方法五:命令行交互式日历
cpp
#include <stdio.h>
#include <stdlib.h>
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int getDaysInMonth(int year, int month) {
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isLeapYear(year)) {
return 29;
}
return days[month - 1];
}
int getFirstDayOfWeek(int year, int month) {
int day = 1;
if (month < 3) {
month += 12;
year--;
}
int k = year % 100;
int j = year / 100;
int h = (day + 13*(month + 1)/5 + k + k/4 + j/4 + 5*j) % 7;
return (h + 6) % 7;
}
void printCalendar(int year, int month) {
char *monthNames[] = {"一月", "二月", "三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "十一月", "十二月"};
printf("\n┌─────────────────────┐\n");
printf("│ %s %d │\n", monthNames[month-1], year);
printf("├─────────────────────┤\n");
printf("│日 一 二 三 四 五 六 │\n");
printf("├─────────────────────┤\n");
int firstDay = getFirstDayOfWeek(year, month);
int daysInMonth = getDaysInMonth(year, month);
printf("│");
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
for (int day = 1; day <= daysInMonth; day++) {
printf("%2d ", day);
if ((day + firstDay) % 7 == 0 && day != daysInMonth) {
printf("│\n│");
}
}
// 填充剩余空格
int remaining = (7 - (daysInMonth + firstDay) % 7) % 7;
for (int i = 0; i < remaining; i++) {
printf(" ");
}
printf("│\n");
printf("└─────────────────────┘\n");
}
void showMenu() {
printf("\n========== 日历系统 ==========\n");
printf("1. 查看指定年月日历\n");
printf("2. 查看全年日历\n");
printf("3. 查看当前月份\n");
printf("4. 退出\n");
printf("请选择操作: ");
}
int main() {
int choice;
int year, month;
while (1) {
showMenu();
scanf("%d", &choice);
switch (choice) {
case 1:
printf("请输入年份: ");
scanf("%d", &year);
printf("请输入月份: ");
scanf("%d", &month);
if (month >= 1 && month <= 12) {
printCalendar(year, month);
} else {
printf("月份输入错误!\n");
}
break;
case 2:
printf("请输入年份: ");
scanf("%d", &year);
for (month = 1; month <= 12; month++) {
printCalendar(year, month);
}
break;
case 3:
{
time_t t = time(NULL);
struct tm *now = localtime(&t);
year = now->tm_year + 1900;
month = now->tm_mon + 1;
printCalendar(year, month);
}
break;
case 4:
printf("感谢使用日历系统!\n");
exit(0);
default:
printf("无效选择,请重新输入!\n");
}
}
return 0;
}
各版本特点总结
-
基础版:最简单的实现,适合初学者理解日历算法
-
全年版:显示整年日历,便于查看全年日期分布
-
季度版:按季度显示,适合商业和学术用途
-
标记版:突出显示当前日期,实用性更强
-
交互版:完整的命令行程序,提供友好的用户界面
核心技术点
-
闰年判断:使用标准的闰年判断规则
-
Zeller公式:计算某天是星期几的经典算法
-
日期对齐:正确处理每月1日的星期位置
-
用户交互:提供多种查看方式和友好的界面