8

日付が与えられました。これを (日、月、年): のように入力します12, 03, 87

今、私は何日も後に日付を見つける必要がありますn

このためのコードを書きましたが、効率的ではありません。より速く動作し、複雑さが少ない優れたロジックを教えてください。

#include <stdio.h>

static int days_in_month[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int day, month, year;

unsigned short day_counter;

int is_leap(int y) {
    return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}

next_day()
{
    day += 1; day_counter++;
    if (day > days_in_month[month]) {
        day = 1;
        month += 1;
        if (month > 12) {
            month = 1;
            year += 1;
            if (is_leap(year)) {
                days_in_month[2] = 29;
            } else {
                days_in_month[2] = 28;
            }
        }
    }
}

set_date(int d, int m, int y) 
{
    m < 1 ? m = 1 : 0;
    m > 12 ? m = 12 : 0;
    d < 1 ? d = 1 : 0;
    d > days_in_month[m] ? d = days_in_month[m] : 0;
    if (is_leap(y)){
        days_in_month[2] = 29;
    } 
    else {
        days_in_month[2] = 28;
    }
    day = d;
    month = m;
    year = y;
}

skip_days(int x)
{
    int i;
    for (i=0;i<x;i++) next_day();
}

print_date()
{
    printf ("day: %d month: %d year: %d\n", day, month, year);
}

int main(int argc, char **argv)
{
    int i;

    set_date(5, 2, 1980);
    skip_days(40);
    day_counter = 0;
    /* after this call next_day each day */

    print_date();
    return 0;
}
4

8 に答える 8

14

より速く動作し、複雑さが少ない優れたロジックを教えてください。

これが実際にアプリケーションのパフォーマンスに重要な部分である場合、何か間違ったことをしている可能性があります。明確さと正確さのために、既存のソリューションに固執する必要があります。開発環境に最も適したものを選択してください。


C アプローチ:

#include <stdio.h>
#include <time.h>

int main()
{        
    /* initialize */
    int y=1980, m=2, d=5;    
    struct tm t = { .tm_year=y-1900, .tm_mon=m-1, .tm_mday=d };
    /* modify */
    t.tm_mday += 40;
    mktime(&t);
    /* show result */
    printf("%s", asctime(&t)); /* prints: Sun Mar 16 00:00:00 1980 */
    return 0;
}

Boost アプローチを使用しない C++:

#include <ctime>
#include <iostream>

int main()
{        
    // initialize
    int y=1980, m=2, d=5;
    std::tm t = {};
    t.tm_year = y-1900;
    t.tm_mon  = m-1;
    t.tm_mday = d;
    // modify
    t.tm_mday += 40;
    std::mktime(&t);
    // show result
    std::cout << std::asctime(&t); // prints: Sun Mar 16 00:00:00 1980
}

Boost.Date_Timeアプローチ:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

int main()
{
    using namespace boost::gregorian;
    // initialize
    date d(1980,2,5);
    // modify
    d += days(40);
    // show result
    std::cout << d << '\n'; // prints: 1980-Mar-16
}
于 2013-03-27T21:03:36.670 に答える
5

標準ライブラリmktime関数には、特定の日付に月数または日数を簡単に追加できるようにするトリックが含まれています。「2 月 45 日」または「40 か月目の 2 日」などの日付を指定すると、それmktimeが正規化されます。適切な日付に。例:

#include <time.h>
#include <stdio.h>

int main() {
    int y = 1980;
    int m = 2;
    int d = 5;
    int skip = 40;

    // Represent the date as struct tm.                                                           
    // The subtractions are necessary for historical reasons.
    struct tm  t = { 0 };
    t.tm_mday = d;
    t.tm_mon = m-1;
    t.tm_year = y-1900;

    // Add 'skip' days to the date.                                                               
    t.tm_mday += skip;
    mktime(&t);

    // Print the date in ISO-8601 format.                                                         
    char buffer[30];
    strftime(buffer, 30, "%Y-%m-%d", &t);
    puts(buffer);
}

を使用して数秒で計算を行う場合と比較してtime_t、このアプローチには、夏時間への移行が問題を引き起こさないという利点があります。

于 2013-03-27T20:54:19.837 に答える
0

最も簡単な方法は、time_t型と対応する関数を使用することです。

mktimetm 構造体を に変換しtime_tます。これは、1970 年 1 月 1 日から始まる秒をカウントする整数値です。

値を取得したら、time_t必要な秒数を追加するだけです (1 日あたり 86400)。

元に戻すには、gmtimeまたはを使用します。localtime

于 2013-03-27T20:32:00.120 に答える
0

必要な日数を time_t オブジェクトに追加するだけです。

#define SECOND              1
#define MINUTE              60 * SECOND
#define HOUR                60 * MINUTE
#define DAY                 24 * HOUR





time_t curTime;
time_t futureTime;

time( & curTime );

futureTime = curTime + (5 * DAY);

struct tm * futureDate = gmtime(&futureTime);
std::cout<<"5 days from now will be: "<<futureDate->tm_mday<<"/"<<futureDate->tm_mon+1<<"/"<<futureDate->tm_year+1900<<std::endl;
于 2013-03-27T20:34:42.160 に答える
0

C++ 演算子を使用して実装でき、日付をクラスとして表現することにより、非常に OOP の方法で実装できます。

#include <iostream>
#include <string>

using namespace std;

class Date {
public:
    Date(size_t year, size_t month, size_t day):m_year(year), m_month(month), m_day(day) {}
    ~Date() {}

    // Add specified number of days to date
    Date operator + (size_t days) const;

    size_t Year()  { return m_year; }
    size_t Month() { return m_month; }
    size_t Day()   { return m_day; }

    string DateStr();
private:
    // Leap year check 
    inline bool LeapYear(int year) const
        { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); }

    // Holds all max days in a general year
    static const int MaxDayInMonth[13];

    // Private members
    size_t m_year;
    size_t m_month;
    size_t m_day;   
};

