C++ 实现万年历(原创)

任务要求

功能要求:

1)提供菜单方式选择,假定输入的年份在1940-2040年之间。

2)输入一个年份,输出是在屏幕上显示该年的日历。

3)输入年月,输出该月的日历,如图2-1所示:

  

                          2- 1 月日历

4)输入年份、月份、日期,计算得到的是这一天据今天有多少天,星期几。

5)输入公历的年月日,输出农历年月日。

6)输入农历节气,输出当年农历的年月日及公历年月日。可以假定只涉及年份是1940年到2040年。

总体设计

将文件三部分 Date.h、main.cpp、Date.cpp

1) Date.h:包括函数的声明。

2) main.cpp:包含调用与模拟交互界面的函数代码

3) Date.cpp:

//输入输入一个年份,输出是在屏幕上显示该年的日历。

void print_annual_calendar(int year)

//输入年月,输出该月的日历。

void print_monthly_calendar(int year,int month)

//输入年份、月份、日期,计算得到的是这一天据今天有多少天,星期几。

void print_number_week(int year,int month ,int day)

//输入公历,显示农历。

void gregorian_to_lunar (int year,int month,int day)

//输入农历节气,输出当年农历的年月日和公历年月日。

void solar_term(char *str)

详细设计说明

(1) 查询距今多少天,星期几?

①计算某一日期到1939年1月1日的天数:getDaysTo1939(int year, int month, int day)

  1. 判断是否是闰年(平年365天,闰年366天),函数如表4-1所示:

4- 1 isLeapYear函数

定义函数

bool isLeapYear(int year)

返回值

若year年是闰年返回true,否则返回false

参数说明

year参数是要判断的年份

  1. 判断某年某月有多少天?函数如表4-2所示:

4- 2 getDaysOfMonth函数

定义函数

int getDaysOfMonth(int year,int month)

返回值

返回year年month月的天数

参数说明

year、month参数分别是要查询的年、月

 例如:计算2020年8月14日到1939年1月1日的天数。首先1939-2019年是整数年,直接判断是否是闰年,然后增加天数。2020年不是整年,但1-7月是整数月,根据年、月获取当月天数累加。最后再加天数day,便得出相距与1939年1月1日的天数。

②计算查询日期距今天多少天?getDaysOfMonthToToday(int year, int month, int day) ,函数如表4-3所示:

  1. 通过函数获取系统时间,通过getDaysTo1939(),获取系统时间距1939年1月1日的天数num1。
  2. 使用键盘输入的日期,通过getDaysTo1939(),获取输入日期距1939年1月1日的天数num2。
  3. 使用num1-num2计算输入日期距今天的天数,正数为已过去时间,负数为未来时间。

4- 3 getDaysOfMonthToToday函数

定义函数

int getDaysOfMonthToToday(int year,int month,int day)

返回值

返回距今天数,正值为过去,负值为未来

参数说明

year、month、day 分别为要查询的年、月、日

③计算输入日期是星期几:getDayOfWeek(int year,int month,int day) ,函数如表4-4所示:

 

  1. 知道1939年1月1日是星期日,然后计算查询日期与1939年距离多少天,然后利用(天数%7)获取余数,得出星期属性。

4- 4 getDayOfWeek函数

定义函数

String getDayOfWeek(int year,int month,int day)

返回值

返回字符串星期数

参数说明

year、month、day 分别为要查询的年、月、日

(2) 打印月日历

  1. 获取当月1日是星期几,通过getDayOfWeek1()获取当月一号是星期几,然后通过打印空格使得当月1日,停在所对应的星期下方,函数如表4-5所示:

4- 5 getDayOfWeek1函数

定义函数

int getDayOfWeek1(int year,int month,int day)

返回值

返回星期数,0代表星期天

参数说明

year、month、day 分别为要查询的年、月、日

  1. 获取当月天数,通过getDaysOfMonth()获取,打印完最后一天时间便结束,函数如表4-6所示:

4- 6 getDaysOfMonth函数

定义函数

int getDaysOfMonth(int year,int month)

返回值

返回year年month月天数

参数说明

year、month分别为要查询的年、月

(3) 打印年日历

① 打印季度日历,函数如表4-7所示:

  1. 首先打印日历头信息三遍(由于是按照季度输出,一行包含三个月),格式:(月份 SUN MON SUN MON TUE WED THU FRI SAT)
  2. 依次打印日历的第一行,每月的第一日对应的星期数,通过打印空格来调整。
  3. 依次打印连续的日期。最后一行,日期与日期之间依然要使用空格来调整位置。

4- 7 print_seasons_calendar函数

定义函数

void print_seasons_calendar(int year,int num)

返回值

无返回值

参数说明

year、num分别为要打印的年、季度,num可取1,2,3,4

① 打印年日历,函数如表4-8所示:

  1. 通过for循环打印四个季度的日历,便完成年日历的输出。

4- 8 print_annual_calendar函数

定义函数

void print_annual_calendar(int year)

返回值

无返回值

参数说明

year为要打印的年份

(4) 公历转农历

① 计算输入的时间距离1939年1月1日的天数。

② 获取农历年天数(通过农历数据表查询):getDayOfNongYear(int year)

  1. 获取农历年是否为闰年,返回闰月月份,函数如表4-9所示:

4- 9 isNongLeapYear函数

定义函数

int isNongLeapYear(int year)

返回值

返回农历year年闰月月份,0表示不闰

参数说明

year为要查询的年

  1. 获取每个月有多少天,函数如表4-10所示:

4- 10 getDaysOfMonthOfNongMonth函数

定义函数

int getDaysOfMonthOfNongMonth(int year,int month)

返回值

返回农历year年month月的天数

参数说明

year、month分别为要查询的年、月

  1. 获取闰月大小,函数如表4-11所示: 

4- 11 is_large_month函数

定义函数

bool is_large_month(int year)

返回值

闰大月返回true,闰小月返回false

参数说明

year为要查询的年

③ 计算农历日期,函数如表4-12所示:

  1. 由于1939年1月1日农历往往是1938年,所以首先减去公历1939年1月1日到农历1939年正月初一的天数。
  2. 循环计算便得出农历日期。日期的文字形式可以保存在数组中进行拼接输出。

4- 12 gregorian_to_lunar函数

定义函数

void gregorian_to_lunar (int year,int month,int day)

返回值

无返回值

参数说明

year、month、day分别为要转换的年、月、日

(5) 查询节气时间,函数如表4-13所示:

  1. 计算二十四节气对应的公历日期(通过寿星公式计算)
  2. 得出公历日期,直接使用公历转农历函数,打印农历日期。

4- 13 solar_term函数

定义函数

void solar_term(int year,char* str)

返回值

无返回值

参数说明

year代表要查询的年份,str表示查询的节气名称,如立秋。

调试与测试

(1) 交互界面显示

 

(2) 打印年日历

 

                      图3- 2 年日历

(3) 打印月日历

            3- 3  月日历

(4) 查询距今多少天,星期几? 

                   3- 4  距今天数,星期数

(5) 公历转农历

                    3- 5  公历转农历

 (6) 查询节气时间

                图3- 6  查询二十四节气

代码实现

Date.h:
#ifndef DATE_H
#define DATE_H
/*输入年份、月份、日期,计算得到的是这一天据今天有多少天?星期几?*/
void print_number_week(int year,int month,int day);
/*输入年月,输出该月的日历。*/
void print_monthly_calendar(int year,int month);
/*输入输入一个年份,输出是在屏幕上显示该年的日历。*/
void print_annual_calendar(int year);
/*输入公历,显示农历。*/
void gregorian_to_lunar (int year,int month,int day);
/*输入年份,二十四节气*/
void solar_term(int year,char* str);
/*欢迎界面*/
void print();
#endif // DATE_H

main.cpp:
#include <iostream>
#include "Date.h"
using namespace std;

