C语言中可将函数实现为可变参数的形式,可以使函数接收一个以上任意多个参数。下面先就一个简单的例子来分析一下可变参数。
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int avg(int n, ...)
{
va_list arg;
int sum = 0;
int i = 0;
va_start(arg, n);
{
for (i = 0; i < n; i++)
{
sum += va_arg(arg, int);
}
}
va_end(arg);
return sum / n;
}
int main()
{
int a = 2;
int b = 4;
int c = 10;
int avg1 = avg(2, a, b);
int avg2 = avg(3, a, b, c);
printf("平均数为%d", avg1);
printf("平均数为%d", avg2);
system("pause");
return 0;
}
声明一个va_list类型变量arg,用于访问参数列表未确定的部分,是通过va_start来初始化的,第一个参数是va_list的变量名,第二个参数是省略号前最后一个有名字的参数。初始化过程吧arg变量设置为指向可变参数的第一个参数。用va_arg来访问,va_arg返回参数的值,并使va_arg指向下一个可变参数。当访问完最后一个参数时,用va_end结束。
我们还需要注意一些问题:
1、可变参数必须从头到尾逐个访问。
2、参数列表至少有一个命名参数,如果一个参数都没有,就无法使用va_start.
3、这些宏无法直接判断实际存在参数的数量。
4、这些宏无法判断每个参数的类型。
5、如果va_arg中指定了错误的类型,其后果是不可预测的。
下面就是我使用可变参数实现简单计算器的代码,欢迎大家参考和指点:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int ddiv(int a, int b)
{
return a / b;
}
int (*pf)(int a, int b)=NULL;
struct s
{
char name[20];
int (*p)(int a, int b);
char flag;
}sr[]={
{ "add", add, '+' },
{ "sub", sub, '-' },
{ "mul", mul, 'X' },
{ "ddiv", ddiv, '/'}
};
void do_math(int argc,char* argv[])
{
int i;
pf = NULL;
for (i = 0; i < sizeof(sr) / sizeof(struct s); i++)
{
if (strcmp(argv[0], sr[i].name) == 0)
{
pf = sr[i].p;
break;
}
}
if (pf!=NULL)
{
int a = atoi(argv[1]);
int b = atoi(argv[2]);
printf("%s%c%s=%d\n", argv[1], sr[i].flag, argv[2], pf(a,b));
}
}
void do_gg(char* buf)
{
int i;
int status = 0;
int argc = 0;
char* argv[10] = {};
for (i = 0; buf[i]; i++)
{
if (status == 0 && !isspace(buf[i]))
{
status = 1;
argv[argc++] = buf+i;
}
else if (isspace(buf[i]))
{
status = 0;
buf[i] = 0;
}
}
argv[argc] = NULL;
do_math(argc, argv);
}
int main(void)
{
char buf[100] = {0};
while (1)
{
printf(">\n");
scanf("%[^\n]%*c", buf);
if ((strcmp(buf, "exit")) == 0)
break;
do_gg(buf);
}
system("pause");
return 0;
}