實現自己的不定參數的函數
阿新 • • 發佈:2017-07-29
nbsp sta 不定 初始化 合成 方便 容易 一個 ()
不定參數在一些特殊場合下是很有用的,例如在字符串的格式化合成,像printf()函數、日誌輸出等場合都很容易想到這樣的結構。
其實,這種方法在C語言裏就已經存在了,也不是什麽新奇特的東西,一般要實現這樣的功能,需要以下幾個函數/類型組成:
va_list 、va_start、va_avg、va_end
頭文件:stdarg.h
先來看兩個例子:
例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
uint GetSum(uint nD1,...)
{
va_list st;
va_start (st, nD1);
uint total = nD1; uint tmp;
while ((tmp = va_arg (st, uint)) != 0)
{
total += tmp;
}
va_end (st);
return total;
}
|
例2:
double sum_series(int num, ...) { double sum = 0.0, t; va_list argptr; va_start(argptr, num);//初始化變元指針 while (num--) { t = va_arg(argptr, double); sum = sum + t; } va_end(argptr); return sum; }
PS:以上兩個例子是摘自網上,我想比較簡單,大家百度一下也是一大堆。
先來說說,這兩種方式的缺點吧:
例1,需要輸入一個“0”作為結束符,而且中間參數中不能出現0;這個條件限制,另外輸入的參數必須是同一種類型,不是非常靈活。
例2,需要預先輸入參數的個數,這裏也有嚴重缺陷的,因為如果輸出的num大於實際後面的參數個數的話,就越界了;另外參數增加就要修改num的輸入值,這樣也不方便;輸入的參數必須是同一種類型,不是非常靈活。
問題,printf可是沒有要求輸入參數的個數以及類型必須統一,這樣的要求哦?
的確,printf很靈活,沒有那麽限制,那麽如何實現呢?難道va_arg存在特殊判斷可以確定最後一個參數?
遺憾的是,va_arg是不知道最後一個參數的,除非像例子裏一樣,告之個數或特殊參數為結尾。。。
那麽printf怎麽做到的?
猜測,printf的第一個參數為 char* ,是個字符串,而且輸入的時候,有參數的時候必須以“%”為開頭,
那麽,問題就簡單了,我們先遍歷一遍,看看%出現幾次(排除%%),不就是知道了個數了。
然後在解析下%後面的s d什麽的,就不是問題了。。。。
最後再給個例子
void DEBUG_LOG(uint nLogID,char *strFmt,...) { char strLog[2048]; //查找“%” va_list lsID; va_start(lsID, strFmt); vsprintf(strLog, strFmt, lsID); va_end(lsID); DEBUG_LOG00(nLogID,strLog); }
實現自己的不定參數的函數