[C++]遍歷可變參數 (va_list)

前言html

  在C++中使用可變參數可沒C#中那麼方便,使用起來也很麻煩,想盡辦法搜了不少資料仍然無果,可是確有一些心得。
 網絡

 

文章
 ide

  1.  http://www.programmer-club.com.tw/ShowSameTitleN/vc/13915.html函數

  2.  va_list、va_start、va_arg、va_end的原理與使用spa

 

正文.net

  一.  遍歷可變參數code

    1.1  傳入的時候指定參數個數orm

void  arg_cnt( int  cnt, ...)
{
    
int  value = 0 ;
    
int  i = 0 ;
    
int  arg_cnt = cnt;
    va_list arg_ptr; 
    va_start(arg_ptr, cnt); 
    
for (i  =   0 ; i  <  cnt; i ++ )
    {
        value 
=  va_arg(arg_ptr, int );
        printf(
" value%d=%d\n " , i + 1 , value);
    }

    va_end(arg_ptr);
htm

}
 blog

      調用方法:「arg_cnt(4,1,2,3,4);」,第一個參數爲傳入參數個數。

    1.2  傳入的時候指定特殊的字符以標示爲結

int  demo(  char  msg, ... )
{
    va_list argp;
    
int  argno  =   0 ;
    
char  para;

    va_start( argp, msg );
    
while  ( 1 )
    {
        para 
=  va_arg( argp,  char );
        
if  ( strcmp( para,  "" ==   0  )
            
break ;
        printf(
" Parameter #%d is: %s\n " , argno, para);
        argno
++ ;
    }
    va_end( argp );

    
return   0 ;

      調用方法:「demo("DEMO", "This", "is", "a", "demo!", "");」,最後一個參數標示結束。
 

 

  二.  探討CString的Format方法

    在學可變參數這節的時候一直很嚮往能達到這種效果,即不用多傳一個參數來指定結束。我臆斷有兩種狀況來實現:

    a).  編譯器作了手腳

      編譯以後有可能改變了函數多傳入了一個參數的個數,有幾個參數編譯的時候是可以知道的。

    b).  使用"%"做爲特殊符號

      實踐中發現若是有%字符出如今Format中的話是會報錯的,全部我推斷他統計了"%"出現的次數,而後解析"%"後面的參數,好比"%d"、"%s",經過統計"%"出現的次數就可以解決參數個數的難度,也就不用咱們傳入參數個數來實現遍歷了。

    c).  相似實現代碼

int  FindCharCount(CString csStr, char  c)
{
    
int  iCount  =   0 ;
    
for ( int  i = 0 ;i < csStr.GetLength();i ++ )
    {
       i 
=  csStr.Find(c ,i  +   1  );
       iCount
++ ;
    }
    
return  iCount;
}

BOOL CppSQLite3Helper::ExecuteNonQuery(
char   *  commandText, const   char   * params ...)
{
    BOOL bResult 
=  TRUE;
    va_list ap;
    
try
    {
        va_start(ap,
params );
        CppSQLite3Statement stmt 
=  m_db.compileStatement(commandText);
        
for ( int  i  =   0  , j  =  FindCharCount(CString(commandText), ' ? ' )  ; i  <  j ; i  ++ )
        {
            stmt.bind(i,va_arg(ap,
char   * ));
        }
        stmt.execDML();
    }
    
catch (CppSQLite3Exception e)
    {
        bResult 
=  FALSE;
    }
    
catch (...)
    {
        bResult 
=  FALSE;
    }
    va_end(ap);

    
return  bResult;
}

      代碼說明:

        這段代碼是在使用Sqlite時封裝的一段代碼,儘可能保持了C#的命名比較習慣一點,這段代碼只是編譯經過了,這裏僅用於說明這個道理和用法,是否是和Format很像 :)

        i.  使用:ExecuteNonQuery("update test set c1 = ? where id = ? ","abc","1")

 

結束

  正文一段內容中代碼均來自網絡,多爲轉載,不知原始出處,仍謝之!  

相關文章
相關標籤/搜索