1. 程式人生 > >實現自己的不定參數的函數

實現自己的不定參數的函數

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);
}

實現自己的不定參數的函數