子任务4:确定程序所需的数据结构
经过以上分析可知,为了得到公历日期对应的星期、农历日期、节气、节日,程序需要预知以下数据:
1月1日的星期:weekday_2025;
1月1日的农历日期:lunar_start_date_2025;
每个农历月份的天数:lm_days_2025;
是否有农历闰月。若有,是几月:lm_leap_month_2025;
每个节气对应的公历日期:solar_terms_2025;
每个节日对应的公历日期或农历日期:feasts。
查阅得到这些信息,以合适的形式写进程序中即可。(把数据写进程序,称为数据“硬编码”,是比较糟糕的做法。但作为最初的探索,却是最快能够看到结果的。后续将分离程序与数据,解决数据“硬编码”的问题)
其中,除了weekday与feasts之外,其余都是每年有一份数据。其中,下一年的weekday可以轻而易举地按照上一年的weekday计算得到,因而只需要保存其中某一年的weekday,而不需要每年都保存一份。
节日feasts与年份无关,比如每年的国庆节都是10月1日、春节都是正月初一,因而也无需每年都保存一份。
其余数据,均与年份有关,需要每年保存一份。
日期表示
日期,是程序中的基本概念,完整的日期包含公历日期、农历日期、星期、节气、节日等多项成员。比如,可以表示为:
struct u_date_t {
short year;
char month;
char day;
};
struct full_date_t {
struct u_date_t solar_date;
struct u_date_t lunar_date;
char weekday;
char solar_term;
char feast;
};
这样做当然是可以的,但可能使程序代码显得冗长。由于T1任务中并没有用到full_date_t结构体的情形,为使程序代码简短,暂不考虑这样表示日期,但保留struct u_date_t结构体作为公历日期与农历日期统一的表示方式。
关键是要解决第2步中“预知数据”的表示及存储。
计算星期几所需的数据
每年1月1日是星期几,可以从1970年1月1日是星期几计算得到。因而,只需要存储weekday_1970即可。
const char weekday_1970 = 4; /* 1970年1月1日是星期四 */
节日对应的日期只需要月、日,可以表示为:
const struct feast_t {
enum {SOLAR, LUNAR} type;
struct u_date_t u_date;
const char * name;
} g_feasts[] = {
{SOLAR, {0, 1, 1}, "元旦"}, {LUNAR,{0, 1, 1}, "春节"},
{SOLAR, {0, 10, 1}, "国庆节"}, {LUNAR, {0,5,5}, "端午节"}
};
更多的节日按同样格式加到结构体数据中即可。借用之前定义的struct u_date_t结构体时,此处用不到其中的year成员,初始化为用不到的0即可。
每年需要单独存储的数据
以下4个数据每年需要单独存储:
1月1日的农历日期:lunar_start_date_2025;
每个农历月份的天数:lm_days_2025;
是否有农历闰月。若有,是几月:lm_leap_month_2025;
每个节气对应的公历日期:solar_terms_2025;
可以放到同一个struct中:
struct lunar_info_t {
struct u_date_t lunar_start_date;
char lm_days[12]; /* 12个农历月每月的天数 */
char lm_leap_month; /* 农历闰月的月份序号,无闰月时为0 */
char solar_terms[24]; /* 24个节气对应的公历日期 */
} g_lunar_info[130] = {……}; /* 从1970~2099共130年 */
完成以上两个struct之后,发现u_date_t.year到处都用不到,删除该成员,相应修改初始化数据。注意:这一步必须要等到最后再做,不要过早地下结论。这旧工作属于“优化”的范畴,过早优化是万恶之源。首先按部就班、不厌其烦地完成可以运行的程序,绝不在程序还不能运行之前开始优化,才是编程的正确做法。
基础数据
除了参与计算的数据之外,星期、农历月份与日期、节气在程序内部都使用整数表示,而输出时都需要转换成字符串,这类数据统一放到基础数据中。
const stuct base_info_t {
const char weekday_1970;
const char * wd_name[7];
const char * lm_name[12];
const char * ld_name[30];
const char * st_name[24];
} g_bi = {
.weekday_1970 = 4,
.wd_name = {"星期日", "星期一", "星期二","星期三","星期四","星期五", "星期六"},
.lm_name = {"正月", "二月","三月", "四月", "五月", "六月",
"七月", "八月", "九月", "十月", "冬月", "腊月"},
.ld_name = {"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八",
"初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六",
"十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四",
"廿五", "廿六", "廿七", "廿八", "廿九", "三十"},
.st_name = {"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨",
"立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑",
"白露", "秋分","寒露", "霜降", "立冬", "小雪", "大雪", "冬至"}
};
有了如上分析和数据基础,可以得到能够正确计算出每天是星期几,以及2025年每天对应农历日期的程序。
写出完整的C语言程序代码。
最新发布