2012-11-05 73 views
2

我想我的大腦剛剛拋出了內存不足的異常並崩潰了, 我的問題是我有一個SYSTEMTIME大小爲3的類成員數組,它是用戶定義的(從.lua讀取的)找到離當前時間最近的時間

SYSTEMTIME m_MatchTime[3]; 

那麼它從文件中讀取這樣:

m_MatchTime[0].wDayOfWeek = static_cast<WORD>(m_Lua.GetGlobalNumber("FirstDay")); 
m_MatchTime[0].wHour = static_cast<WORD>(m_Lua.GetGlobalNumber("FirstHour")); 
m_MatchTime[0].wMinute = static_cast<WORD>(m_Lua.GetGlobalNumber("FirstMinute")); 

m_MatchTime[1].wDayOfWeek = static_cast<WORD>(m_Lua.GetGlobalNumber("SecondDay")); 
m_MatchTime[1].wHour = static_cast<WORD>(m_Lua.GetGlobalNumber("SecondHour")); 
m_MatchTime[1].wMinute = static_cast<WORD>(m_Lua.GetGlobalNumber("SecondMinute")); 

m_MatchTime[2].wDayOfWeek = static_cast<WORD>(m_Lua.GetGlobalNumber("ThirdDay")); 
m_MatchTime[2].wHour = static_cast<WORD>(m_Lua.GetGlobalNumber("ThirdHour")); 
m_MatchTime[2].wMinute = static_cast<WORD>(m_Lua.GetGlobalNumber("ThirdMinute")); 

現在我有一個方法:

SYSTEMTIME cTime; 
GetLocalTime(&cTime); 

我必須計算從三個用戶定義的時間中的哪一個是BEFORE並且接近當前時間,然後計算剩餘的時間, (請注意,星期日= 0,星期六= 6,還要注意只有wDayOfWeek,wHour和wMinute必須進行比較,得到最接近)

編輯:現在我授予500bounty一個解決方案,請注意,我想要的例子,

今天:第4天,小時3,分鐘0,
日期:第5天,第5小時,第30分鐘
到目前爲止的剩餘時間爲:1天2小時30分

+2

使用SystemTimeToFileTime(),所以你可以簡單地比較數字。 –

+0

SystemTimeToFileTime()忽略'wDayOfWeek'成員,並且需要根據示例代碼未給出的有效附加成員(如年,月,日)。 – Chad

+0

從您的編輯:「今天:第4天...,日期:第5天......」這不是說日期是*今天*之後1天2小時30分鐘嗎? – dasblinkenlight

回答

0

我已經提出瞭解決方案的算法,我知道它遠離最專業的方式去做,但它迄今爲止完美無瑕。

