万年历程序
新旧历界限为1752年9月
相关信息看论坛内
http://www.vcgood.com/bbs/forum_posts.asp?TID=2567
编译MinGW
gcc xcal.c -o xcal.exe –std=c99
windows下测试通过
[code]
/**********************************************************************/
/* project : 万年历 */
/* version : Ver 0.9 */
/* file : xcal.c */
/* author : xstar.wxb */
/* date : 2008/07/31 */
/* history : */
/**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
/* 星期 */
#define WEEKDAY "Su Mo Tu We Th Fr Sa"
/* 数字的ASCII码形式 */
char NUM[ 10 ] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
/* 月份 */
char *MONTH[ 12 ] = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
/* 月份数据 */
/* MONDAY[ 0 ] 为平年数据 */
/* MONDAY[ 1 ] 为闰年数据 */
/* MONDAY[ 2 ] 为特殊年份数据 1752年 */
int MONDAY[ 3 ][ 12 ] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 19, 31, 30, 31 }
};
/* 日期与星期对应结构 */
typedef struct _DAY {
int monthday;
int weekday;
} DAY;
/* 儒略历(Julian Calendar) 1 - 1751 */
int JulianCalendar(int year, int month, DAY *day);
/* 格里历(GregorianCalendar) 1753 - ... */
int GregorianCalendar(int year, int month, DAY *day);
/* 特殊的1752年 */
int Special1752(int year, int month, DAY *day);
/* 显示日历函数 */
int displaymonth(int year, int month, int days, DAY *day);
/* 主函数 */
int main(int argc, char *argv[])
{
int year = 0; /* 输入的年份(1 - 9999) */
int month = 0; /* 输入的月份(1 - 12) */
int days = 0; /* 返回值,输入月份的天数 */
DAY day[ 31 ]; /* 返回值,输入月份的日期和星期对应关系 */
/* 参数个数判断 */
if (argc != 3)
{
/* 错误的时候,显示用法 */
printf( "Usage: xcal month year\n" );
return -1;
}
/* 转换为数字 */
year = atoi( argv[ 2 ] );
month = atoi( argv[ 1 ] );
/* 判断输入的参数,简单判断 */
if ((year < 1) || (year > 9999))
{
printf( "1 <= year <= 9999\n" );
return -1;
}
/* 判断输入的参数,简单判断 */
if ((month < 1) || (month > 12))
{
printf( "1 <= month <= 12\n" );
return -1;
}
/* 判断输入的年份,调用适用的历法 */
if (year < 1752) {
/* 儒略历(Julian Calendar) 1 - 1751 */
days = JulianCalendar( year, month, &day[ 0 ] );
} else if (year == 1752) {
/* 特殊的1752年 */
days = Special1752( year, month, &day[ 0 ] );
} else if (year > 1752) {
/* 格里历(GregorianCalendar) 1753 - ... */
days = GregorianCalendar( year, month, &day[ 0 ] );
}
/* 显示日历 */
displaymonth( year, month, days, &day[ 0 ] );
return 0;
}
/* 儒略历(Julian Calendar) */
/* 公元1年1月1日为星期六 */
/* 1年1月1日 - 1752年9月2日 */
/* 1 3 5 7 8 10 12 为大月,31天 */
/* 4 6 9 11 为小月,30天 */
/* 2 能被4整除的年份为闰年,29天,其他年份为平年,28天 */
int JulianCalendar(int year, int month, DAY *day)
{
int leap = 0; /* 适用的月份数据 */
int firstday = 6; /* 每月1日的星期数 */
/* 是否为闰年,设置适用的月份数据 */
if ((year % 4) == 0)
{
leap = 1;
}
/* 计算每年的1月1日的星期数 */
/* 计算累加天数,1月1日: 前一年平年星期数累加一,前一年闰年星期数加二 */
/* year年1月1日 */
firstday = (5 + (5 * year - 1) / 4) % 7;
/* 计算month月1日的星期数 */
for (int i = 0; i < month - 1; i++)
{
firstday += MONDAY[ leap ][ i ];
}
/* year年month月1日 */
firstday = firstday % 7;
/* month月 */
for (int i = 0; i < MONDAY[ leap ][ month - 1 ]; i++)
{
day->monthday = i + 1;
day->weekday = (firstday + i) % 7;
day++;
}
/* 返回当月天数 */
return MONDAY[ leap ][ month - 1 ];
}
/* 格里历(GregorianCalendar) */
/* 公元1753年1月1日为星期一 */
/* 1752年9月14日 - 现在,现行历法标准 */
/* 1 3 5 7 8 10 12 为大月,31天 */
/* 4 6 9 11 为小月,30天 */
/* 2 能被4整除且不能被100整除或能被400整除的年份为闰年,29天,其他年份为平年,28天 */
int GregorianCalendar(int year, int month, DAY *day)
{
int leap = 0; /* 适用的月份数据 */
int firstday = 1; /* 每月1日的星期数 */
int days = 0; /* 累加天数 */
/* 是否为闰年,设置适用的月份数据 */
if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0))
{
leap = 1;
}
/* 计算每年的1月1日的星期数 */
/* 初始化 */
days = 0;
/* 计算累加天数,1月1日: 前一年平年星期数累加一,前一年闰年星期数加二 */
for (int n = 1753; n < year; n++)
{
if ((((n % 4) == 0) && ((n % 100) != 0)) || ((n % 400) == 0))
{
days += 2; /* 闰年 */
} else {
days++; /* 平年 */
}
}
/* year年1月1日 */
firstday = (firstday + days) % 7;
/* 计算month月1日的星期数 */
for (int i = 0; i < month - 1; i++)
{
firstday += MONDAY[ leap ][ i ];
}
/* year年month月1日 */
firstday = firstday % 7;
/* month月 */
for (int i = 0; i < MONDAY[ leap ][ month - 1 ]; i++)
{
day->monthday = i + 1;
day->weekday = (firstday + i) % 7;
day++;
}
/* 返回当月天数 */
return MONDAY[ leap ][ month - 1 ];
}
/* 推行新历法的时候为了消除历法和太阳周期的误差,1752年9月2日下一日期为1752年9月14日 */
/* 为计算方便这一年单独提取出来计算 */
/* 公元1752年1月1日为星期三 */
int Special1752(int year, int month, DAY *day)
{
int leap = 2; /* 适用的月份数据 特殊年份 */
int firstday = 3; /* 每月1日的星期数 */
/* 计算month月1日的星期数 */
for (int i = 0; i < month - 1; i++)
{
firstday += MONDAY[ leap ][ i ];
}
/* 1752年month月1日 */
firstday = firstday % 7;
/* 9月份特殊处理 */
if (month == 9)
{
/* month月 */
for (int i = 0; i < MONDAY[ leap ][ month - 1 ]; i++)
{
day->monthday = i + 1;
/* 1752年9月2日下一日期为1752年9月14日 */
if (day->monthday > 2)
{
day->monthday += 11;
}
day->weekday = (firstday + i) % 7;
day++;
}
/* 返回当月天数 */
return MONDAY[ leap ][ month - 1 ];
}
/* 其他月份的处理 */
for (int i = 0; i < MONDAY[ leap ][ month - 1 ]; i++)
{
day->monthday = i + 1;
day->weekday = (firstday + i) % 7;
day++;
}
/* 返回当月天数 */
return MONDAY[ leap ][ month - 1 ];
}
/* 显示日历函数 */
int displaymonth(int year, int month, int days, DAY *day)
{
int line = 0; /* 行 */
/* 显示用 */
char BUFF[ 6 ][ 21 ] = {
" ", /* 20 space */
" ",
" ",
" ",
" ",
" "
};
/* 初始化 */
line = 0;
/* 设置每行显示的内容 */
for (int i = 0; i < days; i++)
{
BUFF[ line ][ day[ i ].weekday * 3 ] = NUM[ day[ i ].monthday / 10 ];
BUFF[ line ][ day[ i ].weekday * 3 + 1 ] = NUM[ day[ i ].monthday % 10 ];
if (day[ i ].weekday == 6)
{
line++;
}
}
/* 显示 */
printf( " %s %4d\n", MONTH[ month - 1], year );
printf( "%s\n", WEEKDAY );
for (int i = 0; i < 6; i++)
{
printf( "%s\n", BUFF[ i ] );
}
return 0;
}
[/code]
>> 本文固定链接: http://www.vcgood.com/archives/2571
楼主发威啦。
风格很好,很佩服!我写的程序刚开始还蛮好,后来要更新升级什么的就乱了 。后来我自己看的都郁闷。搂主可以传授点经验么?
经验没什么啊!
找个好点的编程规范!严格遵守!
另外写完后,多做检查!格式化一下!
这个程序还可以规范一下的!比如接口的说明等!
另外接口参数有效性的判断等!这些都是需要完善一下的!所以版本暂时定为0.9版本!
另外还有两个功能没实现!
一是显示一年的年历!
当参数为一个的时候!参数为年份数据!
按
year
1 2 3
4 5 6
7 8 9
10 11 12
显示年历
二是显示当前月份!
当没有任何参数输入的时候!显示当前月份的月历!