一个日历核心算法的实现 前传1:日历算法C语言实现

这段代码是去年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;
}

About 寒江独钓雪

A man's freedom world!
This entry was posted in C学习笔记心得, 算法研究. Bookmark the permalink.

留下评论

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>