所謂“時”,可以分成時間點和時間段兩大類,時間點的概念就好比知道現在是幾時幾分,而時間段主要用於計量這段程序運行了多久,或者用於定時觸發中斷。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(¤tTime, &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庫中亦提供了很方便的計時函數,還提供了顯示進度的功能,有的函數可以精確到微秒,我將在下一篇博文中進行介紹。