計時函數

所謂“時”,可以分成時間點和時間段兩大類,時間點的概念就好比知道現在是幾時幾分,而時間段主要用於計量這段程序運行了多久,或者用於定時觸發中斷。C/C++中有多種方法可以實現計時。

1. 用time()得到時間點

需要包含頭文件<time.h>或者是<ctime>,time()的函數原型爲:

time_t time ( time_t * timer );

其中time_t是64位的整型,用於計算自1970年1月1日以來逝去的秒數,既可以通過返回值來得到秒數,也可以通過傳入參數來獲得秒數,函數的使用方法如下:

1 int main()
2 {
3     const time_t t = time(NULL); // time_t t = 0; time(&t);也可以
4     cout << "自1970年以來,已經過去了 " << t << "" << endl;
5 }

運行結果如下:

可以通過兩次時間點之差來獲得時間段。由time()得到的僅僅是一個很大的秒數,怎樣才能將之轉換成我們日常生活中能用到的年、月、日、時、分和秒呢?

 

2. 用localtime()得到有意義的時間點

需要包含頭文件<time.h>或者是<ctime>,localtime()的函數原型如下:

struct tm * localtime ( const time_t * timer );

返回的是名爲tm的結構體,而tm結構體中則存儲了諸如年、月、日之類的有意義的時間點,函數的用法如下:

複製代碼
 1 int main()
 2 {
 3 const time_t t = time(NULL);
 4     tm* currentTime = localtime(&t);
 5     cout << "當前年:" << 1900 + currentTime->tm_year << endl
 6         << "當前月:" << currentTime->tm_mon + 1 << endl
 7         << "當前日:" << currentTime->tm_mday << endl
 8         << "當前時:" << currentTime->tm_hour  << endl
 9         << "當前分:" << currentTime->tm_min << endl
10         << "當前秒:" << currentTime->tm_sec << endl;
11     cout << "今天是星期 " << currentTime->tm_wday << endl
12         << "今天是年中的第 " << currentTime->tm_yday + 1 << "" << endl;
13 }
複製代碼

首先用time函數得到自元年以來逝去的秒數,接着由localtime(秒數)即可得到存儲有意義時間點的結構體,tm結構體中的tm_year表示自1900年以來逝去的年,所以要輸出現在是多少年,要記得加上1900;tm_mon表示當前月,注意這裏的取值範圍是[0, 11],所以對之+1則得到生活意義上的月;表示當前天的情況稍稍複雜一些,比如今年是2013年1月5日,常用的天是5,即今天是本月的第5天,用tm_mday表示,mday表示month day;也可以說今天是週六,即今天是本週的第6天,用tm_wday表示,wday表示week day;同樣也可以說今天是整個一年中的第5天,即今天是本年的第5天,用tm_yday表示,yday表示year day,注意1月1號的tm_yday是0,所以對之+1以更符合生活上的概念。下面的時、分、秒的概念也就相對容易了,用tm_hour表示時,tm_min表示分,tm_sec表示秒。

上面程序的運行結果如下:

下面我們列個表總結一下:

tm_year            當前年(自1900年以來逝去的年數,一般對之+1900)

tm_mon            當前月(注意起始是0,所以一般對之+1)

tm_mday          當前日

tm_wday          星期幾

tm_yday           年中的第幾天(注意起始是0,所以一般對之+1)

tm_hour           當前時

tm_min             當前分

tm_sec             當前秒

如果你用的是Visual Studio的編譯器,那麼直接使用localtime()函數,編譯器會給出warning,說這個函數不安全,並推薦使用localtime_s()。localtime_s()的函數接口如下:

errno_t localtime_s(

   struct tm* _tm,

   const time_t *time

);

我看了一下微軟的文檔,貌似這個函數對原來函數的“安全”改進就在於用返回值判斷函數運行是否成功。所以很簡單地,我們只要把上述程序傳入的參數形式修改一下:

複製代碼
 1 int main()
 2 {
 3 const time_t t = time(NULL);
 4     tm currentTime = {0};
 5     int err = localtime_s(&currentTime, &t);
 6     if(err)
 7     {
 8         cout << "函數運行不成功!" << endl;
 9         exit(1);
10     }
11     cout << "當前年:" << 1900 + currentTime.tm_year << endl
12         << "當前月:" << currentTime.tm_mon + 1 << endl
13         << "當前日:" << currentTime.tm_mday << endl
14         << "當前時:" << currentTime.tm_hour  << endl
15         << "當前分:" << currentTime.tm_min << endl
16         << "當前秒:" << currentTime.tm_sec << endl;
17     cout << "今天是星期 " << currentTime.tm_wday << endl
18         << "今天是年中的第 " << currentTime.tm_yday + 1 << "" << endl;
19 }
複製代碼

tm結構體中能表示的最小單位是“秒”,在有些實時應用時,可能需要更精確的度量,該怎麼辦呢?

 

3. 用<windows.h>中的GetLocalTime()函數得到有意義的時間點

windows.h頭文件中的GetLocalTime()函數可以精確到毫秒,函數接口如下:

void GetLocalTime(SYSTEMTIME* systemTime);

SYSTEMTIME是類似於tm的結構體,使用方法很簡單,如下面的程序所示,

複製代碼
 1 int main()
 2 {
 3     SYSTEMTIME systemTime;
 4     GetLocalTime(&systemTime);
 5     cout << "當前年:" << systemTime.wYear << endl
 6         << "當前月:" << systemTime.wMonth << endl
 7         << "當前日:" << systemTime.wDay << endl
 8         << "當前時:" << systemTime.wHour << endl
 9         << "當前分:" << systemTime.wMinute << endl
10         << "當前秒:" << systemTime.wSecond << endl
11         << "當前毫秒:" << systemTime.wMilliseconds << endl;
12     cout << "當前是星期 " << systemTime.wDayOfWeek << endl;
13     return 0;
14 }
複製代碼

運行結果如下:

可以看到,SYSTEMTIME結構體中的成員都是生活意義上的,不用+1或者+1900來修正,其實看變量名也已經知道它的含義了,但在這裏還是不妨做個表:

wYear                  當前年

wMonth               當前月

wDay                   當前日

wHour                 當前時

wMinute               當前分

wSecond              當前秒

wMilliseconds     當前毫秒

wDayOfWeek      當前是星期幾

 

time(),localtime()以及GetLocalTime()都只需要系統自帶的頭文件即可,boost庫中亦提供了很方便的計時函數,還提供了顯示進度的功能,有的函數可以精確到微秒,我將在下一篇博文中進行介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章