怎么查询最新网站,三水网站建设哪家好,如何用代码制作小程序,全球十大购物平台名人说#xff1a;路漫漫其修远兮#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者#xff1a;Code_流苏(CSDN)#xff08;一个喜欢古诗词和编程的Coder#x1f60a;#xff09; 专栏介绍#xff1a;《编程项目实战》 目录 一、为什么要开发一个日历程序#xff… 名人说路漫漫其修远兮吾将上下而求索。—— 屈原《离骚》 创作者Code_流苏(CSDN)一个喜欢古诗词和编程的Coder 专栏介绍《编程项目实战》 目录 一、为什么要开发一个日历程序1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用 二、核心算法深度解析1. 基姆拉尔森公式时间计算的利器2. 闰年判断精确到每一天3. 月份天数计算处理边界情况 三、程序架构设计思路1. Color类颜色管理专家2. Calendar类核心业务逻辑3. CalendarApp类用户交互界面 四、完整代码实现五、功能特性详细展示1. 彩色日历显示2. 个人纪念日管理3. 完善的错误处理 六、编程技巧与扩展方向1. 核心技术亮点2. 可扩展功能方向 总结 ️ 写在前面日历作为我们日常生活中不可或缺的工具承载着时间的流转和重要时刻的记录。今天我们将用C从零开始构建一个功能完善的日历程序不仅能显示传统节假日和二十四节气还支持个人纪念日管理。让我们一起走进编程的时光隧道
一、为什么要开发一个日历程序
在这个数字化时代手机和电脑自带的日历已经非常便利但作为程序员我们总是希望能够亲手打造属于自己的工具。开发日历程序不仅能够
1. 深入理解时间算法
日历程序的核心在于时间计算特别是给定年月日如何计算星期几这个经典算法问题。我们将使用著名的基姆拉尔森公式来解决这个问题。这个公式虽然看起来复杂但其背后蕴含着深刻的数学原理。
2. 练习面向对象设计
通过设计Calendar类、Color类和CalendarApp类我们能够体验到面向对象编程的核心思想封装、继承和多态。这种设计让代码更加模块化、可维护。
3. 学习数据结构应用
程序中使用了map存储节假日数据vector管理纪念日列表这些都是STL容器在实际项目中的典型应用场景。
二、核心算法深度解析
1. 基姆拉尔森公式时间计算的利器
基姆拉尔森计算公式是一个用于计算指定日期是星期几的数学公式其表达式为 W (d 2*m 3*(m1)/5 y y/4 - y/100 y/400) mod 7
公式解读
d日期中的日数m月份数特别注意1月和2月要当作上一年的13月和14月y年份数W计算结果0星期日1星期一…6星期六
// 核心计算函数
int getFirstDayOfWeek(int y, int m) {// 处理1月和2月的特殊情况if (m 3) {m 12;y--;}int k y % 100;int j y / 100;int h (1 (13 * (m 1)) / 5 k k / 4 j / 4 - 2 * j) % 7;return (h 5) % 7; // 转换为星期一为1的格式
}2. 闰年判断精确到每一天
闰年的判断规则看似简单实则需要考虑多个条件
bool isLeapYear(int y) {return (y % 4 0 y % 100 ! 0) || (y % 400 0);
}规则解析
能被4整除且不能被100整除的年份是闰年能被400整除的年份也是闰年这个规则确保了400年中有97个闰年精确度极高
3. 月份天数计算处理边界情况
int getDaysInMonth(int y, int m) {int days[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};if (m 2 isLeapYear(y)) return 29;return days[m - 1];
}三、程序架构设计思路
基于面向对象设计原则我们将程序分为三个核心类 1. Color类颜色管理专家
class Color {
public:static void setRed() { cout \033[31m; } // 节假日专用红色static void setGreen() { cout \033[32m; } // 节气专用绿色static void setBlue() { cout \033[34m; } // 标题专用蓝色static void reset() { cout \033[0m; } // 重置颜色
};设计亮点使用ANSI转义序列实现终端颜色控制让程序界面更加生动美观。
2. Calendar类核心业务逻辑
这是程序的心脏负责
日期计算和验证节假日和节气数据管理日历格式化显示特殊日期查询功能
3. CalendarApp类用户交互界面
采用菜单驱动的设计模式提供友好的用户操作体验。
四、完整代码实现
以下是完整的程序代码确保在Dev-C中完美运行
#include iostream
#include iomanip
#include string
#include vector
#include map
#include cstdio
#include limits using namespace std;// 颜色控制类
class Color {
public:static void setRed() { cout \033[31m; }static void setGreen() { cout \033[32m; }static void setBlue() { cout \033[34m; }static void setYellow() { cout \033[33m; }static void setPurple() { cout \033[35m; }static void reset() { cout \033[0m; }
};// 日历核心类
class Calendar {
private:int year, month;mapstring, string holidays;mapstring, string solarTerms;vectorstring anniversaries;// 判断是否为闰年bool isLeapYear(int y) {return (y % 4 0 y % 100 ! 0) || (y % 400 0);}// 计算某年某月1号是星期几 (0星期日, 1星期一, ..., 6星期六)int getFirstDayOfWeekAdjusted(int y, int m) {if (m 3) {m 12;y--;}int w (1 y y / 4 - y / 100 y / 400 (13 * (m 1)) / 5) % 7;return (w 6) % 7;}// 初始化节假日数据void initHolidays() {holidays[01-01] 元旦; holidays[02-14] 情人节;holidays[03-08] 妇女节; holidays[03-12] 植树节;holidays[04-01] 愚人节; holidays[05-01] 劳动节;holidays[05-04] 青年节; holidays[06-01] 儿童节;holidays[07-01] 建党节; holidays[08-01] 建军节;holidays[09-10] 教师节; holidays[10-01] 国庆节;holidays[11-11] 光棍节; holidays[12-25] 圣诞节;}// 初始化二十四节气void initSolarTerms() {solarTerms[02-04] 立春; solarTerms[02-19] 雨水;solarTerms[03-05] 惊蛰; solarTerms[03-20] 春分;solarTerms[04-05] 清明; solarTerms[04-20] 谷雨;solarTerms[05-05] 立夏; solarTerms[05-21] 小满;solarTerms[06-05] 芒种; solarTerms[06-21] 夏至;solarTerms[07-07] 小暑; solarTerms[07-23] 大暑;solarTerms[08-07] 立秋; solarTerms[08-23] 处暑;solarTerms[09-07] 白露; solarTerms[09-23] 秋分;solarTerms[10-08] 寒露; solarTerms[10-23] 霜降;solarTerms[11-07] 立冬; solarTerms[11-22] 小雪;solarTerms[12-07] 大雪; solarTerms[12-22] 冬至;solarTerms[01-05] 小寒; solarTerms[01-20] 大寒;}// 格式化日期为MM-DD格式string formatDate(int m, int d) {char buffer[10];sprintf(buffer, %02d-%02d, m, d);return string(buffer);}public:Calendar() {initHolidays();initSolarTerms();}// **修改点2**: 将 getDaysInMonth 移动到 public 区域以便外部可以调用// 获取某月的天数int getDaysInMonth(int y, int m) {if (m 1 || m 12) return 0; // 增加对月份的健壮性判断int days[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};if (m 2 isLeapYear(y)) return 29;return days[m - 1];}void setDate(int y, int m) {year y;month m;}void addAnniversary(int m, int d, const string event) {char buffer[150];sprintf(buffer, %02d-%02d: %s, m, d, event.c_str());anniversaries.push_back(string(buffer));}void display() {cout \n;Color::setBlue();cout \n;cout year 年 setw(2) month 月 日历\n;cout \n;Color::reset();cout 日 一 二 三 四 五 六\n;cout ----------------------------\n;int firstDay getFirstDayOfWeekAdjusted(year, month);int daysInMonth getDaysInMonth(year, month);for (int i 0; i firstDay; i) {cout ;}for (int day 1; day daysInMonth; day) {string dateKey formatDate(month, day);bool isSpecial false;if (holidays.count(dateKey)) { Color::setRed(); isSpecial true; }else if (solarTerms.count(dateKey)) { Color::setGreen(); isSpecial true; }cout setw(3) day;if (isSpecial) Color::reset();cout ;if ((day firstDay) % 7 0) {cout \n;}}if ((daysInMonth firstDay) % 7 ! 0) cout \n;cout \n;displayLegend();displaySpecialDays();displayAnniversaries();}void displayLegend() {Color::setPurple();cout \n;cout 图例说明\n;cout \n;Color::reset();Color::setRed(); cout 红色; Color::reset(); cout - 节假日 ;Color::setGreen(); cout 绿色; Color::reset(); cout - 二十四节气\n\n;}void displaySpecialDays() {Color::setYellow();cout \n;cout 本月特殊日子\n;cout \n;Color::reset();bool hasSpecial false;for (int day 1; day getDaysInMonth(year, month); day) {string dateKey formatDate(month, day);if (holidays.count(dateKey)) {Color::setRed();cout month 月 day 日: holidays[dateKey] \n;Color::reset();hasSpecial true;}if (solarTerms.count(dateKey)) {Color::setGreen();cout month 月 day 日: solarTerms[dateKey] \n;Color::reset();hasSpecial true;}}if (!hasSpecial) cout 本月无特殊节日或节气\n;cout \n;}void displayAnniversaries() {if (!anniversaries.empty()) {Color::setPurple();cout \n;cout 个人纪念日\n;cout \n;Color::reset();// **修改点1**: 将 C11 的范围 for 循环改为 C98 兼容的传统 for 循环for (size_t i 0; i anniversaries.size(); i) {cout anniversaries[i] \n;}cout \n;}}void queryDate(int day) {if (day 1 || day getDaysInMonth(year, month)) {Color::setRed(); cout 无效的日期\n; Color::reset();return;}string dateKey formatDate(month, day);cout \n year 年 month 月 day 日信息\n;cout ----------------------------------------\n;int dayOfWeek (getFirstDayOfWeekAdjusted(year, month) day - 1) % 7;string weekDays[] {星期日, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六};cout 星期: weekDays[dayOfWeek] \n;if (holidays.count(dateKey)) {Color::setRed(); cout 节假日: holidays[dateKey] \n; Color::reset();}if (solarTerms.count(dateKey)) {Color::setGreen(); cout 节气: solarTerms[dateKey] \n; Color::reset();}if (dayOfWeek 0 || dayOfWeek 6) {Color::setBlue(); cout 提醒: 今天是周末\n; Color::reset();}cout \n;}
};// 主程序类
class CalendarApp {
private:Calendar calendar;void showMenu() {Color::setPurple();cout \n\n;cout 日历程序菜单\n;cout \n;Color::reset();cout 1. 显示日历\n;cout 2. 查询特定日期\n;cout 3. 添加纪念日\n;cout 4. 切换年月\n;cout 5. 帮助说明\n;cout 0. 退出程序\n;cout \n;cout 请选择操作: ;}void showHelp() {Color::setYellow();cout \n\n;cout 帮助说明\n;cout \n;Color::reset();cout 本程序功能说明\n;cout - 支持公历日历显示\n;cout - 自动标注中国传统节假日\n;cout - 显示二十四节气\n;cout - 支持个人纪念日管理\n;cout - 支持特定日期查询\n;cout - 自动识别闰年和周末\n\n;cout 使用说明\n;cout - 红色数字表示节假日\n;cout - 绿色数字表示二十四节气\n;cout - 可以添加个人重要纪念日\n;cout - 支持1900-2100年的日历显示\n\n;}bool inputDate(int year, int month) {cout 请输入年份 (1900-2100): ;cin year;if (cin.fail() || year 1900 || year 2100) {Color::setRed(); cout 年份输入无效或超出范围\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);return false;}cout 请输入月份 (1-12): ;cin month;if (cin.fail() || month 1 || month 12) {Color::setRed(); cout 月份输入无效或超出范围\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);return false;}return true;}void waitForEnter() {cout \n按回车键继续...;cin.ignore(numeric_limitsstreamsize::max(), \n);cin.get();}public:void run() {Color::setBlue();cout \n;cout 欢迎使用简易日历程序\n;cout \n;Color::reset();int currentYear 2024, currentMonth 1;cout 请先设置要查看的年月\n;while (!inputDate(currentYear, currentMonth)) {cout 请重新输入\n;}calendar.setDate(currentYear, currentMonth);int choice;do {showMenu();cin choice;while(cin.fail()){Color::setRed(); cout 无效的选择请输入菜单对应的数字\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);showMenu();cin choice;}switch (choice) {case 1:calendar.display();break;case 2: {int day;cout 请输入要查询的日期: ;cin day;if(cin.fail()){Color::setRed(); cout 日期输入无效请输入一个数字\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);break;}calendar.queryDate(day);break;}case 3: {int month, day;string eventName;cout 请输入纪念日月份: ;cin month;if (cin.fail()) {Color::setRed(); cout 月份输入无效请输入一个数字\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);break;}cout 请输入纪念日日期: ;cin day;if (cin.fail()) {Color::setRed(); cout 日期输入无效请输入一个数字\n; Color::reset();cin.clear();cin.ignore(numeric_limitsstreamsize::max(), \n);break;}cout 请输入纪念日名称: ;cin.ignore(numeric_limitsstreamsize::max(), \n);getline(cin, eventName);// 使用 calendar.getDaysInMonth 进行更精确的日期检查if (month 1 month 12 day 1 day calendar.getDaysInMonth(2024, month)) { // 2024年可以随便写只要是闰年检查即可或者用当前年份calendar.addAnniversary(month, day, eventName);Color::setGreen(); cout 纪念日添加成功\n; Color::reset();} else {Color::setRed(); cout 输入的日期范围无效\n; Color::reset();}break;}case 4: {int year, month;if (inputDate(year, month)) {calendar.setDate(year, month);Color::setGreen(); cout 日期切换成功\n; Color::reset();}break;}case 5:showHelp();break;case 0:Color::setBlue(); cout 感谢使用日历程序再见\n; Color::reset();break;default:Color::setRed(); cout 无效的选择请重新输入\n; Color::reset();break;}if (choice ! 0) {waitForEnter();}} while (choice ! 0);}
};int main() {CalendarApp app;app.run();return 0;
}五、功能特性详细展示
1. 彩色日历显示
程序采用ANSI颜色控制实现 红色数字传统节假日醒目标注 绿色数字二十四节气生动展示 蓝色标题界面层次分明 2. 个人纪念日管理
支持添加生日、结婚纪念日、重要约会等个人重要日期让日历更具个性化。 月份代指的是 — 月日期代指的是 — 日
3. 完善的错误处理
程序具备完善的输入验证机制
年份范围检查1900-2100月份合法性验证1-12日期有效性检查友好的错误提示信息 六、编程技巧与扩展方向
1. 核心技术亮点
面向对象设计采用单一职责原则每个类都有明确的功能定位。
STL容器运用
mapstring, string高效的节假日数据检索vectorstring动态的纪念日列表管理
算法优化基姆拉尔森公式的时间复杂度为O(1)相比传统的累加计算方法效率提升显著。
2. 可扩展功能方向
在原有功能基础上日历程序还可以进一步扩展
例如加入事件提醒与倒计时功能实现自动提示重要事项通过文件保存实现数据持久化确保信息在重启后不丢失结合Qt等GUI库构建图形界面提升用户体验此外还可接入网络API实现节假日信息的自动更新增强实用性与智能化程度。
总结
通过这个C日历程序的开发我们体验了从需求分析到代码实现从功能测试到用户体验的完整开发流程。
在当前C技术快速发展的2024-2025年掌握这样的项目开发经验对于提升编程能力和简历含金量都有重要意义。无论你是C初学者还是有经验的开发者这个项目都能为你的技术成长添砖加瓦。
希望这篇文章能够帮助你理解C编程的魅力也期待你能在此基础上开发出更加精彩的应用程序 技术提示完整代码已经过Dev-C环境测试确保兼容性。如果你在其他编译器中遇到问题主要检查头文件包含和编译器标准设置。 创作者Code_流苏(CSDN)一个喜欢古诗词和编程的Coder