鱼C论坛

 找回密码
 立即注册
查看: 2806|回复: 13

[已解决]关于julianday的日期和时间求法

[复制链接]
发表于 2019-10-1 12:57:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.求助各位大神,关于julianday的日期求法,本次程序是奠定一个起始日期epoch=2000年1月1日0点0分0秒;然后要求计算从任意日期—————>例如:2018年1月1日0时0分0秒到epoch之间的时间跨度。
2.完成对年,月,日之间的加减运算,在此期间需要注意的是要判断闰年(因为闰年的2月是29天,(如果输入的日期月份大于3月而且是闰年的话。。))
3.还要注意月份之间的相加和相减,因为2018年3月-2017年10月=0年5月, 2018年4月20日+11天=2018年5月1日。
4.接着需要从电脑自动获取现在的时间,然后依次打印
5.最后需要验证程序,老师让我们输出从2019年1月1日0时0分0秒连续加100天的数值,全部输出。
老师的要求如下:
#include <time.h>
class JulianDate {
private:
    static int EPOCH;
    //        int mon, day, year, hour, min, second;
    // this representation would make difference VERY UGLY
    // diff between Jan. 1 2001 12:03:04  and Feb 26 2028 11:19:02
    double jday; // number of days since epoch
};
/*
        how many days in a year? 365
        leap year: if year MOD 4 == 0 LEAP EXCEPT

                   if year MOD 100 == 0 NOT LEAP YEAR Except

                                                 if year MOD 400 == 0 LEAP
Leap years:
 NO 1900
 YES 1904
 YES 1908
 YES 2000
 NO 2100
 YES 2400
    days since EPOCH = 365 * (year - 2000) + years/4 - ....
2018 - 2000 = 18
seconds in a day = 24*60*60 = 86400
hh:mm:ss
00:00:00  0.0
12:00:00  0.5

 */

int JulianDate::EPOCH = 2000; // Jan.1 2000, 00:00:00 = 0
int main() {
    JulianDate newyear(2018, 1, 1, 0,0,0);
    JulianDate valentine(2018, 2, 14, 12,0,0); // 0.5
    JulianDate today; // get it from the system time: time(nullptr)
    // localtime
    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';
    cout << "\nyear: " << newyear.getYear()
         << "\nmonth: " << newyear.getMonth()
         << "\nday: " << newyear.getDay()
         << "\nhour: " << newyear.getHour()
         << "\nmin: " << newyear.getMin()
         << "\nsec: " << newyear.getSec() << '\n';
    JulianDate d1(2019, 1, 1, 0,0,0);
    for (int i = 0; i < 100; i++)
        cout << d1 + i;
}

下面是我根据老师上课的要求写的代码,但是很多bug,也有很多不足,求大神帮我改一下和完善下,然后和我解释下谢谢呢!!
#include <iostream>
#include <time.h>
using namespace std;
class JulianDate {
private:
    static int EPOCH;
    int mon, day, year, hour, min, second;
    //        int mon, day, year, hour, min, second;
    // this representation would make difference VERY UGLY
    // diff between Jan. 1 2001 12:03:04  and Feb 26 2028 11:19:02
    double jday; // number of days since epoch
    const static int daysPerMonth[12];
    const static int cumulativeDaysUpToMonth[12];
    const static int monthNames[12];
public:
    JulianDate(int year, int mon, int day, int hour, int min, int second) {
        double dy = year - 2000;
        double days = 365 * dy + dy / 4 - dy / 100 + dy / 400;   //这里的闰年加减感觉错了,2000年好像是闰年,但是dy/4感觉少了一年、、但是老师叫我们这样算的。。
        days += cumulativeDaysUpToMonth[mon - 1];                   //怎么判断2个年份之间的闰年然后把多的天数加上呢?
        days += day;                                           //还要注意如果输入的那年刚好是闰年。月份大于3和小于3的区别
        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
            if (mon >= 3) {
                days++;
            } else {
                days = days;
            }
        }
    }

    friend JulianDate operator+(JulianDate d, int addday){
        return JulianDate(d.year,d.mon,d.day+addday,d.hour,d.min,d.second);
    }
    friend double operator-(JulianDate n, JulianDate v){
        return (v.year-n.year,v.mon-n.mon,v.day-n.day,v.hour,v.min,v.second);
    }
    JulianDate( ) {
        time_t now=time(nullptr);
}

    double getYear(){
        return year;
    }
    double getMonth(){
        return mon;
    }
    double getDay(){
        return day;
    }
    double getHour(){
        return hour;
    }
    double getMin(){
        return min;
    }
    double getSec(){
        return second;
    }


    friend ostream& operator <<(ostream& s, JulianDate f){
        return s<<"("<<f.year<<","<<JulianDate::monthNames[f.mon]<<","<<f.day<<","<<f.hour<<","<<f.min<<","<<f.second<<")"<<endl;
    }

};
const int JulianDate::daysPerMonth[12] =

        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

