C 語言初學教材 - 第五章 處理時間的函數

我們之前把處理時間的工作全部放在函數 printtime() 中,因此從標準函數庫 time.h time() 取得秒數值,或是由 localtime() 得到結構 tm 的指標,與我們自行定義的結構 my_tm ,這些全都在 printtime() 中完成。



可是有時候呼叫端,也就是需要呼叫 printtime() 處理時間的函數,有時候也會需要以上這些數值,例如累計程式執行時間,那麼在程式開始執行時就需要呼叫一次 time() ,程式結束前另外呼叫一次 time() ,然後把兩次的秒數值相減,就會得到程式執行的總秒數。


如果我們需要在程式不同的地方顯示時間,而非每次都空兩行,印出時間訊息,然後再空兩行的固定格式,那我們就需要一個結構 my_tm 的變數來操作,這時候如果只有 printtime() 就不會很實用。


接下來我們繼續討論各種不同處理時間函數的設計方式,主要差別在於設置參數及回傳值。首先,若是以 time() 回傳的秒數值當參數,函數回傳結構 my_tm ,這樣的函數原型宣告如下
My_Time myTimeS(time_t seconds);


因此,參數是型態 time_t 的 seconds , time_t 屬於整數型態的一種,因此算是基本資料型態,回傳值則是結構 my_tm 。注意,這裡的 My_Time 是用 typedef 定義的新型態名稱。


實作程式碼如下
My_Time myTimeS(time_t seconds)
{
    struct tm *tmPtr = localtime(&seconds);
    My_Time mt;
    
    mt.year = tmPtr->tm_year + 1900;
    mt.month = tmPtr->tm_mon + 1;
    mt.day = tmPtr->tm_mday;
    mt.hour = tmPtr->tm_hour;
    if (mt.hour < 12 ) {
        mt.isam = 1;
        mt.hourt = tmPtr->tm_hour;
    }
    else {
        mt.isam = 0;
        mt.hourt = tmPtr->tm_hour - 12;
    }
    mt.min = tmPtr->tm_min;
    mt.sec = tmPtr->tm_sec;
    
    return mt;
}


因此利用這個函數 myTimeS() ,我們便可得到結構 my_tm 的回傳值。


完整的範例程式碼及編譯執行,請繼續參考


回傳結構由於是拷貝的副本,容易佔用不少記憶體去,所以我們可以直接以指向結構 my_tm 的指標當參數,讓函數直接修改在函數 main() 宣告的結構 my_tm ,這麼一來,就不需要有回傳值了。


基於以指標當參數的想法,函數原型如下
void myTimeS2(My_Time *nowPtr);


這裡我們只用指向結構 my_tm 的指標當參數,所以取得 time() 回傳的秒數值,要在函數 myTimeS2() 中進行,如下
void myTimeS2(My_Time *nowPtr)
{
    time_t seconds = time(NULL);
    struct tm *tmPtr = localtime(&seconds);
    
    nowPtr->year = tmPtr->tm_year + 1900;
    nowPtr->month = tmPtr->tm_mon + 1;
    nowPtr->day = tmPtr->tm_mday;
    nowPtr->hour = tmPtr->tm_hour;
    if (nowPtr->hour < 12 ) {
        nowPtr->isam = 1;
        nowPtr->hourt = tmPtr->tm_hour;
    }
    else {
        nowPtr->isam = 0;
        nowPtr->hourt = tmPtr->tm_hour - 12;
    }
    nowPtr->min = tmPtr->tm_min;
    nowPtr->sec = tmPtr->tm_sec;
}


完整的範例程式碼及編譯執行,請繼續參考


問題與討論
  1. 比較回傳結構跟結構指標當參數的優劣。
  2. 可以直接回傳指向結構 my_tm 的指標嗎?




沒有留言: