万年历算法的实现(C语言--gcc编译)

/*
* cal.c 

*
现行的格里历是从儒略历演化而来的。儒略历每4年一个润年,润年366天,平年365天。
*
如果从公元1年算的话,那么凡是能够被4整除的都是润年。从天文角度看,儒略历这种 
*
历法是有误差的,到16世纪误差已经达到了10天。1582年,罗马教皇对儒略历进行了 
*
一次校定,该年的10-5到10-14这10天被抹掉,并规定凡不能被400整除的世纪年不再 
*
算为润年,校定之后的儒略历即为现行的格里历。 

*
但是英国直到1752年才开始使用格里历,此时时间误差已经达到了11天,原因是1700 
*
年在儒略历中是润年,而在格里历中是平年。1752年英国议会决定将本年的9-3到9-13 
*
这11天抹掉,以同步格里历。当时美国不是英国的殖民地,所以在美国的日历中也是没有 
*
1752-9-3到1752-9-13这11天的。 我们知道UNIX系统源于美国,Linux系统源于UNIX, 
*
这就是为什么当我们在Linux系统中敲"cal 9 1752"这条命令时,会看到一个只有19天 
*
的9月。 

*
以上内容参考自维基百科 

*       
本程序模似Linux中cal命令的部分功能。允许输入的年分为1...9999。 
*       
编译器:gcc
V4.5.0 

*       
分析: 
*           
1752年是特殊年,1752-9月是特殊年中的特殊月。 

*           
1752-9-2之前,采用的是儒略历,凡能被4整除都为润年;1752-9-14之后,采用的是 
*           
格里历,不能被400整除的世纪年不再作为润年。 

*           
格里历闰年计算方法 
*           
世纪年     ***4000的倍数    
**3200/1900的倍数     400的倍数    
100的倍数    
4的倍数 
*            
结果         不闰      
        不闰            
  闰            不闰
        闰

*           
注: 
*               
3200/1900的倍数是天文科学家研究出来 
*               
增加4000的倍数不闰更准确,但目前只是世纪年还不足4000,因此尚未用途 

*           
格里历在400年的周期中有146,097天,恰好是20,871
星期。所以,例如,格里历七年、 
*           
407年、807年、1207年、1607年、2007年的日期与星期是完全相同的。也就是说,格里 
*           
历每400年一个周期。 

*           
公元1-1-1,按儒略历是周六,按格里历是周一;因1752-9-2之前采用的都是儒略历,所以 
*           
公元1-1-1应该是周六。 
*           
1752-9-14是周四。 
*        
   
*           
公元1-1-1到1752-9-2,日期是连续的,儒略历;公元1752-9-14至今,日期是连续的,格里历。 

*           
对于给定的一个 年(Y)-月(M)-日(D) ,则从公元1-1-1到   
给定的日期的天数为: 
*               
1752-9-2前:365*(Y-1)+(Y-1)/4+e,其中e表示从Y-1-1到Y-M-D的天数, 
*               
且这天是该周的第((Y-1)+(Y-1)/4+5+e)%7天。 
*        
   
*               
1752-9-14后:365*(Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e, 
*               
且这天是该周的第((Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e)%7天。 
*    
   
   
*           
需要注意的是,从1-1-1到1752-9-14之后的某个日期的天数并非实际的天数,它只是根据格里历的 
*           
的规则推算出来的,目的也只是为了得到日期与星期的对应。 

*       
算法思想: 
*           
对于年历,若能知道本年的1月1日是周几,也就知道了本年的年历分布。 
*           
对于月历,若能知道本月的1日是周几,也就知道了本月的月历分布。 
*           
所以关键是正确的推算出给定的一个日期是星期几。以下为推算方法: 
*               
1752-9-2之前:((Y-1)+(Y-1)/4+5+e)%7 
*               
1752-9-14之后:((Y-1)+(Y-1)/4-(Y-1)/100+(Y-1)/400+e)%7 
*           
把1800-2199年当成一个周期,对于其后的日期,只需在1800-2199之间找到 
*           
对应的日期,就可以知道是星期几,这样就不用再考虑4000年之后4000的倍数 
*           
不是润年这种情况。 (Y-1800)%400+1800 
*/
 