const int JulianDate::cumulativeDaysUpToMonth[12] =

        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334                  //老师说要用数组做,他说这样做很丑陋但是必须的。。


        };
const int JulianDate::monthNames[12] =

        {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

int JulianDate::EPOCH = 2000; // Jan.1 2000, 00:00:00 = 0
/*
        how many days in a year? 365
        leap year: if year MOD 4 == 0 LEAP EXCEPT
                   if year MOD 100 == 0 NOT LEAP YEAR Except
                                                 if year MOD 400 == 0 LEAP
Leap years:
 NO 1900
 YES 1904
 YES 1908
 YES 2000
 NO 2100

 YES 2400
    days since EPOCH = 365 * (year - 2000) + years/4 - ....
2018 - 2000 = 18
seconds in a day = 24*60*60 = 86400
hh:mm:ss
00:00:00  0.0
12:00:00  0.5
*/

int main() {
    JulianDate newyear(2018, 1, 1, 0,0,0);
    JulianDate valentine(2018, 2, 14, 12,0,0); // 0.5
    JulianDate today; // get it from the system time: time(nullptr)
    // localtime
    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';
    cout << "\nyear: " << newyear.getYear()
         << "\nmonth: " << newyear.getMonth()
         << "\nday: " << newyear.getDay()
         << "\nhour: " << newyear.getHour()
         << "\nmin: " << newyear.getMin()
         << "\nsec: " << newyear.getSec() << '\n';
    JulianDate d1(2019, 1, 1, 0,0,0);
    for (int i = 0; i < 100; i++)
        cout << d1 + i;
}
最佳答案
2019-10-2 11:37:36
本帖最后由 superbe 于 2019-10-3 12:18 编辑
#include <iostream>
#include <time.h>
#include <iomanip>
using namespace std;

class JulianDate {

private:
    static int EPOCH;
    int mon, day, year, hour, min, second;
    double jday;    //number of days since epoch
    const static int daysPerMonth[12];
    const static int cumulativeDaysUpToMonth[12];
    const static int monthNames[12];
    void  calJday();

public:
    JulianDate(){}
    JulianDate(int year, int mon, int day, int hour, int min, int second);
    int getYear(){ return year; }
    int getMonth(){ return mon; }
    int getDay(){ return day; }
    int getHour(){ return hour; }
    int getMin(){ return min; }
    int getSec(){ return second; }
    double getJday(){ return jday; }
    static bool isLeapYear(int year);
    friend JulianDate operator+(JulianDate &date, int days);     //重载+
    friend double operator-(JulianDate &d1, JulianDate &d2);     //重载-
    friend ostream& operator<<(ostream &out, const JulianDate &date);  //重载<<

};

int JulianDate::EPOCH = 2000;    //Jan.1 2000, 00:00:00 = 0
const int JulianDate::daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int JulianDate::cumulativeDaysUpToMonth[12] = {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
const int JulianDate::monthNames[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

/* 构造函数 */
JulianDate::JulianDate(int year, int mon, int day, int hour, int min, int second) {
        this->year = year;
        this->mon = mon;
        this->day = day;
        this->hour = hour;
        this->min = min;
        this->second = second;
        calJday();
}

/* 计算jday的函数 */
void JulianDate::calJday(){
        int dy = year - EPOCH;                                  //与EPOCH相差的整年数
        if(dy>0)  dy-=1;
        double days = 365 * dy + dy / 4 - dy / 100 + dy / 400;  //计算整年的总天数,dy/4-dy/100+dy/400是算闰年多出来的天数
        days += cumulativeDaysUpToMonth[mon - 1];               //补加上从1月开始整月的天数
        days += day - 1;                                            //补加上不满整月的天数
        if(isLeapYear(year) && mon>2)  days ++;                   //如果year是闰年并且超过2月份,补加上1天
        days += (hour*3600 + min*60 + second)*1.0/86400;
        jday = days;
}

/* 判断是否闰年的函数 */
bool JulianDate::isLeapYear(int year){
        bool isLeap = (!(year%4) && year%100) || (year%400==0);
        return isLeap;
}

/* 重载运算符+ */
JulianDate operator+(JulianDate &date, int days){
        JulianDate dt = date;        //调用了默认复制构造函数
        for(int i=1; i<= days; i++){
                dt.day ++;                //增加1天
                int daysInMon = dt.daysPerMonth[dt.mon-1];        //当月天数
                if(dt.isLeapYear(dt.year) && dt.mon==2) daysInMon += 1;  //闰年2月份加1天
                if(dt.day > daysInMon){  //如果大于当月天数
                        dt.day = 1;          //日变成下月1号
                        dt.mon ++;           //月份加1
                        if(dt.mon > 12){     //如果月份超过12
                                dt.mon = 1;      //月份变成下年的1月份
                                dt.year ++;      //年份加1
                        }
                }
        }
        dt.jday += days;
        return dt;
}

/* 重载运算符- */
double operator-(JulianDate &d1, JulianDate &d2){
        return d1.jday-d2.jday;
}

/* 重载运算符<< */
ostream& operator<<(ostream &os,const JulianDate &date){
        os << date.year << "-"<< date.mon << "-" <<date.day << " "
            << date.hour << ":" << date.min << ":" << date.second << " "
            << fixed << setprecision(1) << date.jday;
        return os;
}


int main() {
        JulianDate newyear(2018, 1, 1, 0, 0, 0);
        JulianDate valentine(2018, 2, 14, 12, 0, 0); //0.5
        double days = valentine - newyear;
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        JulianDate today(ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
        JulianDate due = today + 7;

        cout << "newyear: " << newyear;
        cout << "\nyear: " << newyear.getYear()
                 << "\nmonth: " << newyear.getMonth()
                 << "\nday: " << newyear.getDay()
                 << "\nhour: " << newyear.getHour()
                 << "\nmin: " << newyear.getMin()
                 << "\nsec: " << newyear.getSec() << '\n';
        cout << "valentine: " << valentine << endl;
        cout << "days between newyear and valentine: " << days << endl;
        cout << "now date: " << today  <<endl;
        cout << "7 days later: " << due <<endl;
        system("pause");
        JulianDate d1(2019, 1, 1, 0, 0, 0);
        cout << "1--100 days since " << d1 << ":" <<endl;
        for (int i = 1; i <= 100; i++){
                cout << d1 + i << endl;
        }

        return 0;
}

上面计算jday的函数,针对EPOCH是闰年是正确的(2000是闰年),如果不是闰年要修改下。
建议换成下面这个比较通用的。是老师要求必须用上面这种方法吗。
/* 计算jday的函数 2 */
void JulianDate::calJday(){
        double days = 0;
        for(int i=EPOCH; i < year; i ++){                       //计算整年的总天数
                days += 365;
                if(isLeapYear(i)) days ++;                  //如果是闰年补加上1天
        }
        days += cumulativeDaysUpToMonth[mon - 1];               //补加上从1月开始整月的天数
        days += day - 1;                                        //补加上不满整月的天数
        if(isLeapYear(year) && mon > 2)  days ++;               //如果year是闰年并且超过2月份,补加上1天
        days += (hour*3600 + min*60 + second)*1.0/86400;
        jday = days;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-10-2 09:38:26 | 显示全部楼层
顶一下我的帖子哇!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-2 11:37:36 | 显示全部楼层    本楼为最佳答案   
本帖最后由 superbe 于 2019-10-3 12:18 编辑
#include <iostream>
#include <time.h>
#include <iomanip>
using namespace std;

class JulianDate {

private:
    static int EPOCH;
    int mon, day, year, hour, min, second;
    double jday;    //number of days since epoch
    const static int daysPerMonth[12];
    const static int cumulativeDaysUpToMonth[12];
    const static int monthNames[12];
    void  calJday();

public:
    JulianDate(){}
    JulianDate(int year, int mon, int day, int hour, int min, int second);
    int getYear(){ return year; }
    int getMonth(){ return mon; }
    int getDay(){ return day; }
    int getHour(){ return hour; }
    int getMin(){ return min; }
    int getSec(){ return second; }
    double getJday(){ return jday; }
    static bool isLeapYear(int year);
    friend JulianDate operator+(JulianDate &date, int days);     //重载+
    friend double operator-(JulianDate &d1, JulianDate &d2);     //重载-
    friend ostream& operator<<(ostream &out, const JulianDate &date);  //重载<<

};

int JulianDate::EPOCH = 2000;    //Jan.1 2000, 00:00:00 = 0
const int JulianDate::daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int JulianDate::cumulativeDaysUpToMonth[12] = {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
const int JulianDate::monthNames[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

/* 构造函数 */
JulianDate::JulianDate(int year, int mon, int day, int hour, int min, int second) {
        this->year = year;
        this->mon = mon;
        this->day = day;
        this->hour = hour;
        this->min = min;
        this->second = second;
        calJday();
}

/* 计算jday的函数 */
void JulianDate::calJday(){
        int dy = year - EPOCH;                                  //与EPOCH相差的整年数
        if(dy>0)  dy-=1;
        double days = 365 * dy + dy / 4 - dy / 100 + dy / 400;  //计算整年的总天数,dy/4-dy/100+dy/400是算闰年多出来的天数
        days += cumulativeDaysUpToMonth[mon - 1];               //补加上从1月开始整月的天数
        days += day - 1;                                            //补加上不满整月的天数
        if(isLeapYear(year) && mon>2)  days ++;                   //如果year是闰年并且超过2月份,补加上1天
        days += (hour*3600 + min*60 + second)*1.0/86400;
        jday = days;
}

/* 判断是否闰年的函数 */
bool JulianDate::isLeapYear(int year){
        bool isLeap = (!(year%4) && year%100) || (year%400==0);
        return isLeap;
}

/* 重载运算符+ */
JulianDate operator+(JulianDate &date, int days){
        JulianDate dt = date;        //调用了默认复制构造函数
        for(int i=1; i<= days; i++){
                dt.day ++;                //增加1天
                int daysInMon = dt.daysPerMonth[dt.mon-1];        //当月天数
                if(dt.isLeapYear(dt.year) && dt.mon==2) daysInMon += 1;  //闰年2月份加1天
                if(dt.day > daysInMon){  //如果大于当月天数
                        dt.day = 1;          //日变成下月1号
                        dt.mon ++;           //月份加1
                        if(dt.mon > 12){     //如果月份超过12
                                dt.mon = 1;      //月份变成下年的1月份
                                dt.year ++;      //年份加1
                        }
                }
        }
        dt.jday += days;
        return dt;
}

/* 重载运算符- */
double operator-(JulianDate &d1, JulianDate &d2){
        return d1.jday-d2.jday;
}

/* 重载运算符<< */
ostream& operator<<(ostream &os,const JulianDate &date){
        os << date.year << "-"<< date.mon << "-" <<date.day << " "
            << date.hour << ":" << date.min << ":" << date.second << " "
            << fixed << setprecision(1) << date.jday;
        return os;
}


int main() {
        JulianDate newyear(2018, 1, 1, 0, 0, 0);
        JulianDate valentine(2018, 2, 14, 12, 0, 0); //0.5
        double days = valentine - newyear;
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        JulianDate today(ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
        JulianDate due = today + 7;

        cout << "newyear: " << newyear;
        cout << "\nyear: " << newyear.getYear()
                 << "\nmonth: " << newyear.getMonth()
                 << "\nday: " << newyear.getDay()
                 << "\nhour: " << newyear.getHour()
                 << "\nmin: " << newyear.getMin()
                 << "\nsec: " << newyear.getSec() << '\n';
        cout << "valentine: " << valentine << endl;
        cout << "days between newyear and valentine: " << days << endl;
        cout << "now date: " << today  <<endl;
        cout << "7 days later: " << due <<endl;
        system("pause");
        JulianDate d1(2019, 1, 1, 0, 0, 0);
        cout << "1--100 days since " << d1 << ":" <<endl;
        for (int i = 1; i <= 100; i++){
                cout << d1 + i << endl;
        }

        return 0;
}

上面计算jday的函数,针对EPOCH是闰年是正确的(2000是闰年),如果不是闰年要修改下。
建议换成下面这个比较通用的。是老师要求必须用上面这种方法吗。
/* 计算jday的函数 2 */
void JulianDate::calJday(){
        double days = 0;
        for(int i=EPOCH; i < year; i ++){                       //计算整年的总天数
                days += 365;
                if(isLeapYear(i)) days ++;                  //如果是闰年补加上1天
        }
        days += cumulativeDaysUpToMonth[mon - 1];               //补加上从1月开始整月的天数
        days += day - 1;                                        //补加上不满整月的天数
        if(isLeapYear(year) && mon > 2)  days ++;               //如果year是闰年并且超过2月份,补加上1天
        days += (hour*3600 + min*60 + second)*1.0/86400;
        jday = days;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-3 06:30:22 | 显示全部楼层
superbe 发表于 2019-10-2 11:37
上面计算jday的函数,针对EPOCH是闰年是正确的(2000是闰年),如果不是闰年要修改下。
建议换成下面这 ...

我觉得老师说的这个方法有瑕疵,虽然老师要求我们用这个方法,但是我觉得应该用正确的比较好。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-3 12:14:22 | 显示全部楼层
superbe 发表于 2019-10-2 11:37
上面计算jday的函数,针对EPOCH是闰年是正确的(2000是闰年),如果不是闰年要修改下。
建议换成下面这 ...

1.我想问下如果把main函数中的获取当前系统时间的程序移出来通过构造函数来求怎么写呢?
2.然后我想问下你的第108行的+1900和+1是什么意思呢?
3.你的第55行是啥意思呢,为啥还要减1天呢,能解释下不满整月的天数是啥意思吗?
4.第56行如果判断是闰年了并且月份大于2,加一天不就可以了吗,为啥还要判断dy%4 !=0然后+1天呢
5.请问你可以和我说下你的69行-85行关于日期计算的内容吗?我有点不懂,你的73行加入了一个变量daysInMon,如果判断是闰年而且大于2月就加一天,这里的+1天是在上面定义的数组中的2月+1吗?
6.我还有一个问题就是,每个月的月份不一样,是如何判断某月的天数到28or29or30or31天的时候变成下一个月的呢?我就是很不明白这个机制,是和上面定义的数组有关吗?
7.接着第6小问,如果天数的加减是>=31天咋办,或者56天,100天,这样隔了很多怎么计算呢?
谢谢,如果你有时间的话麻烦给我详细解释下日期的加减。。。万分感谢!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-3 13:15:33 From FishC Mobile | 显示全部楼层
本帖最后由 superbe 于 2019-10-3 13:30 编辑

1. 这样写 Juliandate(tm *ltm){......} 里面写代码给成员赋值并调用calJday(),类似现在这个构造函数,只不过每个值是从ltm取得的,例如this->second=ltm->tm_sec
2. localtime函数返回的年份是从1900年起算的,月份是从0开始的,所以分别加1900和1
3. 例如2000年1月1日12:00:00,这个时刻是12小时1还不够1天,应该是0.5天,所以当天这一天不能直接加1,而是根据时分秒计算0.几天。
4. 这个代码我已经改了,见第一个calJday()函数。其实这个函数也可以修改成通用的。
5. 这个函数是逐日增加,超过当月就月份加1,从下一个月开始继续加。并且如果月份超过12,就年份加1,从下一年继续增加。2月份天数不是加到数组里,而是一个单独的变量。
6. 没错,就是利用那个天数的数组。一月份天数是daysPerMonth[0],二月份天数是daysPerMonth[1],以此类推。循环到某个月的时候,根据对应数组元素的值就可以判断是否超过了。
7. 是逐天计算的,看了上面5.的回答就明白了吧。

补充一下,不满整月天数就是最后一个月的天数,例如2015年3月15日,最后的3月天数就是15天。(减掉1天)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-3 21:37:38 | 显示全部楼层
superbe 发表于 2019-10-3 13:15
1. 这样写 Juliandate(tm *ltm){......} 里面写代码给成员赋值并调用calJday(),类似现在这个构造函数,只 ...

好的,谢谢你,我今晚下课回来好好琢磨下,哎,为啥你们学的都这么好,为啥我总是写不出来,你能教教我一些技巧吗,快期中考试了-。-
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-6 07:32:26 | 显示全部楼层
superbe 发表于 2019-10-3 13:15
1. 这样写 Juliandate(tm *ltm){......} 里面写代码给成员赋值并调用calJday(),类似现在这个构造函数,只 ...

我想问一下,我的第一个问题我还是不是特别会,我们老师的main函数里要计算的如下:
JulianDate today; // get it from the system time: time(nullptr)
    // localtime
    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';
但是我试了好几个都不行:
/*JulianDate( int today_year,int today_mon,int today_day,int today_hour,int today_min,int today_sec){
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        return (ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
    }

    JulianDate(tm *ltm){
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        return (ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);

    }
      JulianDate( double today){
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        return today(ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec);
    }
     */
你可以帮我下一下吗?还有就是,如果我要把月份都换成string怎么写呢?代码如下:
const string Date::monthNames[12] =
        {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

万分感谢!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-6 19:16:00 | 显示全部楼层
本帖最后由 superbe 于 2019-10-6 19:25 编辑

先説你这几个构造函数的问题吧。构造函数里常常要给成员变量赋值,比如this->year=year; 前一个year是成员,后一个year是参数,也就是説你的参数是什么,就利用这个参数给成员赋值。而你第1个构造函数的几个参数在函数里完全没用到;第2个构造函数的参数ltm,在函数里又重新定义了一个ltm,和参数里的ltm没关系了;第3个构造函数的参数today是double类型,而后面today(....)这种形式是什么意思呢,怎么double还带参数呢,这种形式像是一个函数调用。另外,构造函数不需要用到return。

你説的构造函数,可以这样写:(带一个tm*类型参数)
JulianDate::JulianDate(tm *ltm) {
        this->year = ltm->tm_year+1900;
        this->mon = ltm->tm_mon+1;
        this->day = ltm->tm_mday;
        this->hour = ltm->tm_hour;
        this->min = ltm->tm_min;
        this->second = ltm->tm_sec;
        calJday();
}
相应的class public下要增加一行:
JulianDate(tm *ltm);
main函数里这样写:
time_t now = time(nullptr);
tm *ltm = localtime(&now);
JulianDate today(ltm);
----------------------------------------------------
第二种方案也可以这样写:(带一个time_t类型参数)
JulianDate::JulianDate(time_t  t) {
        tm *ltm = localtime(&t);
        this->year = ltm->tm_year+1900;
        this->mon = ltm->tm_mon+1;
        this->day = ltm->tm_mday;
        this->hour = ltm->tm_hour;
        this->min = ltm->tm_min;
        this->second = ltm->tm_sec;
        calJday();
}
相应的class public下要增加一行:
JulianDate(time_t t);
main函数里这样写:
time_t now = time(nullptr);
JulianDate today(now);
---------------------------------------------------------
第三种方案也可以这样写:(不带参数,也就是成了默认构造函数)
JulianDate::JulianDate(){
        time_t now = time(nullptr);
        tm *ltm = localtime(&now);
        this->year = ltm->tm_year+1900;
        this->mon = ltm->tm_mon+1;
        this->day = ltm->tm_mday;
        this->hour = ltm->tm_hour;
        this->min = ltm->tm_min;
        this->second = ltm->tm_sec;
        calJday();
}
相应的class public下原来的默认构造函数:
JulianDate(){} 改成 JulianDate();
main函数里这样写:
JulianDate today;
---------------------------------------------------------
通过这三个方案的比较,你发现了吧,如果构造函数没有参数,它只好自己去调用time和localtime,如果main传递给它了,它就可以直接使用了。

我发的代码里没有用到monthNames[12]数组,你看哪里需要,我再看怎么改吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-9 11:44:13 | 显示全部楼层
本帖最后由 丶不离不弃 于 2019-10-9 11:46 编辑
superbe 发表于 2019-10-6 19:16
先説你这几个构造函数的问题吧。构造函数里常常要给成员变量赋值,比如this->year=year; 前一个year是成员 ...


恩恩,我这几天都在准备考试,我们老师要求就是需要在输出的时候,把原来的阿拉伯数字的月份改为jan Feb, Mar。。。。。2018-Jan-1 0:0:0就是这样呢。谢谢!
然后像上面说的,需要把get服务器现在时间的函数放在上面构造函数,不放在main函数里,main函数里仅仅这样写:
JulianDate today; // get it from the system time: time(nullptr)
    // localtime
    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-9 13:15:21 | 显示全部楼层
本帖最后由 superbe 于 2019-10-9 14:13 编辑

嗯,那就是第三种构造函数就可以了。
月份输出英文的话,要改动几个地方:

1. 头文件增加:#include <string>

2. class private下原来的monthNames这行改成:
    const static string monthNames[12];

3. class外面JulianDate::monthNames[12]这行改成:
    const string JulianDate::monthNames[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

4. 原来的重载运算符<<函数改成:
ostream& operator<<(ostream &os,const JulianDate &date){
        os << date.year << "-" << date.monthNames[date.mon-1] << "-" <<date.day << " "
            << date.hour << ":" << date.min << ":" << date.second << " "
            << fixed << setprecision(1) << date.jday;
        return os;
}

你测试下能不能满足要求。
我不发完整代码了,自己改下吧,这样比较熟悉。
在CLion里测试了下,可能需要把 nullptr 改成 NULL。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-10 09:50:31 | 显示全部楼层
superbe 发表于 2019-10-9 13:15
嗯,那就是第三种构造函数就可以了。
月份输出英文的话,要改动几个地方:

我已经弄好了,代码如下:
#include <iostream>
#include <time.h>
#include <iomanip>
#include <string>
using namespace std;

class JulianDate {

private:
    static int EPOCH;
    int mon, day, year, hour, min, second;
    double jday;    //number of days since epoch
    const static int daysPerMonth[12];
    const static int cumulativeDaysUpToMonth[12];
    const static string monthNames[12];
    void  calJday();

public:
    JulianDate();
    JulianDate(int year, int mon, int day, int hour, int min, int second)
            :year(year),mon(mon),day(day),hour(hour),min(min),second(second){}
    int getYear(){ return year; }
    string getMonth(){ return monthNames[mon-1]; }
    int getDay(){ return day; }
    int getHour(){ return hour; }
    int getMin(){ return min; }
    int getSec(){ return second; }
    double getJday(){ return jday; }
    static bool isLeapYear(int year);
    friend JulianDate operator+(JulianDate &date, int days);     //overload +
    friend double operator-(JulianDate &d1, JulianDate &d2);     //-
    friend ostream& operator<<(ostream & os, const JulianDate &date);  //<<

};

int JulianDate::EPOCH = 2000;    //Jan.1 2000, 00:00:00 = 0
const int JulianDate::daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int JulianDate::cumulativeDaysUpToMonth[12] = {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
const string JulianDate::monthNames[12] =
        {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

/* get the system time */
JulianDate::JulianDate(){
    time_t now = time(nullptr);
    tm *ltm = localtime(&now);
    this->year = ltm->tm_year+1900;  //the year is based on 1900
    this->mon = ltm->tm_mon+1;// the month is calculated from month 0;
    this->day = ltm->tm_mday;
    this->hour = ltm->tm_hour;
    this->min = ltm->tm_min;
    this->second = ltm->tm_sec;
    //calJday();
}

/* calculate jday */
void JulianDate::calJday(){
    double days = 0;
    for(int i=EPOCH; i < year; i++){                       //total days
        days += 365;
        if(isLeapYear(i)) days ++;                  //if leap year , days+1
    }
    days += cumulativeDaysUpToMonth[mon - 1];
    days += day - 1;                                        //if not full day at the end
    if(isLeapYear(year) && mon > 2)  days ++;               //if leap year and month>2
    days += (hour*3600 + min*60 + second)*1.0/86400;
    jday = days;
}

/* judge if it is leap year */
bool JulianDate::isLeapYear(int year){
    bool isLeap = (!(year%4) && year%100) || (year%400==0);
    return isLeap;
}

/* overload+ */
JulianDate operator+(JulianDate &date, int days){
    JulianDate dt = date;
    for(int i=1; i<= days; i++){
        dt.day ++;
        int daysInMon = dt.daysPerMonth[dt.mon-1];        //the day on the month
        if(dt.isLeapYear(dt.year) && dt.mon==2) daysInMon += 1;  //if it on feb, add 1 day
        if(dt.day > daysInMon){  //if > recent month
            dt.day = 1;          //change to the first day of next month
            dt.mon ++;           //
            if(dt.mon > 12){     //if month > 12
                dt.mon = 1;      //change to the jan of next year
                dt.year ++;      //add year
            }
        }
    }
    dt.jday += days;
    return dt;
}

/* overload- */
double operator-(JulianDate &d1, JulianDate &d2){
    return d1.jday-d2.jday;
}
/* overload<< */
ostream& operator<<(ostream & s,const JulianDate& date){
    s << left<<setw(2)<<date.year << "-" << date.monthNames[date.mon-1] << "-" <<date.day << " "
      << date.hour << ":" << date.min << ":" << date.second << " ";
      //<< fixed << setprecision(1)<< date.jday;
    return s;
}


int main() {
    JulianDate newyear(2018, 1, 1, 0,0,0);
    JulianDate valentine(2018, 2, 14, 12,0,0); // 0.5
    JulianDate today; // get it from the system time: time(nullptr)
    // localtime

    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';

    cout << "\nyear: " << newyear.getYear()
         << "\nmonth: " << newyear.getMonth()
         << "\nday: " << newyear.getDay()
         << "\nhour: " << newyear.getHour()
         << "\nmin: " << newyear.getMin()
         << "\nsec: " << newyear.getSec() << '\n';
    JulianDate d1(2019, 1, 1, 0,0,0);
    for (int i = 0; i < 100; i++)
        cout << d1 + i<<endl;

}

我还有几个问题麻烦你有时间的时候回答下:
1.如果我把ostream&哪里的date.jday注释掉,是不是calJay()就没用了呢,
2.如果我把JulianDay里面的calday()注释掉,保留输出流的date.jday,为什么在最后输出的时候还是会输出天数呢?第一行输出的是7,然后后面连续加100天输出的是从1--100,我想问这里的date.jday输出的是什么呢?
理论上不是应该输出调用callday()函数中的距离2000年1月1日的日子吗,为啥是7&1-100呢?难道必须调用callday()才可以吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-10-10 09:51:19 | 显示全部楼层
superbe 发表于 2019-10-9 13:15
嗯,那就是第三种构造函数就可以了。
月份输出英文的话,要改动几个地方:

我已经弄好了,代码如下:
#include <iostream>
#include <time.h>
#include <iomanip>
#include <string>
using namespace std;

class JulianDate {

private:
    static int EPOCH;
    int mon, day, year, hour, min, second;
    double jday;    //number of days since epoch
    const static int daysPerMonth[12];
    const static int cumulativeDaysUpToMonth[12];
    const static string monthNames[12];
    void  calJday();

public:
    JulianDate();
    JulianDate(int year, int mon, int day, int hour, int min, int second)
            :year(year),mon(mon),day(day),hour(hour),min(min),second(second){}
    int getYear(){ return year; }
    string getMonth(){ return monthNames[mon-1]; }
    int getDay(){ return day; }
    int getHour(){ return hour; }
    int getMin(){ return min; }
    int getSec(){ return second; }
    double getJday(){ return jday; }
    static bool isLeapYear(int year);
    friend JulianDate operator+(JulianDate &date, int days);     //overload +
    friend double operator-(JulianDate &d1, JulianDate &d2);     //-
    friend ostream& operator<<(ostream & os, const JulianDate &date);  //<<

};

int JulianDate::EPOCH = 2000;    //Jan.1 2000, 00:00:00 = 0
const int JulianDate::daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int JulianDate::cumulativeDaysUpToMonth[12] = {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
const string JulianDate::monthNames[12] =
        {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

/* get the system time */
JulianDate::JulianDate(){
    time_t now = time(nullptr);
    tm *ltm = localtime(&now);
    this->year = ltm->tm_year+1900;  //the year is based on 1900
    this->mon = ltm->tm_mon+1;// the month is calculated from month 0;
    this->day = ltm->tm_mday;
    this->hour = ltm->tm_hour;
    this->min = ltm->tm_min;
    this->second = ltm->tm_sec;
    //calJday();
}

/* calculate jday */
void JulianDate::calJday(){
    double days = 0;
    for(int i=EPOCH; i < year; i++){                       //total days
        days += 365;
        if(isLeapYear(i)) days ++;                  //if leap year , days+1
    }
    days += cumulativeDaysUpToMonth[mon - 1];
    days += day - 1;                                        //if not full day at the end
    if(isLeapYear(year) && mon > 2)  days ++;               //if leap year and month>2
    days += (hour*3600 + min*60 + second)*1.0/86400;
    jday = days;
}

/* judge if it is leap year */
bool JulianDate::isLeapYear(int year){
    bool isLeap = (!(year%4) && year%100) || (year%400==0);
    return isLeap;
}

/* overload+ */
JulianDate operator+(JulianDate &date, int days){
    JulianDate dt = date;
    for(int i=1; i<= days; i++){
        dt.day ++;
        int daysInMon = dt.daysPerMonth[dt.mon-1];        //the day on the month
        if(dt.isLeapYear(dt.year) && dt.mon==2) daysInMon += 1;  //if it on feb, add 1 day
        if(dt.day > daysInMon){  //if > recent month
            dt.day = 1;          //change to the first day of next month
            dt.mon ++;           //
            if(dt.mon > 12){     //if month > 12
                dt.mon = 1;      //change to the jan of next year
                dt.year ++;      //add year
            }
        }
    }
    dt.jday += days;
    return dt;
}

/* overload- */
double operator-(JulianDate &d1, JulianDate &d2){
    return d1.jday-d2.jday;
}
/* overload<< */
ostream& operator<<(ostream & s,const JulianDate& date){
    s << left<<setw(2)<<date.year << "-" << date.monthNames[date.mon-1] << "-" <<date.day << " "
      << date.hour << ":" << date.min << ":" << date.second << " ";
      //<< fixed << setprecision(1)<< date.jday;
    return s;
}


int main() {
    JulianDate newyear(2018, 1, 1, 0,0,0);
    JulianDate valentine(2018, 2, 14, 12,0,0); // 0.5
    JulianDate today; // get it from the system time: time(nullptr)
    // localtime

    double days = valentine - newyear;
    JulianDate due = today + 7;
    cout << due << '\n';

    cout << "\nyear: " << newyear.getYear()
         << "\nmonth: " << newyear.getMonth()
         << "\nday: " << newyear.getDay()
         << "\nhour: " << newyear.getHour()
         << "\nmin: " << newyear.getMin()
         << "\nsec: " << newyear.getSec() << '\n';
    JulianDate d1(2019, 1, 1, 0,0,0);
    for (int i = 0; i < 100; i++)
        cout << d1 + i<<endl;

}

我还有几个问题麻烦你有时间的时候回答下:
1.如果我把ostream&哪里的date.jday注释掉,是不是calJay()就没用了呢,
2.如果我把JulianDay里面的calday()注释掉,保留输出流的date.jday,为什么在最后输出的时候还是会输出天数呢?第一行输出的是7,然后后面连续加100天输出的是从1--100,我想问这里的date.jday输出的是什么呢?
理论上不是应该输出调用callday()函数中的距离2000年1月1日的日子吗,为啥是7&1-100呢?难道必须调用callday()才可以吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-10 11:58:12 | 显示全部楼层
1.这里注释掉,就不输出jday了,所以对于输出来说calJday()是没用了。但是main里还有这行:double days = valentine - newyear; 看重载-的函数就知道,这个减法是由jday相减实现的,而jday是由calJday()计算出的,所以应该有calJday()函数。(注:main里计算出了days但没输出days!)

2.注释掉calJday()而保留输出jday,那就是没有计算jday的值反而要输出它的值。jay的值不是你计算给它的,你不确定它是多少。不同的编译器可能不同,在CLion和DevC++下默认值是0,而VS下是一个未知数(因为它们带的编译器不同)。所以你在CLion下today中jday等于0,而接着today+7使jday变成7,所以输出的是7。后面d1中jday也是0,接着输出d1+(1--100)天不就是输出1--100吗。如果在VS下输出就不一样了,我电脑上jday会输出一串很长的数。结论就是必须调用calJday()才能使jday正确。当然也可以改成一个public的成员函数,在创建对象后调用而不在构造函数里调用。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-16 22:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表