循环中增加日期

时间:2014-10-31 10:26:22

标签: c++ loops

这是一项练习;我禁止使用C ++的内置日期功能或任何现成的库。

我有这段代码:

#include <iostream>
#include <vector>

using namespace std;


bool IsLeap(unsigned int  year)
{
    if (year % 4 != 0) return false;
    else
        if (year % 100 != 0) return true;
        else
            if (year % 400 != 0) return false;
            else
                return true;
}

class Date
{
public:
    unsigned short int Day;
    unsigned short int Month;
    unsigned short int Year;
    unsigned short int DayOfWeek;
};

int MonthLimit(int Month, int year)
{
    switch (Month)
    {
    case 4:
    case 6:
    case 9:
    case 11:
    {
        return 30;
        break;
    }
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 12:
    {
        return 31;
        break;
    }
    case 2:
        if (IsLeap(year))
        {
            return 29;
            break;
        }
        else
        {
            return 28;
            break;
        }

    }
}



const Date FirstDayEver = { 1, 1, 1900, 1 };  //January 1, 1900 was on a Monday.

int main()
{
    unsigned int years;
    cin >> years;

    vector<int> counters(7);   //whenever a 13th falls on a day X, we increment the Xth counter. It's that simple


    for (Date i = FirstDayEver; !((i.Day == 31) && (i.Month == 12) && (i.Year == 1900 + years - 1)); i.Day++)
    {
        i.DayOfWeek = (i.DayOfWeek + 1) % 7;
        if (i.Month == MonthLimit(i.Month, i.Year))
        {
            i.Month++;
            i.Day = 1;
            cout << "Proceeded to " << i.Day << "." << i.Month << "." << i.Year << "\n";
        }
        if ((i.Day == 31) && (i.Month == 12))
        {
            i.Year++;
            i.Day = 1;
            i.Month = 1;
            cout << "Proceeded to " << i.Day << "." << i.Month << "." << i.Year << "\n";
        }

        if (i.Day == 13)
        {
            counters[i.DayOfWeek]++;
            cout << i.Day << "." << i.Month << "." << i.Year << " was a " << i.DayOfWeek << "\n";
        }
    }

    cout << counters[6] << " " << counters[7] << " " << counters[1] << " " << counters[2] << " " << counters[3] << " " << counters[4] << " " << counters[5] << "\n";

    exit(0);
}

调试信息(cout s)用于查看循环中是否发生任何事情。 到目前为止,唯一发生的事情是很多线路说&#34; 13.1.1900是&#34;数量不一。 我认为增加日期的理想逻辑在代码中是相当清楚的,但我试图增加错误。 哪里是我的错?

2 个答案:

答案 0 :(得分:1)

首先,

if (i.Month == MonthLimit(i.Month, i.Year))

将月份与月份中的天数进行比较 由于第一个月是1,而那个月有31天,因此您永远不会增加月份 由于你永远不会增加月份,你永远不会增加年份 (如果你已经命名了函数&#34; DaysInMonth&#34;或者其他更清楚它返回的东西,你可能会发现这更容易。)

你想要

if (i.Day == MonthLimit(i.Month, i.Year))

其次,MonthLimit缺少10月的案例。

答案 1 :(得分:1)

您的增量程序太复杂了 我实际上还在努力弄清楚它们是如何组合在一起的(边缘情况等),但似乎你试图独立地每天/每月/每年进行。

你可以在这样一个简单的函数中完成所有的递增:

void increment_Date(Date &d)
{
    d.DayOfWeek = (d.DayOfWeek + 1) % 7; //increase weekday
    if (++d.Day > MonthLimit(d.Month, d.Year)//increase day, if larger than month size...
    {
        d.Day = 1;                           //reset day to 1
        if (++d.Month > 12)                  //increase month, if larger than year size
        {
          d.Month = 1;                       //reset month to 1
          d.Year++;                          //increase year
        }
    }
}

逻辑更简单,因为我以一种与你似乎完全不同的方式接近它 在上面的函数中,我首先增加最小单位(天),检查溢出,然后在需要时移动到月(等等)。

这种方式的工作原理与汽车里程拨号的数字仅在拨号到达10并且返回0时才会打勾。或者,添加1到9和&# 39;溢出&#39;进入数字的10位数。

否则你的代码很好。 MonthLimit的Switch语句是一个不错的选择。 我在函数中添加一个switch语句,以返回一周中的字符串:

std::String printable_DOW(int DOW)
{
    switch (DOW)
    case 0:
        return "Sunday";
    case 1:
        return "Monday";
    case 2:
        return "Tuesday";
    case 3:
        return "Wednesday";
    case 4:
        return "Thursday";
    case 5:
        return "Friday";
    case 6:
        return "Saturday";
}

print_date功能:

void print_date(Date d)
{
    std::cout<< printable_DOW(d.DayOfWeek) 
             << ", " << d.Day << "." << d.Month << "." d.Year;
}

并且很容易将它们放在一起并使用它们:

int main
{

    Date my_date;
    my_date.Day = 1;
    my_date.Month = 1;
    my_date.Year = 2000;
    my_date.DayOfWeek = 0;  //assuming 0 == Sunday, 1 = Monday...
    for (int daycount = 0; daycount < 5114 /*days since 1/1/2000 to today*/; daycount++)
    {
        increment_date(my_date);
        //debug:
        print_date(my_date);
    }
    //print "today's" date:
    print_date(my_date);
}

作为一个班级: 它主要在这里和(大多数)工作。随意编辑人物!

class date
{
private:
    unsigned short int day;
    unsigned short int month;
    unsigned short int year;
    unsigned short int day_of_week;
    int month_limit();
    bool is_leap_year();
public:
    date();
    date(int in_day, int in_month, int in_year, int in_day_of_week);
    date& date::operator=(date rhs)
    date& operator++();    //pre-increment (++date)
    date operator++(int);  //post-increment (date++)

    //these are "special" they don't work exactly as you might think and are slightly broken right now,
    //but I'm putting them in regardless
    //they also don't work on DOW right now.
    date& operator+=(const date& rhs)               
    date& operator-=(const date& rhs)
    inline date operator+(date lhs, const date& rhs)
    inline date operator-(date lhs, const date& rhs)
}
//phwew

date::date(int in_day, int in_month, int in_year, int in_day_of_week)
{
    this->day = in_day;
    this->month = in_month;
    this->year = in_year;
    this->day_of_week = in_doay_of_week;
}

date::month_limit()
{
    switch (this->month)
    {
    case 4:
    case 6:
    case 9:
    case 11:
    {
        return 30;
        break;
    }
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 12:
    {
        return 31;
        break;
    }
    case 2:
        if (is_leap_year(this->year))
        {
            return 29;
            break;
        }
        else
        {
            return 28;
            break;
        }

    }
}

bool is_leap_year()
{
    if (this->year % 4 != 0) return false;
    else
        if (this->year % 100 != 0) return true;
        else
            if (this->year % 400 != 0) return false;
            else
                return true;
}

date& date::operator=(date rhs)
{
  swap(rhs);
  return *this;
}

date& date::operator++()
{
    this->day_of_week = (this->day_of_week + 1) % 7; //increase weekday
    this->day++;
    if (++(this->day) > month_limit())           //increase day, if larger than month size...
        {
            this->day = 1;                           //reset day to 1
            if (++this->month > 12)                  //increase month, if larger than year size
            {
              this->month = 1;                       //reset month to 1
              this->year++;                          //increase year
            }
        }
    return *this;
}

date date::operator++(int)
{
    date tmp(*this);
    operator++();
    return tmp;
}

//adds years on, then months, then days
date& date::operator+=(const date& rhs)
{
    this->year  += rhs.year;
    this->month += rhs.month;
    this->day   += rhs.day;
    if (this->month > 12)  //get to the right month
    {
        this->year  = this->month / 12;
        this->month = this->month % 12;
    }
    if (this->day > month_limit())
    {
        this->month = this->day / month_limit();
        this->day   = this->day % month_limit();
        if (this->month > 12)  //recalculate  **yes, I know this is currently wrong if more than one month is added on in days**
        {
            this->year  = this->month / 12;
            this->month = this->month % 12;
        }
    }
    return *this;
}

inline date date::operator+(date lhs, const date& rhs)
{
  lhs += rhs;
  return lhs;
}

//subtracts years, then months, then days
date& date::operator-=(const date& rhs)
{
    if ((rhs.year < this->year) || ((rhs.year == this->year) && (rhs.month < this->month))
       || (((rhs.year == this->year) && (rhs.month == this->month)) && (rhs.day < this->day)
    {
        swap(rhs);
    }
    this->year -= rhs.year;
    this->month -= rhs.month;
    this->day -= rhs.day;

    return *this;
}

inline date date::operator+(date lhs, const date& rhs)
{
  lhs += rhs;
  return lhs;
}