zoukankan      html  css  js  c++  java
  • [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")

    结束

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

  • 相关阅读:
    javaweb学习总结(二十九)——EL表达式
    javaweb学习总结(二十八)——JSTL标签库之核心标签
    javaweb学习总结(二十七)——jsp简单标签开发案例和打包
    在Servlet使用getServletContext()获取ServletContext对象出现java.lang.NullPointerException(空指针)异常的解决办法
    javaweb学习总结(二十六)——jsp简单标签标签库开发(二)
    javaweb学习总结(二十五)——jsp简单标签开发(一)
    javaweb学习总结(二十四)——jsp传统标签开发
    javaweb学习总结(二十三)——jsp自定义标签开发入门
    javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册
    javaweb学习总结(二十一)——JavaWeb的两种开发模式
  • 原文地址:https://www.cnblogs.com/over140/p/1756570.html
Copyright © 2011-2022 走看看