// Define MaxDayInMonth
const int Date::MaxDayInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/// Add specified number of days to date
Date Date::operator + (size_t days) const {
    // Maximum days in the month
    int nMaxDays(MaxDayInMonth[m_month] + (m_month == 2 && LeapYear(m_year) ? 1 : 0));

    // Initialize the Year, Month, Days
    int nYear(m_year);
    int nMonth(m_month);
    int nDays(m_day + days);

    // Iterate till it becomes a valid day of a month
    while (nDays > nMaxDays) {
        // Subtract the max number of days of current month
        nDays -= nMaxDays;

        // Advance to next month
        ++nMonth;

        // Falls on to next year?
        if (nMonth > 12) {
            nMonth = 1; // January
            ++nYear;    // Next year
        }

        // Update the max days of the new month
        nMaxDays = MaxDayInMonth[nMonth] + (nMonth == 2 && LeapYear(nYear) ? 1 : 0);
    }

    // Construct date
    return Date(nYear, nMonth, nDays);
}

/// Get the date string in yyyy/mm/dd format
string Date::DateStr() {
    return to_string(m_year) 
        + string("/")
        + string(m_month < 10 ? string("0") + to_string(m_month) : to_string(m_month))
        + string("/")
        + string(m_day < 10 ? string("0") + to_string(m_day) : to_string(m_day)); 
}


int main() {
    // Add n days to a date
    cout << Date(2017, 6, 25).DateStr() << " + 10 days = "
         << (Date(2017, 6, 25) /* Given Date */ + 10 /* Days to add */).DateStr() << endl;

    return 0;
}

Output
2017/06/25 + 10 days = 2017/07/05
于 2017-06-22T12:21:35.397 に答える
-1

日付フィールドを直接操作するのではなく、エポックからの秒数を使用して計算する方が簡単な場合があります。

たとえば、次のプログラムは今から7 日後の日付を出力します。

#include <stdio.h>
#include <time.h>

main()
{
    time_t t;
    struct tm *tmp;

    time(&t);

    /* add a week to today */
    t += 7 * 24 * 60 * 60;

    tmp = localtime(&t);
    printf("%02d/%02d/%02d\n", tmp->tm_mon+1, tmp->tm_mday,
        tmp->tm_year % 100);
}
于 2013-03-27T20:34:14.690 に答える