int main() 
{ 
SYSTEMTIME m_MatchTime[3]; 


// Monday: 00:00 
m_MatchTime[0].wDayOfWeek = 1; 
m_MatchTime[0].wHour = 22; 
m_MatchTime[0].wMinute = 4; 

// Sunday: 01:00 
m_MatchTime[1].wDayOfWeek = 4; 
m_MatchTime[1].wHour = 1; 
m_MatchTime[1].wMinute = 0; 

// Wednesday: 15:30 
m_MatchTime[2].wDayOfWeek = 6; 
m_MatchTime[2].wHour = 15; 
m_MatchTime[2].wMinute = 30; 

// Sunday 23:00 
SYSTEMTIME cTime; 
cTime.wDayOfWeek = 3; 
cTime.wHour = 14; 
cTime.wMinute = 5; 

/* std::cout << timediff_2(cTime, m_MatchTime[0]) << "\n"; 
std::cout << timediff_2(cTime, m_MatchTime[1]) << "\n"; 
std::cout << timediff_2(cTime, m_MatchTime[2]) << "\n";*/ 

vector<size_t>m_Time; 
if(cTime.wDayOfWeek == 0) 
{ 
    for(int i =0; i<3; i++) 
    { 
     if(cTime.wDayOfWeek >= m_MatchTime[i].wDayOfWeek) 
      m_Time.push_back(timediff_2(cTime, m_MatchTime[i])); 
    } 

    if(m_Time.size() == 0) //trim right 
    { 
     for(int i =0; i<3; i++) 
     { 
      if(cTime.wDayOfWeek <= m_MatchTime[i].wDayOfWeek) 
       m_Time.push_back(timediff_2(cTime, m_MatchTime[i])); 
     } 
    } 
} 
else 
{ 
    for(int i =0; i<3; i++) 
    { 
     if(cTime.wDayOfWeek <= m_MatchTime[i].wDayOfWeek) 
      m_Time.push_back(timediff_2(cTime, m_MatchTime[i])); 
    } 

    if(m_Time.size() == 0) //trim right 
    { 
     for(int i =0; i<3; i++) 
     { 
      if(cTime.wDayOfWeek >= m_MatchTime[i].wDayOfWeek) 
       m_Time.push_back(timediff_2(cTime, m_MatchTime[i])); 
     } 
    } 
} 


std::sort(m_Time.begin(), m_Time.end()); 

SYSTEMTIME nearest; 
if(m_Time.size() > 0) 
{ 
    for(int l=0; l<3; l++) 
    { 
     if(timediff_2(cTime, m_MatchTime[l]) == m_Time.at(0)) 
     { 
      nearest = m_MatchTime[l]; 
      break; 
     } 
    } 
} 

unsigned int manydaysleft = howmanydaysuntil( nearest.wDayOfWeek , cTime.wDayOfWeek); 
unsigned int manyhoursleft = howmanyhoursuntil( nearest.wHour, cTime.wHour); 
if(nearest.wHour < cTime.wHour) //manydaysleft will always be > 0 
    manydaysleft--; 
unsigned int manyminutesleft = howmanyminutesuntil(nearest.wMinute, cTime.wMinute); 
if(nearest.wMinute < cTime.wMinute) 
    manyhoursleft--; 



/*cout 
    << manydaysleft << endl 
    << manyhoursleft << endl 
    << manyminutesleft << endl;*/ 

cout << "CurrentTime\n" 
    << "Day:" << cTime.wDayOfWeek 
    << "Hour:" << cTime.wHour 
    << "Min:" << cTime.wMinute 

    << "\nDay:" << nearest.wDayOfWeek 
    << "Hour:" << nearest.wHour 
    << "Min:" << nearest.wMinute 

    << "\nDay:" << manydaysleft 
    << "Hour:" << manyhoursleft 
    << "Min:" << manyminutesleft; 

    return 0; 
} 
5

考慮到問題領域,似乎執行時間的嚴格排序是不必要的(或者甚至是可取的),您只需要查找一組時間中哪一個最接近給定的sentinel值。這將需要線性複雜性,但很容易實現。

我建議計算一個已知曆元的時差,在這種情況下,星期日00:00:00以秒爲單位,然後比較每一次從這一點的差異,看看哪一個最接近。

#include <Windows.h> 
#include <algorithm> 
#include <iostream> 

long seconds_from_sunday_epoch(const SYSTEMTIME& t) 
{ 
    size_t seconds = t.wDayOfWeek * 86400; 
    seconds += t.wHour * 3600; 
    seconds += t.wMinute * 60; 
    return seconds; 
} 

size_t timediff_2(const SYSTEMTIME& t0, const SYSTEMTIME& t1) 
{ 
    size_t seconds_diff = std::abs(
     seconds_from_sunday_epoch(t0) - 
     seconds_from_sunday_epoch(t1)); 

    return seconds_diff; 
} 

int main() 
{ 
    SYSTEMTIME m_MatchTime[3]; 


    // Monday: 00:00 
    m_MatchTime[0].wDayOfWeek = 1; 
    m_MatchTime[0].wHour = 0; 
    m_MatchTime[0].wMinute = 0; 

    // Sunday: 01:00 
    m_MatchTime[1].wDayOfWeek = 0; 
    m_MatchTime[1].wHour = 1; 
    m_MatchTime[1].wMinute = 0; 

    // Wednesday: 15:30 
    m_MatchTime[2].wDayOfWeek = 3; 
    m_MatchTime[2].wHour = 15; 
    m_MatchTime[2].wMinute = 30; 

    // Sunday 23:00 
    SYSTEMTIME cTime; 
    cTime.wDayOfWeek = 0; 
    cTime.wHour = 23; 
    cTime.wMinute = 0; 

    std::cout << timediff_2(cTime, m_MatchTime[0]) << "\n"; 
    std::cout << timediff_2(cTime, m_MatchTime[1]) << "\n"; 
    std::cout << timediff_2(cTime, m_MatchTime[2]) << "\n"; 
} 
+0

非常好的一點,修復(現在)是讀者的練習:)。這個問題比星期六/星期天還要大,但這是最大的差異。週五/週一,週四/週日等等也有問題。 – Chad

+0

這個「bug」太明顯了,不能修復。我已經爲計算星期幾差異提供了必要的邏輯表格。我沒有完全審查它,但我認爲這是正確的。 – Chad

+0

矩陣的理念。 – andre

3

所以問題是,你坐在一個圓,想知道閹從D1去的距離D2權(剩餘在同一個星期)或左(一個值到下一個直通星期日)是短。

首先,您應該將日期轉換爲公式分鐘+小時* 60 +週日* 60 * 24的值。這會給你一週的時間。

#include <stdlib.h> 
int minOfWeek (int d, int h, int m) { 
    return d*60*24+h*60+m; 
} 

下一個找到最小距離:

const int minutesInWeek=60*24*7; 
int bestDistance (int minutes1, int minutes2) { 
    int d=abs (minutes1-minutes2); 
    int dNext=minutesInWeek-d; 
    return d<dNext?d:dNext; 
} 

所以從您的實際時間計算minOfWeek,與所有的3次餵給它在本週的bestDistance和佔用最小的數...

0

const unsigned n = 3; //與實際陣列尺寸替換

auto packtime = [](const SYSTEMTIME& t)->unsigned 
{ 
    return t.wDayOfWeek*24*60 + t.wHour*60 + t.wMinute; 
}; 
auto unpacktime = [](unsigned total)->SYSTEMTIME 
{ 
    SYSTEMTIME ret; 

    ret.wDayOfWeek = total/(60*24); 
    total %= (60*24); 
    ret.wHour = total/60; 
    ret.wMinute = total%60; 

    return ret; 
}; 

unsigned const wraptime = 7*24*60; 
unsigned targettime = packtime(cTime); 

unsigned mintimedif = wraptime + 1; 
unsigned mindifidx; 
unsigned timedif; 

for(unsigned i=0; i<n; ++i) 
{ 
    timedif = packtime(m_MatchTime[i]); 

    if(timedif < targettime) 
     timedif = targettime - timedif; 
    else 
     timedif = wraptime - timedif + targettime; 

    if(timedif < mintimedif) 
    { 
     mintimedif = timedif; 
     mindifidx = i; 
    } 
} 

SYSTEMTIME dif = unpacktime(mintimedif); 

std::cout<<"Today: Day "<<cTime.wDayOfWeek<<" Hour "<<cTime.wHour<<" Minute "<<cTime.wMinute<<std::endl; 
std::cout<<"Nearest day: Day "<<m_MatchTime[mindifidx].wDayOfWeek<<" Hour "<<m_MatchTime[mindifidx].wHour<<" Minute "<<m_MatchTime[mindifidx].wMinute<<std::endl; 
std::cout<<"Difference: "<<dif.wDayOfWeek<<" days "<<dif.wHour<<" hours "<<dif.wMinute<<" minutes"<<std::endl;</code> 
2

標準C++庫允許通過移動所述比較日期函子,和使用該std::sort過載,需要一個自定義比較器的「魔」而完美地解決這一點。

這裏是你如何與代碼很少線(link to a quick test on ideone)做到這一點:

class ClosestTo { 
    int minute_now; 
    int abs_minute(const SYSTEMTIME& t) const { 
     return 60 * (24 * t.wDayOfWeek + t.wHour) + t.wMinute; 
    } 
    int diff_to_now(const SYSTEMTIME& t) const { 
     int res = abs_minute(t) - minute_now; 
     // Has the date passed this week? 
     if (res < 0) { 
      // Yes, the date has passed - move to next week: 
      res += 7*24*60; 
     } 
     return res; 
    } 
public: 
    ClosestTo(const SYSTEMTIME& now) 
    : minute_now(abs_minute(now)) { 
    } 
    // This is the operator the std::sort is going to call to determine ordering 
    bool operator() (const SYSTEMTIME& lhs, const SYSTEMTIME& rhs) const { 
     // Pick the date implying the shortest difference to minute_now 
     return diff_to_now(lhs) < diff_to_now(rhs); 
    } 
}; 

就是這樣,真的!有了這個比較在手,你可以這樣你的三個日期排序:

ClosestTo cmp(cTime); 
sort(m_MatchTime, m_MatchTime+3, cmp); 

現在最近的日期是該指數爲零:

SYSTEMTIME &nearest = m_MatchTime[0]; 
相關問題