[C++]遍历可变参数 (va_list)

简介:

正文

  一.  遍历可变参数

    1.1  传入的时候指定参数个数

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


 

      调用方法:“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")



本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/583022,如需转载请自行联系原作者

相关文章
|
C# Windows 容器
C#或Winform中的消息通知之系统托盘的气泡提示窗口(系统toast通知)、ToolTip控件和ToolTipText属性
NotifyIcon控件表示系统右下角任务栏上的托盘图标,其ShowBalloonTip方法用于显示气球状提示框(Win10只有为本地Toast通知),ToolTip\oolTipText可以...
3256 0
C#或Winform中的消息通知之系统托盘的气泡提示窗口(系统toast通知)、ToolTip控件和ToolTipText属性
|
弹性计算 容器 RDMA
在Kubernetes上使用RDMA
### RDMA RDMA(全称RemoteDirect Memory Access) 它为了解决网络传输中服务器端数据处理的延迟而产生。 它的原理是将待传输的数据从一台计算机的内存,直接传输到另一台计算机的内存,整个传输过程无需操作系统和协议栈的介入。
10484 0
UE4动画蓝图节点Layered blend per bone详解
UE4动画蓝图节点Layered blend per bone详解
644 1
|
网络安全 Windows
window powershell 查看ssh
window powershell 查看ssh
766 0
|
存储
在使用 realloc 函数时,如何避免数据丢失?
在使用 realloc 函数动态调整内存大小时,为避免数据丢失,应先将原指针保存到临时变量中,调用 realloc 后检查返回值是否为 NULL,若为 NULL 则保留原指针,否则更新指针并释放临时变量。
|
存储 JSON Go
一文搞懂 Golang 高性能日志库 Zerolog
一文搞懂 Golang 高性能日志库 Zerolog
1168 0
【Qt 学习笔记】Qt窗口 | 标准对话框 | 颜色对话框QColorDialog
【Qt 学习笔记】Qt窗口 | 标准对话框 | 颜色对话框QColorDialog
2336 3
|
iOS开发
XCode控制台调试无法看到函数跟踪或无法看到输出的日志问题及解决方案
XCode控制台调试无法看到函数跟踪或无法看到输出的日志问题及解决方案
852 0
|
存储 安全 C++
【C++ 泛型编程 高级篇】C++可变参数模板探索:编程技巧与实战应用
【C++ 泛型编程 高级篇】C++可变参数模板探索:编程技巧与实战应用
752 0