刚开始,有一道题,分别用字符数组和字符指针作函数参数两种方法编程实现如下功能:在字符串中删除与某字符相同的字符。看到这道题我就想到了java的函数重载,想想怎样在C中实现这个技巧。
结果,发现了stdarg.h这个头文件,可以实现传入不同的参数,并且个数任意,不由得想到了android编程中的实现那个异步任务的时候
class A extends AsyncTask<String, Integer, String>{ @Override protected String doInBackground(String... arg0) { // TODO Auto-generated method stub return null; } }
那个doInBackground(String... arg0),好类似,可以传入不同个数的参数。还有C语言中printf和scanf两个函数更令我好奇。
题外话:现在就开始面向过程与面向对象是相通的,可能面向对象是把面向过程做了更好地封装,所用的编程思想是相通的,所用的人生哲学是不同的,面向过程就像做题,一步一步规规矩矩的去解题,而面向对象更倾向于用一些已经抽象封装好的东西,你只需要知道我用什么方法去解题--------这只是一个学渣渣的感觉,相信继续学习,会有不同感触。
现在思考一下用函数求任意多的实数的平均数,当然你不能要求预先输入要求几个数的平均数,也就是说你不能用动态申请内存的方式去创建数组作为参数进行运算。
那么就真正来用一下stdarg.h吧!
代码如下:
#include<stdio.h> #include<stdarg.h> double Average(double num1,...); void main(){ printf("%lf",Average(4.0,6.0,8.0,0.0)); } double Average(double num1,...){ double sum = num1 , count = 1 ,value = 0.0; va_list num;//可变参数列表的指针 va_start(num,num1);
/*这个函数接受两个参数,一个是va_list类型的指针(va_list 一般是char指针),另一个是固定参数的名称,就是从哪个参数开始*/ for(;(value = va_arg(num,double)) != 0.0;){ /*这个函数也是两个参数,第一个是va_list类型的指针,但是它将这个指针先+1,然后再返回 这个指针指向的值,另一个是要返回的类型*/ //printf("%lf",value); sum += value; count++; } va_end(num);//必须要释放,不然不会报错,但是结果完全不对 return sum/count ; }
#ifdef _M_ALPHA typedef struct { char *a0; /* pointer to first homed integer argument */ int offset; /* byte offset of next parameter */ } va_list; #else typedef char * va_list; #endif _M_ALPHA是指DEC ALPHA(Alpha AXP)架构。所以一般情况下va_list所定义变量为字符指针。
可以看出在条件编译时va_list不同,但更可能是一个char的指针,不然就是一个结构体类型。
但是这和java的不同,明显这里至少要有一个参数,并且参数的类型可以判断,而且这个程序最后一个参数必须是0.0,所以感到很不好用。
那么大家会问,printf可以输出任意的东西,为什么。那是因为这个函数第一个参数是一个字符串,有这个字符串可以知道后面变量的数据类型和个数。