●為什麼要用不定參數寫Log API ?
每次在寫 Log 之前就要宣告一個字串,再用 sprintf 或 Format 來處理,實在不方便,還要去控制字串的宣告位置、次數,多次寫Log的位置都有相同的宣告,程式碼也變得難閱讀。
不如直接將 Format 參數帶入 API,再由 Log API 來處理字串,是更好的方法。
●做法說明
// 以下為資料來源與參考資料文章(Copy & Paste)
http://blog.yam.com/csylvia/article/17973254
先講解一下什麼是不定參數,
最知名的例子就是 printf(),
你可以這樣使用
printf( "Hello." );
也可以這樣使用
printf( "Hello %s", szName );
printf( "Hello %s, you have drunk %d cups of coffee", szName, iNumber );
函式中可以只有一條字串,
也可以字串後夾帶許多參數,
這樣的函式的定義當然不可能是這樣:
printf( char* string, char* param1 );
printf( char* string, char* param1, int param2 );
printf( char* string, int param1 );
...
這樣有幾百、幾千種組合啊?!=口=|||b
這就是「不定參數」發揮的地方了。
可以看到 printf 的 prototype:
int printf(const char *format [,argument]...);
那三個點就是表示不定參數(參數的個數、型態不限定)。
用法大家非常清楚,
那假如今天想寫一個接受不定參數的函式要怎麼做?
這就要應用到 va_arg()、va_end()、va_start() 三個 macro 來完成,
根據手邊的《C/C++》內的說明如下:
va_arg():它可以讓函數後面所接的引數不必維持固定的個數。第一次呼叫時,會傳回引數列最前面的第一個引數,接下來每次呼叫會自動傳回下一個引數內容。
va_end():當使用 va_arg() 完成取得所有引數內容後呼叫此 macro,通常是為了執行 return 動作。
va_start():在使用 va_arg() 前必須先呼叫此 macro,如此才能順利找到「不定引數列」的最前面內容。
此外還有幾個相關函式:
vfprintf():將 argument list 的內容輸出到資料流。
vprintf():將 argument list 的值寫到標準輸出(standard output)。
vsprintf():將 argument list 的值輸出到字串緩衝區(string buffer)。
--------------------------------------------------------------------------------------------------
/*
NAME:
WriteLog(LPCTSTR sFormat, ...)
PARAMETER:
sFormat : 傳入的 Format 字串
... : Format 字串的參數
RETURN:
COMMENT:
*/
void CTekKLine::WriteLog(LPCTSTR sFormat, ...)
{
va_list pArgList;
TCHAR sBuffer[2048];
FILE *pFile;
CString sPath;
CString sTemp;
CTime tNow = CTime::GetCurrentTime();
// 取出傳入的 Format
va_start(pArgList, sFormat);
_vsnwprintf(sBuffer, sizeof(sBuffer) / sizeof(TCHAR), sFormat, pArgList);
va_end(pArgList);
// 建立資料夾
sPath = _T(".\\log");
CreateDirectory(sPath, NULL);
// 組成路徑
sTemp.Format(_T("%s\\kline.log"), sPath);
pFile = _tfopen(sTemp, _T("a+t"));
// 寫入檔案
sTemp.Format(_T("[%04d%02d%02d %02d:%02d:%02d] %s\n"),
tNow.GetYear(), tNow.GetMonth(), tNow.GetDay(), tNow.GetHour(), tNow.GetMinute(), tNow.GetSecond(),
sBuffer);
_fputts(sTemp, pFile);
fclose(pFile);
}