日期計算器

gogogo_sky發表於2017-05-15

一、完成功能

1.日期+/-天數=返回日期
2.日期-日期=返回天數
3.列印某年某月的本月日曆;
這裡寫圖片描述

二、功能分析

見圖:
這裡寫圖片描述

三、原始碼

//完成功能
//1.日期+/-天數=返回日期
//2.日期-日期=返回天數
//3.列印某年某月的本月日曆;
#pragma once;
#include<iostream>
using namespace std;
class Date
{
friend ostream& operator<<(ostream& os,const Date& d);
friend istream& operator>>(istream& is,Date& d);
public:
    Date(int year=1949,int month=10,int day=1)//全預設構造
        :_year(year)
        ,_month(month)
        ,_day(day)
    {}
public:
      Date& operator+(const int& day)//日期+天數=返回日期
     {
         return Approach(*this,day);
     }
     Date& operator-(const int& day)//日期-天數=返回日期
     {
        return Past(*this,day);
     }
     int operator-(const Date& d2) //日期-日期=返回天數
     {
         int ret=DayNum(*this,d2);
         return ret; 
     }
     void PrintfMonth()//列印該日期所在月份日曆
     {
         _PrintfMonth(*this);
     }
     bool operator<(const Date& d)const//過載小於
     {
         if ((_year<d._year)||
             (_year==d._year&&_month<d._month)||
             (_year==d._year&&_month==d._month&&_day<d._day))
         {
             return true;
         }
         return false;
     }
     bool operator==(const Date& d)const//過載等於
     {
          if ((_year==d._year)&&(_month==d._month)&&(_day==d._day))
          {
              return true;
          }
          return false;
     }
     bool operator!=(const Date& d)const//過載不等於
     {
         if (!(*this==d))
         {
             return true;
         }
         return false;
     }
     bool operator>(const Date& d)const//過載大於
     {
        if (!(*this<d && *this==d))
        {
            return true;
        }
        return false;
     }

     void operator++()//過載前置++
     {
         _day+=1;
         if (_day>GetMonthDay(*this))
            {
                _month+=1;              
                if (_month>12)
                {
                    _year+=1;
                    _month=1;
                }
                _day=1;
            }
     }
private:
    Date& Approach(Date& d1, const int& day)//日期+天數=返回日期-----✔
    {
        int Allday=day+d1._day;
        while(Allday>GetMonthDay(d1))
        {
            Allday=Allday-GetMonthDay(d1);
            d1._month+=1;
            if (d1._month>12)
            {
                d1._year+=1;
                d1._month=1;
            }
        }
        d1._day=Allday;
        return d1;
    }
    Date& Past( Date& d1, const int& day)//日期-天數=返回日期-----✔
    {
        int __day=d1._day-day;
        if (__day>0)
        {
            d1._day=__day;
        }
        else
        {
            d1._month-=1;
            if (d1._month<1)
            {
                d1._month=12;
                d1._year-=1;
            }
            while (GetMonthDay(d1)-(-__day)<=0)//注意等於0,也要向前進一個月
            {
                __day=GetMonthDay(d1)-(-__day);
               d1._month-=1;
               if (d1._month<1)
               {
                   d1._month=12;
                   d1._year-=1;
               }
            }
            d1._day=GetMonthDay(d1)-(-__day);
        }
        return d1;
    }
    int DayNum( Date& d1,const Date& d2)//日期-日期=返回天數-----✔
    {
        int count=0;
        if (d1<d2)//d1<d2
        {
            while (d1!=d2)
            {
                count++;
                ++d1;
            }
            return count;
        }
        else//d1>=d2
        {
            Date tmpd1=(Date)d2;
            Date tmpd2=d1;
            DayNum(tmpd1,tmpd2);
        }
    }
    void _PrintfMonth(const Date& d)//列印某個日期當月日曆
    {
         cout.width(7);
         cout<<"日";
         cout.width(7);
         cout<<"一";
         cout.width(7);
         cout<<"二";
         cout.width(7);
         cout<<"三";
         cout.width(7);
         cout<<"四";
         cout.width(7);
         cout<<"五";
         cout.width(7);
         cout<<"六"<<endl;
         int year=d._year;
         int month=d._month;
         if ((d._month==1)||(d._month==2))//將當月1,2月份看為上一年的13,14月份
         {
             year-=1;
             month+=12;
         }

         //******************以下程式碼只考慮1582年10月4日之後的月曆列印***************
         //蔡勒公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
         //w:星期; w對7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六
         //y:年(年數後兩位數)c:世紀-1(年數前兩位數)d:日
         //m:月(m大於等於3,小於等於14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月來計算,比如2003年1月1日要看作2002年的13月1日來計算)
         int c=int(year/100);
         int y=year-100*c;
         //計算當前月份第一天為星期幾,d==1
         int w=y+int(y/4)+int(c/4)-2*c+(26*(month+1)/10)+1-1;//***一定要注意帶方括號取整數的算式,要加上int的強制型別轉換
         w=(w%7+7)%7;//處理負數的情況----我在這裡花了一早上才看出來問題
         for (int i=0;i<w;i++)//處理第一行空白處
         {
             cout.width(7);
             cout<<" ";
         }
         for (int i=0;i<7-w;i++)//處理第一行日期
         {
             cout.width(7);
             cout<<i+1;
         } 
         cout<<endl;
         int count=0;
         for (int i=7-w;i<GetMonthDay(d);i++)
         {

              cout.width(7);
              cout<<i+1;
              count++;
              if ((count)/7==1)
              {
                cout<<endl;
                count=0;
              }
         }
         cout<<endl;
    }
    bool LeapYear(const Date& d)//判斷瑞年
    {
        if ((d._year%4==0 && d._year%100!=0)||(d._year%400==0))
        {
            return true;
        }
        return false;
    }
    int GetMonthDay(const Date& d)//獲取某個月份的天數
    {
        int arr[]={31,28,31,30,31,30,31,31,30,31,30,31};
        if(LeapYear(d)&&(d._month==2))
        {
            return arr[1]+1;
        }
        else
            return arr[d._month-1];
    }
private:
    int _year;
    int _month;
    int _day;
};

ostream& operator<<(ostream& os,const Date& d)
{
   os<<d._year<<"-"<<d._month<<"-"<<d._day;
   return os;
}
istream& operator>>(istream& is, Date& d)
{
    is>>d._year>>d._month>>d._day;
    return is;
}
void menu()
{
   cout<<"*******************歡迎使用日期計算器*************"<<endl;
   cout<<"*************請根據下面提示按鍵符號選擇功能*************"<<endl;
   cout<<"*************  1.計算多少天以後日期      *************"<<endl;
   cout<<"*************  2.計算多少天以前日期      *************"<<endl;
   cout<<"*************  3.計算二個日期之間的天數  *************"<<endl;
   cout<<"*************  4.列印某年某月的日曆      *************"<<endl;
   cout<<"*************  0.退出                    *************"<<endl;
}
int main()
{
    menu();
    int n=1;
    while (n)
    {
        cout<<"請按鍵選擇相應的服務:";
        cin>>n;
        switch(n)
        {
        case 1:
            { 
                Date d;
                int n=0;
                cout<<"請輸入開始日期:";
                cin>>d;
                cout<<"請輸入天數:";
                cin>>n;
                cout<<n<<"天以後的日期是:"<<(d+n)<<endl;
                cout<<"請繼續使用"<<endl;
                break;
            }
        case 2:
            { 
                Date d;
                int n=0;
                cout<<"請輸入開始日期:";
                cin>>d;
                cout<<"請輸入天數:";
                cin>>n;
                cout<<n<<"天以前的日期是:"<<(d-n)<<endl;
                cout<<"請繼續使用"<<endl;
                break;
            }
        case 3:
            { 
                Date d;
                Date d1;
                cout<<"請輸入開始日期:";
                cin>>d;
                cout<<"請輸入終止日期:";
                cin>>d1;
                cout<<"兩個日期之前相差:"<<(d-d1)<<"天"<<endl;
                cout<<"請繼續使用"<<endl;
                break;
            }
        case 4:
            { 
                cout<<"請輸入日期";
                Date d;
                cin>>d;
                cout<<"本月的日曆為:"<<endl;
                d.PrintfMonth();
                break;
            }
        case 0:
            break;
        default:
            cout<<"輸入錯誤!"<<endl;
            break;
        }
    }
    return 0;
}

總結:

(1)注意引用的使用可以提高程式的執行效率;
(2)靜態成員函式的使用,可以使得物件導向的程式的變得容易;
(3)新型別物件要進行輸入輸入,必須進行輸入輸出元運算子,並在類內宣告為友緣函式;
(4)善於重在運算子可以使物件之間或者物件自己的有關問題,變得簡單;
(5)注意函式的複用會試程式碼量變小,且問題變得簡單,直觀;
(6)注意蔡勒公式中對第一次算出的w的值進行 負數處理;

相關文章