int main()
{

    int num;
    char solar_Terms[3];
    int year,month,day;
    print();
    while(1)
    {

        cout<<"
请选择服务序号:";
        cin>>num;
        switch(num)
        {
        case 1:
            cout<<"请输入要查询的年份:";
            cin>>year;
            print_annual_calendar(year);
            break;
        case 2:
            cout<<"请输入要查询的年、月:";
            cin>>year>>month;
            print_monthly_calendar(year,month);
            break;
        case 3:
            cout<<"请输入要查询的年、月、日:";
            cin>>year>>month>>day;
            print_number_week(year,month,day);
            break;
        case 4:
            cout<<"请输入要查询的年、月、日:";
            cin>>year>>month>>day;
            gregorian_to_lunar (year,month,day);
            break;
        case 5:
            cout<<"请输入要查询的年份及节气:";
            cin>>year>>solar_Terms;
            solar_term(year,solar_Terms);
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

Date.cpp:
#include "Date.h"
#include <stdio.h>
#include <ctime>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string.h>

using namespace std;


/*农历查询表  来源:https://www.jianshu.com/p/57e7bd43c00b    */
/*第1位    表示假如有闰月,0代表闰小月,1代表闰大月
 *第2-4位  表示12个二进制位 一位表示一个月是大月还是小月
 *最后1位  表示闰哪个月,0表示不闰*/
unsigned int LunarCalendar[199] =
{
    /*1900年开始*/
    /*0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
    0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
    0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
    0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,*/
    /*我的日历要求1940-2040年 以上用不到*/

    0x0c950,/*1939年*/   /*查询公历1940年1月,农历其实是1939年*/
    0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
    0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
    0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
    0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
    0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
    0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
    0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
    0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
    0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
    0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
    0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0
};

/*获取系统时间*/
void gettime(int &year,int &month,int &day)
{
    time_t time1;
    struct tm *ptime;
    time(&time1);
    ptime = localtime(&time1);
    year=ptime->tm_year + 1900;
    month=ptime->tm_mon + 1;
    day=ptime->tm_mday;
}

/*判断year年是否是闰年*/
bool isLeapYear(int year)
{
    /*可以被4且100整除或者可以被400整除*/
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/*获取year年month月有多少天*/
int getDaysOfMonth(int year,int month)
{
    /*平年各月公历天数*/
    int days[12]= {31,28,31,30,31,30,31,31,30,31,30,31};
    if(isLeapYear(year)&&month==2)
        return 29;
    else
        return days[month-1];
}

/*获取year年month月day日到1939年1月1日的天数*/
int getDayTo1939(int year,int month,int day)
{
    int days=0;
    /*从1939年开始计算,直到year-1年,它们都是整数年*/
    for(int i=year-1; i>=1939; i--)
    {
        if(isLeapYear(i))
            days+=366;
        else
            days+=365;
    }
    /*计算year年1月到year年month-1月  它们是整数月*/
    for(int i=month-1; i>0; i--)
    {
        days+=getDaysOfMonth(year,i);
    }
    /*计算year年month月1日到yera年month月day日天数*/
    days+=day;
    return days-1;
}

/*获取year年month月day日是星期几*/
string getDayOfWeek(int year,int month,int day)
{
    string weeks[7]= {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
    /*获取year年month月day日到1939年1月1日的天数*/
    int days=getDayTo1939(year,month,day);
    int week=days%7;
    return weeks[week];
}
/*整型版星期几*/
int getDayOfWeek1(int year,int month,int day)
{
    int days=getDayTo1939(year,month,day);
    int week=days-(days/7)*7;
    return week;
}

/*获取year年month月day日到现在的天数 正值为过去,负值为未来*/
int getDaysOfMonthToToday(int year,int month,int day)
{
    int nowyear;
    int nowmonth;
    int nowday;
    gettime(nowyear,nowmonth,nowday);
    /*现在时间到1939年1月1日的天数*/
    int nowto1939=getDayTo1939(nowyear,nowmonth,nowday);
    /*输入的时间到1939年1月1日的天数*/
    int tempto1939=getDayTo1939(year,month,day);
    /*正数为过去,负数为未来*/
    return nowto1939-tempto1939;
}

/*检查年月日合法性*/
bool checkDate(int year,int month,int day)
{
    /*还需要判断 year年month月  是否含day天,比如4月有30天,输入31就是错误的*/
    if(year<1939||year>2041||month<0||month>12||day<0||day>getDaysOfMonth(year,month))
        return false;
    else
        return true;
}


void print_number_week(int year,int month,int day)
{
    if(!checkDate(year,month,day))
    {
        cout<<"日期输入出错,请确保日期正确性!"<<endl;
        return;
    }
    if(getDaysOfMonthToToday(year,month,day)>0)
        cout<<year<<""<<month<<""<<day<<""<<getDayOfWeek(year,month,day)<<"	距现在已过去"<<getDaysOfMonthToToday(year,month,day)<<""<<endl;
    else
        cout<<year<<""<<month<<""<<day<<""<<getDayOfWeek(year,month,day)<<"	距现在还有"<<-getDaysOfMonthToToday(year,month,day)<<""<<endl;
}

/*输入年份月份输出月日历表*/
void print_monthly_calendar(int year,int month)
{
    if(year>2041||year<1939||month>12||month<1)
    {
        cout<<"日期输入出错,请确保日期正确性!"<<endl;
        return;
    }
    cout<<"	"<<year<<""<<month<<""<<endl;
    cout<<" SUN MON TUE WED THU FRI SAT"<<endl;
    /*计算year年month月1日星期几*/
    int week=getDayOfWeek1(year,month,1);
    /*调整1日到对应的星期数*/
    for(int i=1; i<=week&&week!=7; i++)
        cout<<"    ";
    /*打印日历信息*/
    for(int i=1; i<=getDaysOfMonth(year,month); i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week+i)%7==0)
            cout<<endl;
    }
}


/*输入年份、季度 一行输出3个月*/
void print_seasons_calendar(int year,int num)
{
    if(num>4||num<0)
    {
        cout<<"输入季度出错!"<<endl;
        return;
    }
    int month=1+3*(num-1);
    /*打印日历头*/
    cout<<month<<" SUN MON TUE WED THU FRI SAT	"<<month+1<<" SUN MON TUE WED THU FRI SAT	"<<month+2<<" SUN MON TUE WED THU FRI SAT"<<endl;
    /*week1、week2、week3 分别代表一个季度的三个月的一日对应星期数*/
    int week1=getDayOfWeek1(year,month,1);
    int week2=getDayOfWeek1(year,month+1,1);
    int week3=getDayOfWeek1(year,month+2,1);
    /*tmp1、tmp2、tmp3分别代表三个月的最大天数*/
    int tmp1=getDaysOfMonth(year,month),tmp2=getDaysOfMonth(year,month+1),tmp3=getDaysOfMonth(year,month+2);

    int day1,day2,day3;

    /*依次输出第一行信息*/
    cout<<"  ";
    for(int i=1; i<=week1 &&week1!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp1; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week1+i)%7==0)
        {
            day1=i+1;
            break;
        }
    }
    cout<<"    ";
    for(int i=1; i<=week2 && week2!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp2; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week2+i)%7==0)
        {
            day2=i+1;
            break;
        }
    }
    cout<<"    ";
    for(int i=1; i<=week3 && week3!=7; i++)
        cout<<"    ";
    for(int i=1; i<=tmp3; i++)
    {
        cout<<setw(3)<<i<<" ";
        if((week3+i)%7==0)
        {
            day3=i+1;
            cout<<endl;
            break;
        }
    }

    /*打印余下信息*/
    for(int j=0; j<5; j++)
    {
        /*如果三个月信息全部打印完,则退出*/
        if(day1>tmp1&&day2>tmp2&&day3>tmp3)
            break;
        /*数字21代表一行三个周,可容纳21天*/
        for(int i=0; i<21;)
        {
            cout<<"  ";
            while(i<7)
            {
                i++;
                /*如果没打印完就打印数字,如果整月天数已经打印完,则输出空格*/
                if(day1<=tmp1)
                    cout<<setw(3)<<day1++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
            /*打印月份与月份之间的间隔*/
            cout<<"    ";
            while(i<14&&i>=7)
            {
                i++;
                if(day2<=tmp2)
                    cout<<setw(3)<<day2++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
            cout<<"    ";
            while(i<21&&i>=14)
            {
                i++;
                if(day3<=tmp3)
                    cout<<setw(3)<<day3++<<" ";
                else
                    cout<<setw(3)<<" "<<" ";
            }
        }
        cout<<endl;
    }
    cout<<endl;
}

/*显示欢迎界面*/
void print()
{
    cout<<"
		欢迎来到我的日历表(1940-2040年)"<<endl;
    cout<<"		功能选择:"<<endl;
    cout<<"		1.查询年日历表"<<endl;
    cout<<"		2.查询月日历表"<<endl;
    cout<<"		3.查询距今多少天?星期几?"<<endl;
    cout<<"		4.输入公历查询农历"<<endl;
    cout<<"		5.输入节气查询对应公历、农历"<<endl;
    cout<<"		*****按0退出*****"<<endl;
}

/*输出年日历表*/
void print_annual_calendar(int year)
{
    if(year>2041||year<1939)
    {
        cout<<"日期输入出错,请确保日期正确性!"<<endl;
        return;
    }
    cout<<"					  "<<"------------"<<endl;
    cout<<"					  "<<year<<"年日历表"<<endl;
    cout<<"					  "<<"------------"<<endl;

    /*循环输出四个季度 打印完整年日历*/
    for(int i=1; i<=4; i++)
    {
        print_seasons_calendar(year,i);
    }
}


string nongMonth[]= {" ","正月","二月","三月","四月","五月","六月","七月","八月","九月","十月","冬月","腊月"};
string nongday[]= {"","","","","","","","","","",""};
string nongday2[]= {"","","廿",""};


/*判断润大小月*/
bool is_large_month(int year)
{
    /*查表找出是否为闰月 判断high是不是为0*/
    int high =(LunarCalendar[year-1939]>>16);
    if(high==0x00)
        return false;
    else
        return true;
}
/*返回 润几月  0代表不闰*/
int isNongLeapYear(int year)
{
    /*输出农历润几月*/
    int low = LunarCalendar[year-1939] & 0xF;
    return low;
}

/*判断农历某年某月多少天*/      /*LunarCalendar 表示农历对照表*/
int getDaysOfMonthOfNongMonth(int year,int month)
{
    /*查表,根据大小月,计算农历月天数*/
    int bit=1 << (16-month);
    if((LunarCalendar[year-1939]/*&0x0000FFFF*/&bit)==0)
        return 29;
    else
        return 30;
}

/*判断某年农历多少天*/
int getDayOfNongYear(int year)
{
    int days=0;
    /*农历十二个月天数*/
    for(int i=1; i<=12; i++)
    {
        days+=getDaysOfMonthOfNongMonth(year,i);
    }
    /*假如有闰月,加上闰月天数*/
    if(isNongLeapYear(year)!=0)
    {
        if(is_large_month(year))
            days+=30;
        else
            days+=29;
    }
    return days;
}


/*输出农历日历*/
void printNong(int days)
{
    int year=1939,month=1,day=1;
    /*由于1939年1月1日往往是农历1938年,所以减去48天,从1939年正月初一计算,因为本计算器计算范围为1940年-2040年 所以可以满足*/
    days-=48;

    /*判断减去下一年的天数,会不会是负值,不是便减去并增加农历年*/
    for(int i=1939; (days-getDayOfNongYear(i))>0; i++)
    {
        days-=getDayOfNongYear(i);
        year=i+1;
    }
    int num;
    int signal=0;
    /*判断减去下一月天数,会不会是负值,不会便农历月加1*/
    for(int j=1; ((days-getDaysOfMonthOfNongMonth(year,j))>0)&&j<12; j++)
    {
        days-=getDaysOfMonthOfNongMonth(year,j);
        if(j==isNongLeapYear(year))
        {
            if(is_large_month(year))
            {
                days-=30;
                num=30;
            }
            else
            {
                days-=29;
                num=29;
            }
        }
        /*当减去农历月的时候,加入变为负值,那么再加回来*/
        if(days<0)
        {
            /*农历闰月标记*/
            signal=1;
            days +=num;
            month=j;
            break;
        }
        month=month+1;
    }
    /*剩余天数便是农历日*/
    day=days;
    cout<<year<<"";
    if(signal==1)
        cout<<"";
    cout<<nongMonth[month];
    if(day>0&&day<=10)
    {
        cout<<""<<nongday[day];
    }
    else if(day>10&&day<20)
    {
        cout<<""<<nongday[day%10];
    }
    else if(day==20)
    {
        cout<<"二十";
    }
    else if(day>20 && day<30)
    {
        cout<<"廿"<<nongday[day%10];
    }
    else if(day==30)
    {
        cout<<"三十";
    }
    cout<<endl;
}

/*打印农历*/
void gregorian_to_lunar (int year,int month,int day)
{
    if(!checkDate(year,month,day))
    {
        cout<<"日期输入出错,请确保日期正确性!"<<endl;
        return;
    }
    cout<<"公历:"<<year<<""<<month<<""<<day<<""<<"   "<<"农历:";
    int days=getDayTo1939(year,month,day);
    /*根据天数打印农历*/
    printNong(days);
}

/*通式寿星公式 计算二十四节气  公式来源:https://www.jianshu.com/p/1f814c6bb475*/
/*20,21世纪C值*/
float C_value_21[]= {3.87,18.73,5.63,20.646,4.81,20.1,5.52,21.04,5.678,21.37,7.108,22.83,7.5,23.13,7.646,23.042,8.318,23.438,7.438,22.36,7.18,21.94,5.4055,20.12};
float C_value_20[]= {4.6295,19.4599,6.3826,21.4155,5.59,20.888,6.318,21.86,6.5,22.2,7.928,23.65,28.35,23.95,8.44,23.822,9.098,24.218,8.218,23.08,7.9,22.6,6.11,20.84};
/*节气基础月*/
float C_month[]= {2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
void solar_term(int year1,char* str)
{
    int year,month,day;
    year=year1;
    int tmp=-1;//表示节气顺序
    const char* temp[24]= {"立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至","小寒","大寒"};
    /*比较字符并赋值tmp 如:0就代表立春*/
    for(int i=0; i<24; i++)
    {
        if(strcmp(str,temp[i])==0)
        {
            tmp=i;
            break;
        }
    }
    if(tmp==-1)
    {
        cout<<"节气拼写出错!"<<endl;
        return;
    }

    if(tmp==0||tmp==1||tmp==22||tmp==23)
    {
        if(year>=2000)
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_21[tmp])-floor((year%100-1)/4);
        }
        else
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_20[tmp])-floor((year%100-1)/4);
        }
    }
    else
    {
        if(year>=2000)
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_21[tmp])-floor((year%100)/4);
        }
        else
        {
            month=C_month[tmp];
            day=floor((year%100)*0.2422+C_value_20[tmp])-floor((year%100)/4);
        }
    }

//特殊情况
    if((year==2026 && tmp==1)||(year==1918 && tmp==21)||(year==2021 && tmp==21)||(year==2019 && tmp==22))
    {
        day--;
    }
    if((year==2084 && tmp==3)||(year==1911 && tmp==6)||(year==2008 && tmp==7)||(year==1902 && tmp==8)||(year==1928 && tmp==9)||(year==1925 && tmp==10)||(year==2016 && tmp==10)||(year==1922&& tmp==11)||(year==2002&&tmp==12)||(year==1927&&tmp==14)||(year==1942&&tmp==15)||(year==2089 && tmp==17)||(year==2089&&tmp==18)||(year==1978&&tmp==19)||(year==2054 && tmp==20)||(year==1982&&tmp==22)||(year==2000 && tmp==23)||(year==2082&&tmp==23))
    {
        day++;
    }
    if(C_month[tmp]>12)
    {
        month=1;
    }
    cout<<temp[tmp]<<": ";
    /*根据公式计算的年月日,将其转换为农历*/
    gregorian_to_lunar (year,month,day);
}
原文地址:https://www.cnblogs.com/handsometaoa/p/13588549.html