C 語言初學教材 - 第四章 進一步處理時間

我們曾經呼叫作業系統的指令 date ,顯示目前時間,也用過 time.h time() 回傳格林威治時間 1970 年 1 月 1 日到現在的總秒數。其實, time.h 中也有其他很多相關處理時間的函數,與一個專門儲存時間格式的結構 tm ,以及兩個算術型態 clock_t 及 time_t 。



函數 time() 回傳的型態其實就是 time_t ,但由於 time_t 也是整數的算術型態,利用 typedef 定義出來的,所以我們之前都可以用 int 型態來處理。


而結構 tm 有如下的成員
成員表示範圍
int tm_sec;0, 61
int tm_min;0, 59
int tm_hour;0, 23
int tm_mday;1, 31
int tm_mon;0, 11
int tm_year;since 1900
int tm_wday;星期的天數0, 6
int tm_yday;今天已過的天數0, 365
int tm_isdst;日光節約時間旗標


結構 tm 中記錄秒的的成員 tm_sec 上限到 61 ,這是因為電腦有用閏秒調整時間。


雖然我們可以直接照結構 tm 的格式處理時間,然而還是有些不方便的地方,例如結構 tm 的年份記錄,我們就得自己加上 1900 ,才能是現在的年份,不然,例如 2010 年,實際上成員 tm_year 所儲存的是整數 110 。


因此我們可以定義一個方便我們自己處理時間的格式,然後要處理時間就接運用自行定義的結構就可以了,基於這個想法,我們採用如下結構 my_tm 的定義
struct my_tm {
    int year;  // 現在年份
    int month; // 月份
    int day;   // 日期
    int hour;  // 二十四小時制的時
    int isam;  // 上午為非 0 值,下午為 0
    int hourt; // 十二小時制的時
    int min;   // 分
    int sec;   // 秒
};


time.h 的函數 localtime() 會回傳指向結構 tm 的指標,這是因為回傳一個結構容易佔去太多記憶體, C 語言是傳值呼叫,記得嗎?回傳結構就會整個結構拷貝一份,所以標準函數庫中一些涉及結構的,大多是以指標作為函數間的傳遞。函數 localtime() 也需要以 time_t 型態的指標當作參數,通常我們會用指向 time() 回傳秒數的指標變數。


全部的程式碼如下
#include <stdio.h>
#include <time.h>

struct my_tm {
    int year;  // 現在年份
    int month; // 月份
    int day;   // 日期
    int hour;  // 二十四小時制的時
    int isam;  // 上午為非 0 值,下午為 0
    int hourt; // 十二小時制的時
    int min;   // 分
    int sec;   // 秒
};

typedef struct my_tm My_Time;

int main(void)
{
    time_t seconds = time(NULL);
    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;
    
    printf("\n\n現在時間是西元 %d 年 %d 月 %d 日", mt.year, mt.month, mt.day);
    printf("%s %d 點 %d 分 %d 秒\n\n", mt.isam ? "上午" : "下午", mt.hourt, mt.min, mt.sec);
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:timetest.c
    功能:示範結構的使用
    作者:張凱慶
    時間:西元2010年7月 */ 


編譯執行這個程式,就可以看到現在時間了



另外,程式的第 39 行,函數 printf() 的第二個參數,我們這裡用了個技巧
mt.isam ? "上午" : "下午"


一個問號 ? 加上一個冒號 : ,這是 C 語言唯一用到三個運算元的條件運算子,若問號前的運算式為真,這個條件運算式的結果就會是冒號前運算式的值,反之,條件運算式的結果就會是冒號後運算式的值。因此,若 mt.isam 為 1 ,轉換字符 %s 就會被 "上午" 代入,若 mt.isam 為 0 ,轉換字符 %s 則會被 "下午" 代入。


問題與討論
  1. time_t 與 int 這兩種型態有何不同?
  2. 為什麼要自己另外定義處理時間的結構?
  3. time.h 另外有個函數 asctime() ,可以將結構 tm 轉變為可印出的字串,這會比使用結構方便嗎?




沒有留言: