这段代码是去年5月花了2天写的,主要是日历、星期的算法试验 。今天碰巧翻出来看到了,若不是随意一翻,真都差点忘掉。
忘掉可不好,可能哪天用上,还是在此做个记录免得忘掉。
记得前面写了篇日历算法相关的文章( 一个日历核心算法的实现),没写完,那个就是根据这个来写的。做这个实际上是为了写JavaScript日历实现,先贴代码,等过段时间有空了,再回头补充这两篇文章。
/**
* 日历,星期 算法试验
* @version 2009-05-06 ~ 07 yhl.lxrm@gmail.com
*/
#include <stdio.h>
#include <stdlib.h>
/**
* 构造日子数据结构
*/
struct DayNode{
int isEmpty;
int day;
int week;
int safeType;
};
typedef struct DayNode SafeDayNode;
/**
* 日期存放结构
*/
struct dateNode{
int year;
int month;
int day;
};
typedef struct dateNode DateNode;
// 给定年月获取当月天数
int getMDay(int y, int m)
{
int mday[12]= {31,28,31,30,31,30,31,31,30,31,30,31} ;
if (( 0 == y % 4 && 0 != y % 100) || 0 == y % 400)
mday[1] = 29;
return mday[m-1];
}
// 获取星期数,0对应星期天 ,1对应星期一,其他类推
int week(int y, int m, int d)
{
int wk ,date_offset=d,im,tmp=0;
if (m <= 12 && m >=1 )
{
for(im=1; im < m; ++im)
{
date_offset += getMDay(y,im);
}
}
//printf("日期偏移量 C = %d \n",date_offset);
/*根据日期计算星期的公式*/
wk = (y-1 + (y - 1)/ 4 - (y - 1) / 100 + (y - 1) / 400 + date_offset ) % 7;
//printf("星期 %d :\n",wk);
return wk;
}
以上是需要用到的功能函数,下面给出日历核心算法的具体实现:
int main(int argc, char *argv[])
{
char wk[7][3] = {"天","一","二","三","四","五","六"};
int y,m,d,w,i=0,j=0,k=0,tabs = 0;
char c=' ';
/*
printf("输入#号结束!\n\n");
while((c=getchar())!= '#'){}
*/
do {
printf("\n请输入年:");
scanf("%d",&y);
printf("\n请输入月:");
scanf("%d",&m);
printf("\n请输入日:");
scanf("%d",&d);
w = week(y,m,d);
printf("\n\t%d年%d月 有 %d 天 \n",y,m,getMDay(y,m));
printf("\n\t%d年%d月%d日 星期 %s\n\n",y,m,d,wk[w]);
/* {{{ start 日历算法 */
/**
* 算出每一行的天日,按照 周天、周一 ...周六的次序
*/
int w_day_start,w_day_end, mDays = getMDay(y,m);
w_day_start = week(y,m,1); // 1号的星期
w_day_end = week(y,m,mDays); // 月底最后一天的星期
/*
printf("\n 1 号星期 %d \n %d 号星期 %d \n" ,w_day_start,mDays,w_day_end);
*/
/**
* 计算日历中间总行数
* 总行数 = 中间总行数 + 加上首尾两行
* 列数为7,按一周天数算
*/
int v_Line = 0,v_Column = 7;
int d_mid_start_first = (7 - w_day_start) + 1;
int d_mid_start_last = (mDays - w_day_end) - 7;
v_Line = (d_mid_start_last - d_mid_start_first)/7 + 1 + 2;
//printf("\n本月行数: %d \n", v_Line);
/*
printf("\n 本月总天数 %d \n 中间起始日期 %d 星期 %d \n 中间结束日期 %d 星期 %d \n ",
mday[d],
d_mid_start_first, week(y,m,d_mid_start_first) ,
d_mid_start_last , week(y,m,d_mid_start_last) );
*/
struct DayNode dnode_array[v_Line][v_Column];
/**
* 计算首行、尾行的空位数
*/
int empty_pre,empty_rear;
empty_pre = w_day_start;
empty_rear = 6 - w_day_end;
/*
printf("\n 首行空位数:%d \n 尾行空位数:%d \n", empty_pre, empty_rear);
*/
/**
* 初始化数组
*/
int iL,iC,iDay=1;
SafeDayNode tmpNode;
for(iL = 0; iL < v_Line; ++iL){
for(iC = 0; iC < v_Column; ++iC)
{
if ( (iL == 0 && empty_pre > 0 && iC < w_day_start ) /*首行 */ ||
(iL == v_Line - 1 && empty_rear> 0 && w_day_end < iC) /* 尾行 */
)
{
tmpNode.isEmpty = 1; /* 空位 */
tmpNode.day = 0;
tmpNode.week = 0;
tmpNode.safeType = -1; /* 需要另行调用函数计算 */
}else{
tmpNode.isEmpty = 0; /* 非空位 */
tmpNode.day = iDay;
tmpNode.week = week(y,m,iDay);
tmpNode.safeType = -1; /* 需要另行调用函数计算 */
++iDay;
}
dnode_array[iL][iC] = tmpNode;
}
}
/* }}} end 日历算法 */
// 下面开始打印日历
for(i = 0; i < 7; ++i){
printf("%5s",wk[i]);
}
for(i = 0;i < v_Line; ++i)
{
printf("\n");
for(j = 0; j < v_Column; ++j)
{
if (!dnode_array[i][j].isEmpty)
printf("%5d",dnode_array[i][j].day);
else
printf(" ");
}
}
printf("\n\n是否结束?y/n : ");
scanf("%s",&c);
printf("\n\n");
if ('y'==c)break;
}while(1);
system("PAUSE");
return 0;
}