精华内容
参与话题
问答
  • 可变参数

    千次阅读 2018-05-21 17:18:51
    从JDK1.0开始几乎每一个版本都会提供许多的新特性,例如,在JDK之中有以下几个代表性的版本 ·JDK1.2:推出了轻量级的JavaGUI设计组件包 Swing ·JDK1.5:退出了...可变参数现在假设有这样一个要求:要求设计一个...

    从JDK1.0开始几乎每一个版本都会提供许多的新特性,例如,在JDK之中有以下几个代表性的版本

      ·JDK1.2:推出了轻量级的JavaGUI设计组件包 Swing

      ·JDK1.5:退出了心得程序结构的设计思想

      ·JDK1.8:Lambda表达式、接口的定义加强


    现在为止已经接触过了一些新特性,例如:自动装箱与拆箱、swith对String的判断支持。

    自动装箱:Integer x=10;

                     Dobule y=20;

    可变参数

    现在假设有这样一个要求:要求设计一个方法用于计算任意个数的整数的相加结果,预算这种开发需求在最早的时候只能够通过数组的方式来实现。

    范例:最初的实现模式

     

    public class TestDemo {
    
    	public static void main(String[] args) {
    	System.out.println(add(new int[] {1}));
    	System.out.println(add(new int[] {1,2,3}));
    	System.out.println(add(new int[] {1,2,3,4,5,6,7,8}));
    	}
    /**	
     * 实现任意个数的数据的相加处理操作
     * @param data 要进行相加操作的数据
     * @return 返回的讴歌数据的相加结果
     */
    	public static int add(int[]data) {
    		int sum=0;
    		for(int x=0;x<data.length;x++) {
    			sum+=data[x];
    		}
    		return sum;
    	}
    
    } 

    但是这种最初的实现方式本身会存在有缺陷,

    我现在需要你设计的并不是一个数组,而是任意多个参数

    所以在JDK1.5之前该操作根本就无法使用,

    而从JDK1.5后追加了一个可变参数,也就是说这个时候的方法定义格式:

    public [static] [final] 返回值 方法名称 (参数类型 ... 参数名称){ }

    这个参数上使用的“...”实际上就明确描述了一个数组的结构。   

      

    public class TestDemo {
    
    	public static void main(String[] args) {
    	System.out.println(add());//随意你传数据的个数
    	System.out.println(add(new int[] {1}));
    	System.out.println(add(1,2,3));//可变参数可以接收参数和数组
    	}
    /**	
     * 实现任意个数的数据的相加处理操作
     * @param data 要进行相加操作的数据
     * @return 返回的讴歌数据的相加结果
     */
    	public static int add(int ...data) {//本身还是一个数组
    		int sum=0;
    		for(int x=0;x<data.length;x++) {
    			sum+=data[x];
    		}
    		return sum;
    	}
    
    } 

    现阶段可以通过一些java中的类库观察到使用,后期开发的时候也会不定期出现在你自己写的代码之中,总之原则:参数个数不确定,随意由用户传递。

    注意点:如果要传递多类参数,可变参数写在最后 

    public static int add(String msg,int ...data) 
    public static void main(String[] args) {
    	System.out.println(add("你好"));//随意你传数据的个数
    	System.out.println(add("你好",new int[] {1}));
    	System.out.println(add("你好",1,2,3));//可变参数可以接收参数和数组
    	}

    因为可变参数都是靠逗号的 不知道到那个逗号才是String

    以后如果要想编写更好的一些程序方法,可变参数是一个很常见的组合

    一个方法只能设置一个可变参数。

    展开全文
  • Python函数可变参数和关键字参数

    万次阅读 2019-07-17 14:22:45
    1.函数定义如下,它能接收多余的普通参数及多余的关键字参数,分别以元组及字典形式进行包装。 def test(*args, **kwargs): print(args) print(kwargs) data = { 'user_info': 'content' } test(1, 2, 3, 4, ...

    1.函数定义如下,它能接收多余的普通参数及多余的关键字参数,分别以元组及字典形式进行包装。

    def test(*args, **kwargs):
        print(args)
        print(kwargs)
    
    
    data = {
        'user_info': 'content'
    }
    test(1, 2, 3, 4, 5, a=1, b=2, data=data)
    
    """
    程序运行结果:
    (1, 2, 3, 4, 5)
    {'a': 1, 'b': 2, 'data': {'user_info': 'content'}}
    可以看到,碰到多余的关键字参数,它自动整体组装成一个字典,
    而字典内部的元素key为等号左边的变量,value为等号右边的值,
    可以简单的理解为把 = 替换成 :
    """
    

     

     

    展开全文
  • 函数中的可变参数 ''' #定义函数 def bmi(*person): for per in person: for item in per: name = item[0] height = item[1] weight = item[2] print('\n' + '='*13 + name + '='*13) print('...
  • 假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为...

    1.#

    假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing).
    #incldue <stdio.h>
    #define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))
    int main(void)
    {
        int y =4;
        PSQR(y);
        PSQR(2+4);
        return 0;
    }
    输出结果:
    the square of y is 16.
    the square of 2+4 is 36.
    第一次调用宏时使用“y”代替#x;第二次调用时用“2+4"代#x。

    2.##

    ##运算符可以用于类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分。这个运算符把两个语言符号组合成单个语言符号。例如:
    #define XNAME(n) x##n
    这样宏调用:
    XNAME(4)
    展开后:
    x4
    程序:
    #include <stdio.h>
    #define XNAME(n) x##n
    #define PXN(n) printf("x"#n" = %d\n",x##n)
    int main(void)
    {
        int XNAME(1)=12;//int x1=12;
        PXN(1);//printf("x1 = %d\n", x1);
        return 0;
    }
    输出结果:
    x1=12

    3.可变参数宏 ...和_ _VA_ARGS_ _

    __VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。
    实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所代表的字符串。比如:
    #define PR(...) printf(__VA_ARGS__)
    int main()
    {
        int wt=1,sp=2;
        PR("hello\n");
        PR("weight = %d, shipping = %d",wt,sp);
        return 0;
    }
    输出结果:
    hello
    weight = 1, shipping = 2
    省略号只能代替最后面的宏参数。
    #define W(x,...,y)错误!


    * 1. 可变参数的宏

    一般在调试打印Debug 信息的时候, 需要可变参数的宏. 从C99开始可以使编译器标准支持可变参数宏(variadic macros), 另外GCC 也支持可变参数宏, 但是两种在细节上可能存在区别.

    1. __VA_ARGS__

    __VA_ARGS__ 将"..." 传递给宏.如
    #define debug(format, ...) fprintf(stderr, fmt, __VA_ARGS__)

    在GCC中也支持这类表示, 但是在G++ 中不支持这个表示.

    2. GCC 的复杂宏

    GCC使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。
    #define debug(format, args...) fprintf (stderr, format, args)

    这和上面举的那个定义的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述。

    3. ##__VA_ARGS__

    上面两个定义的宏, 如果出现debug("A Message") 的时候, 由于宏展开后有个多余的逗号, 所以将导致编译错误. 为了解决这个问题,CPP使用一个特殊的‘##’操作。

    #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
    这里,如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。

    4. 其他方法

    一种流行的技巧是用一个单独的用括弧括起来的的 "参数" 定义和调用宏, 参数在宏扩展的时候成为类似 printf() 那样的函数的整个参数列表。 
    #define DEBUG(args) (printf("DEBUG: "), printf(args))

    * 2. 可变参数的函数

    写可变参数的C函数要在程序中用到以下这些宏:
    void va_start( va_list arg_ptr, prev_param )
    type va_arg( va_list arg_ptr, type )
    void va_end( va_list arg_ptr )

    va在这里是variable-argument(可变参数)的意思,这些宏定义在stdarg.h中.下面我们写一个简单的可变参数的函数,该函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值.

    [cpp] view plain copy
    void simple_va_fun(int i, ...)  
    {  
       va_list arg_ptr;  
       int j=0;  
        
       va_start(arg_ptr, i);  
       j=va_arg(arg_ptr, int);  
       va_end(arg_ptr);  
       printf("%d %d\n", i, j);  
       return;  
    }  

    在程序中可以这样调用:
    [cpp] view plain copy
    simple_va_fun(100);  
    simple_va_fun(100,200);  

    从这个函数的实现可以看到,使用可变参数应该有以下步骤:
    1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针.
    2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.
    3)然后用va_arg返回可变的参数,并赋值给整数j. va_arg的第二个参数是你要返回的参数的类型,这里是int型.
    4)最后用va_end宏结束可变参数的获取.然后你就可以在函数里使用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获取各个参数.

    如果我们用下面三种方法调用的话,都是合法的,但结果却不一样:
    1)simple_va_fun(100);
    结果是:100 -123456789(会变的值)
    2)simple_va_fun(100,200);
    结果是:100 200
    3)simple_va_fun(100,200,300);
    结果是:100 200

    我们看到第一种调用有错误,第二种调用正确,第三种调用尽管结果正确,但和我们函数最初的设计有冲突.下面一节我们探讨出现这些结果的原因和可变参数在编译器中是如何处理的.

    * 3. 可变参数函数原理

    va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于硬件平台的不同,编译器的不同,所以定义的宏也有所不同,下面以VC++中stdarg.h里x86平台的宏定义摘录如下:

    [cpp] view plain copy
    typedef char * va_list;  
    #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )  
    #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )  
    #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )  
    #define va_end(ap) ( ap = (va_list)0 )   
    定义_INTSIZEOF(n)主要是为了内存对齐,C语言的函数是从右向左压入堆栈的(设数据进栈方向为从高地址向低地址发展,即首先压入的数据在高地址). 下图是函数的参数在堆栈中的分布位置:

    低地址   |-----------------------------|<-- &v
           |第n-1个参数(最后一个固定参数)|
           |-----------------------------|<--va_start后ap指向
           |第n个参数(第一个可变参数) |
           |-----------------------------|
           |....... |
           |-----------------------------|
           |函数返回地址 |
    高地址 |-----------------------------|

    1. va_list 被定义为char *
    2. va_start 将地址ap定义为 &v+_INTSIZEOF(v),而&v是固定参数在堆栈的地址,所以va_start(ap, v)以后,ap指向第一个可变参数在堆栈的地址
    3. va_arg 取得类型t的可变参数值,以int型为例,va_arg取int型的返回值:
       j= ( *(int*)((ap += _INTSIZEOF(int))-_INTSIZEOF(int)) );
    4. va_end 使ap不再指向堆栈,而是跟NULL一样.这样编译器不会为va_end产生代码. 

    在不同的操作系统和硬件平台的定义有些不同,但原理却是相似的. 

    * 4. 小结

    对于可变参数的函数,因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢,可变参数的类型和个数需要在该函数中由程序代码控制;另外,编译器对可变参数的函数的原型检查不够严格,对编程查错不利.
    所以我们写一个可变函数的C函数时,有利也有弊,所以在不必要的场合,无需用到可变参数.如果在C++里,我们应该利用C++的多态性来实现可变参数的功能,尽量避免用C语言的方式来实现.

    * 5. 附一些代码

    #define debug(format, ...)               fprintf(stderr, fmt, __VA_ARGS__)  
    #define debug(format, args...)       fprintf (stderr, format, args)  
    #define debug(format, ...)              fprintf (stderr, format, ## __VA_ARGS__)  

    // 使用va... 实现
    void debug(const char *fmt, ...)  
    {  
        int nBuf;  
        char szBuffer[1024];  
        va_list args;  
      
        va_start(args, fmt);  
        nBuf = vsprintf(szBuffer, fmt, args) ;  
        assert(nBuf >= 0);  
      
        printf("QDOGC ERROR:%s\n",szBuffer);  
        va_end(args);  

    --------------------- 
     

    展开全文
  • 传递可变参数

    2019-02-21 15:26:03
    (1) #define Print(...) printf(__VA_ARGS__) (2) #include &lt;stdio.h&gt; #include &lt;stdarg.h&gt; #include &lt;ctype.h&gt; static void __cdecl odprintf(const char ...{char ...

    (1)

    #define Print(...)              printf(__VA_ARGS__)

    (2)

    #include <stdio.h>
    #include <stdarg.h>
    #include <ctype.h>

    static void __cdecl odprintf(const char *format, ...)
    {char buf[4096], *p = buf;
    va_list args;
    va_start(args, format);
    p += _vsnprintf(p, sizeof buf - 1, format, args);
    va_end(args);
    while ( p > buf && isspace(p[-1]) )
    {
    *--p = '\0';
    *p++ = '\r';
    *p++ = '\n';*p = '\0';
    }
    OutputDebugString(buf);
    }

     

    展开全文
  • Java可变参数

    2020-08-01 19:26:04
    目录 1可变参数【应用】 2可变参数的使用【应用】 ...如果一个方法有多个参数,包含可变参数可变参数要放在最后 可变参数的基本使用 public class ArgsDemo01 { public static void ma...
  • C语言可变参数

    万次阅读 2019-02-14 11:38:27
    C语言可变参数可以使用宏函数取出,宏函数在头文件stdarg.h中。 贴出如下简单的代码,博客转载自: https://www.cnblogs.com/edver/p/8419807.html 亦可参考:...
  • 上述代码中“#1”处应该怎样定义可变参数,因为可能in()中需要添加很多ID。查阅过关于"_variadic ### int[]_"的用法,但是还是一头雾水。 请各位大神赐教, 谢谢! 上述代码仅为一个简单的阐明想法的例题,如果...
  • 定义java方法可变参数

    千次阅读 2020-01-16 10:26:55
    以校验参数非空为例: public class checkParams { //非空校验 public static boolean checkString(String ... params) { boolean boo=true; if(params ==null||"".equals(params)) { return false; }...
  • Java可变参数以及一个简单应用

    万次阅读 多人点赞 2019-06-13 22:46:42
    一、背景 写代码的时候接触到了Java可变... 可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理。 注意:可变参数必须位于最后一项。 2.2 特点 只能出现在参数列表的最后; ...位...
  • 可变参数可变参数宏的使用

    千次阅读 2018-06-12 09:15:19
    可变参数的宏一般在调试打印Debug 信息的时候, 需要可变参数的宏. 从C99开始可以使编译器标准支持可变参数宏(variadic macros), 另外GCC 也支持可变参数宏, 但是两种在细节上可能存在区别.1. __VA_ARGS____VA_ARGS_...
  • GO 可变参数 ...

    万次阅读 2020-03-06 01:03:58
    GO 可变参数 …args & args… 文章目录GO 可变参数 ...args & args...1、内部实现2、使用3、函数间的传递参考 1、内部实现 可变参数 …Type 等效于 []Type 的切片,当 …Type 未传递数值时为 的切片 []Type,...
  • Java可变参数/可变长参数

    千次阅读 2016-10-20 10:52:32
    Java可变参数/可变长参数传递的参数不确定长度,是变长的参数,例如小例子:package demo; public class Demo { public static int sum(int n, int... nums) { for (int i = 0; i ; i++) { n = n + nums[i];...
  • 1.位置可变参数( * ) 在形式参数名称前加一个星号 *,则代表使用该形式参数可以接收任意多个参数,而且接收的参数将会以元组的方式组织。 例: def func(*args): #arg形参以元组的方式组织传入的实参 print(args)...
  • C++11 可变参数

    2020-03-24 14:26:34
    C++11的可变参数模板,对参数进行了高度的泛化,可以表示 任意数目 任意类型 语法为 class或者typename后面加… Template<class ... T>void func(T ... args) { cout<<”num is”<<sizeof ......
  • 什么是可变参数

    2020-02-09 11:18:23
    何为可变参数 可变参数是允许调用参数数量不同的方法。 我们来举一个例子 public class DemoTest { public static void main(String[] args) { int i = sum(1,2,3); System.out.println(i); } //此方法可以...
  • PHP可变参数

    2019-05-06 16:09:00
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • 之前看到论坛上有人问,如何在一个可变参数函数中调用另一个可变参数函数,其实一句话就可以搞定: #define debug_print(fmt,...) printf(fmt, ##__VA_ARGS__) 转自:...
  • 可变参数的认识

    2019-12-06 11:59:52
    可变参数是c语言函数中参数的个数和类型是不定的;具有可变参数的函数,称为可变参数函数。要注意的是,可变参数函数必须有一个以上的固定参数,可变参数必须作为最后一个函数参数。 ...代表的就是可变参数,将来...
  • Java方法的可选参数 可变参数

    千次阅读 2018-11-07 13:13:21
    Java方法的可选参数 可变参数

空空如也

1 2 3 4 5 ... 20
收藏数 27,301
精华内容 10,920
关键字:

可变参数