#include
<stdio.h>
#include <string.h>
#include <time.h>
void
PrintHelp();
int*
CurrentCal();
int CheckYear(int year);
int CheckMonth(int month);
int CheckDay(int year, int month, int day);
int IsNum(char *argv);
int
IsLegalParameter(int argc, char **argv);
long
StrToLong(char *argv);
long
Power(int baseNumber, int
exponent);
void PrintCalendar(int year);
void PrintCommonCalendar(int
year, int row);
void
PrintOneQuarter(int year, int
mfOfWeek, int mfDays, int
msOfWeek,
        int msDays, int mtOfWeek, int mtDays, int row);
void Print1752_3Quarter();
void
PrintMonthlyCalendar(int year, int month);
void PrintMonthName(char *, int year);
void PrintCommonMonthlyCalendar(int
dayOfWeek, int days);
void
PrintDayOfWeek(int year, int
month, int day);
int
DayOfWeek(int year, int
month, int day);
int
CurrentDays(int year, int
month, int day);
int
a;
int main(int argc, char **argv) {
    int year, month, day;
    int flag =
IsLegalParameter(argc, argv);
    switch (flag) {
    case -1:
   
    printf("Syntax
Error!\n\n");
        PrintHelp();
 
      break;
 
  case 0:
   
    PrintMonthlyCalendar(*(CurrentCal()), *(CurrentCal() + 1));
        break;
 
  case 1: {
   
    a = strlen(*(argv
+ 1));
 
      switch (argc)
{
        case
2:
 
          year =
StrToLong(*(argv + 1));
 
          if
(!CheckYear(year)) {
     
          break;
         
  }
            printf("
%4d\n\n", year);
           
PrintCalendar(year);
            break;
        case 3:
            year
= StrToLong(*(argv + 1));
 
          if
(!CheckYear(year)) {
     
          break;
         
  }
            month =
StrToLong(*(argv + 2));
 
          month =
StrToLong(*(argv + 2));
 
          if
(!CheckMonth(month)) {
   
            break;
         
  }
           
PrintMonthlyCalendar(year, month);
         
  break;
     
  case 4:
   
        year =
StrToLong(*(argv + 1));
 
          if
(!CheckYear(year)) {
     
          break;
         
  }
            month =
StrToLong(*(argv + 2));
 
          if
(!CheckMonth(month)) {
   
            break;
         
  }
            day =
StrToLong(*(argv + 3));
 
          if
(!CheckDay(year, month, day)) {
 
              break;
         
  }
            PrintDayOfWeek(year,
month, day);
            break;
 
      default:
            year
= StrToLong(*(argv + 1));
 
          if
(!CheckYear(year)) {
     
          break;
         
  }
            month =
StrToLong(*(argv + 2));
 
          if
(!CheckMonth(month)) {
   
            break;
         
  }
            day =
StrToLong(*(argv + 3));
 
          if
(!CheckDay(year, month, day)) {
 
              break;
         
  }
            PrintDayOfWeek(year,
month, day);
            break;
 
      }
    }
    default:
        break;
 
  }
    return 0;
}
 
void PrintHelp() {
   
printf("usage:cal [<YEAR> [<MONTH>
[<DAY>]]");
}
 
int CheckYear(int year) {
    if
(year == 0 || year > 9999) {
        printf("cal: year %d not in range 1..9999\n",
year);
        return 0;
    }
    return
1;
}
int CheckMonth(int month) {
    if
(month < 1
|| month >
12) {
       
printf("cal: month %d not in range
(1..12)\n", month);
        return
0;
    }
    return 1;
}
int
CheckDay(int year, int
month, int day) {
   
switch (month) {
   
case 1:
   
    if (day <
1 || day > 31) {
 
          printf("cal: day
%d not in range (1..31)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
2:
 
      if ((year < 1753 &&
year % 4 == 0) ||
((year % 4 == 0 &&
year % 100
           
    != 0) || year % 400 ==
0)) {
         
  if (day < 1 ||
day > 29)
{
                printf("cal: day %d not in range (1..29)\n",
day);
                return 0;
           
}
        }
        if (day <
1 || day > 28) {
 
          printf("cal: day
%d not in range (1..28)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
3:
 
      if (day < 1 ||
day > 31)
{
            printf("cal:
day %d not in range (1..31)\n", day);
     
      return 0;
        }
 
      return 1;
        break;
 
  case 4:
   
    if (day <
1 || day > 30) {
 
          printf("cal: day
%d not in range (1..30)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
5:
 
      if (day < 1 ||
day > 31)
{
            printf("cal:
day %d not in range (1..31)\n", day);
     
      return 0;
        }
 
      return 1;
        break;
 
  case 6:
   
    if (day <
1 || day > 30) {
 
          printf("cal: day
%d not in range (1..30)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
7:
 
      if (day < 1 ||
day > 31)
{
            printf("cal:
day %d not in range (1..31)\n", day);
     
      return 0;
        }
 
      return 1;
        break;
 
  case 8:
   
    if (day <
1 || day > 31) {
 
          printf("cal: day
%d not in range (1..31)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
9:
 
      if (day < 1 ||
day > 30)
{
            printf("cal:
day %d not in range (1..30)\n", day);
     
      return 0;
        }
 
      return 1;
        break;
 
  case 10:
   
    if (day <
1 || day > 31) {
 
          printf("cal: day
%d not in range (1..31)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    case
11:
 
      if (day < 1 ||
day > 30)
{
            printf("cal:
day %d not in range (1..30)\n", day);
     
      return 0;
        }
 
      return 1;
        break;
 
  case 12:
   
    if (day <
1 || day > 31) {
 
          printf("cal: day
%d not in range (1..31)\n", day);
       
    return 0;
 
      }
        return
1;
        break;
    default:
        break;
 
      return 0;
    }
}
 
/**
* 以下函数返回一个包含当前年 月 日的整型数组
*/
int*
CurrentCal() {
    time_t nowtime;
    struct tm *timeinfo;
    time(&nowtime);
 
  timeinfo = localtime(&nowtime);
 
  int cal[3];
    cal[0] = timeinfo->tm_year + 1900;
 
  cal[1] =
timeinfo->tm_mon + 1;
    cal[2] = timeinfo->tm_mday;
    return cal;
}
 
/**
*
以下函数打印年历,以月为单位,分成四行打印,每行打印三个月
*/
void PrintCalendar(int year) {
    int
i;
    for (i = 0; i <
4; ++i)
{
        switch (i) {
       
case 0:
   
        //打印第1行,1-3月的月历
       
    printf(" January February
March\n");
           
printf(
                 
  "-------------------- --------------------
--------------------\n");
         
  printf(
               
    "Su Mo Tu We Th Fr Sa Su Mo Tu We Th
Fr Sa Su Mo Tu We Th Fr Sa\n");
       
    PrintCommonCalendar(year, 1);
           
break;
       
case 1:
   
        //打印第2行,4-6月的月历
       
    printf(" April May
June\n");
           
printf(
                 
  "-------------------- --------------------
--------------------\n");
         
  printf(
               
    "Su Mo Tu We Th Fr Sa Su Mo Tu We Th
Fr Sa Su Mo Tu We Th Fr Sa\n");
       
    PrintCommonCalendar(year, 2);
           
break;
       
case 2:
   
        //打印第3行,7-9月的月历
       
    printf(
             
      " July August
September\n");
           
printf(
                 
  "-------------------- --------------------
--------------------\n");
         
  printf(
               
    "Su Mo Tu We Th Fr Sa Su Mo Tu We Th
Fr Sa Su Mo Tu We Th Fr Sa\n");
       
    PrintCommonCalendar(year, 3);
           
break;
       
case 3:
   
        //打印第4行,11-12月的月历
       
    printf(
             
      " October November
December\n");
           
printf(
                 
  "-------------------- --------------------
--------------------\n");
         
  printf(
               
    "Su Mo Tu We Th Fr Sa Su Mo Tu We Th
Fr Sa Su Mo Tu We Th Fr Sa\n");
       
    PrintCommonCalendar(year, 4);
           
break;
       
default:
           
break;
       
}
    }
}
 
/**
*
打印出给定年,给定行的3个月的月历。
*/
void PrintCommonCalendar(int
year, int row) {
   
int mfOfWeek, mfDays; //mfOfWeek表示该行第1个月的1号是周几,mfDays表示第1个月的天数
 
  int msOfWeek, msDays; //mfOfWeek表示该行第2个月的1号是周几,mfDays表示第2个月的天数
 
  int mtOfWeek, mtDays; //mfOfWeek表示该行第3个月的1号是周几,mfDays表示第3个月的天数
 
  switch (row) {
   
case 1:
   
    mfOfWeek = DayOfWeek(year,
1, 1);
 
      mfDays = 31;
 
      msOfWeek =
DayOfWeek(year, 2, 1);
        msDays = 28;
   
    mtOfWeek = DayOfWeek(year,
3, 1);
 
      mtDays = 31;
 
      PrintOneQuarter(year, mfOfWeek, mfDays, msOfWeek,
msDays, mtOfWeek,
             
  mtDays, row);
        break;
    case
2:
 
      mfOfWeek =
DayOfWeek(year, 4, 1);
        mfDays = 30;
   
    msOfWeek = DayOfWeek(year,
5, 1);
 
      msDays = 31;
 
      mtOfWeek =
DayOfWeek(year, 6, 1);
        mtDays = 30;
   
    PrintOneQuarter(year, mfOfWeek, mfDays, msOfWeek, msDays,
mtOfWeek,
               
mtDays, row);
        break;
    case
3:
 
      if (year == 1752) {
 
          Print1752_3Quarter();
   
        break;
       
}
        mfOfWeek =
DayOfWeek(year, 7, 1);
        mfDays = 31;
   
    msOfWeek = DayOfWeek(year,
8, 1);
 
      msDays = 31;
 
      mtOfWeek =
DayOfWeek(year, 9, 1);
        mtDays = 30;
   
    PrintOneQuarter(year, mfOfWeek, mfDays, msOfWeek, msDays,
mtOfWeek,
               
mtDays, row);
        break;
    case
4:
 
      mfOfWeek =
DayOfWeek(year, 10, 1);
        mfDays = 31;
   
    msOfWeek = DayOfWeek(year,
11, 1);
        msDays = 30;
   
    mtOfWeek = DayOfWeek(year,
12, 1);
        mtDays = 31;
   
    PrintOneQuarter(year, mfOfWeek, mfDays, msOfWeek, msDays,
mtOfWeek,
               
mtDays, row);
        break;
    default:
        break;
 
  }
}
 
/**
*
以下函数打印一个季度,也即是在同一行上的3个月的月历。
*
* 打印方式肯定是从上到下,从左到右依次打印。
*
*
每月至多有6周,至少有5周;第1周、第5周和第6周(如果有第6周)是需要特殊处理
*
的三个周,因为这3周并不一定总是有7天。
*/
void PrintOneQuarter(int year, int mfOfWeek, int mfDays, int msOfWeek,
       
int msDays, int mtOfWeek, int mtDays, int row) {
    int
mfDay = 1, msDay
= 1, mtDay = 1; //对已经打印的天数记数
 
  int i, j;
   
char space = 32;
   
//如果要打印的是1-3月的月历,则应该判断一下该年的2月是29天不是29天
 
  if (row == 1) {
 
      if ((year < 1753 &&
year % 4 == 0) ||
(year >=
1753 &&
((year % 4 == 0
   
            && year %
100 != 0) || year % 400 ==
0))) {
         
  msDays = 29;
        }
 
  }
    for (i = 0; i <
6; ++i)
{
        if (i
== 0)
{
            //输出第一个月的第一周
         
  if (mfOfWeek >
0) {
         
      printf("%*c", 3 * mfOfWeek,
space);
            }
   
        for (j
= mfOfWeek; j < 7; ++j)
{
                printf("%2d ", mfDay);
       
        mfDay++;
           
}
            //输出第二个月的第一周
         
  printf("%*c", 3 * msOfWeek + 1, space);
 
          for
(j = msOfWeek; j < 7; ++j)
{
                printf("%2d ", msDay);
       
        msDay++;
           
}
            //输出第三个月的第一周
         
  printf("%*c", 3 * mtOfWeek + 1, space);
 
          for
(j = mtOfWeek; j < 7; ++j)
{
                printf("%2d ", mtDay);
       
        mtDay++;
           
}
            continue;
       
}
 
        //打印2-4周
        if (i <
4) {
         
  printf(
               
    "\n%2d %2d %2d %2d %2d %2d %2d %2d %2d
%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d",
   
                mfDay, mfDay + 1, mfDay + 2, mfDay + 3, mfDay + 4, mfDay
 
                   
      + 5, mfDay + 6, msDay, msDay +
1, msDay + 2, msDay
         
                  + 3, msDay + 4, msDay + 5, msDay + 6, mtDay,
mtDay
                 
          + 1, mtDay + 2, mtDay + 3, mtDay + 4, mtDay + 5,
           
        mtDay + 6);
           
mfDay += 7;
           
msDay += 7;
           
mtDay += 7;
           
continue;
     
  }
 
        //打印第1个月的第5周或第6周
       
if (mfDays - mfDay > 6) { //未打印天数不少于7天时,能够占满1周,直接打印
     
      printf("\n%2d %2d %2d %2d %2d
%2d %2d ", mfDay, mfDay + 1,
mfDay
                 
  + 2,
mfDay + 3, mfDay
+ 4, mfDay + 5, mfDay + 6);
   
        mfDay += 7;
        } else
{ //未打印天数不足一周时,按以下方式打印
   
        printf("\n");
           
for (j =
0; j < 7; ++j) {
 
              //有数据打印数据,没有数据用空格填充
       
        if (mfDay
<= mfDays)
{
                   
printf("%2d ", mfDay++);
           
    } else {
 
                 
printf(" ");
       
        }
           
}
        }
       
printf(" ");
 
   
    //打印第2个月的第5周或第6周
 
      if (msDays - msDay > 6) {
           
printf("%2d %2d %2d %2d %2d %2d %2d ", msDay,
msDay + 1, msDay
+ 2,
 
                  msDay + 3, msDay + 4, msDay + 5, msDay + 6);
   
        msDay += 7;
        } else
{
            for (j = 0; j < 7;
++j) {
         
      if (msDay <= msDays)
{
                   
printf("%2d ", msDay++);
           
    } else {
 
                 
printf(" ");
       
        }
           
}
        }
       
printf(" ");
 
   
    //打印第3个月的第5周或第6周
 
      if (mtDays - mtDay > 6) {
           
printf("%2d %2d %2d %2d %2d %2d %2d ", mtDay,
mtDay + 1, mtDay
+ 2,
 
                  mtDay + 3, mtDay + 4, mtDay + 5, mtDay + 6);
   
        mtDay += 7;
        } else
{
            for (j = 0; j < 7;
++j) {
         
      if (mtDay <= mtDays)
{
                   
printf("%2d ", mtDay++);
           
    }
            }
 
      }
    }
    printf("\n");
}
 
/**
*特殊的1752年第3季度:7月8月9月
*/
void
Print1752_3Quarter() {
    char space =
32;
    printf("%10c1
2 3 4%21c1%9c1 2 14 15 16\n", space, space, space);
 
  printf(" 5 6 7 8 9 10 11 2 3 4 5 6 7 8 17 18
19 20 21 22 23\n");
    printf("12 13 14 15 16 17 18 9 10 11 12 13 14 15 24 25 26 27 28
29 30\n");
    printf("19 20 21
22 23 24 25 16 17 18 19 20 21 22\n");
    printf("26 27 28 29 30 31 23 24 25 26 27 28
29\n");
    printf("%22c30
31\n", space);
}
 
/**
*
打印指定月的月历
*/
void
PrintMonthlyCalendar(int year, int month) {
    int
dayOfWeek = DayOfWeek(year, month, 1);
    switch (month) {
    case 1:
       
PrintMonthName("January", year);
 
      PrintCommonMonthlyCalendar(dayOfWeek, 31);
 
      break;
 
  case 2:
   
    PrintMonthName("February",
year);
        if (year <
1753 &&
year % 4 == 0) {
 
          PrintCommonMonthlyCalendar(dayOfWeek,
29);
         
  break;
     
  } else if ((year %
4 == 0 && year
% 100 != 0) ||
year % 400 == 0) {
 
          PrintCommonMonthlyCalendar(dayOfWeek,
29);
         
  break;
     
  }
       
PrintCommonMonthlyCalendar(dayOfWeek, 28);
        break;
 
  case 3:
   
    PrintMonthName("March",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  case 4:
   
    PrintMonthName("April",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 30);
        break;
 
  case 5:
   
    PrintMonthName("May",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  case 6:
   
    PrintMonthName("June",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 30);
        break;
 
  case 7:
   
    PrintMonthName("July",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  case 8:
   
    PrintMonthName("August",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  case 9:
   
    PrintMonthName("September",
year);
        if (year ==
1752) {
         
  //特殊的1752-9
     
      printf(
           
        "Su Mo Tu We Th Fr Sa\n
1 2 14 15 16\n17 18 19 20 21 22 23\n24 25 26 27 28 29
30");
            break;
 
      }
       
PrintCommonMonthlyCalendar(dayOfWeek, 30);
        break;
 
  case 10:
   
    PrintMonthName("October",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  case 11:
   
    PrintMonthName("November",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 30);
        break;
 
  case 12:
   
    PrintMonthName("December",
year);
       
PrintCommonMonthlyCalendar(dayOfWeek, 31);
        break;
 
  default:
        break;
 
  }
 
}
 
/**
*
以下函数的作用仅仅是将月名在水平方向上打印到月历的中间
*/
void PrintMonthName(char *monthName, int
year) {
    char space
= 32;
 
  int preSpaces =
0;
    preSpaces =
(21 -
strlen(monthName) - a - 1) /
2;
    printf("%*c%s
%d\n", preSpaces, space, monthName, year);
   
printf("--------------------\n");
}
 
/**
*
根据一个月的天数及该月有几天这两个参数,打印出该月的月历
*/
void PrintCommonMonthlyCalendar(int
dayOfWeek, int days) {
 
  int i, j, day =
1;
    char space =
32;
    int weeks =
(days + dayOfWeek) / 7 +
1; //计算出该月有几周
    printf("Su
Mo Tu We Th Fr Sa\n");
    printf("%*c",
3 * dayOfWeek,
space);
    for (i = 0; i <
weeks; ++i) {
       
if (i ==
0) {
         
  //打印第1周
       
    for (j =
dayOfWeek; j < 7; ++j) {
 
              printf("%2d
", day);
               
day++;
         
  }
            continue;
 
      }
 
        //打印第2周到倒数第2周
        if (i <
weeks - 1)
{
            printf("\n%2d
%2d %2d %2d %2d %2d %2d", day, day +
1, day + 2, day
           
        + 3,
day + 4, day
+ 5, day + 6);
   
        day += 7;
           
continue;
     
  }
 
        //打印最后一周
       
printf("\n");
       
for (j =
0; j < 7; ++j) {
 
          if
(day <= days)
{
                printf("%2d ", day++);
           
}
        }
       
printf("\n");
   
}
 
}
 
/**
*
打印给定的年、月、日是周几
*/
void
PrintDayOfWeek(int year, int
month, int day) {
   
char *names[9] =
{ "Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday",
         
  "Friday", "Saturday" };
    int
dayOfWeek = DayOfWeek(year, month,
day);
    if (dayOfWeek
== -1)
{
        return;
    }
   
printf("%d-%d-%d: %s\n", year, month, day,
*(names +
dayOfWeek));
}
 
/**
*
以下函数返回给定的年、月、日是周几
*/
int
DayOfWeek(int year, int
month, int day) {
   
if ((year < 1752) || (year == 1752 && month
< 9) || (year == 1752 &&
month
            == 9 &&
day < 3))
{
        return ((year -
1) + (year - 1) /
4 +
CurrentDays(year, month, day) + 5)
 
              % 7;
   
}
 
    if (year
== 1752 && month ==
9 &&
(day > 2
&& day < 14)) {
 
      printf("本万年历中没有%d-%d-%d这一天\n", year, month,
day);
        return -1;
    }
 
   
if (year > 2199) {
 
      year = (year - 1800) %
400 + 1800;
    }
    return ((year -
1) + (year - 1) /
4 - (year - 1) /
100 + (year
- 1) / 400
   
        +
CurrentDays(year, month, day)) % 7;
}
 
/**
* 以下函数计算从给定年的1-1到month-day的天数
*/
int CurrentDays(int year, int month, int day) {
    int
days = 0;
    switch (month) {
    case 1:
        days =
day;
        break;
    case
2:
 
      days = 31
+ day;
        break;
    case
3:
 
      days = 59
+ day;
        break;
    case
4:
 
      days = 90
+ day;
        break;
    case
5:
 
      days = 120
+ day;
        break;
    case
6:
 
      days = 151
+ day;
        break;
    case
7:
 
      days = 181
+ day;
        break;
    case
8:
 
      days = 212
+ day;
        break;
    case
9:
 
      days = 243
+ day;
        break;
    case
10:
 
      days = 273
+ day;
        break;
    case
11:
 
      days = 304
+ day;
        break;
    case
12:
 
      days = 334
+ day;
        break;
    default:
        break;
 
  }
 
    if
(year < 1753
&& year % 4 ==
0) {
        if (month >
2) {
         
  ++days;
       
}
    } else if
((year % 4 == 0 &&
year % 100 != 0) ||
year % 400 == 0) {
 
      if (month > 2) {
 
          ++days;
        }
 
  }
    return
days;
}
 
/*
*
以下函数判断一个字符串是否能被转换成数字
*/
int IsNum(char *argv)
{
    while (*argv
!= ‘\0‘)
{
        if
(*argv >= 48 &&
*argv <= 57) {
 
          argv++;
           
continue;
     
  }
        return 0;
    }
    return
1;
}
 
/*
*以下函数判断输入的参数是否合法
*/
int
IsLegalParameter(int argc, char **argv) {
    if (argc ==
1) {
        return 0; //0表示没有输入参数
    }
   
while (argc > 1) {
 
      if (!IsNum(*(argv + --argc)))
{
            return -1; //-1表示输入的参数不合法
       
}
    }
    return 1; //1表示输入了参数,并且参数是合法的
}
 
/**
*
以下函数将一个字符串转换成数字。
*/
long
StrToLong(char *argv) {
    if (!IsNum(argv)) {
       
return 0;
    }
 
   
long result = 0;
   
int argvLength = strlen(argv);
    int
nums[argvLength - 1];
    int *pInt = nums;
 
    do
{
        *(pInt++) = *argv
- 48;
 
      argv++;
   
} while (*argv != ‘\0‘);
 
 
  pInt = nums;
    do {
        result
+= *pInt * Power(10, argvLength
- 1);
 
      pInt++;
   
    argvLength--;
   
} while (argvLength !=
0);
    return result;
}
 
/*
* According to the base number and the exponent
calculate power.
* 根据基数和指数,计算出乘方数。
*/
long
Power(int baseNumber, int
exponent) {
    long
result = 1;
    if (exponent ==
0) {
        return 1;
    }
    do
{
        result *=
baseNumber;
        exponent--;
    } while (exponent != 0);
 
  return
result;
}

运行效果

来自为知笔记(Wiz)

万年历算法的实现(C语言--gcc编译),码迷,mamicode.com

时间: 2024-10-13 01:13:34

万年历算法的实现(C语言--gcc编译)的相关文章

1 C语言 gcc 介绍 C 语言编译 main接受参数

1         第一个c语言的hello world 1.1      include头文件包含 头文件包含,写法#include<文件名>, 1.2      main函数 这个就是C语言程序的入口,所有的C程序都是从main开始执行,一个C的源程序必须有一个main函数,也只能有一个main函数 1.3      注释 //注释一行 /* */代表块注释,可以注释多行代码 1.4      {}括号和代码块 代表一个代码单元 1.5      声明 C语言规定,所有的变量和函数必须先声

C语言的编译过程、安装gcc编译器以及设置环境变量

以我对C语言编译过程的了解,我用了一点时间画了一个图,提供给大家参考一下,希望有些能对您的问题提上帮助. 前几天刚初步学习了C语言的编译过程,感触挺深的.在C语言中头文件其实起了一个很大的作用. 1.头文件可以不需要编译 2.可以查看具体的声明 3.头文件加上实现文件的o文件提交给使用者即可 ,不需要知道源代码 4..o文件预先编译,所以整个项目编译时,会大大提高编译的时间 . 5.当一个文件(A.c文件)依赖于头文件(b.h)时 ,如果b.c编译之后形成的b.o文件重新编译后,a.o的文件不需

gcc编译c语言

摘自<Linux程序设计>第四版,人民邮电出版社 c语言程序的编译与调试<<使用gcc编译,gdb调试>> 程序编译过程:词法分析-->语法分析-->中间代码生成-->代码优化-->目标代码生成gcc编译器:预处理(preprocessing)-->编译(compilation)-->汇编(assembly)-->连接(link) 文件后缀名说明:.c:c语言代码.a:由目标文件构成的库文件.C,.cc,.cpp:C++代码.h

C语言的编译过程和GCC编译参数

C语言的编译一般有三个步骤: 预编译: gcc -E -o a.e a.c 预编译a.c文件,生成的目标文件名为a.e 预编译就是将include包含的头文件内容替换到C文件中,同时删除代码中没用的注释 示例: //main.c #include <stdio.h> #include "sum.h" int main(){ int m = 6; int n = 5; int result = sum(m,n);  printf("hello\n%\n",

GCC 编译详解 (转)

朋友用C调用lua的库,但是不能直接调用源码,必须要编译成静态链接库才可以使用,问学长说是因为要分开编译链接.这就不理解了,于是转一篇讲编译的文章学习一下,补补课… GNU CC(简称为Gcc)是GNU项目中符合ANSI C标准的编译系统,能够编译用C.C++和Object C等语言编写的程序.Gcc不仅功能强大,而且可以编译如C.C++.Object C.Java.Fortran.Pascal.Modula-3和Ada等多种语言,而且Gcc又是一个交叉平台编译器,它能够在当前CPU平台上为多种

[原]高版本gcc编译哟优化可能导致问题

系统:ubuntu14.04 编译器:gcc4.8.2 问题描述:工作需要,使用libnids,所以就下了最新版本的1.24,编译安装后,发现tcp报文重组工作无法完成,具体表现为虽然通过nids_register_tcp函数注册了回调函数,但函数一直不能被执行,通过对libnids执行流程的跟踪,发现在计算checksum的时候出了问题,checksum的值一直不为零,导致libnids认为数据报损坏. 不明所以,但通过思考,觉得问题应该处在编译器上,是不是64位和32为的问题呢?源码中并没有

C语言程序编译过程

最近在编译DM8168的ARM端程序时经常出现未定义.重定义等报错,由于源码文件多,包含关系比较多,所以自己添加时容易乱.深深的体会到,好的代码风格是如此重要,之前也在看代码重构,以后应该更加注意代码的质量.经思考总结规律如下: 1.公用的数据结构等写为一个头文件,其他源文件包含此头文件.同时为了让不同源文件里的函数都可以使用,公用的函数可以放在此头文件中声明. 2.其他源文件里声明的变量,如果想在另一个文件里用,需要extern声明,这样可以避免各种全局变量的交互混杂. 理解的比较浅,希望高人

探讨排序算法的实现

排序算法是我们工作中使用最普遍的算法,常见的语言库中基本都会有排序算法的实现,比如c标准库的qsort,stl的sort函数等.本文首先介绍直接插入排序,归并排序,堆排序,快速排序和基数排序等比较排序算法,然后介绍计数排序,基数排序等具有线性时间的排序算法.本文主要讨论算法的实现方法,并不会过多介绍基本理论. 评价一个排序算法优劣适用与否,一般需要从三个方面来分析 时间复杂度.用比较操作和移动操作数的最高次项表示,由于在实际应用中最在乎的是运行时间的上限,所以一般取输入最坏情况的下的运行时间作为

linux 下gcc 编译结构体问题

最近在linux 学习c语言的编程,发现好多原来在vs 上的在linux 都编译不过去,今天就遇到了一个问题就是结构体的编译的问题, 结构体大概的定义是 struct Node{ int a; int b; }; 在利用gcc 编译的时候就显示 错误:‘Node’未声明(在此函数内第一次使用), 这就让我感觉很奇怪,原来这都是可以的 后来查了资料改成这个样子就可以了 typedef struct Node{ int a; int b; }Node; 这样就编译成功了.