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

简介:

前言

  在C++中使用可变参数可没C#中那么方便,使用起来也很麻烦,想尽办法搜了很多资料仍然无果,但是确有一些心得。

 

文章

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

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

 

正文

  一.  遍历可变参数

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

 

结束

  正文一段内容中代码均来自网络,多为转载,不知原始出处,仍谢之! 


转载:http://www.cnblogs.com/over140/archive/2010/06/12/1756570.html

目录
相关文章
|
10月前
|
算法 C++ 容器
模拟实现c++中的list模版
模拟实现c++中的list模版
|
11月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
537 3
|
12月前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
266 1
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
391 7
|
Java 机器人 程序员
从入门到精通:五种 List 遍历方法对比与实战指南
小米是一位热爱分享技术的程序员,本文详细介绍了 Java 中遍历 List 的五种方式:经典 for 循环、增强 for 循环、Iterator 和 ListIterator、Stream API 以及 forEach 方法。每种方式都有其适用场景和优缺点,例如 for 循环适合频繁访问索引,增强 for 循环和 forEach 方法代码简洁,Stream API 适合大数据量操作,ListIterator 支持双向遍历。文章通过生动的小故事和代码示例,帮助读者更好地理解和选择合适的遍历方式。
541 2
|
存储 编译器 C++
C++ initializer_list&&类型推导
在 C++ 中,`initializer_list` 提供了一种方便的方式来初始化容器和传递参数,而右值引用则是实现高效资源管理和移动语义的关键特性。尽管在实际应用中 `initializer_list&&` 并不常见,但理解其类型推导和使用方式有助于深入掌握现代 C++ 的高级特性。
183 4
|
11月前
|
数据采集 存储 算法
【C++数据结构——图】图的遍历(头歌教学实验平台习题) 【合集】
本文介绍了图的遍历算法,包括深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历通过递归方式从起始节点深入探索图,适用于寻找路径、拓扑排序等场景;广度优先遍历则按层次逐层访问节点,适合无权图最短路径和网络爬虫等应用。文中提供了C++代码示例,演示了如何实现这两种遍历方法,并附有测试用例及结果,帮助读者理解和实践图的遍历算法。
651 0
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
390 3
|
存储 算法 C++
【C++打怪之路Lv10】-- list
【C++打怪之路Lv10】-- list
165 1
|
存储 C++ 容器
C++入门9——list的使用
C++入门9——list的使用
169 1