2014-02-19 235 views
2

我對c編程相對比較陌生,並且即時工作的項目需要非常準確的時間,因此我試着編寫一些東西來創建毫秒精度的時間戳。這似乎工作,但我的問題是這樣,是正確的方式還是有一個更簡單的方法?這裏是我的代碼:c中的時間戳以毫秒爲單位精度

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

void wait(int milliseconds) 
{ 
    clock_t start = clock(); 
    while(1) if(clock() - start >= milliseconds) break; 
} 

int main() 
{ 
    time_t now; 
    clock_t milli; 
    int waitMillSec = 2800, seconds, milliseconds = 0; 
    struct tm * ptm; 

    now = time(NULL); 
    ptm = gmtime (&now); 
    printf("time before: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds); 

    /* wait until next full second */ 
    while(now == time(NULL)); 

    milli = clock(); 
    /* DO SOMETHING HERE */ 
    /* for testing wait a user define period */ 
    wait(waitMillSec); 
    milli = clock() - milli; 

    /*create timestamp with milliseconds precision */ 
    seconds = milli/CLOCKS_PER_SEC; 
    milliseconds = milli%CLOCKS_PER_SEC; 
    now = now + seconds; 
    ptm = gmtime(&now); 
    printf("time after: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds); 
    return 0; 
} 

回答

4

下面的代碼似乎有可能提供毫秒級粒度:

#include <windows.h> 
#include <stdio.h> 

int main(void) { 
    SYSTEMTIME t; 
    GetSystemTime(&t); // or GetLocalTime(&t) 
    printf("The system time is: %02d:%02d:%02d.%03d\n", 
     t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); 
    return 0; 
} 

這是基於http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950%28v=vs.85%29.aspx。上述代碼片段在Windows 7上使用CYGWIN進行了測試。

對於Windows 8,存在GetSystemTimePreciseAsFileTime,它「以最高可能的精度級別(< 1us)檢索當前系統日期和時間。」

您的原始方法可能會99.99%的時間(忽略一個小錯誤,下面描述)。你的方法是:

  • 等待下一秒開始,反覆調用time(),直到值改變。
  • time()保存該值。
  • 將值從clock()中保存。
  • 使用當前值clock()和兩個保存的值計算所有後續時間。

你的小錯誤是,你有前兩個逆轉。

但即使有這個固定的,這不能保證工作100%,因爲沒有原子性。兩個問題:

  • 您的代碼循環time(),直到您進入下一秒。但你如何你呢?它可能是1/2秒,甚至幾秒鐘(例如,如果您正在運行帶有斷點的調試器)。

  • 然後您撥打clock()。但是,此保存的值必須與保存的time()的值「匹配」。 如果這兩個電話幾乎是瞬時的,因爲他們通常是,那麼這很好。但是Windows(和Linux)時間片等等是沒有保證的。

另一個問題是clock的粒度。如果CLOCKS_PER_SEC是1000,就像你係統上的情況一樣,那麼你當然可以做的最好的是1毫秒。但它可能比這更糟糕:在Unix系統上它通常爲15毫秒。您可以通過將clock替換爲QueryPerformanceCounter(),來改善此問題,如timespec equivalent for windows的答案中所述,但這可能不適用於給定前兩個問題。

+1

非常感謝您的快速響應。當我回到工作機器時,我會試試這個。直到現在,我不敢使用任何Windows標頭。不幸的是,我不得不使用Windows XP和Visual Studio 6.0,希望這不會是一個問題。 – morten

+0

@morten:msdn鏈接表示'GetSystemTime'在Windows 2000及更高版本上可用,並且我剛剛證實它似乎可以在我的XP Home SP3機器上運行。祝你好運,並告訴我們你最終做了什麼。 –

+1

只是想說,謝謝你,我剛剛實施你的想法,一切工作正常 – morten

0

時鐘週期並不能保證以毫秒爲單位。您需要將clock()的輸出顯式轉換爲毫秒。

t1 = clock(); 
// do something 
t2 = clock(); 
long millis = (t2 - t1) * (1000.0/CLOCKS_PER_SEC); 
0

既然你是在Windows上,你爲什麼不使用Sleep()

+0

可悲的是我不知道它。正如我所說,我對c編程頗爲陌生,並且花了相當長的時間纔想出了一個等待函數:) – morten

+0

@morten - 繁忙的循環不必要地消耗了大量的CPU。非零Sleep()將當前進程的時間片放回內核,以便它可以安排另一個進程運行。 – CubicleSoft

相關問題