【C】——可变参数

  写代码之前要先介绍一下可变参数的备用知识; 

  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_list:用来保存宏va_start、va_arg和va_end所需信息的一种类型。为了访问变长参数列表中的参数,必须声明va_list类型的一个对象。定义: typedef char *  va_list;
  • va_start:访问变长参数列表中的参数之前使用的宏,它初始化用va_list声明的对象,初始化结果供宏va_arg和va_end使用;
  • va_arg: 展开成一个表达式的宏,该表达式具有变长参数列表中下一个参数的值和类型。每次调用va_arg都会修改。用va_list声明的对象,从而使该对象指向参数列表中的下一个参数;
  • va_end:该宏使程序能够从变长参数列表用宏va_start引用的函数中正常返回。

  va在这里是variable-argument(可变参数)的意思.   
  这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件.下面我们写一个简单的可变参数的函数,改函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值.

  了解了这些知识之后就可以写下我们的第一个可变参数的函数了;

 1 void myprintf(const char *format, ...)
 2 {
 3     va_list argp;        //定义保存函数参数的结构
 4     int argno = 0;        //记录参数个数
 5     char *para;        //存放取出的字符串参数
 6 
 7     va_start(argp, format);    //argp指向传入的第一个可选参数
 8 
 9     while(1)
10     {
11         para = va_arg( argp, char *);    //取出当前的参数,类型为char *
12         if(strcmp( para, "\0") == 0)
13             break;
14         printf("parameter  #%d is %s\n",argno,para);
15         argno++;
16     }
17     printf("format is %s\n",format);
18     va_end(argp);        //将argp置为NULL
19 }

  需要注意的是

  1. 函数定义的时候第二个参数必须是三个.;
  2. 必须用va_start宏初始化argp;
  3. 用完之后必须用va_end宏将argp置空;

  此函数的调用方法是: myprintf("printf","this","is","a","text","!","\0");//取\0为结束符 我们需要用一个字符'\0'来确定是否是最后一个字符;

  此函数是从第二个参数来输出的;那么第一个参数是用来干什么的呢?貌似第一个函数除了初始化的时候用到了,其他的时候都没有用到。我们再写一个函数来看看第一个参数的用处:

 1 void myprintf_two(int format, ...)
 2 {
 3     va_list argp;
 4     int argno = 0;
 5     int fora = format;
 6     char *para;
 7 
 8     va_start(argp,format);
 9     while(fora--)
10     {
11         para = va_arg(argp,char *);
12         printf("parameter  #%d %s\n",argno,para);
13         argno++;
14     }
15     printf("format is %d\n",format);
16     va_end(argp);
17 
18 }

  哦,原来第一个参数可以是int类型的;这下了解了第一个函数的用处了吧@!

  在用可变参数函数的时候需要注意一点,就是在获取float类型的时候一定要用double接收;来看个函数:

 1 double add(int n, ...)
 2 {
 3     va_list argp;
 4     va_start(argp,n);
 5     double sum = .0;
 6     while(n--)
 7         sum += va_arg(argp,double);
 8     va_end(argp);
 9     return sum;
10 }

  如果把va_arg(argp,double)改成:va_arg(argp,float)就会报错了:

  就这么多吧,附上完整的代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdarg.h>
 4 
 5 void myprintf(const char *format, ...)
 6 {
 7     va_list argp;        //定义保存函数参数的结构
 8     int argno = 0;        //记录参数个数
 9     char *para;        //存放取出的字符串参数
10 
11     va_start(argp, format);    //argp指向传入的第一个可选参数
12 
13     while(1)
14     {
15         para = va_arg( argp, char *);    //取出当前的参数,类型为char *
16         if(strcmp( para, "\0") == 0)
17             break;
18         printf("parameter  #%d is %s\n",argno,para);
19         argno++;
20     }
21     printf("format is %s\n",format);
22     va_end(argp);        //将argp置为NULL
23 }
24 
25 void myprintf_two(int format, ...)
26 {
27     va_list argp;
28     int argno = 0;
29     int fora = format;
30     char *para;
31 
32     va_start(argp,format);
33     while(fora--)
34     {
35         para = va_arg(argp,char *);
36         printf("parameter  #%d %s\n",argno,para);
37         argno++;
38     }
39     printf("format is %d\n",format);
40     va_end(argp);
41 
42 }
43 
44 double add(int n, ...)
45 {
46     va_list argp;
47     va_start(argp,n);
48     double sum = .0;
49     while(n--)
50         sum += va_arg(argp,double);
51     va_end(argp);
52     return sum;
53 }
54 
55 int main(void)
56 {
57     myprintf("printf","this","is","a","text","!","\0");    //取\0为结束符
58     myprintf_two(4,"this","is","a","text");
59     printf("sum(10,20) = %g\n",add(2,10.0,20.0));
60     return 0;
61 }
View Code

  利用 vsnprintf 配合 va_list 操作传递进来的参数:

#include <stdio.h>
#include <stdarg.h>
int mon_log(char* format, ...)
{
char str_tmp[50];
int i=0;
va_list vArgList;                            //定义一个va_list型的变量,这个变量是指向参数的指针.
va_start (vArgList, format);                 //用va_start宏初始化变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数
i=_vsnprintf(str_tmp, 50, format, vArgList); //注意,不要漏掉前面的_
va_end(vArgList);                            //用va_end宏结束可变参数的获取
return i;                                    //返回参数的字符个数中间有逗号间隔
}
//调用上面的函数
void main() 
{
    int i=mon_log("%s,%d,%d,%d","asd",2,3,4);
    printf("%d\n",i);
}

 

 

 

 

posted @ 2013-06-21 16:47  net小伙  阅读(350)  评论(0)    收藏  举报